diff mbox series

[FFmpeg-devel] avcodec/ffv1: Support slice coding mode 1 with golomb rice

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

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Michael Niedermayer Oct. 25, 2024, 1:57 a.m. UTC
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(-)

Comments

Lynne Oct. 25, 2024, 2:24 a.m. UTC | #1
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 mbox series

Patch

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;