History

avcodec/magicyuvenc: Avoid intermediate buffer

Given that we can calculate the size of each slice in advance, we can determine the position in the output packet where it needs to be put and can therefore avoid the intermediate buffer.

Andreas Rheinhardt committed 1 year ago

Commit e8b97b71 parent 6e6e4e01 file · +14 −30Browse files

Unified · Split

libavcodec/magicyuvenc.c+14−30
@@ -60,7 +60,7 @@ typedef struct Slice { · 59 unmodified lines
60 unsigned pos;60 unsigned pos;
61 unsigned size;61 unsigned size;
62 uint8_t *slice;62 uint8_t *slice;
63 uint8_t *bitslice;63 uint8_t *dst;
64 int64_t counts[256];64 int64_t counts[256];
65} Slice;65} Slice;
66 66
@@ -74,7 +74,6 @@ typedef struct MagicYUVContext { · 7 unmodified lines
74 int correlate;74 int correlate;
75 int hshift[4];75 int hshift[4];
76 int vshift[4];76 int vshift[4];
77 unsigned bitslice_size;
78 uint8_t *decorrelate_buf[2];77 uint8_t *decorrelate_buf[2];
79 Slice *slices;78 Slice *slices;
80 HuffEntry he[4][256];79 HuffEntry he[4][256];
@@ -224,7 +223,6 @@ static av_cold int magy_encode_init(AVCodecContext *avctx) · 143 unmodified lines
224 s->decorrelate_buf[1] = s->decorrelate_buf[0] + (s->nb_slices * s->slice_height) * aligned_width;223 s->decorrelate_buf[1] = s->decorrelate_buf[0] + (s->nb_slices * s->slice_height) * aligned_width;
225 }224 }
226 225
227 s->bitslice_size = avctx->width * s->slice_height + 2;
228 for (int n = 0; n < s->nb_slices; n++) {226 for (int n = 0; n < s->nb_slices; n++) {
229 for (int i = 0; i < s->planes; i++) {227 for (int i = 0; i < s->planes; i++) {
230 Slice *sl = &s->slices[n * s->planes + i];228 Slice *sl = &s->slices[n * s->planes + i];
@@ -233,10 +231,9 @@ static av_cold int magy_encode_init(AVCodecContext *avctx) · 2 unmodified lines
233 sl->height = AV_CEIL_RSHIFT(sl->height, s->vshift[i]);231 sl->height = AV_CEIL_RSHIFT(sl->height, s->vshift[i]);
234 sl->width = AV_CEIL_RSHIFT(avctx->width, s->hshift[i]);232 sl->width = AV_CEIL_RSHIFT(avctx->width, s->hshift[i]);
235 233
236 sl->bitslice = av_malloc(s->bitslice_size + AV_INPUT_BUFFER_PADDING_SIZE);
237 sl->slice = av_malloc(avctx->width * (s->slice_height + 2) +234 sl->slice = av_malloc(avctx->width * (s->slice_height + 2) +
238 AV_INPUT_BUFFER_PADDING_SIZE);235 AV_INPUT_BUFFER_PADDING_SIZE);
239 if (!sl->slice || !sl->bitslice) {236 if (!sl->slice) {
240 av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer.\n");237 av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer.\n");
241 return AVERROR(ENOMEM);238 return AVERROR(ENOMEM);
242 }239 }
@@ -426,21 +423,16 @@ static int encode_table(AVCodecContext *avctx, · 183 unmodified lines
426 return 0;423 return 0;
427}424}
428 425
429static int encode_plane_slice_raw(const uint8_t *src, uint8_t *dst,426static void encode_plane_slice_raw(const uint8_t *src, uint8_t *dst, int dst_size,
430 int width, int height, int prediction)427 int width, int height, int prediction)
431{428{
432 unsigned count = width * height;429 unsigned count = width * height;
433 430
434 dst[0] = 1;431 dst[0] = 1;
435 dst[1] = prediction;432 dst[1] = prediction;
433 AV_WN32(dst + dst_size - 4, 0);
436 434
437 memcpy(dst + 2, src, count);435 memcpy(dst + 2, src, count);
438 count += 2;
439 AV_WN32(dst + count, 0);
440 if (count & 3)
441 count += 4 - (count & 3);
442
443 return count;
444}436}
445 437
446static void encode_plane_slice(const uint8_t *src, uint8_t *dst, unsigned dst_size,438static void encode_plane_slice(const uint8_t *src, uint8_t *dst, unsigned dst_size,
@@ -482,11 +474,11 @@ static int encode_slice(AVCodecContext *avctx, void *tdata, · 35 unmodified lines
482 Slice *sl = &s->slices[n * s->planes + i];474 Slice *sl = &s->slices[n * s->planes + i];
483 475
484 if (sl->encode_raw)476 if (sl->encode_raw)
485 encode_plane_slice_raw(sl->slice, sl->bitslice,477 encode_plane_slice_raw(sl->slice, sl->dst, sl->size,
486 sl->width, sl->height, s->frame_pred);478 sl->width, sl->height, s->frame_pred);
487 else479 else
488 encode_plane_slice(sl->slice,480 encode_plane_slice(sl->slice,
489 sl->bitslice,481 sl->dst,
490 sl->size,482 sl->size,
491 sl->width, sl->height,483 sl->width, sl->height,
492 s->he[i], s->frame_pred);484 s->he[i], s->frame_pred);
@@ -612,32 +604,25 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, · 119 unmodified lines
612 tables_size = put_bytes_count(&pbit, 1);604 tables_size = put_bytes_count(&pbit, 1);
613 bytestream2_skip_p(&pb, tables_size);605 bytestream2_skip_p(&pb, tables_size);
614 606
615 for (int i = 0; i < s->planes; ++i) {607 for (int i = 0; i < s->nb_slices; ++i) {
616 for (int j = 0; j < s->nb_slices; ++j) {608 for (int j = 0; j < s->planes; ++j) {
617 Slice *const sl = &s->slices[j * s->planes + i];609 Slice *const sl = &s->slices[i * s->planes + j];
618 int64_t size = 0;610 int64_t size = 0;
619 611
620 for (size_t k = 0; k < FF_ARRAY_ELEMS(sl->counts); ++k)612 for (size_t k = 0; k < FF_ARRAY_ELEMS(sl->counts); ++k)
621 size += sl->counts[k] * s->he[i][k].len;613 size += sl->counts[k] * s->he[j][k].len;
622 size = AV_CEIL_RSHIFT(size, 3);614 size = AV_CEIL_RSHIFT(size, 3);
623 sl->encode_raw = size >= sl->width * sl->height;615 sl->encode_raw = size >= sl->width * sl->height;
624 if (sl->encode_raw)616 if (sl->encode_raw)
625 size = sl->width * sl->height;617 size = sl->width * sl->height;
626 sl->size = FFALIGN(size + 2, 4);618 sl->size = FFALIGN(size + 2, 4);
619 sl->pos = bytestream2_tell_p(&pb);
620 sl->dst = pb.buffer;
621 bytestream2_skip_p(&pb, sl->size);
627 }622 }
628 }623 }
629 avctx->execute2(avctx, encode_slice, NULL, NULL, s->nb_slices);624 avctx->execute2(avctx, encode_slice, NULL, NULL, s->nb_slices);
630 625
631 for (int n = 0; n < s->nb_slices; n++) {
632 for (int i = 0; i < s->planes; i++) {
633 Slice *sl = &s->slices[n * s->planes + i];
634
635 sl->pos = bytestream2_tell_p(&pb);
636
637 bytestream2_put_buffer(&pb, sl->bitslice, sl->size);
638 }
639 }
640
641 pos = bytestream2_tell_p(&pb);626 pos = bytestream2_tell_p(&pb);
642 bytestream2_seek_p(&pb, 32, SEEK_SET);627 bytestream2_seek_p(&pb, 32, SEEK_SET);
643 bytestream2_put_le32(&pb, s->slices[0].pos - 32);628 bytestream2_put_le32(&pb, s->slices[0].pos - 32);
@@ -665,7 +650,6 @@ static av_cold int magy_encode_close(AVCodecContext *avctx) · 21 unmodified lines
665 Slice *sl = &s->slices[i];650 Slice *sl = &s->slices[i];
666 651
667 av_freep(&sl->slice);652 av_freep(&sl->slice);
668 av_freep(&sl->bitslice);
669 }653 }
670 av_freep(&s->slices);654 av_freep(&s->slices);
671 av_freep(&s->decorrelate_buf);655 av_freep(&s->decorrelate_buf);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t