You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
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@outlook.com>
This commit is contained in:
@@ -391,8 +391,8 @@ static int count_plane_slice(AVCodecContext *avctx, int n, int plane)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int encode_table(AVCodecContext *avctx,
|
static void generate_codes(AVCodecContext *avctx,
|
||||||
PutByteContext *pb, HuffEntry *he, int plane)
|
HuffEntry *he, int plane)
|
||||||
{
|
{
|
||||||
MagicYUVContext *s = avctx->priv_data;
|
MagicYUVContext *s = avctx->priv_data;
|
||||||
PTable counts[256];
|
PTable counts[256];
|
||||||
@@ -414,14 +414,15 @@ static int encode_table(AVCodecContext *avctx,
|
|||||||
magy_huffman_compute_bits(counts, he, codes_counts, 256, 12);
|
magy_huffman_compute_bits(counts, he, codes_counts, 256, 12);
|
||||||
|
|
||||||
calculate_codes(he, codes_counts);
|
calculate_codes(he, codes_counts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_codes(PutByteContext *pb, const HuffEntry he[256])
|
||||||
|
{
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
// The seven low bits are len; the top bit means the run of
|
// The seven low bits are len; the top bit means the run of
|
||||||
// codes of this length has length one.
|
// codes of this length has length one.
|
||||||
bytestream2_put_byte(pb, he[i].len);
|
bytestream2_put_byte(pb, he[i].len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encode_plane_slice_raw(const uint8_t *src, uint8_t *dst,
|
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)
|
const AVFrame *frame, int *got_packet)
|
||||||
{
|
{
|
||||||
MagicYUVContext *s = avctx->priv_data;
|
MagicYUVContext *s = avctx->priv_data;
|
||||||
const int width = avctx->width, height = avctx->height;
|
|
||||||
const int slice_height = s->slice_height;
|
|
||||||
PutByteContext pb;
|
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;
|
||||||
|
|
||||||
ret = ff_alloc_packet(avctx, pkt, (256 + 4 * s->nb_slices + width * height) *
|
avctx->execute2(avctx, predict_slice, (void *)frame, NULL, s->nb_slices);
|
||||||
s->planes + 256);
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
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->width);
|
||||||
bytestream2_put_le32(&pb, avctx->height);
|
bytestream2_put_le32(&pb, avctx->height);
|
||||||
bytestream2_put_le32(&pb, avctx->width);
|
bytestream2_put_le32(&pb, avctx->width);
|
||||||
bytestream2_put_le32(&pb, slice_height);
|
bytestream2_put_le32(&pb, s->slice_height);
|
||||||
bytestream2_put_le32(&pb, 0);
|
|
||||||
|
|
||||||
for (int i = 0; i < s->planes; i++) {
|
// Slice position is relative to the current position (i.e. 32)
|
||||||
bytestream2_put_le32(&pb, 0);
|
bytestream2_put_le32(&pb, header_size - 32);
|
||||||
for (int j = 1; j < s->nb_slices; j++)
|
|
||||||
bytestream2_put_le32(&pb, 0);
|
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);
|
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);
|
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)
|
||||||
|
output_codes(&pb, s->he[i]);
|
||||||
|
|
||||||
for (int i = 0; i < s->planes; i++)
|
|
||||||
encode_table(avctx, &pb, 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;
|
|
||||||
|
|
||||||
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);
|
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;
|
*got_packet = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user