1 /*
2 *
3 * Copyright 2010 Rockchip Electronics Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <string.h>
19
20 #include "mpp_env.h"
21 #include "mpp_mem.h"
22 #include "mpp_debug.h"
23
24 #include "mpp_bitread.h"
25 #include "h263d_parser.h"
26 #include "h263d_syntax.h"
27
28 RK_U32 h263d_debug = 0;
29
30 #define h263d_dbg(flag, fmt, ...) _mpp_dbg(h263d_debug, flag, fmt, ## __VA_ARGS__)
31 #define h263d_dbg_f(flag, fmt, ...) _mpp_dbg_f(h263d_debug, flag, fmt, ## __VA_ARGS__)
32
33 #define h263d_dbg_func(fmt, ...) h263d_dbg_f(H263D_DBG_FUNCTION, fmt, ## __VA_ARGS__)
34 #define h263d_dbg_bit(fmt, ...) h263d_dbg(H263D_DBG_BITS, fmt, ## __VA_ARGS__)
35 #define h263d_dbg_status(fmt, ...) h263d_dbg(H263D_DBG_STATUS, fmt, ## __VA_ARGS__)
36
37 #define H263_STARTCODE 0x00000080 /* 17 zero and 1 one */
38 #define H263_STARTCODE_MASK 0x00FFFF80
39 #define H263_GOB_ZERO 0x00000000
40 #define H263_GOB_ZERO_MASK 0x0000007C
41
42 #define H263_SF_SQCIF 1 /* 001 */
43 #define H263_SF_QCIF 2 /* 010 */
44 #define H263_SF_CIF 3 /* 011 */
45 #define H263_SF_4CIF 4 /* 100 */
46 #define H263_SF_16CIF 5 /* 101 */
47 #define H263_SF_CUSTOM 6 /* 110 */
48 #define H263_EXTENDED_PTYPE 7 /* 111 */
49 #define H263_EXTENDED_PAR 15 /* 1111 */
50
51 typedef struct H263Hdr_t {
52 H263VOPType pict_type;
53 RK_S32 width;
54 RK_S32 height;
55 RK_U32 TR;
56 RK_U32 quant;
57
58 // frame related parameter
59 RK_S64 pts;
60 RK_S32 slot_idx;
61 RK_U32 enqueued;
62 RK_U32 hdr_bits;
63 } H263Hdr;
64
65 typedef struct {
66 // global paramter
67 MppBufSlots frame_slots;
68 RK_U32 use_internal_pts;
69 RK_U32 found_i_vop;
70
71 // frame size parameter
72 RK_S32 width;
73 RK_S32 height;
74 RK_S32 hor_stride;
75 RK_S32 ver_stride;
76 RK_U32 info_change;
77 RK_U32 eos;
78
79 // spliter parameter
80 RK_S32 pos_frm_start; // negtive - not found; non-negtive - position of frame start
81 RK_S32 pos_frm_end; // negtive - not found; non-negtive - position of frame end
82
83 // bit read context
84 BitReadCtx_t *bit_ctx;
85
86 // decoding parameter
87 H263Hdr hdr_curr;
88 H263Hdr hdr_ref0;
89
90 // dpb/output information
91 RK_S32 output;
92 RK_S64 pts;
93 RK_S64 dts;
94
95 // syntax for hal
96 h263d_dxva2_picture_context_t *syntax;
97 } H263dParserImpl;
98
99 static RK_U32 h263d_fmt_to_dimension[8][2] = {
100 { 0, 0 }, /* invalid */
101 { 128, 96 }, /* SQCIF */
102 { 176, 144 }, /* QCIF */
103 { 352, 288 }, /* CIF */
104 { 704, 576 }, /* 4CIF */
105 { 1408, 1152 }, /* 16CIF */
106 { 0, 0 }, /* custorm */
107 { 0, 0 }, /* extend */
108 };
109
h263d_fill_picture_parameters(const H263dParserImpl * p,DXVA_PicParams_H263 * pp)110 static void h263d_fill_picture_parameters(const H263dParserImpl *p,
111 DXVA_PicParams_H263 *pp)
112 {
113 const H263Hdr *hdr_curr = &p->hdr_curr;
114 const H263Hdr *hdr_ref0 = &p->hdr_ref0;
115
116 pp->short_video_header = 1;
117 pp->vop_coding_type = hdr_curr->pict_type;
118 pp->vop_quant = hdr_curr->quant;
119 pp->wDecodedPictureIndex = hdr_curr->slot_idx;
120 pp->wForwardRefPictureIndex = hdr_ref0->slot_idx;
121 pp->vop_time_increment_resolution = 30000;
122 pp->vop_width = hdr_curr->width;
123 pp->vop_height = hdr_curr->height;
124
125 // Rockchip special data
126 pp->prev_coding_type = hdr_ref0->pict_type;
127 pp->header_bits = hdr_curr->hdr_bits;
128 }
129
h263_syntax_init(h263d_dxva2_picture_context_t * syntax)130 static void h263_syntax_init(h263d_dxva2_picture_context_t *syntax)
131 {
132 DXVA2_DecodeBufferDesc *data = &syntax->desc[0];
133
134 //!< commit picture paramters
135 memset(data, 0, sizeof(*data));
136 data->CompressedBufferType = DXVA2_PictureParametersBufferType;
137 data->pvPVPState = (void *)&syntax->pp;
138 data->DataSize = sizeof(syntax->pp);
139 syntax->data[0] = data;
140
141 //!< commit bitstream
142 data = &syntax->desc[1];
143 memset(data, 0, sizeof(*data));
144 data->CompressedBufferType = DXVA2_BitStreamDateBufferType;
145 syntax->data[1] = data;
146 }
147
h263_parse_picture_header(H263dParserImpl * p,BitReadCtx_t * gb)148 static MPP_RET h263_parse_picture_header(H263dParserImpl *p, BitReadCtx_t *gb)
149 {
150 RK_U32 val = 0;
151 H263Hdr *hdr_curr = &p->hdr_curr;
152 H263VOPType pict_type = H263_INVALID_VOP;
153
154 /* start code */
155 READ_BITS(gb, 17, &val); /* start code */
156 mpp_assert(val == 1);
157
158 /* gob */
159 READ_BITS(gb, 5, &val); /* gob */
160 mpp_assert(val == 0);
161
162 /* time reference */
163 READ_BITS(gb, 8, &hdr_curr->TR);
164
165 /* first 5 bit of PTYPE */
166 SKIP_BITS(gb, 5);
167
168 /* source format */
169 READ_BITS(gb, 3, &val); /* source format */
170 hdr_curr->width = h263d_fmt_to_dimension[val][0];
171 hdr_curr->height = h263d_fmt_to_dimension[val][1];
172 if (!hdr_curr->width && !hdr_curr->height) {
173 mpp_err_f("unsupport source format %d\n", val);
174 return MPP_NOK;
175 }
176
177 /* picture coding type: 0 - INTRA, 1 - INTER */
178 READ_BITS(gb, 1, &val);
179 pict_type = val;
180
181 /* last 4 bit for PTYPE: UMV, AP mode, PB frame */
182 READ_BITS(gb, 4, &val);
183 if (val) {
184 mpp_err_f("unsupport PTYPE mode %x\n", val);
185 return MPP_NOK;
186 }
187
188 READ_BITS(gb, 5, &val);
189 hdr_curr->quant = val;
190
191 SKIP_BITS(gb, 1);
192
193 READ_BITS(gb, 1, &val);
194 while (val) {
195 SKIP_BITS(gb, 8);
196 READ_BITS(gb, 1, &val);
197 }
198
199 if (!p->found_i_vop)
200 p->found_i_vop = (pict_type == H263_I_VOP);
201
202 if (!p->found_i_vop)
203 return MPP_NOK;
204
205 hdr_curr->hdr_bits = gb->used_bits;
206 hdr_curr->pict_type = pict_type;
207
208 return MPP_OK;
209 __BITREAD_ERR:
210 mpp_err_f("found error stream\n");
211 return MPP_ERR_STREAM;
212 }
213
mpp_h263_parser_init(H263dParser * ctx,MppBufSlots frame_slots)214 MPP_RET mpp_h263_parser_init(H263dParser *ctx, MppBufSlots frame_slots)
215 {
216 BitReadCtx_t *bit_ctx = mpp_calloc(BitReadCtx_t, 1);
217 H263dParserImpl *p = mpp_calloc(H263dParserImpl, 1);
218 h263d_dxva2_picture_context_t *syntax = mpp_calloc(h263d_dxva2_picture_context_t, 1);
219
220 if (NULL == p || NULL == bit_ctx || NULL == syntax) {
221 mpp_err_f("malloc context failed\n");
222 if (p)
223 mpp_free(p);
224 if (bit_ctx)
225 mpp_free(bit_ctx);
226 if (syntax)
227 mpp_free(syntax);
228 return MPP_NOK;
229 }
230
231 mpp_buf_slot_setup(frame_slots, 4);
232 p->frame_slots = frame_slots;
233 p->pos_frm_start = -1;
234 p->pos_frm_end = -1;
235 p->bit_ctx = bit_ctx;
236 p->hdr_curr.slot_idx = H263_INVALID_VOP;
237 p->hdr_ref0.slot_idx = H263_INVALID_VOP;
238 h263_syntax_init(syntax);
239 p->syntax = syntax;
240
241 mpp_env_get_u32("h263d_debug", &h263d_debug, 0);
242
243 *ctx = p;
244 return MPP_OK;
245 }
246
mpp_h263_parser_deinit(H263dParser ctx)247 MPP_RET mpp_h263_parser_deinit(H263dParser ctx)
248 {
249 H263dParserImpl *p = (H263dParserImpl *)ctx;
250 if (p) {
251 if (p->bit_ctx) {
252 mpp_free(p->bit_ctx);
253 p->bit_ctx = NULL;
254 }
255 if (p->syntax) {
256 mpp_free(p->syntax);
257 p->syntax = NULL;
258 }
259 mpp_free(p);
260 }
261 return MPP_OK;
262 }
263
mpp_h263_parser_flush(H263dParser ctx)264 MPP_RET mpp_h263_parser_flush(H263dParser ctx)
265 {
266 H263dParserImpl *p = (H263dParserImpl *)ctx;
267 MppBufSlots slots = p->frame_slots;
268 H263Hdr *hdr_curr = &p->hdr_ref0;
269 RK_S32 index = hdr_curr->slot_idx;
270
271 h263d_dbg_func("in\n");
272
273 if (!hdr_curr->enqueued && index >= 0) {
274 mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE);
275 mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY);
276 hdr_curr->enqueued = 1;
277 }
278
279 h263d_dbg_func("out\n");
280
281 return MPP_OK;
282 }
283
mpp_h263_parser_reset(H263dParser ctx)284 MPP_RET mpp_h263_parser_reset(H263dParser ctx)
285 {
286 H263dParserImpl *p = (H263dParserImpl *)ctx;
287 MppBufSlots slots = p->frame_slots;
288 H263Hdr *hdr_curr = &p->hdr_ref0;
289 H263Hdr *hdr_ref0 = &p->hdr_ref0;
290 RK_S32 index = hdr_curr->slot_idx;
291
292 h263d_dbg_func("in\n");
293
294 if (index >= 0) {
295 mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE);
296 hdr_curr->slot_idx = -1;
297 }
298
299 index = hdr_ref0->slot_idx;
300 if (index >= 0) {
301 mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE);
302 hdr_ref0->slot_idx = -1;
303 }
304
305 p->found_i_vop = 0;
306
307 h263d_dbg_func("out\n");
308
309 return MPP_OK;
310 }
311
mpp_h263_parser_split(H263dParser ctx,MppPacket dst,MppPacket src)312 MPP_RET mpp_h263_parser_split(H263dParser ctx, MppPacket dst, MppPacket src)
313 {
314 MPP_RET ret = MPP_NOK;
315 H263dParserImpl *p = (H263dParserImpl *)ctx;
316 RK_U8 *dst_buf = mpp_packet_get_data(dst);
317 size_t dst_len = mpp_packet_get_length(dst);
318 RK_U8 *src_buf = mpp_packet_get_pos(src);
319 RK_S32 src_len = (RK_S32)mpp_packet_get_length(src);
320 RK_S32 pos_frm_start = p->pos_frm_start;
321 RK_S32 pos_frm_end = p->pos_frm_end;
322 RK_U32 src_eos = mpp_packet_get_eos(src);
323 RK_S32 src_pos = 0;
324 RK_U32 state = (RK_U32) - 1;
325
326 h263d_dbg_func("in\n");
327
328 mpp_assert(src_len);
329
330 if (dst_len) {
331 mpp_assert(dst_len >= 4);
332 state = ((RK_U32)(dst_buf[dst_len - 1]) << 0) |
333 ((RK_U32)(dst_buf[dst_len - 2]) << 8) |
334 ((RK_U32)(dst_buf[dst_len - 3]) << 16) |
335 ((RK_U32)(dst_buf[dst_len - 4]) << 24);
336 }
337
338 if (pos_frm_start < 0) {
339 // scan for frame start
340 for (src_pos = 0; src_pos < src_len; src_pos++) {
341 state = (state << 8) | src_buf[src_pos];
342 if ((state & H263_STARTCODE_MASK) == H263_STARTCODE &&
343 (state & H263_GOB_ZERO_MASK) == H263_GOB_ZERO) {
344 pos_frm_start = src_pos - 2;
345 src_pos++;
346 break;
347 }
348 }
349 }
350
351 if (pos_frm_start >= 0) {
352 // scan for frame end
353 for (; src_pos < src_len; src_pos++) {
354 state = (state << 8) | src_buf[src_pos];
355
356 if ((state & H263_STARTCODE_MASK) == H263_STARTCODE &&
357 (state & H263_GOB_ZERO_MASK) == H263_GOB_ZERO) {
358 pos_frm_end = src_pos - 2;
359 break;
360 }
361 }
362 if (src_eos && src_pos == src_len) {
363 pos_frm_end = src_len;
364 mpp_packet_set_eos(dst);
365 }
366 }
367
368 //mpp_log("pkt pos: start %d end %d len: left %d in %d\n",
369 // pos_frm_start, pos_frm_end, dst_len, src_len);
370
371 if (pos_frm_start < 0 || pos_frm_end < 0) {
372 // do not found frame start or do not found frame end, just copy the hold buffer to dst
373 memcpy(dst_buf + dst_len, src_buf, src_len);
374 // update dst buffer length
375 mpp_packet_set_length(dst, dst_len + src_len);
376 // set src buffer pos to end to src buffer
377 mpp_packet_set_pos(src, src_buf + src_len);
378 } else {
379 // found both frame start and frame end - only copy frame
380 memcpy(dst_buf + dst_len, src_buf, pos_frm_end);
381 mpp_packet_set_length(dst, dst_len + pos_frm_end);
382
383 // set src buffer pos to end to src buffer
384 mpp_packet_set_pos(src, src_buf + pos_frm_end);
385 mpp_assert((RK_S32)mpp_packet_get_length(src) == (src_len - pos_frm_end));
386 mpp_packet_set_length(src, src_len - pos_frm_end);
387
388 // return ok indicate the frame is ready and reset frame start/end position
389 ret = MPP_OK;
390 pos_frm_start = -1;
391 pos_frm_end = -1;
392 }
393
394 p->pos_frm_start = pos_frm_start;
395 p->pos_frm_end = pos_frm_end;
396
397 h263d_dbg_func("out\n");
398
399 return ret;
400 }
401
mpp_h263_parser_decode(H263dParser ctx,MppPacket pkt)402 MPP_RET mpp_h263_parser_decode(H263dParser ctx, MppPacket pkt)
403 {
404 MPP_RET ret = MPP_NOK;
405 H263dParserImpl *p = (H263dParserImpl *)ctx;
406 BitReadCtx_t *gb = p->bit_ctx;
407 RK_U8 *buf = mpp_packet_get_data(pkt);
408 RK_S32 len = (RK_S32)mpp_packet_get_length(pkt);
409 RK_U32 startcode = 0xff;
410 RK_S32 i = 0;
411
412 h263d_dbg_func("in\n");
413
414 while (i < len) {
415 startcode = (startcode << 8) | buf[i++];
416
417 if (startcode >> (32 - 22) == 0x20) {
418 i -= 4;
419 h263d_dbg_bit("found startcode at byte %d\n", i);
420 break;
421 }
422 }
423
424 if (i == len) {
425 mpp_err_f("can not found start code in len %d packet\n", len);
426 goto __BITREAD_ERR;
427 }
428
429 // setup bit read context
430 mpp_set_bitread_ctx(gb, buf + i, len - i);
431
432 ret = h263_parse_picture_header(p, gb);
433 if (ret)
434 goto __BITREAD_ERR;
435
436 p->width = p->hdr_curr.width;
437 p->height = p->hdr_curr.height;
438 p->pts = mpp_packet_get_pts(pkt);
439 p->dts = mpp_packet_get_dts(pkt);
440 __BITREAD_ERR:
441 h263d_dbg_status("found i_frame %d frame_type %d ret %d\n",
442 p->found_i_vop, p->hdr_curr.pict_type, ret);
443
444 mpp_packet_set_pos(pkt, buf);
445 mpp_packet_set_length(pkt, 0);
446 p->eos = mpp_packet_get_eos(pkt);
447
448 h263d_dbg_func("out\n");
449
450 return ret;
451 }
452
mpp_h263_parser_setup_syntax(H263dParser ctx,MppSyntax * syntax)453 MPP_RET mpp_h263_parser_setup_syntax(H263dParser ctx, MppSyntax *syntax)
454 {
455 H263dParserImpl *p = (H263dParserImpl *)ctx;
456 h263d_dxva2_picture_context_t *syn = p->syntax;
457
458 h263d_dbg_func("in\n");
459
460 h263d_fill_picture_parameters(p, &syn->pp);
461
462 // fill bit stream parameter
463 syn->data[1]->DataSize = p->bit_ctx->buf_len;
464 syn->data[1]->DataOffset = p->hdr_curr.hdr_bits;
465 syn->data[1]->pvPVPState = p->bit_ctx->buf;
466
467 syntax->number = 2;
468 syntax->data = syn->data;
469
470 h263d_dbg_func("out\n");
471
472 return MPP_OK;
473 }
474
mpp_h263_parser_setup_hal_output(H263dParser ctx,RK_S32 * output)475 MPP_RET mpp_h263_parser_setup_hal_output(H263dParser ctx, RK_S32 *output)
476 {
477 H263dParserImpl *p = (H263dParserImpl *)ctx;
478 RK_S32 index = -1;
479
480 h263d_dbg_func("in\n");
481
482 if (p->found_i_vop) {
483 H263Hdr *hdr_curr = &p->hdr_curr;
484 MppBufSlots slots = p->frame_slots;
485 MppFrame frame = NULL;
486
487 mpp_frame_init(&frame);
488 mpp_frame_set_width(frame, p->width);
489 mpp_frame_set_height(frame, p->height);
490 mpp_frame_set_hor_stride(frame, MPP_ALIGN(p->width, 16));
491 mpp_frame_set_ver_stride(frame, MPP_ALIGN(p->height, 16));
492
493 /*
494 * set slots information
495 * 1. output index MUST be set
496 * 2. get unused index for output if needed
497 * 3. set output index as hal_input
498 * 4. set frame information to output index
499 * 5. if one frame can be display, it SHOULD be enqueued to display queue
500 */
501 mpp_buf_slot_get_unused(slots, &index);
502 mpp_buf_slot_set_flag(slots, index, SLOT_HAL_OUTPUT);
503 mpp_frame_set_pts(frame, p->pts);
504 mpp_frame_set_dts(frame, p->dts);
505 mpp_frame_set_mode(frame, MPP_FRAME_FLAG_FRAME);
506
507 mpp_buf_slot_set_prop(slots, index, SLOT_FRAME, frame);
508 mpp_frame_deinit(&frame);
509 mpp_assert(NULL == frame);
510
511 hdr_curr->slot_idx = index;
512 }
513
514 p->output = index;
515 *output = index;
516
517 h263d_dbg_func("out\n");
518
519 return MPP_OK;
520 }
521
mpp_h263_parser_setup_refer(H263dParser ctx,RK_S32 * refer,RK_S32 max_ref)522 MPP_RET mpp_h263_parser_setup_refer(H263dParser ctx, RK_S32 *refer, RK_S32 max_ref)
523 {
524 H263dParserImpl *p = (H263dParserImpl *)ctx;
525 H263Hdr *hdr_curr = &p->hdr_curr;
526 MppBufSlots slots = p->frame_slots;
527 RK_S32 index;
528
529 h263d_dbg_func("in\n");
530
531 memset(refer, -1, sizeof(max_ref * sizeof(*refer)));
532 if (hdr_curr->pict_type == H263_P_VOP) {
533 index = p->hdr_ref0.slot_idx;
534 if (index >= 0) {
535 mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT);
536 refer[0] = index;
537 }
538 }
539
540 h263d_dbg_func("out\n");
541
542 return MPP_OK;
543 }
544
mpp_h263_parser_update_dpb(H263dParser ctx)545 MPP_RET mpp_h263_parser_update_dpb(H263dParser ctx)
546 {
547 H263dParserImpl *p = (H263dParserImpl *)ctx;
548 MppBufSlots slots = p->frame_slots;
549 H263Hdr *hdr_curr = &p->hdr_curr;
550 H263Hdr *hdr_ref0 = &p->hdr_ref0;
551 RK_S32 index = hdr_curr->slot_idx;
552
553 h263d_dbg_func("in\n");
554
555 mpp_assert(index >= 0);
556 mpp_buf_slot_set_flag(slots, index, SLOT_CODEC_USE);
557 mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE);
558 mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY);
559 hdr_curr->enqueued = 1;
560
561 index = hdr_ref0->slot_idx;
562 if (index >= 0) {
563 mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE);
564 hdr_ref0->slot_idx = -1;
565 }
566
567 // swap current to ref0
568 *hdr_ref0 = *hdr_curr;
569 hdr_curr->slot_idx = H263_INVALID_VOP;
570 hdr_curr->pts = 0;
571 hdr_curr->enqueued = 0;
572
573 h263d_dbg_func("out\n");
574
575 return MPP_OK;
576 }
577
578
579
580