[libav-devel] [PATCH 2/6] h264: parse frame packing arrangement SEI messages and save relevant stereo3d information

Vittorio Giovara vittorio.giovara at gmail.com
Tue Nov 26 11:01:49 CET 2013


---
 libavcodec/h264.c     |   41 +++++++++++++++++++++++++++++++++++++++++
 libavcodec/h264.h     |   11 ++++++++++-
 libavcodec/h264_sei.c |   40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 86d453b..74ad9ed 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -27,6 +27,7 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/stereo3d.h"
 #include "internal.h"
 #include "cabac.h"
 #include "cabac_functions.h"
@@ -2029,6 +2030,46 @@ static void decode_postinit(H264Context *h, int setup_finished)
         }
     }
 
+    if (h->sei_frame_packing_present &&
+        h->frame_packing_arrangement_type >= 0 &&
+        h->frame_packing_arrangement_type <= 6 &&
+        h->content_interpretation_type > 0 &&
+        h->content_interpretation_type < 3) {
+        AVStereo3D *stereo = av_stereo3d_create_side_data(&cur->f);
+        if (!stereo)
+            return;
+
+        switch (h->frame_packing_arrangement_type) {
+        case 0:
+            stereo->type = AV_STEREO3D_CHECKERS;
+            break;
+        case 1:
+            stereo->type = AV_STEREO3D_LINES;
+            break;
+        case 2:
+            stereo->type = AV_STEREO3D_COLUMNS;
+            break;
+        case 3:
+            if (h->quincunx_subsampling)
+                stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX;
+            else
+                stereo->type = AV_STEREO3D_SIDEBYSIDE;
+            break;
+        case 4:
+            stereo->type = AV_STEREO3D_TOPBOTTOM;
+            break;
+        case 5:
+            stereo->type = AV_STEREO3D_FRAMESEQUENCE;
+            break;
+        case 6:
+            stereo->type = AV_STEREO3D_2D;
+            break;
+        }
+
+        if (h->content_interpretation_type == 2)
+            stereo->flags = AV_STEREO3D_FLAG_INVERT;
+    }
+
     // FIXME do something with unavailable reference frames
 
     /* Sort B-frames into display order */
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 920e3fc..a828bf9 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -123,7 +123,8 @@ typedef enum {
     SEI_BUFFERING_PERIOD            = 0,   ///< buffering period (H.264, D.1.1)
     SEI_TYPE_PIC_TIMING             = 1,   ///< picture timing
     SEI_TYPE_USER_DATA_UNREGISTERED = 5,   ///< unregistered user data
-    SEI_TYPE_RECOVERY_POINT         = 6    ///< recovery point (frame # to decoder sync)
+    SEI_TYPE_RECOVERY_POINT         = 6,   ///< recovery point (frame # to decoder sync)
+    SEI_TYPE_FRAME_PACKING          = 45,  ///< frame packing arrangement
 } SEI_Type;
 
 /**
@@ -586,6 +587,14 @@ typedef struct H264Context {
     int prev_interlaced_frame;
 
     /**
+     * frame_packing_arrangment SEI message
+     */
+    int sei_frame_packing_present;
+    int frame_packing_arrangement_type;
+    int content_interpretation_type;
+    int quincunx_subsampling;
+
+    /**
      * Bit set of clock types for fields/frames in picture timing SEI message.
      * For each found ct_type, appropriate bit is set (e.g., bit 1 for
      * interlaced).
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 27a2c76..746c213 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -42,6 +42,7 @@ void ff_h264_reset_sei(H264Context *h)
     h->sei_dpb_output_delay         =  0;
     h->sei_cpb_removal_delay        = -1;
     h->sei_buffering_period_present =  0;
+    h->sei_frame_packing_present    =  0;
 }
 
 static int decode_picture_timing(H264Context *h)
@@ -175,6 +176,40 @@ static int decode_buffering_period(H264Context *h)
     return 0;
 }
 
+static int decode_frame_packing_arrangement(H264Context *h)
+{
+    int cancel;
+    int quincunx =  0;
+    int content  = -1;
+    int type     = -1;
+
+    get_ue_golomb(&h->gb);              // frame_packing_arrangement_id
+    cancel = get_bits1(&h->gb);         // frame_packing_arrangement_cancel_flag
+    if (cancel == 0) {
+        type = get_bits(&h->gb, 7);     // frame_packing_arrangement_type
+        quincunx = get_bits1(&h->gb);   // quincunx_sampling_flag
+        content = get_bits(&h->gb, 6);  // content_interpretation_type
+
+        // the following skips: spatial_flipping_flag, frame0_flipped_flag,
+        // field_views_flag, current_frame_is_frame0_flag,
+        // frame0_self_contained_flag, frame1_self_contained_flag
+        skip_bits(&h->gb, 6);
+
+        if (quincunx == 0 && type != 5)
+            skip_bits(&h->gb, 16);      // frame[01]_grid_position_[xy]
+        skip_bits(&h->gb, 8);           // frame_packing_arrangement_reserved_byte
+        get_ue_golomb(&h->gb);          // frame_packing_arrangement_repetition_period
+    }
+    skip_bits1(&h->gb);                 // frame_packing_arrangement_extension_flag
+
+    h->sei_frame_packing_present      = (cancel == 0);
+    h->frame_packing_arrangement_type = type;
+    h->content_interpretation_type    = content;
+    h->quincunx_subsampling           = quincunx;
+
+    return 0;
+}
+
 int ff_h264_decode_sei(H264Context *h)
 {
     while (get_bits_left(&h->gb) > 16) {
@@ -217,6 +252,11 @@ int ff_h264_decode_sei(H264Context *h)
             if (ret < 0)
                 return ret;
             break;
+        case SEI_TYPE_FRAME_PACKING:
+            ret = decode_frame_packing_arrangement(h);
+            if (ret < 0)
+                return ret;
+            break;
         default:
             av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type);
             skip_bits(&h->gb, 8 * size);
-- 
1.7.9.5



More information about the libav-devel mailing list