]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/cfhdenc.c
doc/filters: Documentation to add sess_config option for tensorflow backend
[ffmpeg] / libavcodec / cfhdenc.c
index 2dccb95d56216115ab19cf73a7878bf31ec0a087..e0b1172ede61a8362a7d1ca4de4aa3f0fa30299f 100644 (file)
@@ -33,6 +33,7 @@
 #include "avcodec.h"
 #include "bytestream.h"
 #include "cfhd.h"
+#include "cfhdencdsp.h"
 #include "put_bits.h"
 #include "internal.h"
 #include "thread.h"
@@ -94,8 +95,11 @@ static const unsigned codebook[256][2] = {
 };
 
 /* Derived by extracting runcodes from existing tables from decoder */
-static const uint16_t runbook[8][3] = {
-    {1,  0x0000,   1}, {7,  0x0069,  12}, {8,  0x00D1,  20}, {9,  0x018A,  32},
+static const uint16_t runbook[18][3] = {
+    {1,  0x0000,   1}, {2,  0x0000,   2}, {3,  0x0000,   3}, {4,  0x0000,   4},
+    {5,  0x0000,   5}, {6,  0x0000,   6}, {7,  0x0000,   7}, {8,  0x0000,   8},
+    {9,  0x0000,   9}, {10, 0x0000,  10}, {11, 0x0000,  11},
+    {7,  0x0069,  12}, {8,  0x00D1,  20}, {9,  0x018A,  32},
     {10, 0x0343,  60}, {11, 0x0685, 100}, {13, 0x18BF, 180}, {13, 0x1BA5, 320},
 };
 
@@ -105,94 +109,94 @@ static const uint16_t runbook[8][3] = {
  */
 static const uint16_t quantization_per_subband[2][3][13][9] = {
     {{
-        { 16, 16,  8,  4,  4,  2,   3,   3,   4, }, // film3+
-        { 16, 16,  8,  4,  4,  2,   3,   3,   4, }, // film3
-        { 16, 16,  8,  4,  4,  2,   4,   4,   6, }, // film2+
-        { 16, 16,  8,  4,  4,  2,   4,   4,   6, }, // film2
-        { 16, 16,  8,  4,  4,  2,   8,   8,  12, }, // film1++
-        { 24, 24, 12,  6,  6,  3,  12,  12,  18, }, // film1+
-        { 24, 24, 12,  6,  6,  3,  12,  12,  18, }, // film1
-        { 32, 32, 24,  8,  8,  6,  16,  16,  24, }, // high+
-        { 32, 32, 24,  8,  8,  6,  16,  16,  24, }, // high
-        { 48, 48, 32, 12, 12,  8,  32,  32,  48, }, // medium+
-        { 48, 48, 32, 12, 12,  8,  32,  32,  48, }, // medium
-        { 64, 64, 48, 16, 16, 12,  48,  48,  64, }, // low+
-        { 64, 64, 48, 16, 16, 12,  64,  64,  96, }, // low
+        { 16, 16,  8,  4,  4,  2,   6,   6,   9, }, // film3+
+        { 16, 16,  8,  4,  4,  2,   6,   6,   9, }, // film3
+        { 16, 16,  8,  4,  4,  2,   7,   7,  10, }, // film2+
+        { 16, 16,  8,  4,  4,  2,   8,   8,  12, }, // film2
+        { 16, 16,  8,  4,  4,  2,  16,  16,  26, }, // film1++
+        { 24, 24, 12,  6,  6,  3,  24,  24,  36, }, // film1+
+        { 24, 24, 12,  6,  6,  3,  24,  24,  36, }, // film1
+        { 32, 32, 24,  8,  8,  6,  32,  32,  48, }, // high+
+        { 32, 32, 24,  8,  8,  6,  32,  32,  48, }, // high
+        { 48, 48, 32, 12, 12,  8,  64,  64,  96, }, // medium+
+        { 48, 48, 32, 12, 12,  8,  64,  64,  96, }, // medium
+        { 64, 64, 48, 16, 16, 12,  96,  96, 144, }, // low+
+        { 64, 64, 48, 16, 16, 12, 128, 128, 192, }, // low
     },
     {
-        { 16, 16,  8,  4,  4,  2,   3,   3,   4, },
-        { 16, 16,  8,  4,  4,  2,   3,   3,   6, },
-        { 16, 16,  8,  4,  4,  2,   4,   4,   6, },
-        { 16, 16,  8,  4,  4,  2,   4,   4,   8, },
-        { 16, 16,  8,  4,  4,  2,   8,   8,  16, },
-        { 24, 24, 12,  6,  6,  3,  12,  12,  18, },
-        { 24, 24, 12,  6,  6,  3,  12,  12,  24, },
-        { 32, 32, 24,  8,  8,  6,  16,  16,  24, },
-        { 48, 48, 32, 12, 12,  8,  16,  16,  32, },
-        { 48, 48, 32, 12, 12,  8,  32,  32,  48, },
-        { 48, 48, 32, 12, 12,  8,  32,  32,  64, },
-        { 64, 64, 48, 16, 16, 12,  48,  48,  64, },
-        { 64, 64, 48, 16, 16, 12,  64,  64,  96, },
+        { 16, 16,  8,  4,  4,  2,   6,   6,   9, }, // film3+
+        { 16, 16,  8,  4,  4,  2,   6,   6,  12, }, // film3
+        { 16, 16,  8,  4,  4,  2,   7,   7,  14, }, // film2+
+        { 16, 16,  8,  4,  4,  2,   8,   8,  16, }, // film2
+        { 16, 16,  8,  4,  4,  2,  16,  16,  26, }, // film1++
+        { 24, 24, 12,  6,  6,  3,  24,  24,  36, }, // film1+
+        { 24, 24, 12,  6,  6,  3,  24,  24,  48, }, // film1
+        { 32, 32, 24,  8,  8,  6,  32,  32,  48, }, // high+
+        { 48, 48, 32, 12, 12,  8,  32,  32,  64, }, // high
+        { 48, 48, 32, 12, 12,  8,  64,  64,  96, }, // medium+
+        { 48, 48, 32, 12, 12,  8,  64,  64, 128, }, // medium
+        { 64, 64, 48, 16, 16, 12,  96,  96, 160, }, // low+
+        { 64, 64, 48, 16, 16, 12, 128, 128, 192, }, // low
     },
     {
-        { 16, 16,  8,  4,  4,  2,   3,   3,   4, },
-        { 16, 16,  8,  4,  4,  2,   3,   3,   6, },
-        { 16, 16,  8,  4,  4,  2,   4,   4,   6, },
-        { 16, 16,  8,  4,  4,  2,   4,   4,   8, },
-        { 16, 16,  8,  4,  4,  2,   8,   8,  16, },
-        { 24, 24, 12,  6,  6,  3,  12,  12,  18, },
-        { 24, 24, 12,  6,  6,  3,  12,  12,  24, },
-        { 32, 32, 24,  8,  8,  6,  16,  16,  24, },
-        { 48, 48, 32, 12, 12,  8,  16,  16,  32, },
-        { 48, 48, 32, 12, 12,  8,  32,  32,  48, },
-        { 48, 48, 32, 12, 12,  8,  32,  32,  64, },
-        { 64, 64, 48, 16, 16, 12,  48,  48,  64, },
-        { 64, 64, 48, 16, 16, 12,  64,  64,  96, },
+        { 16, 16,  8,  4,  4,  2,   6,   6,   9, }, // film3+
+        { 16, 16,  8,  4,  4,  2,   6,   6,  12, }, // film3
+        { 16, 16,  8,  4,  4,  2,   7,   7,  14, }, // film2+
+        { 16, 16,  8,  4,  4,  2,   8,   8,  16, }, // film2
+        { 16, 16,  8,  4,  4,  2,  16,  16,  26, }, // film1++
+        { 24, 24, 12,  6,  6,  3,  24,  24,  36, }, // film1+
+        { 24, 24, 12,  6,  6,  3,  24,  24,  48, }, // film1
+        { 32, 32, 24,  8,  8,  6,  32,  32,  48, }, // high+
+        { 48, 48, 32, 12, 12,  8,  32,  32,  64, }, // high
+        { 48, 48, 32, 12, 12,  8,  64,  64,  96, }, // medium+
+        { 48, 48, 32, 12, 12,  8,  64,  64, 128, }, // medium
+        { 64, 64, 48, 16, 16, 12,  96,  96, 160, }, // low+
+        { 64, 64, 48, 16, 16, 12, 128, 128, 192, }, // low
     }},
     {{
-        { 16, 16,  8, 16, 16,  8,  24,  24,  36, },
-        { 16, 16,  8, 16, 16,  8,  32,  32,  48, },
-        { 16, 16,  8, 16, 16,  8,  48,  48,  72, },
-        { 16, 16,  8, 16, 16,  8,  64,  64,  96, },
-        { 16, 16,  8, 20, 20, 10,  80,  80, 128, },
-        { 24, 24, 12, 24, 24, 12,  96,  96, 144, },
-        { 24, 24, 12, 24, 24, 12, 128, 128, 192, },
-        { 32, 32, 24, 32, 32, 24, 192, 192, 288, },
-        { 32, 32, 24, 32, 32, 24, 256, 256, 384, },
-        { 48, 48, 32, 48, 48, 32, 256, 256, 384, },
-        { 48, 48, 32, 48, 48, 32, 512, 512, 768, },
-        { 56, 56, 40, 56, 56, 40, 512, 512, 768, },
-        { 64, 64, 48, 64, 64, 48, 512, 512, 768, },
+        { 16, 16,  8, 16, 16,  8,  24,  24,  36, }, // film3+
+        { 16, 16,  8, 16, 16,  8,  24,  24,  36, }, // film3
+        { 16, 16,  8, 16, 16,  8,  32,  32,  48, }, // film2+
+        { 16, 16,  8, 16, 16,  8,  32,  32,  48, }, // film2
+        { 16, 16,  8, 20, 20, 10,  80,  80, 128, }, // film1++
+        { 24, 24, 12, 24, 24, 12,  96,  96, 144, }, // film1+
+        { 24, 24, 12, 24, 24, 12,  96,  96, 144, }, // film1
+        { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high+
+        { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high
+        { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium+
+        { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium
+        { 56, 56, 40, 56, 56, 40, 512, 512, 768, }, // low+
+        { 64, 64, 48, 64, 64, 48, 512, 512, 768, }, // low
     },
     {
-        { 16, 16,  8, 16, 16,  8,  24,  24,  36, },
-        { 16, 16,  8, 16, 16,  8,  32,  32,  48, },
-        { 16, 16,  8, 16, 16,  8,  48,  48,  72, },
-        { 16, 16,  8, 16, 16,  8,  64,  64,  96, },
-        { 16, 16,  8, 20, 20, 10,  80,  80, 128, },
-        { 24, 24, 12, 24, 24, 12,  96,  96, 144, },
-        { 24, 24, 12, 24, 24, 12, 128, 128, 192, },
-        { 32, 32, 24, 32, 32, 24, 192, 192, 288, },
-        { 32, 32, 24, 32, 32, 24, 256, 256, 384, },
-        { 48, 48, 32, 48, 48, 32, 256, 256, 384, },
-        { 48, 48, 32, 48, 48, 32, 512, 512, 768, },
-        { 56, 56, 40, 56, 56, 40, 512, 512, 768, },
-        { 64, 64, 48, 64, 64, 48, 512, 512, 768, },
+        { 16, 16,  8, 16, 16,  8,  24,  24,  36, }, // film3+
+        { 16, 16,  8, 16, 16,  8,  48,  48,  72, }, // film3
+        { 16, 16,  8, 16, 16,  8,  48,  48,  72, }, // film2+
+        { 16, 16,  8, 16, 16,  8,  64,  64,  96, }, // film2
+        { 16, 16,  8, 20, 20, 10,  80,  80, 128, }, // film1++
+        { 24, 24, 12, 24, 24, 12,  96,  96, 144, }, // film1+
+        { 24, 24, 12, 24, 24, 12, 192, 192, 288, }, // film1
+        { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high+
+        { 32, 32, 24, 32, 32, 24, 256, 256, 384, }, // high
+        { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium+
+        { 48, 48, 32, 48, 48, 32, 512, 512, 768, }, // medium
+        { 56, 56, 40, 56, 56, 40, 512, 512, 768, }, // low+
+        { 64, 64, 48, 64, 64, 48,1024,1024,1536, }, // low
     },
     {
-        { 16, 16,  8, 16, 16,  8,  24,  24,  36, },
-        { 16, 16,  8, 16, 16,  8,  32,  32,  48, },
-        { 16, 16,  8, 16, 16,  8,  48,  48,  72, },
-        { 16, 16,  8, 16, 16,  8,  64,  64,  96, },
-        { 16, 16, 10, 20, 20, 10,  80,  80, 128, },
-        { 24, 24, 12, 24, 24, 12,  96,  96, 144, },
-        { 24, 24, 12, 24, 24, 12, 128, 128, 192, },
-        { 32, 32, 24, 32, 32, 24, 192, 192, 288, },
-        { 32, 32, 24, 32, 32, 24, 256, 256, 384, },
-        { 48, 48, 32, 48, 48, 32, 256, 256, 384, },
-        { 48, 48, 32, 48, 48, 32, 512, 512, 768, },
-        { 56, 56, 40, 56, 56, 40, 512, 512, 768, },
-        { 64, 64, 48, 64, 64, 48, 512, 512, 768, },
+        { 16, 16,  8, 16, 16,  8,  24,  24,  36, }, // film3+
+        { 16, 16,  8, 16, 16,  8,  48,  48,  72, }, // film3
+        { 16, 16,  8, 16, 16,  8,  48,  48,  72, }, // film2+
+        { 16, 16,  8, 16, 16,  8,  64,  64,  96, }, // film2
+        { 16, 16, 10, 20, 20, 10,  80,  80, 128, }, // film1++
+        { 24, 24, 12, 24, 24, 12,  96,  96, 144, }, // film1+
+        { 24, 24, 12, 24, 24, 12, 192, 192, 288, }, // film1
+        { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high+
+        { 32, 32, 24, 32, 32, 24, 256, 256, 384, }, // high
+        { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium+
+        { 48, 48, 32, 48, 48, 32, 512, 512, 768, }, // medium
+        { 56, 56, 40, 56, 56, 40, 512, 512, 768, }, // low+
+        { 64, 64, 48, 64, 64, 48,1024,1024,1536, }, // low
     }},
 };
 
@@ -235,6 +239,9 @@ typedef struct CFHDEncContext {
     uint16_t lut[1024];
     Runbook  rb[321];
     Codebook cb[513];
+    int16_t *alpha;
+
+    CFHDEncDSPContext dsp;
 } CFHDEncContext;
 
 static av_cold int cfhd_encode_init(AVCodecContext *avctx)
@@ -263,10 +270,10 @@ static av_cold int cfhd_encode_init(AVCodecContext *avctx)
         int width  = i ? avctx->width >> s->chroma_h_shift : avctx->width;
         int height = i ? FFALIGN(avctx->height >> s->chroma_v_shift, 8) :
                          FFALIGN(avctx->height >> s->chroma_v_shift, 8);
-        ptrdiff_t stride = FFALIGN(width / 8, 8) * 8;
+        ptrdiff_t stride = (FFALIGN(width / 8, 8) + 64) * 8;
 
-        w8 = FFALIGN(width / 8, 8);
-        h8 = height / 8;
+        w8 = FFALIGN(width / 8, 8) + 64;
+        h8 = FFALIGN(height, 8) / 8;
         w4 = w8 * 2;
         h4 = h8 * 2;
         w2 = w4 * 2;
@@ -328,7 +335,7 @@ static av_cold int cfhd_encode_init(AVCodecContext *avctx)
 
     s->rb[0].run = 0;
 
-    for (int i = 1, j = 0; i < 320 && j < 7; j++) {
+    for (int i = 1, j = 0; i < 320 && j < 17; j++) {
         int run = runbook[j][2];
         int end = runbook[j+1][2];
 
@@ -339,8 +346,8 @@ static av_cold int cfhd_encode_init(AVCodecContext *avctx)
         }
     }
 
-    s->rb[320].bits = runbook[7][1];
-    s->rb[320].size = runbook[7][0];
+    s->rb[320].bits = runbook[17][1];
+    s->rb[320].size = runbook[17][0];
     s->rb[320].run = 320;
 
     for (int i = 0; i < 256; i++) {
@@ -355,53 +362,26 @@ static av_cold int cfhd_encode_init(AVCodecContext *avctx)
             s->lut[i] = last;
     }
 
-    return 0;
-}
+    ff_cfhdencdsp_init(&s->dsp);
 
-static inline void filter(int16_t *input, ptrdiff_t in_stride,
-                          int16_t *low, ptrdiff_t low_stride,
-                          int16_t *high, ptrdiff_t high_stride,
-                          int len)
-{
-    low[(0>>1) * low_stride]   = av_clip_int16(input[0*in_stride] + input[1*in_stride]);
-    high[(0>>1) * high_stride] = av_clip_int16((5 * input[0*in_stride] - 11 * input[1*in_stride] +
-                                                4 * input[2*in_stride] +  4 * input[3*in_stride] -
-                                                1 * input[4*in_stride] -  1 * input[5*in_stride] + 4) >> 3);
-
-    for (int i = 2; i < len - 2; i += 2) {
-        low[(i>>1) * low_stride]   = av_clip_int16(input[i*in_stride] + input[(i+1)*in_stride]);
-        high[(i>>1) * high_stride] = av_clip_int16(((-input[(i-2)*in_stride] - input[(i-1)*in_stride] +
-                                                      input[(i+2)*in_stride] + input[(i+3)*in_stride] + 4) >> 3) +
-                                                      input[(i+0)*in_stride] - input[(i+1)*in_stride]);
-    }
+    if (s->planes != 4)
+        return 0;
 
-    low[((len-2)>>1) * low_stride]   = av_clip_int16(input[((len-2)+0)*in_stride] + input[((len-2)+1)*in_stride]);
-    high[((len-2)>>1) * high_stride] = av_clip_int16((11* input[((len-2)+0)*in_stride] - 5 * input[((len-2)+1)*in_stride] -
-                                                      4 * input[((len-2)-1)*in_stride] - 4 * input[((len-2)-2)*in_stride] +
-                                                      1 * input[((len-2)-3)*in_stride] + 1 * input[((len-2)-4)*in_stride] + 4) >> 3);
-}
-
-static void horiz_filter(int16_t *input, int16_t *low, int16_t *high,
-                         int width)
-{
-    filter(input, 1, low, 1, high, 1, width);
-}
+    s->alpha = av_calloc(avctx->width * avctx->height, sizeof(*s->alpha));
+    if (!s->alpha)
+        return AVERROR(ENOMEM);
 
-static void vert_filter(int16_t *input, ptrdiff_t in_stride,
-                        int16_t *low, ptrdiff_t low_stride,
-                        int16_t *high, ptrdiff_t high_stride, int len)
-{
-    filter(input, in_stride, low, low_stride, high, high_stride, len);
+    return 0;
 }
 
 static void quantize_band(int16_t *input, int width, int a_width,
                           int height, unsigned quantization)
 {
-    const int factor = (1 << 16) / quantization;
+    const int16_t factor = (uint32_t)(1U << 15) / quantization;
 
     for (int i = 0; i < height; i++) {
         for (int j = 0; j < width; j++)
-            input[j] = av_clip_intp2((input[j] * factor) / 65536, 10);
+            input[j] = av_clip_intp2(((input[j] * factor + 16384 * FFSIGN(input[j])) / 32768), 10);
         input += a_width;
     }
 }
@@ -418,19 +398,41 @@ static int put_runcode(PutBitContext *pb, int count, const Runbook *const rb)
     return 0;
 }
 
+static void process_alpha(const int16_t *src, int width, int height, ptrdiff_t stride, int16_t *dst)
+{
+    for (int i = 0; i < height; i++) {
+        for (int j = 0; j < width; j++) {
+            int alpha = src[j];
+
+            if (alpha > 0 && alpha < 4080) {
+                alpha *= 223;
+                alpha += 128;
+                alpha >>= 8;
+                alpha += 256;
+            }
+
+            dst[j] = av_clip_uintp2(alpha, 12);
+        }
+
+        src += stride;
+        dst += width;
+    }
+}
+
 static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                              const AVFrame *frame, int *got_packet)
 {
     CFHDEncContext *s = avctx->priv_data;
+    CFHDEncDSPContext *dsp = &s->dsp;
     PutByteContext *pby = &s->pby;
     PutBitContext *pb = &s->pb;
     const Codebook *const cb = s->cb;
     const Runbook *const rb = s->rb;
     const uint16_t *lut = s->lut;
     unsigned pos;
-    int ret = 0;
+    int ret;
 
-    for (int plane = 0; plane < s->planes && !ret; plane++) {
+    for (int plane = 0; plane < s->planes; plane++) {
         int width = s->plane[plane].band[2][0].width;
         int a_width = s->plane[plane].band[2][0].a_width;
         int height = s->plane[plane].band[2][0].height;
@@ -438,39 +440,37 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         int16_t *input = (int16_t *)frame->data[act_plane];
         int16_t *low = s->plane[plane].l_h[6];
         int16_t *high = s->plane[plane].l_h[7];
-        const ptrdiff_t in_stride = frame->linesize[act_plane] / 2;
+        ptrdiff_t in_stride = frame->linesize[act_plane] / 2;
         int low_stride, high_stride;
 
-        for (int i = 0; i < height * 2; i++) {
-            horiz_filter(input, low, high, width * 2);
-            input += in_stride;
-            low += a_width;
-            high += a_width;
+        if (plane == 3) {
+            process_alpha(input, avctx->width, avctx->height,
+                          in_stride, s->alpha);
+            input = s->alpha;
+            in_stride = avctx->width;
         }
 
+        dsp->horiz_filter(input, low, high,
+                          in_stride, a_width, a_width,
+                          width * 2, height * 2);
+
         input = s->plane[plane].l_h[7];
         low = s->plane[plane].subband[7];
         low_stride = s->plane[plane].band[2][0].a_width;
         high = s->plane[plane].subband[9];
         high_stride = s->plane[plane].band[2][0].a_width;
 
-        for (int i = 0; i < width; i++) {
-            vert_filter(input, a_width, low, low_stride, high, high_stride, height * 2);
-            input++;
-            low++;
-            high++;
-        }
+        dsp->vert_filter(input, low, high,
+                         a_width, low_stride, high_stride,
+                         width, height * 2);
 
         input = s->plane[plane].l_h[6];
         low = s->plane[plane].l_h[7];
         high = s->plane[plane].subband[8];
 
-        for (int i = 0; i < width; i++) {
-            vert_filter(input, a_width, low, low_stride, high, high_stride, height * 2);
-            input++;
-            low++;
-            high++;
-        }
+        dsp->vert_filter(input, low, high,
+                         a_width, low_stride, high_stride,
+                         width, height * 2);
 
         a_width = s->plane[plane].band[1][0].a_width;
         width = s->plane[plane].band[1][0].width;
@@ -488,34 +488,25 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         }
 
         input = s->plane[plane].l_h[7];
-        for (int i = 0; i < height * 2; i++) {
-            horiz_filter(input, low, high, width * 2);
-            input += a_width * 2;
-            low += low_stride;
-            high += high_stride;
-        }
+        dsp->horiz_filter(input, low, high,
+                          a_width * 2, low_stride, high_stride,
+                          width * 2, height * 2);
 
         input = s->plane[plane].l_h[4];
         low = s->plane[plane].subband[4];
         high = s->plane[plane].subband[6];
 
-        for (int i = 0; i < width; i++) {
-            vert_filter(input, a_width, low, low_stride, high, high_stride, height * 2);
-            input++;
-            low++;
-            high++;
-        }
+        dsp->vert_filter(input, low, high,
+                         a_width, low_stride, high_stride,
+                         width, height * 2);
 
         input = s->plane[plane].l_h[3];
         low = s->plane[plane].l_h[4];
         high = s->plane[plane].subband[5];
 
-        for (int i = 0; i < width; i++) {
-            vert_filter(input, a_width, low, low_stride, high, high_stride, height * 2);
-            input++;
-            low++;
-            high++;
-        }
+        dsp->vert_filter(input, low, high,
+                         a_width, low_stride, high_stride,
+                         width, height * 2);
 
         a_width = s->plane[plane].band[0][0].a_width;
         width = s->plane[plane].band[0][0].width;
@@ -535,34 +526,25 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         }
 
         input = s->plane[plane].l_h[4];
-        for (int i = 0; i < height * 2; i++) {
-            horiz_filter(input, low, high, width * 2);
-            input += a_width * 2;
-            low += low_stride;
-            high += high_stride;
-        }
+        dsp->horiz_filter(input, low, high,
+                          a_width * 2, low_stride, high_stride,
+                          width * 2, height * 2);
 
         low = s->plane[plane].subband[1];
         high = s->plane[plane].subband[3];
         input = s->plane[plane].l_h[1];
 
-        for (int i = 0; i < width; i++) {
-            vert_filter(input, a_width, low, low_stride, high, high_stride, height * 2);
-            input++;
-            low++;
-            high++;
-        }
+        dsp->vert_filter(input, low, high,
+                         a_width, low_stride, high_stride,
+                         width, height * 2);
 
         low = s->plane[plane].subband[0];
         high = s->plane[plane].subband[2];
         input = s->plane[plane].l_h[0];
 
-        for (int i = 0; i < width; i++) {
-            vert_filter(input, a_width, low, low_stride, high, high_stride, height * 2);
-            input++;
-            low++;
-            high++;
-        }
+        dsp->vert_filter(input, low, high,
+                         a_width, low_stride, high_stride,
+                         width, height * 2);
     }
 
     ret = ff_alloc_packet2(avctx, pkt, 64LL + s->planes * (2LL * avctx->width * avctx->height + 1000LL), 0);
@@ -590,7 +572,7 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     bytestream2_put_be16(pby, s->planes);
 
     bytestream2_put_be16(pby, EncodedFormat);
-    bytestream2_put_be16(pby, avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 1 : 3);
+    bytestream2_put_be16(pby, avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 1 : 3 + (s->planes == 4));
 
     bytestream2_put_be16(pby, WaveletCount);
     bytestream2_put_be16(pby, 3);
@@ -611,7 +593,7 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     bytestream2_put_be16(pby, avctx->height);
 
     bytestream2_put_be16(pby, -FrameNumber);
-    bytestream2_put_be16(pby, avctx->frame_number);
+    bytestream2_put_be16(pby, frame->pts & 0xFFFF);
 
     bytestream2_put_be16(pby, Precision);
     bytestream2_put_be16(pby, avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 10 : 12);
@@ -676,7 +658,7 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
         for (int l = 0; l < 3; l++) {
             for (int i = 0; i < 3; i++) {
-                s->plane[p].quantization[1 + l * 3 + i] = quantization_per_subband[avctx->pix_fmt != AV_PIX_FMT_YUV422P10][p][s->quality][l * 3 + i];
+                s->plane[p].quantization[1 + l * 3 + i] = quantization_per_subband[avctx->pix_fmt != AV_PIX_FMT_YUV422P10][p >= 3 ? 0 : p][s->quality][l * 3 + i];
             }
         }
 
@@ -760,7 +742,7 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
                 for (int m = 0; m < height; m++) {
                     for (int j = 0; j < stride; j++) {
-                        int16_t index = FFSIGN(data[j]) * lut[FFABS(data[j])];
+                        int16_t index = j >= width ? 0 : FFSIGN(data[j]) * lut[FFABS(data[j])];
 
                         if (index < 0)
                             index += 512;
@@ -784,7 +766,7 @@ static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                 put_bits(pb, cb[512].size, cb[512].bits);
 
                 flush_put_bits(pb);
-                bytestream2_skip_p(pby, put_bits_count(pb) >> 3);
+                bytestream2_skip_p(pby, put_bytes_output(pb));
                 padd = (4 - (bytestream2_tell_p(pby) & 3)) & 3;
                 while (padd--)
                     bytestream2_put_byte(pby, 0);
@@ -831,6 +813,8 @@ static av_cold int cfhd_encode_close(AVCodecContext *avctx)
             s->plane[i].l_h[j] = NULL;
     }
 
+    av_freep(&s->alpha);
+
     return 0;
 }
 
@@ -861,9 +845,9 @@ static const AVClass cfhd_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-AVCodec ff_cfhd_encoder = {
+const AVCodec ff_cfhd_encoder = {
     .name             = "cfhd",
-    .long_name        = NULL_IF_CONFIG_SMALL("Cineform HD"),
+    .long_name        = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"),
     .type             = AVMEDIA_TYPE_VIDEO,
     .id               = AV_CODEC_ID_CFHD,
     .priv_data_size   = sizeof(CFHDEncContext),
@@ -875,6 +859,8 @@ AVCodec ff_cfhd_encoder = {
     .pix_fmts         = (const enum AVPixelFormat[]) {
                           AV_PIX_FMT_YUV422P10,
                           AV_PIX_FMT_GBRP12,
+                          AV_PIX_FMT_GBRAP12,
                           AV_PIX_FMT_NONE
                         },
+    .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP,
 };