[FFmpeg-cvslog] avcodec/magicyuvenc: Calculate proper packet size in advance
Andreas Rheinhardt
git at videolan.org
Sun Apr 20 23:31:25 EEST 2025
ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Thu Apr 17 08:27:38 2025 +0200| [1ab50cced5a02798bbb7efc3333b1c4a06989317] | committer: Andreas Rheinhardt
avcodec/magicyuvenc: Calculate proper packet size in advance
This can be easily done because we have a count of the number of
values and the length of the associated codes. This allows
to switch to ff_get_encode_buffer() and thereby avoids an implicit
intermediate buffer.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=1ab50cced5a02798bbb7efc3333b1c4a06989317
---
libavcodec/magicyuvenc.c | 94 +++++++++++++++++++++++-------------------------
1 file changed, 44 insertions(+), 50 deletions(-)
diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c
index 071dce1be3..d29379d3c1 100644
--- a/libavcodec/magicyuvenc.c
+++ b/libavcodec/magicyuvenc.c
@@ -391,8 +391,8 @@ static int count_plane_slice(AVCodecContext *avctx, int n, int plane)
return 0;
}
-static int encode_table(AVCodecContext *avctx,
- PutByteContext *pb, HuffEntry *he, int plane)
+static void generate_codes(AVCodecContext *avctx,
+ HuffEntry *he, int plane)
{
MagicYUVContext *s = avctx->priv_data;
PTable counts[256];
@@ -414,14 +414,15 @@ static int encode_table(AVCodecContext *avctx,
magy_huffman_compute_bits(counts, he, codes_counts, 256, 12);
calculate_codes(he, codes_counts);
+}
+static void output_codes(PutByteContext *pb, const HuffEntry he[256])
+{
for (int i = 0; i < 256; i++) {
// The seven low bits are len; the top bit means the run of
// codes of this length has length one.
bytestream2_put_byte(pb, he[i].len);
}
-
- return 0;
}
static void encode_plane_slice_raw(const uint8_t *src, uint8_t *dst,
@@ -547,13 +548,35 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *frame, int *got_packet)
{
MagicYUVContext *s = avctx->priv_data;
- const int width = avctx->width, height = avctx->height;
- const int slice_height = s->slice_height;
PutByteContext pb;
- int pos, ret = 0;
+ int header_size = 32 + (4 + 1) * (s->planes * s->nb_slices + 1)
+ + 256 * s->planes /* Hufftables */;
+ int64_t pkt_size = header_size;
+ int ret;
+
+ avctx->execute2(avctx, predict_slice, (void *)frame, NULL, s->nb_slices);
+
+ for (int i = 0; i < s->planes; i++)
+ generate_codes(avctx, s->he[i], i);
+
+ for (int i = 0; i < s->nb_slices; ++i) {
+ for (int j = 0; j < s->planes; ++j) {
+ Slice *const sl = &s->slices[i * s->planes + j];
+ int64_t size = 0;
- ret = ff_alloc_packet(avctx, pkt, (256 + 4 * s->nb_slices + width * height) *
- s->planes + 256);
+ for (size_t k = 0; k < FF_ARRAY_ELEMS(sl->counts); ++k)
+ size += sl->counts[k] * s->he[j][k].len;
+ size = AV_CEIL_RSHIFT(size, 3);
+ sl->encode_raw = size >= sl->width * sl->height;
+ if (sl->encode_raw)
+ size = sl->width * sl->height;
+ sl->size = FFALIGN(size + 2, 4);
+ sl->pos = pkt_size;
+ pkt_size += sl->size;
+ }
+ }
+
+ ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0);
if (ret < 0)
return ret;
@@ -573,13 +596,17 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
bytestream2_put_le32(&pb, avctx->width);
bytestream2_put_le32(&pb, avctx->height);
bytestream2_put_le32(&pb, avctx->width);
- bytestream2_put_le32(&pb, slice_height);
- bytestream2_put_le32(&pb, 0);
+ bytestream2_put_le32(&pb, s->slice_height);
- for (int i = 0; i < s->planes; i++) {
- bytestream2_put_le32(&pb, 0);
- for (int j = 1; j < s->nb_slices; j++)
- bytestream2_put_le32(&pb, 0);
+ // Slice position is relative to the current position (i.e. 32)
+ bytestream2_put_le32(&pb, header_size - 32);
+
+ for (int i = 0; i < s->planes; ++i) {
+ for (int j = 0; j < s->nb_slices; ++j) {
+ Slice *const sl = &s->slices[j * s->planes + i];
+ bytestream2_put_le32(&pb, sl->pos - 32);
+ sl->dst = pkt->data + sl->pos;
+ }
}
bytestream2_put_byte(&pb, s->planes);
@@ -589,44 +616,11 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
bytestream2_put_byte(&pb, n * s->planes + i);
}
- avctx->execute2(avctx, predict_slice, (void *)frame, NULL, s->nb_slices);
-
- for (int i = 0; i < s->planes; i++)
- encode_table(avctx, &pb, s->he[i], i);
+ for (int i = 0; i < s->planes; ++i)
+ output_codes(&pb, s->he[i]);
- for (int i = 0; i < s->nb_slices; ++i) {
- for (int j = 0; j < s->planes; ++j) {
- Slice *const sl = &s->slices[i * s->planes + j];
- int64_t size = 0;
-
- for (size_t k = 0; k < FF_ARRAY_ELEMS(sl->counts); ++k)
- size += sl->counts[k] * s->he[j][k].len;
- size = AV_CEIL_RSHIFT(size, 3);
- sl->encode_raw = size >= sl->width * sl->height;
- if (sl->encode_raw)
- size = sl->width * sl->height;
- sl->size = FFALIGN(size + 2, 4);
- sl->pos = bytestream2_tell_p(&pb);
- sl->dst = pb.buffer;
- bytestream2_skip_p(&pb, sl->size);
- }
- }
avctx->execute2(avctx, encode_slice, NULL, NULL, s->nb_slices);
- pos = bytestream2_tell_p(&pb);
- bytestream2_seek_p(&pb, 32, SEEK_SET);
- bytestream2_put_le32(&pb, s->slices[0].pos - 32);
- for (int i = 0; i < s->planes; i++) {
- for (int n = 0; n < s->nb_slices; n++) {
- Slice *sl = &s->slices[n * s->planes + i];
-
- bytestream2_put_le32(&pb, sl->pos - 32);
- }
- }
- bytestream2_seek_p(&pb, pos, SEEK_SET);
-
- pkt->size = bytestream2_tell_p(&pb);
-
*got_packet = 1;
return 0;
More information about the ffmpeg-cvslog
mailing list