---
 libavcodec/h264.c     |   54 +++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/h264.h     |   24 +++++++++++++++++++++-
 libavcodec/h264_sei.c |   40 ++++++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 5ff55ce..849f99a 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"
@@ -2011,6 +2012,59 @@ static void decode_postinit(H264Context *h, int 
setup_finished)
         }
     }
 
+    if (h->sei_frame_packing_present) {
+        AVFrameSideData *side_data;
+        AVStereo3D stereo;
+
+        switch (h->frame_packing_arrangement_type) {
+            case SEI_FPA_CHECKERBOARD:
+                stereo.type = AV_STEREO3D_CHECKERS;
+                break;
+            case SEI_FPA_LINE_INTERLEAVED:
+                stereo.type = AV_STEREO3D_LINES;
+                break;
+            case SEI_FPA_COLUMN_INTERLEAVED:
+                stereo.type = AV_STEREO3D_COLUMNS;
+                break;
+            case SEI_FPA_SIDE_BY_SIDE:
+                stereo.type = AV_STEREO3D_SIDEBYSIDE;
+                break;
+            case SEI_FPA_TOP_AND_BOTTOM:
+                stereo.type = AV_STEREO3D_TOPBOTTOM;
+                break;
+            case SEI_FPA_FRAME_ALTERNATE:
+                stereo.type = AV_STEREO3D_FRAMESEQUENCE;
+                break;
+            case SEI_FPA_2D:
+                stereo.type = AV_STEREO3D_NOT_REALLY;
+                break;
+            default:
+                stereo.type = AV_STEREO3D_NONE;
+                break;
+        }
+
+        /* skip allocation if unknown type */
+        if (stereo.type != AV_STEREO3D_NONE) {
+            stereo.info = AV_STEREO3D_NORMAL;
+            if (h->content_interpretation_type == 2)
+                stereo.info |= AV_STEREO3D_ORDER_INVERT;
+
+            if (h->quincunx_subsampling)
+                stereo.info |= AV_STEREO3D_QUINCUNX;
+
+            if (stereo.type != AV_STEREO3D_FRAMESEQUENCE)
+                stereo.info |= AV_STEREO3D_SIZE_HALF;
+
+            side_data = av_frame_new_side_data(&cur->f,
+                                               AV_FRAME_DATA_STEREO3D,
+                                               sizeof(AVStereo3D));
+            if (!side_data)
+                return;
+
+            memcpy(side_data->data, &stereo, sizeof(AVStereo3D));
+        }
+    }
+
     // FIXME do something with unavailable reference frames
 
     /* Sort B-frames into display order */
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 3ef8420..9e0c6ba 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;
 
 /**
@@ -142,6 +143,19 @@ typedef enum {
 } SEI_PicStructType;
 
 /**
+ * type in frame packing arrangement SEI message
+ */
+typedef enum {
+    SEI_FPA_CHECKERBOARD             = 0,  ///<  0: quincux
+    SEI_FPA_LINE_INTERLEAVED         = 1,  ///<  1: line interleaving
+    SEI_FPA_COLUMN_INTERLEAVED       = 2,  ///<  2: column interleaving
+    SEI_FPA_SIDE_BY_SIDE             = 3,  ///<  3: side by side
+    SEI_FPA_TOP_AND_BOTTOM           = 4,  ///<  4: top and bottom
+    SEI_FPA_FRAME_ALTERNATE          = 5,  ///<  5: frame alternate
+    SEI_FPA_2D                       = 6,  ///<  6: not stereo
+} SEI_FramePackingType;
+
+/**
  * Sequence parameter set
  */
 typedef struct SPS {
@@ -586,6 +600,14 @@ typedef struct H264Context {
     int prev_interlaced_frame;
 
     /**
+     * frame_packing_arrangment SEI message
+     */
+    int sei_frame_packing_present;
+    SEI_FramePackingType 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..f01b4d6 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 != SEI_FPA_FRAME_ALTERNATE)
+            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

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to