---
libavcodec/h264.c | 31 +++++++++++++++++++++++++++++++
libavcodec/h264.h | 22 +++++++++++++++++++++-
libavcodec/h264_sei.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index d53907e..725831a 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -27,6 +27,7 @@
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
+#include "libavutil/stereoscopy.h"
#include "internal.h"
#include "cabac.h"
#include "cabac_functions.h"
@@ -1924,6 +1925,36 @@ static void decode_postinit(H264Context *h, int
setup_finished)
}
}
+ if (h->sei_frame_packing_present) {
+ AVFrameSideData *side_data =
+ av_frame_new_side_data(&cur->f,
+ AV_FRAME_DATA_STEREO3D,
+ sizeof(uint32_t));
+
+ switch (h->frame_packing_arrangement_type) {
+ case SEI_FPA_CHECKERBOARD:
+ *side_data->data = AV_STEREO3D_CHECKERS; break;
+ case SEI_FPA_LINE_INTERLEAVED:
+ *side_data->data = AV_STEREO3D_LINES; break;
+ case SEI_FPA_COLUMN_INTERLEAVED:
+ *side_data->data = AV_STEREO3D_COLUMNS; break;
+ case SEI_FPA_SIDE_BY_SIDE:
+ *side_data->data = AV_STEREO3D_SIDEBYSIDE; break;
+ case SEI_FPA_TOP_AND_BOTTOM:
+ *side_data->data = AV_STEREO3D_TOPBOTTOM; break;
+ case SEI_FPA_FRAME_ALTERNATE:
+ *side_data->data = AV_STEREO3D_FRAMESEQUENCE; break;
+ }
+
+ if (h->content_interpretation_type == 2)
+ *side_data->data |= AV_STEREO3D_ORDER_RL;
+ else
+ *side_data->data |= AV_STEREO3D_ORDER_LR;
+
+ if (*side_data->data != AV_STEREO3D_FRAMESEQUENCE)
+ *side_data->data |= AV_STEREO3D_SIZE_HALF;
+ }
+
// 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..09e230a 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,18 @@ 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_FramePackingType;
+
+/**
* Sequence parameter set
*/
typedef struct SPS {
@@ -586,6 +599,13 @@ 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;
+
+ /**
* 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 df4c49f..8fd4874 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){
@@ -156,6 +157,37 @@ static int decode_buffering_period(H264Context *h){
return 0;
}
+static int decode_frame_packing_arrangement(H264Context *h){
+ int cancel, quincunx;
+ 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;
+
+ return 0;
+}
+
int ff_h264_decode_sei(H264Context *h){
while (get_bits_left(&h->gb) > 16) {
int size, type;
@@ -187,6 +219,10 @@ int ff_h264_decode_sei(H264Context *h){
if(decode_buffering_period(h) < 0)
return -1;
break;
+ case SEI_TYPE_FRAME_PACKING:
+ if(decode_frame_packing_arrangement(h) < 0)
+ return -1;
+ break;
default:
skip_bits(&h->gb, 8*size);
}
--
1.7.9.5
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel