xref: /OK3568_Linux_fs/external/mpp/mpp/codec/dec/h263/h263d_parser.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 
94     // syntax for hal
95     h263d_dxva2_picture_context_t *syntax;
96 } H263dParserImpl;
97 
98 static RK_U32 h263d_fmt_to_dimension[8][2] = {
99     {    0,    0 },       /* invalid */
100     {  128,   96 },       /* SQCIF   */
101     {  176,  144 },       /* QCIF    */
102     {  352,  288 },       /* CIF     */
103     {  704,  576 },       /* 4CIF    */
104     { 1408, 1152 },       /* 16CIF   */
105     {    0,    0 },       /* custorm */
106     {    0,    0 },       /* extend  */
107 };
108 
h263d_fill_picture_parameters(const H263dParserImpl * p,DXVA_PicParams_H263 * pp)109 static void h263d_fill_picture_parameters(const H263dParserImpl *p,
110                                           DXVA_PicParams_H263 *pp)
111 {
112     const H263Hdr *hdr_curr = &p->hdr_curr;
113     const H263Hdr *hdr_ref0 = &p->hdr_ref0;
114 
115     pp->short_video_header = 1;
116     pp->vop_coding_type = hdr_curr->pict_type;
117     pp->vop_quant = hdr_curr->quant;
118     pp->wDecodedPictureIndex = hdr_curr->slot_idx;
119     pp->wForwardRefPictureIndex = hdr_ref0->slot_idx;
120     pp->vop_time_increment_resolution = 30000;
121     pp->vop_width = hdr_curr->width;
122     pp->vop_height = hdr_curr->height;
123 
124     // Rockchip special data
125     pp->prev_coding_type = hdr_ref0->pict_type;
126     pp->header_bits = hdr_curr->hdr_bits;
127 }
128 
h263_syntax_init(h263d_dxva2_picture_context_t * syntax)129 static void h263_syntax_init(h263d_dxva2_picture_context_t *syntax)
130 {
131     DXVA2_DecodeBufferDesc *data = &syntax->desc[0];
132 
133     //!< commit picture paramters
134     memset(data, 0, sizeof(*data));
135     data->CompressedBufferType = DXVA2_PictureParametersBufferType;
136     data->pvPVPState = (void *)&syntax->pp;
137     data->DataSize = sizeof(syntax->pp);
138     syntax->data[0] = data;
139 
140     //!< commit bitstream
141     data = &syntax->desc[1];
142     memset(data, 0, sizeof(*data));
143     data->CompressedBufferType = DXVA2_BitStreamDateBufferType;
144     syntax->data[1] = data;
145 }
146 
h263_parse_picture_header(H263dParserImpl * p,BitReadCtx_t * gb)147 static MPP_RET h263_parse_picture_header(H263dParserImpl *p, BitReadCtx_t *gb)
148 {
149     RK_U32 val = 0;
150     H263Hdr *hdr_curr = &p->hdr_curr;
151     H263VOPType pict_type = H263_INVALID_VOP;
152 
153     /* start code */
154     READ_BITS(gb, 17, &val); /* start code */
155     mpp_assert(val == 1);
156 
157     /* gob */
158     READ_BITS(gb, 5, &val); /* gob */
159     mpp_assert(val == 0);
160 
161     /* time reference */
162     READ_BITS(gb, 8, &hdr_curr->TR);
163 
164     /* first 5 bit of PTYPE */
165     SKIP_BITS(gb, 5);
166 
167     /* source format */
168     READ_BITS(gb, 3, &val); /* source format */
169     hdr_curr->width  = h263d_fmt_to_dimension[val][0];
170     hdr_curr->height = h263d_fmt_to_dimension[val][1];
171     if (!hdr_curr->width && !hdr_curr->height) {
172         mpp_err_f("unsupport source format %d\n", val);
173         return MPP_NOK;
174     }
175 
176     /* picture coding type: 0 - INTRA, 1 - INTER */
177     READ_BITS(gb, 1, &val);
178     pict_type = val;
179 
180     /* last 4 bit for PTYPE: UMV, AP mode, PB frame */
181     READ_BITS(gb, 4, &val);
182     if (val) {
183         mpp_err_f("unsupport PTYPE mode %x\n", val);
184         return MPP_NOK;
185     }
186 
187     READ_BITS(gb, 5, &val);
188     hdr_curr->quant = val;
189 
190     SKIP_BITS(gb, 1);
191 
192     READ_BITS(gb, 1, &val);
193     while (val) {
194         SKIP_BITS(gb, 8);
195         READ_BITS(gb, 1, &val);
196     }
197 
198     if (!p->found_i_vop)
199         p->found_i_vop = (pict_type == H263_I_VOP);
200 
201     if (!p->found_i_vop)
202         return MPP_NOK;
203 
204     hdr_curr->hdr_bits = gb->used_bits;
205     hdr_curr->pict_type = pict_type;
206 
207     return MPP_OK;
208 __BITREAD_ERR:
209     mpp_err_f("found error stream\n");
210     return MPP_ERR_STREAM;
211 }
212 
mpp_h263_parser_init(H263dParser * ctx,MppBufSlots frame_slots)213 MPP_RET mpp_h263_parser_init(H263dParser *ctx, MppBufSlots frame_slots)
214 {
215     BitReadCtx_t *bit_ctx = mpp_calloc(BitReadCtx_t, 1);
216     H263dParserImpl *p = mpp_calloc(H263dParserImpl, 1);
217     h263d_dxva2_picture_context_t *syntax = mpp_calloc(h263d_dxva2_picture_context_t, 1);
218 
219     if (NULL == p || NULL == bit_ctx || NULL == syntax) {
220         mpp_err_f("malloc context failed\n");
221         if (p)
222             mpp_free(p);
223         if (bit_ctx)
224             mpp_free(bit_ctx);
225         if (syntax)
226             mpp_free(syntax);
227         return MPP_NOK;
228     }
229 
230     mpp_buf_slot_setup(frame_slots, 4);
231     p->frame_slots      = frame_slots;
232     p->pos_frm_start    = -1;
233     p->pos_frm_end      = -1;
234     p->bit_ctx          = bit_ctx;
235     p->hdr_curr.slot_idx = H263_INVALID_VOP;
236     p->hdr_ref0.slot_idx = H263_INVALID_VOP;
237     h263_syntax_init(syntax);
238     p->syntax = syntax;
239 
240     mpp_env_get_u32("h263d_debug", &h263d_debug, 0);
241 
242     *ctx = p;
243     return MPP_OK;
244 }
245 
mpp_h263_parser_deinit(H263dParser ctx)246 MPP_RET mpp_h263_parser_deinit(H263dParser ctx)
247 {
248     H263dParserImpl *p = (H263dParserImpl *)ctx;
249     if (p) {
250         if (p->bit_ctx) {
251             mpp_free(p->bit_ctx);
252             p->bit_ctx = NULL;
253         }
254         if (p->syntax) {
255             mpp_free(p->syntax);
256             p->syntax = NULL;
257         }
258         mpp_free(p);
259     }
260     return MPP_OK;
261 }
262 
mpp_h263_parser_flush(H263dParser ctx)263 MPP_RET mpp_h263_parser_flush(H263dParser ctx)
264 {
265     H263dParserImpl *p = (H263dParserImpl *)ctx;
266     MppBufSlots slots = p->frame_slots;
267     H263Hdr *hdr_curr = &p->hdr_ref0;
268     RK_S32 index = hdr_curr->slot_idx;
269 
270     h263d_dbg_func("in\n");
271 
272     if (!hdr_curr->enqueued && index >= 0) {
273         mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE);
274         mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY);
275         hdr_curr->enqueued = 1;
276     }
277 
278     h263d_dbg_func("out\n");
279 
280     return MPP_OK;
281 }
282 
mpp_h263_parser_reset(H263dParser ctx)283 MPP_RET mpp_h263_parser_reset(H263dParser ctx)
284 {
285     H263dParserImpl *p = (H263dParserImpl *)ctx;
286     MppBufSlots slots = p->frame_slots;
287     H263Hdr *hdr_curr = &p->hdr_ref0;
288     H263Hdr *hdr_ref0 = &p->hdr_ref0;
289     RK_S32 index = hdr_curr->slot_idx;
290 
291     h263d_dbg_func("in\n");
292 
293     if (index >= 0) {
294         mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE);
295         hdr_curr->slot_idx = -1;
296     }
297 
298     index = hdr_ref0->slot_idx;
299     if (index >= 0) {
300         mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE);
301         hdr_ref0->slot_idx = -1;
302     }
303 
304     p->found_i_vop = 0;
305 
306     h263d_dbg_func("out\n");
307 
308     return MPP_OK;
309 }
310 
mpp_h263_parser_split(H263dParser ctx,MppPacket dst,MppPacket src)311 MPP_RET mpp_h263_parser_split(H263dParser ctx, MppPacket dst, MppPacket src)
312 {
313     MPP_RET ret = MPP_NOK;
314     H263dParserImpl *p = (H263dParserImpl *)ctx;
315     RK_U8 *dst_buf = mpp_packet_get_data(dst);
316     size_t dst_len = mpp_packet_get_length(dst);
317     RK_U8 *src_buf = mpp_packet_get_pos(src);
318     RK_S32 src_len = (RK_S32)mpp_packet_get_length(src);
319     RK_S32 pos_frm_start = p->pos_frm_start;
320     RK_S32 pos_frm_end   = p->pos_frm_end;
321     RK_U32 src_eos = mpp_packet_get_eos(src);
322     RK_S32 src_pos = 0;
323     RK_U32 state = (RK_U32) - 1;
324 
325     h263d_dbg_func("in\n");
326 
327     mpp_assert(src_len);
328 
329     if (dst_len) {
330         mpp_assert(dst_len >= 4);
331         state = ((RK_U32)(dst_buf[dst_len - 1]) <<  0) |
332                 ((RK_U32)(dst_buf[dst_len - 2]) <<  8) |
333                 ((RK_U32)(dst_buf[dst_len - 3]) << 16) |
334                 ((RK_U32)(dst_buf[dst_len - 4]) << 24);
335     }
336 
337     if (pos_frm_start < 0) {
338         // scan for frame start
339         for (src_pos = 0; src_pos < src_len; src_pos++) {
340             state = (state << 8) | src_buf[src_pos];
341             if ((state & H263_STARTCODE_MASK) == H263_STARTCODE &&
342                 (state & H263_GOB_ZERO_MASK)  == H263_GOB_ZERO) {
343                 pos_frm_start = src_pos - 2;
344                 src_pos++;
345                 break;
346             }
347         }
348     }
349 
350     if (pos_frm_start >= 0) {
351         // scan for frame end
352         for (; src_pos < src_len; src_pos++) {
353             state = (state << 8) | src_buf[src_pos];
354 
355             if ((state & H263_STARTCODE_MASK) == H263_STARTCODE &&
356                 (state & H263_GOB_ZERO_MASK)  == H263_GOB_ZERO) {
357                 pos_frm_end = src_pos - 2;
358                 break;
359             }
360         }
361         if (src_eos && src_pos == src_len) {
362             pos_frm_end = src_len;
363             mpp_packet_set_eos(dst);
364         }
365     }
366 
367     //mpp_log("pkt pos: start %d end %d len: left %d in %d\n",
368     //        pos_frm_start, pos_frm_end, dst_len, src_len);
369 
370     if (pos_frm_start < 0 || pos_frm_end < 0) {
371         // do not found frame start or do not found frame end, just copy the hold buffer to dst
372         memcpy(dst_buf + dst_len, src_buf, src_len);
373         // update dst buffer length
374         mpp_packet_set_length(dst, dst_len + src_len);
375         // set src buffer pos to end to src buffer
376         mpp_packet_set_pos(src, src_buf + src_len);
377     } else {
378         // found both frame start and frame end - only copy frame
379         memcpy(dst_buf + dst_len, src_buf, pos_frm_end);
380         mpp_packet_set_length(dst, dst_len + pos_frm_end);
381 
382         // set src buffer pos to end to src buffer
383         mpp_packet_set_pos(src, src_buf + pos_frm_end);
384         mpp_assert((RK_S32)mpp_packet_get_length(src) == (src_len - pos_frm_end));
385         mpp_packet_set_length(src, src_len - pos_frm_end);
386 
387         // return ok indicate the frame is ready and reset frame start/end position
388         ret = MPP_OK;
389         pos_frm_start = -1;
390         pos_frm_end = -1;
391     }
392 
393     p->pos_frm_start = pos_frm_start;
394     p->pos_frm_end   = pos_frm_end;
395 
396     h263d_dbg_func("out\n");
397 
398     return ret;
399 }
400 
mpp_h263_parser_decode(H263dParser ctx,MppPacket pkt)401 MPP_RET mpp_h263_parser_decode(H263dParser ctx, MppPacket pkt)
402 {
403     MPP_RET ret = MPP_NOK;
404     H263dParserImpl *p = (H263dParserImpl *)ctx;
405     BitReadCtx_t *gb = p->bit_ctx;
406     RK_U8 *buf = mpp_packet_get_data(pkt);
407     RK_S32 len = (RK_S32)mpp_packet_get_length(pkt);
408     RK_U32 startcode = 0xff;
409     RK_S32 i = 0;
410 
411     h263d_dbg_func("in\n");
412 
413     while (i < len) {
414         startcode = (startcode << 8) | buf[i++];
415 
416         if (startcode >> (32 - 22) == 0x20) {
417             i -= 4;
418             h263d_dbg_bit("found startcode at byte %d\n", i);
419             break;
420         }
421     }
422 
423     if (i == len) {
424         mpp_err_f("can not found start code in len %d packet\n", len);
425         goto __BITREAD_ERR;
426     }
427 
428     // setup bit read context
429     mpp_set_bitread_ctx(gb, buf + i, len - i);
430 
431     ret = h263_parse_picture_header(p, gb);
432     if (ret)
433         goto __BITREAD_ERR;
434 
435     p->width  = p->hdr_curr.width;
436     p->height = p->hdr_curr.height;
437     p->pts  = mpp_packet_get_pts(pkt);
438 __BITREAD_ERR:
439     h263d_dbg_status("found i_frame %d frame_type %d ret %d\n",
440                      p->found_i_vop, p->hdr_curr.pict_type, ret);
441 
442     mpp_packet_set_pos(pkt, buf);
443     mpp_packet_set_length(pkt, 0);
444     p->eos = mpp_packet_get_eos(pkt);
445 
446     h263d_dbg_func("out\n");
447 
448     return ret;
449 }
450 
mpp_h263_parser_setup_syntax(H263dParser ctx,MppSyntax * syntax)451 MPP_RET mpp_h263_parser_setup_syntax(H263dParser ctx, MppSyntax *syntax)
452 {
453     H263dParserImpl *p = (H263dParserImpl *)ctx;
454     h263d_dxva2_picture_context_t *syn = p->syntax;
455 
456     h263d_dbg_func("in\n");
457 
458     h263d_fill_picture_parameters(p, &syn->pp);
459 
460     // fill bit stream parameter
461     syn->data[1]->DataSize   = p->bit_ctx->buf_len;
462     syn->data[1]->DataOffset = p->hdr_curr.hdr_bits;
463     syn->data[1]->pvPVPState = p->bit_ctx->buf;
464 
465     syntax->number = 2;
466     syntax->data = syn->data;
467 
468     h263d_dbg_func("out\n");
469 
470     return MPP_OK;
471 }
472 
mpp_h263_parser_setup_hal_output(H263dParser ctx,RK_S32 * output)473 MPP_RET mpp_h263_parser_setup_hal_output(H263dParser ctx, RK_S32 *output)
474 {
475     H263dParserImpl *p = (H263dParserImpl *)ctx;
476     RK_S32 index = -1;
477 
478     h263d_dbg_func("in\n");
479 
480     if (p->found_i_vop) {
481         H263Hdr *hdr_curr = &p->hdr_curr;
482         MppBufSlots slots = p->frame_slots;
483         MppFrame frame = NULL;
484 
485         mpp_frame_init(&frame);
486         mpp_frame_set_width(frame, p->width);
487         mpp_frame_set_height(frame, p->height);
488         mpp_frame_set_hor_stride(frame, MPP_ALIGN(p->width, 16));
489         mpp_frame_set_ver_stride(frame, MPP_ALIGN(p->height, 16));
490 
491         /*
492          * set slots information
493          * 1. output index MUST be set
494          * 2. get unused index for output if needed
495          * 3. set output index as hal_input
496          * 4. set frame information to output index
497          * 5. if one frame can be display, it SHOULD be enqueued to display queue
498          */
499         mpp_buf_slot_get_unused(slots, &index);
500         mpp_buf_slot_set_flag(slots, index, SLOT_HAL_OUTPUT);
501         mpp_frame_set_pts(frame, p->pts);
502         mpp_frame_set_mode(frame, MPP_FRAME_FLAG_FRAME);
503 
504         mpp_buf_slot_set_prop(slots, index, SLOT_FRAME, frame);
505         mpp_frame_deinit(&frame);
506         mpp_assert(NULL == frame);
507 
508         hdr_curr->slot_idx = index;
509     }
510 
511     p->output = index;
512     *output = index;
513 
514     h263d_dbg_func("out\n");
515 
516     return MPP_OK;
517 }
518 
mpp_h263_parser_setup_refer(H263dParser ctx,RK_S32 * refer,RK_S32 max_ref)519 MPP_RET mpp_h263_parser_setup_refer(H263dParser ctx, RK_S32 *refer, RK_S32 max_ref)
520 {
521     H263dParserImpl *p = (H263dParserImpl *)ctx;
522     H263Hdr *hdr_curr = &p->hdr_curr;
523     MppBufSlots slots = p->frame_slots;
524     RK_S32 index;
525 
526     h263d_dbg_func("in\n");
527 
528     memset(refer, -1, sizeof(max_ref * sizeof(*refer)));
529     if (hdr_curr->pict_type == H263_P_VOP) {
530         index = p->hdr_ref0.slot_idx;
531         if (index >= 0) {
532             mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT);
533             refer[0] = index;
534         }
535     }
536 
537     h263d_dbg_func("out\n");
538 
539     return MPP_OK;
540 }
541 
mpp_h263_parser_update_dpb(H263dParser ctx)542 MPP_RET mpp_h263_parser_update_dpb(H263dParser ctx)
543 {
544     H263dParserImpl *p = (H263dParserImpl *)ctx;
545     MppBufSlots slots = p->frame_slots;
546     H263Hdr *hdr_curr = &p->hdr_curr;
547     H263Hdr *hdr_ref0 = &p->hdr_ref0;
548     RK_S32 index = hdr_curr->slot_idx;
549 
550     h263d_dbg_func("in\n");
551 
552     mpp_assert(index >= 0);
553     mpp_buf_slot_set_flag(slots, index, SLOT_CODEC_USE);
554     mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE);
555     mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY);
556     hdr_curr->enqueued = 1;
557 
558     index = hdr_ref0->slot_idx;
559     if (index >= 0) {
560         mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE);
561         hdr_ref0->slot_idx = -1;
562     }
563 
564     // swap current to ref0
565     *hdr_ref0 = *hdr_curr;
566     hdr_curr->slot_idx  = H263_INVALID_VOP;
567     hdr_curr->pts       = 0;
568     hdr_curr->enqueued  = 0;
569 
570     h263d_dbg_func("out\n");
571 
572     return MPP_OK;
573 }
574 
575 
576 
577