]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/h264_sei.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / h264_sei.c
index 5f68a139a3061ad5d7f9e01a710c58fd91fe3cee..999fce7b349fc51a65d9a1ca3b0c649e6205fce5 100644 (file)
@@ -204,27 +204,72 @@ static int decode_buffering_period(H264Context *h){
     return 0;
 }
 
+static int decode_frame_packing(H264Context *h, int size){
+    int bits = get_bits_left(&h->gb);
+
+    h->sei_fpa.frame_packing_arrangement_id          = get_ue_golomb(&h->gb);
+    h->sei_fpa.frame_packing_arrangement_cancel_flag = get_bits(&h->gb, 1);
+    if (!h->sei_fpa.frame_packing_arrangement_cancel_flag) {
+        h->sei_fpa.frame_packing_arrangement_type  = get_bits(&h->gb, 7);
+        h->sei_fpa.quincunx_sampling_flag          = get_bits(&h->gb, 1);
+        h->sei_fpa.content_interpretation_type     = get_bits(&h->gb, 6);
+        skip_bits(&h->gb, 1); /* spatial_flipping_flag */
+        skip_bits(&h->gb, 1); /* frame0_flipped_flag */
+        skip_bits(&h->gb, 1); /* field_views_flag */
+        skip_bits(&h->gb, 1); /* current_frame_is_frame0_flag */
+        skip_bits(&h->gb, 1); /* frame0_self_contained_flag */
+        skip_bits(&h->gb, 1); /* frame1_self_contained_flag */
+        if (!h->sei_fpa.quincunx_sampling_flag && h->sei_fpa.frame_packing_arrangement_type != 5) {
+            skip_bits(&h->gb, 4); /* frame0_grid_position_x */
+            skip_bits(&h->gb, 4); /* frame0_grid_position_y */
+            skip_bits(&h->gb, 4); /* frame1_grid_position_x */
+            skip_bits(&h->gb, 4); /* frame1_grid_position_y */
+        }
+        skip_bits(&h->gb, 8); /* frame_packing_arrangement_reserved_byte */
+        h->sei_fpa.frame_packing_arrangement_repetition_period = get_ue_golomb(&h->gb) /* frame_packing_arrangement_repetition_period */;
+    }
+    skip_bits(&h->gb, 1); /* frame_packing_arrangement_extension_flag */
+
+    if (h->avctx->debug & FF_DEBUG_PICT_INFO)
+        av_log(h->avctx, AV_LOG_DEBUG, "SEI FPA %d %d %d %d %d %d\n",
+                                       h->sei_fpa.frame_packing_arrangement_id,
+                                       h->sei_fpa.frame_packing_arrangement_cancel_flag,
+                                       h->sei_fpa.frame_packing_arrangement_type,
+                                       h->sei_fpa.quincunx_sampling_flag,
+                                       h->sei_fpa.content_interpretation_type,
+                                       h->sei_fpa.frame_packing_arrangement_repetition_period);
+    skip_bits_long(&h->gb, 8*size - (bits - get_bits_left(&h->gb)));
+    return 0;
+}
+
 int ff_h264_decode_sei(H264Context *h){
     while (get_bits_left(&h->gb) > 16) {
-        int size, type;
+        int type;
+        unsigned size, next;
 
         type=0;
         do{
             if (get_bits_left(&h->gb) < 8)
-                return -1;
+                return AVERROR_INVALIDDATA;
             type+= show_bits(&h->gb, 8);
         }while(get_bits(&h->gb, 8) == 255);
 
         size=0;
         do{
             if (get_bits_left(&h->gb) < 8)
-                return -1;
+                return AVERROR_INVALIDDATA;
             size+= show_bits(&h->gb, 8);
         }while(get_bits(&h->gb, 8) == 255);
 
         if(h->avctx->debug&FF_DEBUG_STARTCODE)
             av_log(h->avctx, AV_LOG_DEBUG, "SEI %d len:%d\n", type, size);
 
+        if (size > get_bits_left(&h->gb) / 8) {
+            av_log(h->avctx, AV_LOG_ERROR, "SEI truncated\n");
+            return AVERROR_INVALIDDATA;
+        }
+        next = get_bits_count(&h->gb) + 8*size;
+
         switch(type){
         case SEI_TYPE_PIC_TIMING: // Picture timing SEI
             if(decode_picture_timing(h) < 0)
@@ -246,9 +291,11 @@ int ff_h264_decode_sei(H264Context *h){
             if(decode_buffering_period(h) < 0)
                 return -1;
             break;
-        default:
-            skip_bits(&h->gb, 8*size);
+        case SEI_TYPE_FRAME_PACKING:
+            if(decode_frame_packing(h, size) < 0)
+                return -1;
         }
+        skip_bits_long(&h->gb, next - get_bits_count(&h->gb));
 
         //FIXME check bits here
         align_get_bits(&h->gb);
@@ -256,3 +303,48 @@ int ff_h264_decode_sei(H264Context *h){
 
     return 0;
 }
+
+const char* ff_h264_sei_stereo_mode(H264Context *h)
+{
+    if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 0) {
+        switch (h->sei_fpa.frame_packing_arrangement_type) {
+            case SEI_FPA_TYPE_CHECKERBOARD:
+                if (h->sei_fpa.content_interpretation_type == 2)
+                    return "checkerboard_rl";
+                else
+                    return "checkerboard_lr";
+            case SEI_FPA_TYPE_INTERLEAVE_COLUMN:
+                if (h->sei_fpa.content_interpretation_type == 2)
+                    return "col_interleaved_rl";
+                else
+                    return "col_interleaved_lr";
+            case SEI_FPA_TYPE_INTERLEAVE_ROW:
+                if (h->sei_fpa.content_interpretation_type == 2)
+                    return "row_interleaved_rl";
+                else
+                    return "row_interleaved_lr";
+            case SEI_FPA_TYPE_SIDE_BY_SIDE:
+                if (h->sei_fpa.content_interpretation_type == 2)
+                    return "right_left";
+                else
+                    return "left_right";
+            case SEI_FPA_TYPE_TOP_BOTTOM:
+                if (h->sei_fpa.content_interpretation_type == 2)
+                    return "bottom_top";
+                else
+                    return "top_bottom";
+            case SEI_FPA_TYPE_INTERLEAVE_TEMPORAL:
+                if (h->sei_fpa.content_interpretation_type == 2)
+                    return "block_rl";
+                else
+                    return "block_lr";
+            case SEI_FPA_TYPE_2D:
+            default:
+                return "mono";
+        }
+    } else if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 1) {
+        return "mono";
+    } else {
+        return NULL;
+    }
+}