[FFmpeg-devel] [PATCH] h264: expose stereo_mode from h264 frame packing info

Michael Niedermayer michaelni at gmx.at
Thu Jun 27 12:34:55 CEST 2013


On Wed, Jun 26, 2013 at 10:20:56PM +0200, Joakim Plate wrote:
> On Mon, Jun 24, 2013 at 12:02 AM, Joakim Plate <elupus at ecce.se> wrote:
> 
> >
> > On Sun, Jun 23, 2013 at 10:35 PM, Joakim Plate <elupus at ecce.se> wrote:
> >
> >> So a simplified patch with it just set as internal data. Is there no way
> >> to construct the string on the fly for options? we could expose the
> >> internal values i suppose. But those are harder to use. This one matches
> >> matroska settings.
> >>
> >
> > I see one problem with this. It can't differentiate between a stream that
> > have frame_packing info and it is cancelled, and one where it's just not
> > supplied. Probably should match matroska in the cancelled state and set it
> > to "mono".
> >
> >
> Updated patch that supplies the data as matadata to the frame on output
> instead of only part of the context.

>  h264.c        |    6 ++++
>  h264.h        |   35 +++++++++++++++++++++++
>  h264_parser.c |    3 +-
>  h264_sei.c    |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 127 insertions(+), 2 deletions(-)
> 4eee469426594ce561e6fd96f27ad649d6ae84da  0001-h264-add-frame-packing-as-stereo_mode-frame-metadata.patch
> From 42d5aea5b2c644d0a70908f744614673ef50e84b Mon Sep 17 00:00:00 2001
> From: Joakim Plate <elupus at ecce.se>
> Date: Wed, 26 Jun 2013 22:20:28 +0200
> Subject: [PATCH 1/1] 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
> ---
>  libavcodec/h264.c        |  6 ++++
>  libavcodec/h264.h        | 35 +++++++++++++++++++-
>  libavcodec/h264_parser.c |  3 +-
>  libavcodec/h264_sei.c    | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 127 insertions(+), 2 deletions(-)
> 
> diff --git a/libavcodec/h264.c b/libavcodec/h264.c
> index bb105ee..b124712 100644
> --- a/libavcodec/h264.c
> +++ b/libavcodec/h264.c
> @@ -1512,6 +1512,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) {
> @@ -4861,6 +4862,8 @@ static int output_frame(H264Context *h, AVFrame *dst, Picture *srcp)
>      if (ret < 0)
>          return ret;
>  
> +    av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0);
> +
>      if (!srcp->crop)
>          return 0;
>  


> @@ -5033,6 +5036,9 @@ static const AVProfile profiles[] = {
>  static const AVOption h264_options[] = {
>      {"is_avc", "is avc", offsetof(H264Context, is_avc), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0},
>      {"nal_length_size", "nal_length_size", offsetof(H264Context, nal_length_size), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 4, 0},
> +    {"frame_packing_arrangement_cancel_flag", "frame_packing_arrangement_cancel_flag", offsetof(H264Context, sei_fpa.frame_packing_arrangement_cancel_flag), FF_OPT_TYPE_INT, {.i64 = -1}, -1, 1, 0},
> +    {"frame_packing_arrangement_type", "frame_packing_arrangement_type", offsetof(H264Context, sei_fpa.frame_packing_arrangement_type), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 6, 0},
> +    {"content_interpretation_type", "content_interpretation_type", offsetof(H264Context, sei_fpa.content_interpretation_type), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 2, 0},
>      {NULL}
>  };

how do these interact with frame threads ?
(as they are not strictly global options and could change per frame)
also exporting the cancel flag seems quite low level, isnt exporting
the current state enough ?



>  
> diff --git a/libavcodec/h264.h b/libavcodec/h264.h
> index ed07ad6..8b64ec6 100644
> --- a/libavcodec/h264.h
> +++ b/libavcodec/h264.h
> @@ -127,7 +127,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;
>  
>  /**
> @@ -146,6 +147,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 {
> @@ -233,6 +247,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 {
> @@ -628,6 +653,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
>  
> @@ -775,6 +802,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 3b7d011..a5d47ed 100644
> --- a/libavcodec/h264_parser.c
> +++ b/libavcodec/h264_parser.c
> @@ -172,6 +172,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;
> @@ -254,7 +255,7 @@ static inline int parse_nal_units(AVCodecParserContext *s,
>              }
>              h->sps       = *h->sps_buffers[h->pps.sps_id];
>              h->frame_num = get_bits(&h->gb, h->sps.log2_max_frame_num);
> -
> + 
>              avctx->profile = ff_h264_get_profile(&h->sps);
>              avctx->level   = h->sps.level_idc;
>  
> diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
> index 5f68a13..49f1c00 100644
> --- a/libavcodec/h264_sei.c
> +++ b/libavcodec/h264_sei.c
> @@ -204,6 +204,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)));

skip_bits_long()


[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

it is not once nor twice but times without number that the same ideas make
their appearance in the world. -- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130627/bf8dd538/attachment.asc>


More information about the ffmpeg-devel mailing list