[FFmpeg-devel] [PATCH v2 3/6] avcodec/cbs_vp9: Write frame data directly
Mark Thompson
sw at jkqxz.net
Mon Nov 18 02:04:51 EET 2019
On 17/11/2019 07:34, Andreas Rheinhardt wrote:
> Writing a unit (always a frame) in cbs_vp9 used an intermediate buffer
> to write the frame header followed by the frame data that was copied
> into said buffer. Afterwards, the final buffer for the frame was
> allocated and everything copied into this buffer. But it is trivial to
> compute the needed size of the final buffer after having written the
> header, so one can allocate the final buffer immediately and copy the
> frame data directly into it.
>
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
> ---
> libavcodec/cbs.c | 4 ++++
> libavcodec/cbs_internal.h | 6 ++++--
> libavcodec/cbs_vp9.c | 25 +++++++++++++++++++------
> 3 files changed, 27 insertions(+), 8 deletions(-)
>
> diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
> index 0badb192d9..9ad2641f6d 100644
> --- a/libavcodec/cbs.c
> +++ b/libavcodec/cbs.c
> @@ -306,6 +306,10 @@ static int cbs_write_unit_data(CodedBitstreamContext *ctx,
> init_put_bits(&pbc, ctx->write_buffer, ctx->write_buffer_size);
>
> ret = ctx->codec->write_unit(ctx, unit, &pbc);
> + if (ret == 1) {
> + // write_unit has already finished the unit.
> + return 0;
> + }
> if (ret < 0) {
> if (ret == AVERROR(ENOSPC)) {
> // Overflow.
> diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h
> index 4c5a535ca6..5768baa9ca 100644
> --- a/libavcodec/cbs_internal.h
> +++ b/libavcodec/cbs_internal.h
> @@ -44,8 +44,10 @@ typedef struct CodedBitstreamType {
> int (*read_unit)(CodedBitstreamContext *ctx,
> CodedBitstreamUnit *unit);
>
> - // Write the data bitstream from unit->content into pbc.
> - // Return value AVERROR(ENOSPC) indicates that pbc was too small.
> + // Write the data bitstream from unit->content into pbc or into unit->data.
> + // Return value AVERROR(ENOSPC) indicates that pbc was too small;
> + // 1 indicates that the unit has already been finished by write_unit
> + // (i.e. unit->data and unit->data_ref have been allocated and filled).
> int (*write_unit)(CodedBitstreamContext *ctx,
> CodedBitstreamUnit *unit,
> PutBitContext *pbc);
> diff --git a/libavcodec/cbs_vp9.c b/libavcodec/cbs_vp9.c
> index 42e4dcf5ac..bc074c4631 100644
> --- a/libavcodec/cbs_vp9.c
> +++ b/libavcodec/cbs_vp9.c
> @@ -526,6 +526,7 @@ static int cbs_vp9_write_unit(CodedBitstreamContext *ctx,
> PutBitContext *pbc)
> {
> VP9RawFrame *frame = unit->content;
> + size_t data_size, header_size;
> int err;
>
> err = cbs_vp9_write_frame(ctx, pbc, frame);
> @@ -535,16 +536,28 @@ static int cbs_vp9_write_unit(CodedBitstreamContext *ctx,
> // Frame must be byte-aligned.
> av_assert0(put_bits_count(pbc) % 8 == 0);
>
> + data_size = header_size = put_bits_count(pbc) / 8;
> + unit->data_bit_padding = 0;
> + flush_put_bits(pbc);
> +
> if (frame->data) {
> - if (frame->data_size > put_bits_left(pbc) / 8)
> - return AVERROR(ENOSPC);
> + if (frame->data_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE
> + - header_size)
> + return AVERROR(ENOMEM);
>
> - flush_put_bits(pbc);
> - memcpy(put_bits_ptr(pbc), frame->data, frame->data_size);
> - skip_put_bytes(pbc, frame->data_size);
> + data_size += frame->data_size;
> }
>
> - return 0;
> + err = ff_cbs_alloc_unit_data(ctx, unit, data_size);
> + if (err < 0)
> + return err;
> +
> + memcpy(unit->data, pbc->buf, header_size);
> +
> + if (frame->data)
> + memcpy(unit->data + header_size, frame->data, frame->data_size);
> +
> + return 1;
> }
>
> static int cbs_vp9_assemble_fragment(CodedBitstreamContext *ctx,
>
I feel like the special return is saying the API isn't quite right in this and the following patches. Can we do better with something like a write_unit_header / write_unit_everything_else pair? (Maybe the second of those can have a pointer argument indicating how many bytes it wants to write?)
- Mark
More information about the ffmpeg-devel
mailing list