diff --git a/packages/multimedia/ffmpeg/patches/1.2.1/ffmpeg-0039-h264-expose-h264-frame-packing-as-stereo_mode-metada.patch b/packages/multimedia/ffmpeg/patches/1.2.1/ffmpeg-0039-h264-expose-h264-frame-packing-as-stereo_mode-metada.patch new file mode 100644 index 0000000000..5c6384f87c --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/1.2.1/ffmpeg-0039-h264-expose-h264-frame-packing-as-stereo_mode-metada.patch @@ -0,0 +1,236 @@ +From 3a6ea59e122d5bc981a2a5c8f9bafcba0f9f8754 Mon Sep 17 00:00:00 2001 +From: Joakim Plate +Date: Wed, 26 Jun 2013 22:07:28 +0200 +Subject: [PATCH 1/1] h264: expose h264 frame packing as stereo_mode metadata + +--- + libavcodec/h264.c | 3 ++ + libavcodec/h264.h | 35 ++++++++++++++- + libavcodec/h264_parser.c | 1 + + libavcodec/h264_sei.c | 85 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 123 insertions(+), 1 deletion(-) + +diff --git a/libavcodec/h264.c b/libavcodec/h264.c +index 937ad7a..85f2372 100644 +--- a/libavcodec/h264.c ++++ b/libavcodec/h264.c +@@ -1437,6 +1437,7 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx) + h->prev_poc_msb = 1 << 16; + h->prev_frame_num = -1; + h->x264_build = -1; ++ h->sei_fpa.frame_packing_arrangement_cancel_flag = -1; + ff_h264_reset_sei(h); + if (avctx->codec_id == AV_CODEC_ID_H264) { + if (avctx->ticks_per_frame == 1) { +@@ -4783,6 +4784,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, + out->f.reference &= ~DELAYED_PIC_REF; + *got_frame = 1; + *pict = out->f; ++ av_dict_set(&pict->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0); + } + + return buf_index; +@@ -4839,6 +4841,7 @@ not_extra: + if (h->next_output_pic && (h->next_output_pic->sync || h->sync>1)) { + *got_frame = 1; + *pict = h->next_output_pic->f; ++ av_dict_set(&pict->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0); + } + } + +diff --git a/libavcodec/h264.h b/libavcodec/h264.h +index 7ea613c..15a0b21 100644 +--- a/libavcodec/h264.h ++++ b/libavcodec/h264.h +@@ -126,7 +126,8 @@ typedef enum { + SEI_TYPE_PIC_TIMING = 1, ///< picture timing + SEI_TYPE_USER_DATA_ITU_T_T35 = 4, ///< user data registered by ITU-T Recommendation T.35 + 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; + + /** +@@ -145,6 +146,19 @@ typedef enum { + } SEI_PicStructType; + + /** ++ * frame_packing_arrangement types ++ */ ++typedef enum { ++ SEI_FPA_TYPE_CHECKERBOARD = 0, ++ SEI_FPA_TYPE_INTERLEAVE_COLUMN = 1, ++ SEI_FPA_TYPE_INTERLEAVE_ROW = 2, ++ SEI_FPA_TYPE_SIDE_BY_SIDE = 3, ++ SEI_FPA_TYPE_TOP_BOTTOM = 4, ++ SEI_FPA_TYPE_INTERLEAVE_TEMPORAL = 5, ++ SEI_FPA_TYPE_2D = 6, ++} SEI_FpaType; ++ ++/** + * Sequence parameter set + */ + typedef struct SPS { +@@ -230,6 +244,17 @@ typedef struct PPS { + } PPS; + + /** ++ * Frame Packing Arrangement Type ++ */ ++typedef struct FPA { ++ int frame_packing_arrangement_id; ++ int frame_packing_arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received ++ SEI_FpaType frame_packing_arrangement_type; ++ int content_interpretation_type; ++ int quincunx_sampling_flag; ++} FPA; ++ ++/** + * Memory management control operation opcode. + */ + typedef enum MMCOOpcode { +@@ -626,6 +651,8 @@ typedef struct H264Context { + */ + int valid_recovery_point; + ++ FPA sei_fpa; ++ + int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag + int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag + +@@ -771,6 +798,12 @@ void ff_h264_filter_mb(H264Context *h, int mb_x, int mb_y, + */ + void ff_h264_reset_sei(H264Context *h); + ++/** ++ * Get stereo_mode string from the h264 frame_packing_arrangement ++ * @param h H.264 context. ++ */ ++const char* ff_h264_sei_stereo_mode(H264Context *h); ++ + /* + * o-o o-o + * / / / +diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c +index 44b92b7..aff9ba1 100644 +--- a/libavcodec/h264_parser.c ++++ b/libavcodec/h264_parser.c +@@ -158,6 +158,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, + h->sei_dpb_output_delay = 0; + h->sei_cpb_removal_delay = -1; + h->sei_buffering_period_present = 0; ++ h->sei_fpa.frame_packing_arrangement_cancel_flag = -1; + + if (!buf_size) + return 0; +diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c +index ece54f1..fc9b96f 100644 +--- a/libavcodec/h264_sei.c ++++ b/libavcodec/h264_sei.c +@@ -194,6 +194,43 @@ 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 */ ++ 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\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); ++ skip_bits(&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; +@@ -236,6 +273,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); + } +@@ -246,3 +286,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; ++ } ++} +-- +1.8.2 +