xref: /rockchip-linux_mpp/mpp/codec/dec/h263/h263d_parser.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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