h264_parser: Set field_order and picture_structure.
authorYusuke Nakamura <muken.the.vfrmaniac@gmail.com>
Tue, 14 May 2013 22:37:36 +0000 (07:37 +0900)
committerAnton Khirnov <anton@khirnov.net>
Fri, 24 May 2013 06:45:05 +0000 (08:45 +0200)
Signed-off-by: Anton Khirnov <anton@khirnov.net>
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_parser.c

index 38e471d..c53ea13 100644 (file)
@@ -2642,11 +2642,10 @@ static void flush_dpb(AVCodecContext *avctx)
     h->parse_context.last_index        = 0;
 }
 
-static int init_poc(H264Context *h)
+int ff_init_poc(H264Context *h, int pic_field_poc[2], int *pic_poc)
 {
     const int max_frame_num = 1 << h->sps.log2_max_frame_num;
     int field_poc[2];
-    Picture *cur = h->cur_pic_ptr;
 
     h->frame_num_offset = h->prev_frame_num_offset;
     if (h->frame_num < h->prev_frame_num)
@@ -2711,10 +2710,11 @@ static int init_poc(H264Context *h)
     }
 
     if (h->picture_structure != PICT_BOTTOM_FIELD)
-        h->cur_pic_ptr->field_poc[0] = field_poc[0];
+        pic_field_poc[0] = field_poc[0];
     if (h->picture_structure != PICT_TOP_FIELD)
-        h->cur_pic_ptr->field_poc[1] = field_poc[1];
-    cur->poc = FFMIN(cur->field_poc[0], cur->field_poc[1]);
+        pic_field_poc[1] = field_poc[1];
+    if (pic_poc)
+        *pic_poc = FFMIN(pic_field_poc[0], pic_field_poc[1]);
 
     return 0;
 }
@@ -3516,7 +3516,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
             h->delta_poc[1] = get_se_golomb(&h->gb);
     }
 
-    init_poc(h);
+    ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc);
 
     if (h->pps.redundant_pic_cnt_present)
         h->redundant_pic_count = get_ue_golomb(&h->gb);
index 484c9d3..3ef8420 100644 (file)
@@ -949,5 +949,6 @@ static av_always_inline int get_dct8x8_allowed(H264Context *h)
 }
 
 void ff_h264_draw_horiz_band(H264Context *h, int y, int height);
+int ff_init_poc(H264Context *h, int pic_field_poc[2], int *pic_poc);
 
 #endif /* AVCODEC_H264_H */
index e5d2c03..1f79f1b 100644 (file)
@@ -116,10 +116,12 @@ static inline int parse_nal_units(AVCodecParserContext *s,
     unsigned int slice_type;
     int state = -1;
     const uint8_t *ptr;
+    int field_poc[2];
 
     /* set some sane default values */
     s->pict_type = AV_PICTURE_TYPE_I;
     s->key_frame = 0;
+    s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
 
     h->avctx= avctx;
     h->sei_recovery_frame_cnt = -1;
@@ -162,6 +164,11 @@ static inline int parse_nal_units(AVCodecParserContext *s,
             break;
         case NAL_IDR_SLICE:
             s->key_frame = 1;
+
+            h->prev_frame_num        = 0;
+            h->prev_frame_num_offset = 0;
+            h->prev_poc_msb          =
+            h->prev_poc_lsb          = 0;
             /* fall through */
         case NAL_SLICE:
             get_ue_golomb(&h->gb);  // skip first_mb_in_slice
@@ -201,6 +208,24 @@ static inline int parse_nal_units(AVCodecParserContext *s,
                 }
             }
 
+            if (h->nal_unit_type == NAL_IDR_SLICE)
+                get_ue_golomb(&h->gb); /* idr_pic_id */
+            if (h->sps.poc_type == 0) {
+                h->poc_lsb = get_bits(&h->gb, h->sps.log2_max_poc_lsb);
+
+                if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME)
+                    h->delta_poc_bottom = get_se_golomb(&h->gb);
+            }
+
+            if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) {
+                h->delta_poc[0] = get_se_golomb(&h->gb);
+
+                if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME)
+                    h->delta_poc[1] = get_se_golomb(&h->gb);
+            }
+
+            ff_init_poc(h, field_poc, NULL);
+
             if(h->sps.pic_struct_present_flag) {
                 switch (h->sei_pic_struct) {
                     case SEI_PIC_STRUCT_TOP_FIELD:
@@ -230,6 +255,38 @@ static inline int parse_nal_units(AVCodecParserContext *s,
                 s->repeat_pict = h->picture_structure == PICT_FRAME ? 1 : 0;
             }
 
+            if (h->picture_structure == PICT_FRAME) {
+                s->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
+                if (h->sps.pic_struct_present_flag) {
+                    switch (h->sei_pic_struct) {
+                        case SEI_PIC_STRUCT_TOP_BOTTOM:
+                        case SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
+                            s->field_order = AV_FIELD_TT;
+                            break;
+                        case SEI_PIC_STRUCT_BOTTOM_TOP:
+                        case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
+                            s->field_order = AV_FIELD_BB;
+                            break;
+                        default:
+                            s->field_order = AV_FIELD_PROGRESSIVE;
+                            break;
+                    }
+                } else {
+                    if (field_poc[0] < field_poc[1])
+                        s->field_order = AV_FIELD_TT;
+                    else if (field_poc[0] > field_poc[1])
+                        s->field_order = AV_FIELD_BB;
+                    else
+                        s->field_order = AV_FIELD_PROGRESSIVE;
+                }
+            } else {
+                if (h->picture_structure == PICT_TOP_FIELD)
+                    s->picture_structure = AV_PICTURE_STRUCTURE_TOP_FIELD;
+                else
+                    s->picture_structure = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;
+                s->field_order = AV_FIELD_UNKNOWN;
+            }
+
             return 0; /* no need to evaluate the rest */
         }
         buf += consumed;