[FFmpeg-devel] [PATCH] avcodec/huffyuv: support AV_PIX_FMT_YUV(A)4XYP16 and GRAY16

Michael Niedermayer michaelni at gmx.at
Thu Jan 23 01:42:16 CET 2014


Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
 libavcodec/huffyuv.h    |   10 +++---
 libavcodec/huffyuvdec.c |   55 ++++++++++++++++++++++++-----
 libavcodec/huffyuvenc.c |   89 ++++++++++++++++++++++++++++++++++-------------
 3 files changed, 118 insertions(+), 36 deletions(-)

diff --git a/libavcodec/huffyuv.h b/libavcodec/huffyuv.h
index 0aecad0..804c3b5 100644
--- a/libavcodec/huffyuv.h
+++ b/libavcodec/huffyuv.h
@@ -39,8 +39,9 @@
 
 #define VLC_BITS 11
 
-#define MAX_BITS 14
+#define MAX_BITS 16
 #define MAX_N (1<<MAX_BITS)
+#define MAX_VLC_N 16384
 
 #if HAVE_BIGENDIAN
 #define B 3
@@ -73,6 +74,7 @@ typedef struct HYuvContext {
     int bgr32;                              //use bgr32 instead of bgr24
     int bps;
     int n;                                  // 1<<bps
+    int vlc_n;                              // number of vlc codes (FFMIN(1<<bps, MAX_VLC_N))
     int alpha;
     int chroma;
     int yuv;
@@ -85,9 +87,9 @@ typedef struct HYuvContext {
     int last_slice_end;
     uint8_t *temp[3];
     uint16_t *temp16[3];                    ///< identical to temp but 16bit type
-    uint64_t stats[4][MAX_N];
-    uint8_t len[4][MAX_N];
-    uint32_t bits[4][MAX_N];
+    uint64_t stats[4][MAX_VLC_N];
+    uint8_t len[4][MAX_VLC_N];
+    uint32_t bits[4][MAX_VLC_N];
     uint32_t pix_bgr_map[1<<VLC_BITS];
     VLC vlc[8];                             //Y,U,V,A,YY,YU,YV,AA
     uint8_t *bitstream_buffer;
diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c
index e110124..4cc4148 100644
--- a/libavcodec/huffyuvdec.c
+++ b/libavcodec/huffyuvdec.c
@@ -120,12 +120,12 @@ static int generate_joint_tables(HYuvContext *s)
         int p, i, y, u;
         for (p = 0; p < 4; p++) {
             int p0 = s->version > 2 ? p : 0;
-            for (i = y = 0; y < s->n; y++) {
+            for (i = y = 0; y < s->vlc_n; y++) {
                 int len0 = s->len[p0][y];
                 int limit = VLC_BITS - len0;
                 if(limit <= 0 || !len0)
                     continue;
-                for (u = 0; u < s->n; u++) {
+                for (u = 0; u < s->vlc_n; u++) {
                     int len1 = s->len[p][u];
                     if (len1 > limit || !len1)
                         continue;
@@ -201,13 +201,13 @@ static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length)
         count = 1 + s->alpha + 2*s->chroma;
 
     for (i = 0; i < count; i++) {
-        if (read_len_table(s->len[i], &gb, s->n) < 0)
+        if (read_len_table(s->len[i], &gb, s->vlc_n) < 0)
             return -1;
-        if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->n) < 0) {
+        if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->vlc_n) < 0) {
             return -1;
         }
         ff_free_vlc(&s->vlc[i]);
-        if ((ret = init_vlc(&s->vlc[i], VLC_BITS, s->n, s->len[i], 1, 1,
+        if ((ret = init_vlc(&s->vlc[i], VLC_BITS, s->vlc_n, s->len[i], 1, 1,
                            s->bits[i], 4, 4, 0)) < 0)
             return ret;
     }
@@ -261,7 +261,6 @@ static av_cold int decode_init(AVCodecContext *avctx)
 {
     HYuvContext *s = avctx->priv_data;
 
-    ff_huffyuv_common_init(avctx);
     memset(s->vlc, 0, 4 * sizeof(VLC));
 
     s->interlaced = s->height > 288;
@@ -281,6 +280,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     s->bps = 8;
     s->n = 1<<s->bps;
+    s->vlc_n = FFMIN(s->n, MAX_VLC_N);
     s->chroma = 1;
     if (s->version >= 2) {
         int method, interlace;
@@ -298,6 +298,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
         } else {
             s->bps = (avctx->extradata[1] >> 4) + 1;
             s->n = 1<<s->bps;
+            s->vlc_n = FFMIN(s->n, MAX_VLC_N);
             s->chroma_h_shift = avctx->extradata[1] & 3;
             s->chroma_v_shift = (avctx->extradata[1] >> 2) & 3;
             s->yuv   = !!(((uint8_t*)avctx->extradata)[2] & 1);
@@ -375,6 +376,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
         case 0x070:
             avctx->pix_fmt = AV_PIX_FMT_GRAY8;
             break;
+        case 0x0F0:
+            avctx->pix_fmt = AV_PIX_FMT_GRAY16;
+            break;
         case 0x170:
             avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
             break;
@@ -399,6 +403,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
         case 0x6D0:
             avctx->pix_fmt = AV_PIX_FMT_YUV444P14;
             break;
+        case 0x6F0:
+            avctx->pix_fmt = AV_PIX_FMT_YUV444P16;
+            break;
         case 0x671:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P;
             break;
@@ -414,6 +421,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
         case 0x6D1:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P14;
             break;
+        case 0x6F1:
+            avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
+            break;
         case 0x672:
             avctx->pix_fmt = AV_PIX_FMT_YUV411P;
             break;
@@ -435,6 +445,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
         case 0x6D5:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P14;
             break;
+        case 0x6F5:
+            avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
+            break;
         case 0x67A:
             avctx->pix_fmt = AV_PIX_FMT_YUV410P;
             break;
@@ -447,6 +460,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
         case 0x790:
             avctx->pix_fmt = AV_PIX_FMT_YUVA444P10;
             break;
+        case 0x7F0:
+            avctx->pix_fmt = AV_PIX_FMT_YUVA444P16;
+            break;
         case 0x771:
             avctx->pix_fmt = AV_PIX_FMT_YUVA422P;
             break;
@@ -456,6 +472,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
         case 0x791:
             avctx->pix_fmt = AV_PIX_FMT_YUVA422P10;
             break;
+        case 0x7F1:
+            avctx->pix_fmt = AV_PIX_FMT_YUVA422P16;
+            break;
         case 0x775:
             avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
             break;
@@ -465,11 +484,14 @@ static av_cold int decode_init(AVCodecContext *avctx)
         case 0x795:
             avctx->pix_fmt = AV_PIX_FMT_YUVA420P10;
             break;
+        case 0x7F5:
+            avctx->pix_fmt = AV_PIX_FMT_YUVA420P16;
+            break;
         default:
             return AVERROR_INVALIDDATA;
         }
     }
-
+    ff_huffyuv_common_init(avctx);
 
     if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P || avctx->pix_fmt == AV_PIX_FMT_YUV420P) && avctx->width & 1) {
         av_log(avctx, AV_LOG_ERROR, "width must be even for this colorspace\n");
@@ -557,10 +579,17 @@ static void decode_422_bitstream(HYuvContext *s, int count)
         dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
     }\
 }
-#define READ_2PIX_PLANE16(dst0, dst1, plane){\
+#define READ_2PIX_PLANE14(dst0, dst1, plane){\
     dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
     dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
 }
+
+#define READ_2PIX_PLANE16(dst0, dst1, plane){\
+    dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\
+    dst0 += get_bits(&s->gb, 2);\
+    dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\
+    dst1 += get_bits(&s->gb, 2);\
+}
 static void decode_plane_bitstream(HYuvContext *s, int count, int plane)
 {
     int i;
@@ -577,6 +606,16 @@ static void decode_plane_bitstream(HYuvContext *s, int count, int plane)
                 READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane);
             }
         }
+    } else if (s->bps <= 14) {
+        if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
+            for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
+                READ_2PIX_PLANE14(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
+            }
+        } else {
+            for(i=0; i<count; i++){
+                READ_2PIX_PLANE14(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
+            }
+        }
     } else {
         if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
             for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c
index 7c19a08..d01ca9c 100644
--- a/libavcodec/huffyuvenc.c
+++ b/libavcodec/huffyuvenc.c
@@ -164,7 +164,7 @@ static int store_table(HYuvContext *s, const uint8_t *len, uint8_t *buf)
 {
     int i;
     int index = 0;
-    int n = s->n;
+    int n = s->vlc_n;
 
     for (i = 0; i < n;) {
         int val = len[i];
@@ -195,10 +195,10 @@ static int store_huffman_tables(HYuvContext *s, uint8_t *buf)
         count = 1 + s->alpha + 2*s->chroma;
 
     for (i = 0; i < count; i++) {
-        if ((ret = ff_huff_gen_len_table(s->len[i], s->stats[i], s->n)) < 0)
+        if ((ret = ff_huff_gen_len_table(s->len[i], s->stats[i], s->vlc_n)) < 0)
             return ret;
 
-        if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->n) < 0) {
+        if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->vlc_n) < 0) {
             return -1;
         }
 
@@ -254,6 +254,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV440P:
     case AV_PIX_FMT_GBRP:
     case AV_PIX_FMT_GRAY8:
+    case AV_PIX_FMT_GRAY16:
     case AV_PIX_FMT_YUVA444P:
     case AV_PIX_FMT_YUVA420P:
     case AV_PIX_FMT_YUVA422P:
@@ -263,20 +264,26 @@ static av_cold int encode_init(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV420P10:
     case AV_PIX_FMT_YUV420P12:
     case AV_PIX_FMT_YUV420P14:
+    case AV_PIX_FMT_YUV420P16:
     case AV_PIX_FMT_YUV422P9:
     case AV_PIX_FMT_YUV422P10:
     case AV_PIX_FMT_YUV422P12:
     case AV_PIX_FMT_YUV422P14:
+    case AV_PIX_FMT_YUV422P16:
     case AV_PIX_FMT_YUV444P9:
     case AV_PIX_FMT_YUV444P10:
     case AV_PIX_FMT_YUV444P12:
     case AV_PIX_FMT_YUV444P14:
+    case AV_PIX_FMT_YUV444P16:
     case AV_PIX_FMT_YUVA420P9:
     case AV_PIX_FMT_YUVA420P10:
+    case AV_PIX_FMT_YUVA420P16:
     case AV_PIX_FMT_YUVA422P9:
     case AV_PIX_FMT_YUVA422P10:
+    case AV_PIX_FMT_YUVA422P16:
     case AV_PIX_FMT_YUVA444P9:
     case AV_PIX_FMT_YUVA444P10:
+    case AV_PIX_FMT_YUVA444P16:
         s->version = 3;
         break;
     case AV_PIX_FMT_RGB32:
@@ -290,6 +297,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
         return AVERROR(EINVAL);
     }
     s->n = 1<<s->bps;
+    s->vlc_n = FFMIN(s->n, MAX_VLC_N);
 
     avctx->bits_per_coded_sample = s->bitstream_bpp;
     s->decorrelate = s->bitstream_bpp >= 24 && !s->yuv && avctx->pix_fmt != AV_PIX_FMT_GBRP;
@@ -362,14 +370,14 @@ static av_cold int encode_init(AVCodecContext *avctx)
         char *p = avctx->stats_in;
 
         for (i = 0; i < 4; i++)
-            for (j = 0; j < s->n; j++)
+            for (j = 0; j < s->vlc_n; j++)
                 s->stats[i][j] = 1;
 
         for (;;) {
             for (i = 0; i < 4; i++) {
                 char *next;
 
-                for (j = 0; j < s->n; j++) {
+                for (j = 0; j < s->vlc_n; j++) {
                     s->stats[i][j] += strtol(p, &next, 0);
                     if (next == p) return -1;
                     p = next;
@@ -379,8 +387,8 @@ static av_cold int encode_init(AVCodecContext *avctx)
         }
     } else {
         for (i = 0; i < 4; i++)
-            for (j = 0; j < s->n; j++) {
-                int d = FFMIN(j, s->n - j);
+            for (j = 0; j < s->vlc_n; j++) {
+                int d = FFMIN(j, s->vlc_n - j);
 
                 s->stats[i][j] = 100000000 / (d + 1);
             }
@@ -394,14 +402,14 @@ static av_cold int encode_init(AVCodecContext *avctx)
     if (s->context) {
         for (i = 0; i < 4; i++) {
             int pels = s->width * s->height / (i ? 40 : 10);
-            for (j = 0; j < s->n; j++) {
-                int d = FFMIN(j, s->n - j);
+            for (j = 0; j < s->vlc_n; j++) {
+                int d = FFMIN(j, s->vlc_n - j);
                 s->stats[i][j] = pels/(d + 1);
             }
         }
     } else {
         for (i = 0; i < 4; i++)
-            for (j = 0; j < s->n; j++)
+            for (j = 0; j < s->vlc_n; j++)
                 s->stats[i][j]= 0;
     }
 
@@ -481,15 +489,26 @@ static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
 #define LOAD2\
             int y0 = s->temp[0][2 * i];\
             int y1 = s->temp[0][2 * i + 1];
-#define LOAD2_16\
+#define LOAD2_14\
             int y0 = s->temp16[0][2 * i] & mask;\
             int y1 = s->temp16[0][2 * i + 1] & mask;
+#define LOAD2_16\
+            int y0 = s->temp16[0][2 * i];\
+            int y1 = s->temp16[0][2 * i + 1];
 #define STAT2\
             s->stats[plane][y0]++;\
             s->stats[plane][y1]++;
+#define STAT2_16\
+            s->stats[plane][y0>>2]++;\
+            s->stats[plane][y1>>2]++;
 #define WRITE2\
             put_bits(&s->pb, s->len[plane][y0], s->bits[plane][y0]);\
             put_bits(&s->pb, s->len[plane][y1], s->bits[plane][y1]);
+#define WRITE2_16\
+            put_bits(&s->pb, s->len[plane][y0>>2], s->bits[plane][y0>>2]);\
+            put_bits(&s->pb, 2, y0&3);\
+            put_bits(&s->pb, s->len[plane][y1>>2], s->bits[plane][y1>>2]);\
+            put_bits(&s->pb, 2, y1&3);
 
     count /= 2;
 
@@ -515,11 +534,11 @@ static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
             WRITE2;
         }
     }
-    } else {
+    } else if (s->bps <= 14) {
         int mask = s->n - 1;
         if (s->flags & CODEC_FLAG_PASS1) {
             for (i = 0; i < count; i++) {
-                LOAD2_16;
+                LOAD2_14;
                 STAT2;
             }
         }
@@ -528,16 +547,38 @@ static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
 
         if (s->context) {
             for (i = 0; i < count; i++) {
-                LOAD2_16;
+                LOAD2_14;
                 STAT2;
                 WRITE2;
             }
         } else {
             for (i = 0; i < count; i++) {
-                LOAD2_16;
+                LOAD2_14;
                 WRITE2;
             }
         }
+    } else {
+        if (s->flags & CODEC_FLAG_PASS1) {
+            for (i = 0; i < count; i++) {
+                LOAD2_16;
+                STAT2_16;
+            }
+        }
+        if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)
+            return 0;
+
+        if (s->context) {
+            for (i = 0; i < count; i++) {
+                LOAD2_16;
+                STAT2_16;
+                WRITE2_16;
+            }
+        } else {
+            for (i = 0; i < count; i++) {
+                LOAD2_16;
+                WRITE2_16;
+            }
+        }
     }
 #undef LOAD2
 #undef STAT2
@@ -663,7 +704,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
             return size;
 
         for (i = 0; i < 4; i++)
-            for (j = 0; j < s->n; j++)
+            for (j = 0; j < s->vlc_n; j++)
                 s->stats[i][j] >>= 1;
     }
 
@@ -899,7 +940,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         char *p = avctx->stats_out;
         char *end = p + 1024*30;
         for (i = 0; i < 4; i++) {
-            for (j = 0; j < s->n; j++) {
+            for (j = 0; j < s->vlc_n; j++) {
                 snprintf(p, end-p, "%"PRIu64" ", s->stats[i][j]);
                 p += strlen(p);
                 s->stats[i][j]= 0;
@@ -968,16 +1009,16 @@ AVCodec ff_ffvhuff_encoder = {
         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV411P,
         AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P,
         AV_PIX_FMT_GBRP,
-        AV_PIX_FMT_GRAY8,
+        AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16,
         AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
         AV_PIX_FMT_GBRAP,
         AV_PIX_FMT_GRAY8A,
-        AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV420P14,
-        AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV422P14,
-        AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14,
-        AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10,
-        AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10,
-        AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10,
+        AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV420P16,
+        AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV422P16,
+        AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16,
+        AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16,
+        AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P16,
+        AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P16,
         AV_PIX_FMT_RGB24,
         AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE
     },
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list