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.
Unified · Split
| @@ -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 | ||
| 429 | static int encode_plane_slice_raw(const uint8_t *src, uint8_t *dst, | 426 | static 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 | ||
| 446 | static void encode_plane_slice(const uint8_t *src, uint8_t *dst, unsigned dst_size, | 438 | static 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 | else | 479 | 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); |