aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorVittorio Giovara <vittorio.giovara@gmail.com>2013-02-20 16:34:58 +0100
committerVittorio Giovara <vittorio.giovara@gmail.com>2013-12-09 16:02:43 +0100
commit5b10ef729f610fcbc9c485e7b643ce53268144cb (patch)
tree4b147db6c5e36bbf1021797ebd2b14c427bee0e4 /libavcodec
parent7e244c68600f479270e979258e389ed5240885fb (diff)
downloadffmpeg-5b10ef729f610fcbc9c485e7b643ce53268144cb.tar.gz
h264: parse frame packing arrangement SEI messages and save relevant stereo3d information
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/h264.c41
-rw-r--r--libavcodec/h264.h11
-rw-r--r--libavcodec/h264_sei.c40
3 files changed, 91 insertions, 1 deletions
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 86d453bba7..29a69608ec 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_CHECKERBOARD;
+ 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 920e3fc1c8..a828bf9e57 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 27a2c7689c..746c2132c1 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);