summaryrefslogtreecommitdiff
path: root/libavcodec/h264_sei.c
diff options
context:
space:
mode:
authorJoakim Plate <elupus@ecce.se>2013-06-27 23:09:06 +0200
committerMichael Niedermayer <michaelni@gmx.at>2013-07-21 16:04:02 +0200
commit8710a634a5d422d9ee9d1578ff1c07cd39f16ce0 (patch)
tree3d0d3f2b5d11adcbb4b247b1c4df04323b7a3664 /libavcodec/h264_sei.c
parent0f229f9b91fe3c4ebd97e88f004d638819b76add (diff)
h264: add frame packing as stereo_mode frame metadata
This matches the matroska defintion of stereo_mode, with no metadata written if no info exist in sei Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/h264_sei.c')
-rw-r--r--libavcodec/h264_sei.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 5f68a139a3..932085230b 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -204,6 +204,44 @@ 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;
@@ -246,6 +284,9 @@ 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(h, size) < 0)
+ return -1;
default:
skip_bits(&h->gb, 8*size);
}
@@ -256,3 +297,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;
+ }
+}