[FFmpeg-devel] [PATCH] avcodec/ffv1: Support for RGBA64 and GBRAP16

Jerome Martinez jerome at mediaarea.net
Mon Feb 5 23:05:50 EET 2018


On 04/02/2018 15:00, Michael Niedermayer wrote:
>
>> diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
>> index b7eea0dd70..2763082540 100644
>> --- a/libavcodec/ffv1enc_template.c
>> +++ b/libavcodec/ffv1enc_template.c
>> @@ -122,8 +122,8 @@ static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w,
>>       return 0;
>>   }
>>   
>> -static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3],
>> -                                    int w, int h, const int stride[3])
>> +static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
>> +                                    int w, int h, const int stride[4])
>>   {
>>       int x, y, p, i;
>>       const int ring_size = s->context_model ? 3 : 2;
>> @@ -152,14 +152,18 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3],
>>                   r = (v >> 16) & 0xFF;
>>                   a =  v >> 24;
>>               } else if (packed) {
>> -                const uint16_t *p = ((const uint16_t*)(src[0] + x*6 + stride[0]*y));
>> +                const uint16_t *p = ((const uint16_t*)(src[0] + x*(3 + s->transparency)*2 + stride[0]*y));
>>                   r = p[0];
>>                   g = p[1];
>>                   b = p[2];
>> +                if (s->transparency)
> transparency should possibly be moved into a local variable

Done, actually both s->transparency and (3 + s->transparency)*2

>
>
>> +                  a = p[3];
>>               } else if (sizeof(TYPE) == 4) {
>>                   g = *((const uint16_t *)(src[0] + x*2 + stride[0]*y));
>>                   b = *((const uint16_t *)(src[1] + x*2 + stride[1]*y));
>>                   r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y));
>> +                if (s->transparency)
>> +                    a = *((const uint16_t *)(src[3] + x*2 + stride[2]*y));
>                                                                 ^^^^^^^^^
> this looks wrong

Stupid typo not seen as strides are same here, fixed (I reviewed again 
the patch, looks like it is the only one in the list of changes).

Updated patch attached.

>
>
> also what speed effect do thes changes to the inner loop have ?

I see same performance, which I expect because when I do performance 
profiling I see that the transformation part is taking less than 0.1% of 
the CPU time and I guess that the CPU prediction stuff does its job here.

-------------- next part --------------
From 0b9501984a8ce95d6e88a448683fd0d9d1473a08 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= <jerome at mediaarea.net>
Date: Thu, 1 Feb 2018 13:11:53 +0100
Subject: [PATCH] avcodec/ffv1: Support for RGBA64 and GBRAP16

---
 libavcodec/ffv1dec.c          | 14 ++++++++++----
 libavcodec/ffv1dec_template.c |  9 +++++++--
 libavcodec/ffv1enc.c          | 16 ++++++++++++++--
 libavcodec/ffv1enc_template.c | 14 ++++++++++----
 4 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 5eadb6b158..923b79f3ab 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -336,14 +336,16 @@ static int decode_slice(AVCodecContext *c, void *arg)
          decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0]    , width, height, p->linesize[0], 0, 2);
          decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
     } else if (f->use32bit) {
-        uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0],
+        uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
                                p->data[1] + ps * x + y * p->linesize[1],
-                               p->data[2] + ps * x + y * p->linesize[2] };
+                               p->data[2] + ps * x + y * p->linesize[2],
+                               p->data[3] + ps * x + y * p->linesize[3] };
         decode_rgb_frame32(fs, planes, width, height, p->linesize);
     } else {
-        uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0],
+        uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
                                p->data[1] + ps * x + y * p->linesize[1],
-                               p->data[2] + ps * x + y * p->linesize[2] };
+                               p->data[2] + ps * x + y * p->linesize[2],
+                               p->data[3] + ps * x + y * p->linesize[3] };
         decode_rgb_frame(fs, planes, width, height, p->linesize);
     }
     if (fs->ac != AC_GOLOMB_RICE && f->version > 2) {
@@ -694,6 +696,10 @@ static int read_header(FFV1Context *f)
             f->avctx->pix_fmt = AV_PIX_FMT_GBRP16;
             f->use32bit = 1;
         }
+        else if (f->avctx->bits_per_raw_sample == 16 && f->transparency) {
+            f->avctx->pix_fmt = AV_PIX_FMT_GBRAP16;
+            f->use32bit = 1;
+        }
     } else {
         av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
         return AVERROR(ENOSYS);
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 37df766773..a25b3384f1 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -107,13 +107,14 @@ static av_always_inline int RENAME(decode_line)(FFV1Context *s, int w,
     return 0;
 }
 
-static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3])
+static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int h, int stride[4])
 {
     int x, y, p;
     TYPE *sample[4][2];
     int lbd    = s->avctx->bits_per_raw_sample <= 8;
     int bits   = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
     int offset = 1 << bits;
+    int transparency = s->transparency;
 
     for (x = 0; x < 4; x++) {
         sample[x][0] = RENAME(s->sample_buffer) +  x * 2      * (w + 6) + 3;
@@ -125,7 +126,7 @@ static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int
     memset(RENAME(s->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(s->sample_buffer)));
 
     for (y = 0; y < h; y++) {
-        for (p = 0; p < 3 + s->transparency; p++) {
+        for (p = 0; p < 3 + transparency; p++) {
             TYPE *temp = sample[p][0]; // FIXME: try a normal buffer
 
             sample[p][0] = sample[p][1];
@@ -158,10 +159,14 @@ static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int
                 *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = g;
                 *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = b;
                 *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r;
+                if (transparency)
+                    *((uint16_t*)(src[3] + x*2 + stride[3]*y)) = a;
             } else {
                 *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b;
                 *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g;
                 *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r;
+                if (transparency)
+                    *((uint16_t*)(src[3] + x*2 + stride[3]*y)) = a;
             }
         }
     }
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 0778f84c9b..49b8d590a3 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -624,6 +624,14 @@ FF_ENABLE_DEPRECATION_WARNINGS
         s->chroma_planes = 1;
         s->bits_per_raw_sample = 8;
         break;
+    case AV_PIX_FMT_RGBA64:
+        s->colorspace = 1;
+        s->transparency = 1;
+        s->chroma_planes = 1;
+        s->bits_per_raw_sample = 16;
+        s->use32bit = 1;
+        s->version = FFMAX(s->version, 1);
+        break;
     case AV_PIX_FMT_RGB48:
         s->colorspace = 1;
         s->chroma_planes = 1;
@@ -649,10 +657,12 @@ FF_ENABLE_DEPRECATION_WARNINGS
         if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
             s->bits_per_raw_sample = 14;
     case AV_PIX_FMT_GBRP16:
+    case AV_PIX_FMT_GBRAP16:
         if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample)
             s->bits_per_raw_sample = 16;
         else if (!s->bits_per_raw_sample)
             s->bits_per_raw_sample = avctx->bits_per_raw_sample;
+        s->transparency = desc->nb_components == 4 || desc->nb_components == 2;
         s->colorspace = 1;
         s->chroma_planes = 1;
         if (s->bits_per_raw_sample >= 16) {
@@ -1024,9 +1034,10 @@ static int encode_slice(AVCodecContext *c, void *arg)
     const int ps     = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
     int ret;
     RangeCoder c_bak = fs->c;
-    const uint8_t *planes[3] = {p->data[0] + ps*x + y*p->linesize[0],
+    const uint8_t *planes[4] = {p->data[0] + ps*x + y*p->linesize[0],
                                 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[2] ? p->data[2] + ps*x + y*p->linesize[2] : NULL,
+                                p->data[3] ? p->data[3] + ps*x + y*p->linesize[3] : NULL};
 
     fs->slice_coding_mode = 0;
     if (f->version > 3) {
@@ -1318,6 +1329,7 @@ AVCodec ff_ffv1_encoder = {
         AV_PIX_FMT_YA8,
         AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12,
         AV_PIX_FMT_GBRP16, AV_PIX_FMT_RGB48,
+        AV_PIX_FMT_GBRAP16, AV_PIX_FMT_RGBA64,
         AV_PIX_FMT_NONE
 
     },
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index b7eea0dd70..b93336538b 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -122,8 +122,8 @@ static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w,
     return 0;
 }
 
-static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3],
-                                    int w, int h, const int stride[3])
+static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
+                                    int w, int h, const int stride[4])
 {
     int x, y, p, i;
     const int ring_size = s->context_model ? 3 : 2;
@@ -132,6 +132,8 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3],
     int packed = !src[1];
     int bits   = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8;
     int offset = 1 << bits;
+    int transparency = s->transparency;
+    int packed_size = (3 + transparency)*2;
 
     s->run_index = 0;
 
@@ -152,14 +154,18 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3],
                 r = (v >> 16) & 0xFF;
                 a =  v >> 24;
             } else if (packed) {
-                const uint16_t *p = ((const uint16_t*)(src[0] + x*6 + stride[0]*y));
+                const uint16_t *p = ((const uint16_t*)(src[0] + x*packed_size + stride[0]*y));
                 r = p[0];
                 g = p[1];
                 b = p[2];
+                if (transparency)
+                  a = p[3];
             } else if (sizeof(TYPE) == 4) {
                 g = *((const uint16_t *)(src[0] + x*2 + stride[0]*y));
                 b = *((const uint16_t *)(src[1] + x*2 + stride[1]*y));
                 r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y));
+                if (transparency)
+                    a = *((const uint16_t *)(src[3] + x*2 + stride[3]*y));
             } else {
                 b = *((const uint16_t *)(src[0] + x*2 + stride[0]*y));
                 g = *((const uint16_t *)(src[1] + x*2 + stride[1]*y));
@@ -179,7 +185,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3],
             sample[2][0][x] = r;
             sample[3][0][x] = a;
         }
-        for (p = 0; p < 3 + s->transparency; p++) {
+        for (p = 0; p < 3 + transparency; p++) {
             int ret;
             sample[p][0][-1] = sample[p][1][0  ];
             sample[p][1][ w] = sample[p][1][w-1];
-- 
2.13.3.windows.1



More information about the ffmpeg-devel mailing list