Re: [FFmpeg-devel] [PATCH 2/3] lavc: Add coded bitstream read/write support for AV1

2018-09-11 Thread James Almer
On 9/9/2018 7:08 PM, Mark Thompson wrote:
> +static void cbs_av1_free_obu(void *unit, uint8_t *content)
> +{
> +AV1RawOBU *obu = (AV1RawOBU*)content;
> +
> +switch (obu->header.obu_type) {
> +case AV1_OBU_TILE_GROUP:
> +cbs_av1_free_tile_data(>tile_group.tile_data);
> +break;
> +case AV1_OBU_FRAME:
> +cbs_av1_free_tile_data(>frame.tile_group.tile_data);
> +break;
> +case AV1_OBU_TILE_LIST:
> +cbs_av1_free_tile_data(>tile_list.tile_data);
> +break;
> +case AV1_OBU_METADATA:
> +cbs_av1_free_metadata(>metadata);
> +break;
> +}
> +
> +av_freep();

Why adding a custom free function for all OBUs when only four types need
it? Sounds like unnecessary overhead for all cases.
IMO what cbs_h2645 does is better, using the default free function where
a custom one isn't needed, then calling a custom free function directly
for those that need one.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 2/3] lavc: Add coded bitstream read/write support for AV1

2018-09-09 Thread James Almer
On 9/9/2018 7:08 PM, Mark Thompson wrote:
> ---
> Against versions which people might have seen before:
> * Removed all of the vestigial annex B support (not useful, we are going to 
> ensure that AVPackets in FFmpeg never hold annex B data).
> * gm_params subexp parsing made sensible - it doesn't compute the actual 
> gm_params values any more, but the code actually makes sense rather than 
> being opaque pasta from the standard.
> * Metadata support added.
> * Tile-group / tile-info / frame-with-tiles OBUs are combined in a hopefully 
> better way.
> * Miscellaneous small fixes.
> 
> Thanks to James Almer for testing and various fixes incorporated into this.
> 
> 
>  configure|2 +
>  libavcodec/Makefile  |1 +
>  libavcodec/av1.h |   88 ++
>  libavcodec/cbs.c |6 +
>  libavcodec/cbs_av1.c | 1293 
>  libavcodec/cbs_av1.h |  429 +++
>  libavcodec/cbs_av1_syntax_template.c | 1676 ++
>  libavcodec/cbs_internal.h|1 +
>  8 files changed, 3496 insertions(+)
>  create mode 100644 libavcodec/cbs_av1.c
>  create mode 100644 libavcodec/cbs_av1.h
>  create mode 100644 libavcodec/cbs_av1_syntax_template.c

[...]

> +static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
> +  CodedBitstreamFragment *frag,
> +  int header)
> +{
> +GetBitContext gbc;
> +uint8_t *data;
> +size_t size;
> +uint64_t obu_length;
> +int pos, err;
> +
> +data = frag->data;
> +size = frag->data_size;
> +
> +while (size > 0) {
> +AV1RawOBUHeader header;
> +uint64_t obu_size;
> +
> +init_get_bits(, data, 8 * size);
> +
> +err = cbs_av1_read_obu_header(ctx, , );

This is generating a lot of noise when using the trace_headers bsf.
Basically printing the header fields twice per OBU, first when
splitting, then again when decomposing.

You can get rid of that and simplify this function a lot if you use the
ff_av1_packet_split() API from av1_parse.h doing more or less the same
to what you're doing for h2645:

static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
  CodedBitstreamFragment *frag,
  int header)
{
CodedBitstreamAV1Context *priv = ctx->priv_data;
int err;

err = ff_av1_packet_split(>read_packet,
  frag->data, frag->data_size,
  ctx->log_ctx);
if (err < 0)
return err;

for (int i = 0; i < priv->read_packet.nb_obus; i++) {
const AV1OBU *obu = >read_packet.obus[i];
uint8_t *data = (uint8_t *)obu->raw_data;
size_t size = obu->raw_size;

err = ff_cbs_insert_unit_data(ctx, frag, -1, obu->type,
  data, size, frag->data_ref);
if (err < 0)
return err;
}

return 0;
}

[...]

> +static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext 
> *rw,
> + AV1RawFrameHeader *current)
> +{
> +CodedBitstreamAV1Context *priv = ctx->priv_data;
> +const AV1RawSequenceHeader *seq;
> +int id_len, all_frames, frame_is_intra, order_hint_bits;
> +int i, err;
> +
> +if (!priv->sequence_header) {
> +av_log(ctx->log_ctx, AV_LOG_ERROR, "No sequence header available: "
> +   "unable to decode frame header.\n");
> +return AVERROR_INVALIDDATA;
> +}
> +seq = priv->sequence_header;
> +
> +id_len = seq->additional_frame_id_length_minus_1 +
> + seq->delta_frame_id_length_minus_2 + 3;
> +all_frames = (1 << AV1_NUM_REF_FRAMES) - 1;
> +
> +if (seq->reduced_still_picture_header) {
> +infer(show_existing_frame, 0);
> +infer(frame_type, AV1_FRAME_KEY);
> +infer(show_frame, 1);
> +infer(showable_frame, 0);
> +frame_is_intra = 1;
> +
> +} else {
> +flag(show_existing_frame);
> +
> +if (current->show_existing_frame) {
> +AV1ReferenceFrameState *frame;
> +
> +fb(3, frame_to_show_map_idx);
> +frame = >ref[current->frame_to_show_map_idx];
> +
> +if (seq->decoder_model_info_present_flag &&
> +!seq->timing_info.equal_picture_interval) {
> +
> fb(seq->decoder_model_info.frame_presentation_time_length_minus_1 + 1,
> +   frame_presentation_time);
> +}
> +
> +if (seq->frame_id_numbers_present_flag)
> +fb(id_len, display_frame_id);
> +
> +if (frame->frame_type == AV1_FRAME_KEY)
> +infer(refresh_frame_flags, all_frames);
> +else
> +infer(refresh_frame_flags, 0);
> +
> +return 0;
> +}
> +
> +fb(2, frame_type);
> +