[FFmpeg-devel] [PATCH] avcodec/cbs_vp9: Write frame data directly

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Thu Nov 14 22:21:42 EET 2019


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.

Also, given that the intermediate buffer now only needs to keep the
header, its size can be drastically reduced.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
I think that 1KB is still quite generous for the header; one could
probably even come up with a drastically lower bound upon reading the
spec (one could probably put the intermediate buffer on the stack and
remove the reallocation stuff).

Similar improvements can be done for the other cbs_*. vp9 is first
because it seems to be the easiest.

 libavcodec/cbs_vp9.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/libavcodec/cbs_vp9.c b/libavcodec/cbs_vp9.c
index bd172100fc..ebb4c573ea 100644
--- a/libavcodec/cbs_vp9.c
+++ b/libavcodec/cbs_vp9.c
@@ -526,12 +526,13 @@ static int cbs_vp9_write_unit(CodedBitstreamContext *ctx,
 {
     CodedBitstreamVP9Context *priv = ctx->priv_data;
     VP9RawFrame *frame = unit->content;
+    size_t header_size, data_size;
     PutBitContext pbc;
     int err;
 
     if (!priv->write_buffer) {
-        // Initial write buffer size is 1MB.
-        priv->write_buffer_size = 1024 * 1024;
+        // Initial write buffer size is 1KB.
+        priv->write_buffer_size = 1024;
 
     reallocate_and_try_again:
         err = av_reallocp(&priv->write_buffer, priv->write_buffer_size);
@@ -556,27 +557,26 @@ static int cbs_vp9_write_unit(CodedBitstreamContext *ctx,
     // Frame must be byte-aligned.
     av_assert0(put_bits_count(&pbc) % 8 == 0);
 
-    unit->data_size        = put_bits_count(&pbc) / 8;
+    data_size = header_size = put_bits_count(&pbc) / 8;
     unit->data_bit_padding = 0;
     flush_put_bits(&pbc);
 
     if (frame->data) {
-        if (unit->data_size + frame->data_size >
-            priv->write_buffer_size) {
-            priv->write_buffer_size *= 2;
-            goto reallocate_and_try_again;
-        }
+        if (frame->data_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE
+                                       - header_size)
+            return AVERROR(ENOMEM);
 
-        memcpy(priv->write_buffer + unit->data_size,
-               frame->data, frame->data_size);
-        unit->data_size += frame->data_size;
+        data_size += frame->data_size;
     }
 
-    err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size);
+    err = ff_cbs_alloc_unit_data(ctx, unit, data_size);
     if (err < 0)
         return err;
 
-    memcpy(unit->data, priv->write_buffer, unit->data_size);
+    memcpy(unit->data, priv->write_buffer, header_size);
+
+    if (frame->data)
+        memcpy(unit->data + header_size, frame->data, frame->data_size);
 
     return 0;
 }
-- 
2.20.1



More information about the ffmpeg-devel mailing list