Message ID | 20241025015721.2271894-1-michael@niedermayer.cc |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel] avcodec/ffv1: Support slice coding mode 1 with golomb rice | expand |
Context | Check | Description |
---|---|---|
andriy/make_x86 | success | Make finished |
andriy/make_fate_x86 | success | Make fate finished |
On 25/10/2024 03:57, Michael Niedermayer wrote: > Sponsored-by: Sovereign Tech Fund > Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> > --- > libavcodec/ffv1dec.c | 20 ++++++++++---------- > libavcodec/ffv1dec_template.c | 3 +++ > libavcodec/ffv1enc.c | 23 ++++++++++++----------- > 3 files changed, 25 insertions(+), 21 deletions(-) > > diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c > index ac8cc8a31dc..de5abfe9b41 100644 > --- a/libavcodec/ffv1dec.c > +++ b/libavcodec/ffv1dec.c > @@ -120,9 +120,8 @@ static int is_input_end(RangeCoder *c, GetBitContext *gb, int ac) > static int decode_plane(FFV1Context *f, FFV1SliceContext *sc, > GetBitContext *gb, > uint8_t *src, int w, int h, int stride, int plane_index, > - int pixel_stride) > + int pixel_stride, int ac) > { > - const int ac = f->ac; > int x, y; > int16_t *sample[2]; > sample[0] = sc->sample_buffer + 3; > @@ -273,6 +272,7 @@ static int decode_slice(AVCodecContext *c, void *arg) > AVFrame * const p = f->picture.f; > const int si = sc - f->slices; > GetBitContext gb; > + int ac = f->ac || sc->slice_coding_mode == 1; > > if (!(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f) > ff_progress_frame_await(&f->last_picture, si); > @@ -305,7 +305,7 @@ static int decode_slice(AVCodecContext *c, void *arg) > x = sc->slice_x; > y = sc->slice_y; > > - if (f->ac == AC_GOLOMB_RICE) { > + if (ac == AC_GOLOMB_RICE) { > if (f->version == 3 && f->micro_version > 1 || f->version > 3) > get_rac(&sc->c, (uint8_t[]) { 129 }); > sc->ac_byte_count = f->version > 2 || (!x && !y) ? sc->c.bytestream - sc->c.bytestream_start - 1 : 0; > @@ -320,17 +320,17 @@ static int decode_slice(AVCodecContext *c, void *arg) > const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift); > const int cx = x >> f->chroma_h_shift; > const int cy = y >> f->chroma_v_shift; > - decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1); > + decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1, ac); > > if (f->chroma_planes) { > - decode_plane(f, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1); > - decode_plane(f, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1); > + decode_plane(f, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1, ac); > + decode_plane(f, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1, ac); > } > if (f->transparency) > - decode_plane(f, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1); > + decode_plane(f, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1, ac); > } else if (f->colorspace == 0) { > - decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2); > - decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2); > + decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2, ac); > + decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2, ac); > } else if (f->use32bit) { > uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0], > p->data[1] + ps * x + y * p->linesize[1], > @@ -344,7 +344,7 @@ static int decode_slice(AVCodecContext *c, void *arg) > p->data[3] + ps * x + y * p->linesize[3] }; > decode_rgb_frame(f, sc, &gb, planes, width, height, p->linesize); > } > - if (f->ac != AC_GOLOMB_RICE && f->version > 2) { > + if (ac != AC_GOLOMB_RICE && f->version > 2) { > int v; > get_rac(&sc->c, (uint8_t[]) { 129 }); > v = sc->c.bytestream_end - sc->c.bytestream - 2 - 5*!!f->ec; > diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c > index 2da6bd935dc..e983d1ba648 100644 > --- a/libavcodec/ffv1dec_template.c > +++ b/libavcodec/ffv1dec_template.c > @@ -143,6 +143,9 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc, > int transparency = f->transparency; > int ac = f->ac; > > + if (sc->slice_coding_mode == 1) > + ac = 1; > + > for (x = 0; x < 4; x++) { > sample[x][0] = RENAME(sc->sample_buffer) + x * 2 * (w + 6) + 3; > sample[x][1] = RENAME(sc->sample_buffer) + (x * 2 + 1) * (w + 6) + 3; > diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c > index a32059886c0..547fb598d6d 100644 > --- a/libavcodec/ffv1enc.c > +++ b/libavcodec/ffv1enc.c > @@ -271,10 +271,9 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state, > > static int encode_plane(FFV1Context *f, FFV1SliceContext *sc, > const uint8_t *src, int w, int h, > - int stride, int plane_index, int pixel_stride) > + int stride, int plane_index, int pixel_stride, int ac) > { > int x, y, i, ret; > - const int ac = f->ac; > const int pass1 = !!(f->avctx->flags & AV_CODEC_FLAG_PASS1); > const int ring_size = f->context_model ? 3 : 2; > int16_t *sample[3]; > @@ -1068,6 +1067,7 @@ static int encode_slice(AVCodecContext *c, void *arg) > p->data[1] ? p->data[1] + ps*x + y*p->linesize[1] : NULL, > p->data[2] ? p->data[2] + ps*x + y*p->linesize[2] : NULL, > p->data[3] ? p->data[3] + ps*x + y*p->linesize[3] : NULL}; > + int ac = f->ac; > > sc->slice_coding_mode = 0; > if (f->version > 3 && f->colorspace == 1) { > @@ -1083,7 +1083,7 @@ retry: > if (f->version > 2) { > encode_slice_header(f, sc); > } > - if (f->ac == AC_GOLOMB_RICE) { > + if (ac == AC_GOLOMB_RICE) { > sc->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&sc->c, f->version > 2) : 0; > init_put_bits(&sc->pb, > sc->c.bytestream_start + sc->ac_byte_count, > @@ -1096,24 +1096,24 @@ retry: > const int cx = x >> f->chroma_h_shift; > const int cy = y >> f->chroma_v_shift; > > - ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1); > + ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1, ac); > > if (f->chroma_planes) { > - ret |= encode_plane(f, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1); > - ret |= encode_plane(f, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1); > + ret |= encode_plane(f, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1, ac); > + ret |= encode_plane(f, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1, ac); > } > if (f->transparency) > - ret |= encode_plane(f, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1); > + ret |= encode_plane(f, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1, ac); > } else if (c->pix_fmt == AV_PIX_FMT_YA8) { > - ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2); > - ret |= encode_plane(f, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2); > + ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2, ac); > + ret |= encode_plane(f, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2, ac); > } else if (f->use32bit) { > ret = encode_rgb_frame32(f, sc, planes, width, height, p->linesize); > } else { > ret = encode_rgb_frame(f, sc, planes, width, height, p->linesize); > } > > - if (f->ac != AC_GOLOMB_RICE) { > + if (ac != AC_GOLOMB_RICE) { > sc->ac_byte_count = ff_rac_terminate(&sc->c, 1); > } else { > flush_put_bits(&sc->pb); // FIXME: nicer padding > @@ -1122,11 +1122,12 @@ retry: > > if (ret < 0) { > av_assert0(sc->slice_coding_mode == 0); > - if (f->version < 4 || !f->ac) { > + if (f->version < 4) { > av_log(c, AV_LOG_ERROR, "Buffer too small\n"); > return ret; > } > av_log(c, AV_LOG_DEBUG, "Coding slice as PCM\n"); > + ac = 1; > sc->slice_coding_mode = 1; > sc->c = c_bak; > goto retry; Is there a reason to support this with Golomb? Being a fallback-only mode for range coding, I don't think there's much point in supporting Golomb coding for it.
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index ac8cc8a31dc..de5abfe9b41 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -120,9 +120,8 @@ static int is_input_end(RangeCoder *c, GetBitContext *gb, int ac) static int decode_plane(FFV1Context *f, FFV1SliceContext *sc, GetBitContext *gb, uint8_t *src, int w, int h, int stride, int plane_index, - int pixel_stride) + int pixel_stride, int ac) { - const int ac = f->ac; int x, y; int16_t *sample[2]; sample[0] = sc->sample_buffer + 3; @@ -273,6 +272,7 @@ static int decode_slice(AVCodecContext *c, void *arg) AVFrame * const p = f->picture.f; const int si = sc - f->slices; GetBitContext gb; + int ac = f->ac || sc->slice_coding_mode == 1; if (!(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f) ff_progress_frame_await(&f->last_picture, si); @@ -305,7 +305,7 @@ static int decode_slice(AVCodecContext *c, void *arg) x = sc->slice_x; y = sc->slice_y; - if (f->ac == AC_GOLOMB_RICE) { + if (ac == AC_GOLOMB_RICE) { if (f->version == 3 && f->micro_version > 1 || f->version > 3) get_rac(&sc->c, (uint8_t[]) { 129 }); sc->ac_byte_count = f->version > 2 || (!x && !y) ? sc->c.bytestream - sc->c.bytestream_start - 1 : 0; @@ -320,17 +320,17 @@ static int decode_slice(AVCodecContext *c, void *arg) const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift); const int cx = x >> f->chroma_h_shift; const int cy = y >> f->chroma_v_shift; - decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1); + decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1, ac); if (f->chroma_planes) { - decode_plane(f, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1); - decode_plane(f, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1); + decode_plane(f, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1, ac); + decode_plane(f, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1, ac); } if (f->transparency) - decode_plane(f, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1); + decode_plane(f, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1, ac); } else if (f->colorspace == 0) { - decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2); - decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2); + decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2, ac); + decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2, ac); } else if (f->use32bit) { uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0], p->data[1] + ps * x + y * p->linesize[1], @@ -344,7 +344,7 @@ static int decode_slice(AVCodecContext *c, void *arg) p->data[3] + ps * x + y * p->linesize[3] }; decode_rgb_frame(f, sc, &gb, planes, width, height, p->linesize); } - if (f->ac != AC_GOLOMB_RICE && f->version > 2) { + if (ac != AC_GOLOMB_RICE && f->version > 2) { int v; get_rac(&sc->c, (uint8_t[]) { 129 }); v = sc->c.bytestream_end - sc->c.bytestream - 2 - 5*!!f->ec; diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c index 2da6bd935dc..e983d1ba648 100644 --- a/libavcodec/ffv1dec_template.c +++ b/libavcodec/ffv1dec_template.c @@ -143,6 +143,9 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc, int transparency = f->transparency; int ac = f->ac; + if (sc->slice_coding_mode == 1) + ac = 1; + for (x = 0; x < 4; x++) { sample[x][0] = RENAME(sc->sample_buffer) + x * 2 * (w + 6) + 3; sample[x][1] = RENAME(sc->sample_buffer) + (x * 2 + 1) * (w + 6) + 3; diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index a32059886c0..547fb598d6d 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -271,10 +271,9 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state, static int encode_plane(FFV1Context *f, FFV1SliceContext *sc, const uint8_t *src, int w, int h, - int stride, int plane_index, int pixel_stride) + int stride, int plane_index, int pixel_stride, int ac) { int x, y, i, ret; - const int ac = f->ac; const int pass1 = !!(f->avctx->flags & AV_CODEC_FLAG_PASS1); const int ring_size = f->context_model ? 3 : 2; int16_t *sample[3]; @@ -1068,6 +1067,7 @@ static int encode_slice(AVCodecContext *c, void *arg) p->data[1] ? p->data[1] + ps*x + y*p->linesize[1] : NULL, p->data[2] ? p->data[2] + ps*x + y*p->linesize[2] : NULL, p->data[3] ? p->data[3] + ps*x + y*p->linesize[3] : NULL}; + int ac = f->ac; sc->slice_coding_mode = 0; if (f->version > 3 && f->colorspace == 1) { @@ -1083,7 +1083,7 @@ retry: if (f->version > 2) { encode_slice_header(f, sc); } - if (f->ac == AC_GOLOMB_RICE) { + if (ac == AC_GOLOMB_RICE) { sc->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&sc->c, f->version > 2) : 0; init_put_bits(&sc->pb, sc->c.bytestream_start + sc->ac_byte_count, @@ -1096,24 +1096,24 @@ retry: const int cx = x >> f->chroma_h_shift; const int cy = y >> f->chroma_v_shift; - ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1); + ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1, ac); if (f->chroma_planes) { - ret |= encode_plane(f, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1); - ret |= encode_plane(f, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1); + ret |= encode_plane(f, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1, ac); + ret |= encode_plane(f, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1, ac); } if (f->transparency) - ret |= encode_plane(f, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1); + ret |= encode_plane(f, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1, ac); } else if (c->pix_fmt == AV_PIX_FMT_YA8) { - ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2); - ret |= encode_plane(f, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2); + ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2, ac); + ret |= encode_plane(f, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2, ac); } else if (f->use32bit) { ret = encode_rgb_frame32(f, sc, planes, width, height, p->linesize); } else { ret = encode_rgb_frame(f, sc, planes, width, height, p->linesize); } - if (f->ac != AC_GOLOMB_RICE) { + if (ac != AC_GOLOMB_RICE) { sc->ac_byte_count = ff_rac_terminate(&sc->c, 1); } else { flush_put_bits(&sc->pb); // FIXME: nicer padding @@ -1122,11 +1122,12 @@ retry: if (ret < 0) { av_assert0(sc->slice_coding_mode == 0); - if (f->version < 4 || !f->ac) { + if (f->version < 4) { av_log(c, AV_LOG_ERROR, "Buffer too small\n"); return ret; } av_log(c, AV_LOG_DEBUG, "Coding slice as PCM\n"); + ac = 1; sc->slice_coding_mode = 1; sc->c = c_bak; goto retry;
Sponsored-by: Sovereign Tech Fund Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> --- libavcodec/ffv1dec.c | 20 ++++++++++---------- libavcodec/ffv1dec_template.c | 3 +++ libavcodec/ffv1enc.c | 23 ++++++++++++----------- 3 files changed, 25 insertions(+), 21 deletions(-)