libavcodec/huffyuvdec.c
2ca5ca29
 /*
  * huffyuv decoder
  *
7cf8918b
  * Copyright (c) 2002-2014 Michael Niedermayer <michaelni@gmx.at>
2ca5ca29
  *
  * see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of
  * the algorithm used
  *
def18e54
  * This file is part of FFmpeg.
2ca5ca29
  *
def18e54
  * FFmpeg is free software; you can redistribute it and/or
2ca5ca29
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
def18e54
  * FFmpeg is distributed in the hope that it will be useful,
2ca5ca29
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
def18e54
  * License along with FFmpeg; if not, write to the Free Software
2ca5ca29
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
b53aab1a
  *
  * yuva, gray, 4:4:4, 4:1:1, 4:1:0 and >8 bit per sample support sponsored by NOA
2ca5ca29
  */
 
 /**
  * @file
  * huffyuv decoder
  */
 
f6577bd9
 #define UNCHECKED_BITSTREAM_READER 1
 
2ca5ca29
 #include "avcodec.h"
 #include "get_bits.h"
 #include "huffyuv.h"
0d439fbe
 #include "huffyuvdsp.h"
2ca5ca29
 #include "thread.h"
9a345802
 #include "libavutil/imgutils.h"
27b1e63f
 #include "libavutil/pixdesc.h"
2ca5ca29
 
 #define classic_shift_luma_table_size 42
059a9348
 static const unsigned char classic_shift_luma[classic_shift_luma_table_size + AV_INPUT_BUFFER_PADDING_SIZE] = {
c065f4a0
     34, 36, 35, 69, 135, 232,   9, 16, 10, 24,  11,  23,  12,  16, 13, 10,
     14,  8, 15,  8,  16,   8,  17, 20, 16, 10, 207, 206, 205, 236, 11,  8,
c1e7fb60
     10, 21,  9, 23,   8,   8, 199, 70, 69, 68,   0,
def18e54
   0,0,0,0,0,0,0,0,
2ca5ca29
 };
 
 #define classic_shift_chroma_table_size 59
059a9348
 static const unsigned char classic_shift_chroma[classic_shift_chroma_table_size + AV_INPUT_BUFFER_PADDING_SIZE] = {
c065f4a0
     66, 36,  37,  38, 39, 40,  41,  75,  76,  77, 110, 239, 144, 81, 82,  83,
     84, 85, 118, 183, 56, 57,  88,  89,  56,  89, 154,  57,  58, 57, 26, 141,
     57, 56,  58,  57, 58, 57, 184, 119, 214, 245, 116,  83,  82, 49, 80,  79,
c1e7fb60
     78, 77,  44,  75, 41, 40,  39,  38,  37,  36,  34,  0,
def18e54
   0,0,0,0,0,0,0,0,
2ca5ca29
 };
 
 static const unsigned char classic_add_luma[256] = {
c065f4a0
      3,  9,  5, 12, 10, 35, 32, 29, 27, 50, 48, 45, 44, 41, 39, 37,
     73, 70, 68, 65, 64, 61, 58, 56, 53, 50, 49, 46, 44, 41, 38, 36,
     68, 65, 63, 61, 58, 55, 53, 51, 48, 46, 45, 43, 41, 39, 38, 36,
     35, 33, 32, 30, 29, 27, 26, 25, 48, 47, 46, 44, 43, 41, 40, 39,
     37, 36, 35, 34, 32, 31, 30, 28, 27, 26, 24, 23, 22, 20, 19, 37,
     35, 34, 33, 31, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 29,
     27, 26, 24, 22, 21, 19, 17, 16, 14, 26, 25, 23, 21, 19, 18, 16,
     15, 27, 25, 23, 21, 19, 17, 16, 14, 26, 25, 23, 21, 18, 17, 14,
     12, 17, 19, 13,  4,  9,  2, 11,  1,  7,  8,  0, 16,  3, 14,  6,
     12, 10,  5, 15, 18, 11, 10, 13, 15, 16, 19, 20, 22, 24, 27, 15,
     18, 20, 22, 24, 26, 14, 17, 20, 22, 24, 27, 15, 18, 20, 23, 25,
     28, 16, 19, 22, 25, 28, 32, 36, 21, 25, 29, 33, 38, 42, 45, 49,
     28, 31, 34, 37, 40, 42, 44, 47, 49, 50, 52, 54, 56, 57, 59, 60,
     62, 64, 66, 67, 69, 35, 37, 39, 40, 42, 43, 45, 47, 48, 51, 52,
     54, 55, 57, 59, 60, 62, 63, 66, 67, 69, 71, 72, 38, 40, 42, 43,
     46, 47, 49, 51, 26, 28, 30, 31, 33, 34, 18, 19, 11, 13,  7,  8,
2ca5ca29
 };
 
 static const unsigned char classic_add_chroma[256] = {
c065f4a0
      3,    1,   2,   2,   2,   2,   3,   3,   7,   5,   7,   5,   8,   6,  11,   9,
      7,   13,  11,  10,   9,   8,   7,   5,   9,   7,   6,   4,   7,   5,   8,   7,
      11,   8,  13,  11,  19,  15,  22,  23,  20,  33,  32,  28,  27,  29,  51,  77,
      43,  45,  76,  81,  46,  82,  75,  55,  56, 144,  58,  80,  60,  74, 147,  63,
     143,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
      80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  27,  30,  21,  22,
      17,  14,   5,   6, 100,  54,  47,  50,  51,  53, 106, 107, 108, 109, 110, 111,
     112, 113, 114, 115,   4, 117, 118,  92,  94, 121, 122,   3, 124, 103,   2,   1,
       0, 129, 130, 131, 120, 119, 126, 125, 136, 137, 138, 139, 140, 141, 142, 134,
     135, 132, 133, 104,  64, 101,  62,  57, 102,  95,  93,  59,  61,  28,  97,  96,
      52,  49,  48,  29,  32,  25,  24,  46,  23,  98,  45,  44,  43,  20,  42,  41,
      19,  18,  99,  40,  15,  39,  38,  16,  13,  12,  11,  37,  10,   9,   8,  36,
       7, 128, 127, 105, 123, 116,  35,  34,  33, 145,  31,  79,  42, 146,  78,  26,
      83,  48,  49,  50,  44,  47,  26,  31,  30,  18,  17,  19,  21,  24,  25,  13,
      14,  16,  17,  18,  20,  21,  12,  14,  15,   9,  10,   6,   9,   6,   5,   8,
       6,  12,   8,  10,   7,   9,   6,   4,   6,   2,   2,   3,   3,   3,   3,   2,
2ca5ca29
 };
 
b53aab1a
 static int read_len_table(uint8_t *dst, GetBitContext *gb, int n)
2ca5ca29
 {
     int i, val, repeat;
 
b53aab1a
     for (i = 0; i < n;) {
2ca5ca29
         repeat = get_bits(gb, 3);
         val    = get_bits(gb, 5);
         if (repeat == 0)
             repeat = get_bits(gb, 8);
b53aab1a
         if (i + repeat > n || get_bits_left(gb) < 0) {
2ca5ca29
             av_log(NULL, AV_LOG_ERROR, "Error reading huffman table\n");
62340581
             return AVERROR_INVALIDDATA;
2ca5ca29
         }
         while (repeat--)
             dst[i++] = val;
     }
     return 0;
 }
 
4420b414
 static int generate_joint_tables(HYuvContext *s)
2ca5ca29
 {
4420b414
     int ret;
3dbf5690
     uint16_t *symbols = av_mallocz(5 << VLC_BITS);
     uint16_t *bits;
     uint8_t *len;
     if (!symbols)
         return AVERROR(ENOMEM);
     bits = symbols + (1 << VLC_BITS);
     len = (uint8_t *)(bits + (1 << VLC_BITS));
4420b414
 
4816d63f
     if (s->bitstream_bpp < 24 || s->version > 2) {
2ca5ca29
         int p, i, y, u;
13f3092b
         for (p = 0; p < 4; p++) {
4816d63f
             int p0 = s->version > 2 ? p : 0;
53167ecf
             for (i = y = 0; y < s->vlc_n; y++) {
c1e7fb60
                 int len0  = s->len[p0][y];
2ca5ca29
                 int limit = VLC_BITS - len0;
c1e7fb60
                 if (limit <= 0 || !len0)
2ca5ca29
                     continue;
c1e7fb60
                 if ((sign_extend(y, 8) & (s->vlc_n-1)) != y)
e6c0da70
                     continue;
53167ecf
                 for (u = 0; u < s->vlc_n; u++) {
2ca5ca29
                     int len1 = s->len[p][u];
0dfc01c2
                     if (len1 > limit || !len1)
2ca5ca29
                         continue;
c1e7fb60
                     if ((sign_extend(u, 8) & (s->vlc_n-1)) != u)
e6c0da70
                         continue;
f67a0d11
                     av_assert0(i < (1 << VLC_BITS));
c065f4a0
                     len[i]     = len0 + len1;
c1e7fb60
                     bits[i]    = (s->bits[p0][y] << len1) + s->bits[p][u];
e6c0da70
                     symbols[i] = (y << 8) + (u & 0xFF);
2ca5ca29
                         i++;
                 }
             }
13f3092b
             ff_free_vlc(&s->vlc[4 + p]);
             if ((ret = ff_init_vlc_sparse(&s->vlc[4 + p], VLC_BITS, i, len, 1, 1,
4420b414
                                           bits, 2, 2, symbols, 2, 2, 0)) < 0)
3dbf5690
                 goto out;
2ca5ca29
         }
     } else {
c065f4a0
         uint8_t (*map)[4] = (uint8_t(*)[4]) s->pix_bgr_map;
2ca5ca29
         int i, b, g, r, code;
         int p0 = s->decorrelate;
         int p1 = !s->decorrelate;
c065f4a0
         /* Restrict the range to +/-16 because that's pretty much guaranteed
          * to cover all the combinations that fit in 11 bits total, and it
          *  does not matter if we miss a few rare codes. */
2ca5ca29
         for (i = 0, g = -16; g < 16; g++) {
c065f4a0
             int len0   = s->len[p0][g & 255];
2ca5ca29
             int limit0 = VLC_BITS - len0;
0dfc01c2
             if (limit0 < 2 || !len0)
2ca5ca29
                 continue;
             for (b = -16; b < 16; b++) {
c065f4a0
                 int len1   = s->len[p1][b & 255];
2ca5ca29
                 int limit1 = limit0 - len1;
0dfc01c2
                 if (limit1 < 1 || !len1)
2ca5ca29
                     continue;
                 code = (s->bits[p0][g & 255] << len1) + s->bits[p1][b & 255];
                 for (r = -16; r < 16; r++) {
                     int len2 = s->len[2][r & 255];
0dfc01c2
                     if (len2 > limit1 || !len2)
2ca5ca29
                         continue;
f67a0d11
                     av_assert0(i < (1 << VLC_BITS));
c065f4a0
                     len[i]  = len0 + len1 + len2;
2ca5ca29
                     bits[i] = (code << len2) + s->bits[2][r & 255];
                     if (s->decorrelate) {
                         map[i][G] = g;
                         map[i][B] = g + b;
                         map[i][R] = g + r;
                     } else {
                         map[i][B] = g;
                         map[i][G] = b;
                         map[i][R] = r;
                     }
                     i++;
                 }
             }
         }
13f3092b
         ff_free_vlc(&s->vlc[4]);
2793b218
         if ((ret = init_vlc(&s->vlc[4], VLC_BITS, i, len, 1, 1,
d0393d79
                             bits, 2, 2, 0)) < 0)
3dbf5690
             goto out;
2ca5ca29
     }
3dbf5690
     ret = 0;
 out:
     av_freep(&symbols);
     return ret;
2ca5ca29
 }
 
 static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length)
 {
     GetBitContext gb;
d0393d79
     int i, ret;
13f3092b
     int count = 3;
2ca5ca29
 
d0393d79
     if ((ret = init_get_bits(&gb, src, length * 8)) < 0)
         return ret;
2ca5ca29
 
13f3092b
     if (s->version > 2)
         count = 1 + s->alpha + 2*s->chroma;
 
     for (i = 0; i < count; i++) {
2793b218
         if ((ret = read_len_table(s->len[i], &gb, s->vlc_n)) < 0)
d0393d79
             return ret;
2793b218
         if ((ret = ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->vlc_n)) < 0)
d0393d79
             return ret;
2ca5ca29
         ff_free_vlc(&s->vlc[i]);
53167ecf
         if ((ret = init_vlc(&s->vlc[i], VLC_BITS, s->vlc_n, s->len[i], 1, 1,
f67a0d11
                            s->bits[i], 4, 4, 0)) < 0)
             return ret;
2ca5ca29
     }
 
4420b414
     if ((ret = generate_joint_tables(s)) < 0)
         return ret;
2ca5ca29
 
     return (get_bits_count(&gb) + 7) / 8;
 }
 
 static int read_old_huffman_tables(HYuvContext *s)
 {
     GetBitContext gb;
d0393d79
     int i, ret;
2ca5ca29
 
     init_get_bits(&gb, classic_shift_luma,
                   classic_shift_luma_table_size * 8);
2793b218
     if ((ret = read_len_table(s->len[0], &gb, 256)) < 0)
d0393d79
         return ret;
2ca5ca29
 
     init_get_bits(&gb, classic_shift_chroma,
                   classic_shift_chroma_table_size * 8);
2793b218
     if ((ret = read_len_table(s->len[1], &gb, 256)) < 0)
d0393d79
         return ret;
2ca5ca29
 
c065f4a0
     for (i = 0; i < 256; i++)
         s->bits[0][i] = classic_add_luma[i];
     for (i = 0; i < 256; i++)
         s->bits[1][i] = classic_add_chroma[i];
2ca5ca29
 
     if (s->bitstream_bpp >= 24) {
         memcpy(s->bits[1], s->bits[0], 256 * sizeof(uint32_t));
c065f4a0
         memcpy(s->len[1], s->len[0], 256 * sizeof(uint8_t));
2ca5ca29
     }
     memcpy(s->bits[2], s->bits[1], 256 * sizeof(uint32_t));
c065f4a0
     memcpy(s->len[2], s->len[1], 256 * sizeof(uint8_t));
2ca5ca29
 
13f3092b
     for (i = 0; i < 4; i++) {
2ca5ca29
         ff_free_vlc(&s->vlc[i]);
f67a0d11
         if ((ret = init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1,
                             s->bits[i], 4, 4, 0)) < 0)
             return ret;
2ca5ca29
     }
 
4420b414
     if ((ret = generate_joint_tables(s)) < 0)
         return ret;
2ca5ca29
 
     return 0;
 }
 
c9d39fc8
 static av_cold int decode_end(AVCodecContext *avctx)
 {
     HYuvContext *s = avctx->priv_data;
     int i;
 
     ff_huffyuv_common_end(s);
     av_freep(&s->bitstream_buffer);
 
     for (i = 0; i < 8; i++)
         ff_free_vlc(&s->vlc[i]);
 
     return 0;
 }
 
2ca5ca29
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     HYuvContext *s = avctx->priv_data;
d0393d79
     int ret;
2ca5ca29
 
9a345802
     ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
     if (ret < 0)
         return ret;
 
0d439fbe
     ff_huffyuvdsp_init(&s->hdsp);
13f3092b
     memset(s->vlc, 0, 4 * sizeof(VLC));
2ca5ca29
 
469de4f5
     s->interlaced = avctx->height > 288;
c065f4a0
     s->bgr32      = 1;
2ca5ca29
 
     if (avctx->extradata_size) {
         if ((avctx->bits_per_coded_sample & 7) &&
             avctx->bits_per_coded_sample != 12)
             s->version = 1; // do such files exist at all?
27b1e63f
         else if (avctx->extradata_size > 3 && avctx->extradata[3] == 0)
2ca5ca29
             s->version = 2;
27b1e63f
         else
             s->version = 3;
2ca5ca29
     } else
         s->version = 0;
 
27b1e63f
     s->bps = 8;
534a8947
     s->n = 1<<s->bps;
53167ecf
     s->vlc_n = FFMIN(s->n, MAX_VLC_N);
27b1e63f
     s->chroma = 1;
     if (s->version >= 2) {
2ca5ca29
         int method, interlace;
 
         if (avctx->extradata_size < 4)
62340581
             return AVERROR_INVALIDDATA;
2ca5ca29
 
b7616f57
         method           = avctx->extradata[0];
c065f4a0
         s->decorrelate   = method & 64 ? 1 : 0;
         s->predictor     = method & 63;
27b1e63f
         if (s->version == 2) {
e9cd8f4d
             s->bitstream_bpp = avctx->extradata[1];
27b1e63f
             if (s->bitstream_bpp == 0)
                 s->bitstream_bpp = avctx->bits_per_coded_sample & ~7;
         } else {
             s->bps = (avctx->extradata[1] >> 4) + 1;
534a8947
             s->n = 1<<s->bps;
53167ecf
             s->vlc_n = FFMIN(s->n, MAX_VLC_N);
27b1e63f
             s->chroma_h_shift = avctx->extradata[1] & 3;
             s->chroma_v_shift = (avctx->extradata[1] >> 2) & 3;
e9cd8f4d
             s->yuv   = !!(avctx->extradata[2] & 1);
             s->chroma= !!(avctx->extradata[2] & 3);
             s->alpha = !!(avctx->extradata[2] & 4);
27b1e63f
         }
b7616f57
         interlace     = (avctx->extradata[2] & 0x30) >> 4;
2ca5ca29
         s->interlaced = (interlace == 1) ? 1 : (interlace == 2) ? 0 : s->interlaced;
b7616f57
         s->context    = avctx->extradata[2] & 0x40 ? 1 : 0;
2ca5ca29
 
d0393d79
         if ((ret = read_huffman_tables(s, avctx->extradata + 4,
                                        avctx->extradata_size - 4)) < 0)
c9d39fc8
             goto error;
c065f4a0
     } else {
2ca5ca29
         switch (avctx->bits_per_coded_sample & 7) {
         case 1:
c065f4a0
             s->predictor   = LEFT;
2ca5ca29
             s->decorrelate = 0;
             break;
         case 2:
c065f4a0
             s->predictor   = LEFT;
2ca5ca29
             s->decorrelate = 1;
             break;
         case 3:
c065f4a0
             s->predictor   = PLANE;
2ca5ca29
             s->decorrelate = avctx->bits_per_coded_sample >= 24;
             break;
         case 4:
c065f4a0
             s->predictor   = MEDIAN;
2ca5ca29
             s->decorrelate = 0;
             break;
         default:
c065f4a0
             s->predictor   = LEFT; // OLD
2ca5ca29
             s->decorrelate = 0;
             break;
         }
         s->bitstream_bpp = avctx->bits_per_coded_sample & ~7;
c065f4a0
         s->context       = 0;
2ca5ca29
 
d0393d79
         if ((ret = read_old_huffman_tables(s)) < 0)
c9d39fc8
             goto error;
2ca5ca29
     }
 
27b1e63f
     if (s->version <= 2) {
         switch (s->bitstream_bpp) {
         case 12:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P;
             s->yuv = 1;
             break;
         case 16:
c1e7fb60
             if (s->yuy2)
27b1e63f
                 avctx->pix_fmt = AV_PIX_FMT_YUYV422;
c1e7fb60
             else
27b1e63f
                 avctx->pix_fmt = AV_PIX_FMT_YUV422P;
             s->yuv = 1;
             break;
         case 24:
c1e7fb60
             if (s->bgr32)
9bb1af8f
                 avctx->pix_fmt = AV_PIX_FMT_0RGB32;
c1e7fb60
             else
27b1e63f
                 avctx->pix_fmt = AV_PIX_FMT_BGR24;
             break;
9bb1af8f
         case 32:
             av_assert0(s->bgr32);
             avctx->pix_fmt = AV_PIX_FMT_RGB32;
             s->alpha = 1;
             break;
27b1e63f
         default:
c9d39fc8
             ret = AVERROR_INVALIDDATA;
             goto error;
2ca5ca29
         }
27b1e63f
         av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt,
                                          &s->chroma_h_shift,
                                          &s->chroma_v_shift);
     } else {
         switch ( (s->chroma<<10) | (s->yuv<<9) | (s->alpha<<8) | ((s->bps-1)<<4) | s->chroma_h_shift | (s->chroma_v_shift<<2)) {
60ab582a
         case 0x070:
             avctx->pix_fmt = AV_PIX_FMT_GRAY8;
             break;
53167ecf
         case 0x0F0:
             avctx->pix_fmt = AV_PIX_FMT_GRAY16;
             break;
13f3092b
         case 0x170:
             avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
             break;
22f59a8c
         case 0x470:
             avctx->pix_fmt = AV_PIX_FMT_GBRP;
             break;
6369766f
         case 0x480:
             avctx->pix_fmt = AV_PIX_FMT_GBRP9;
             break;
         case 0x490:
             avctx->pix_fmt = AV_PIX_FMT_GBRP10;
             break;
         case 0x4B0:
             avctx->pix_fmt = AV_PIX_FMT_GBRP12;
             break;
         case 0x4D0:
             avctx->pix_fmt = AV_PIX_FMT_GBRP14;
             break;
         case 0x4F0:
             avctx->pix_fmt = AV_PIX_FMT_GBRP16;
             break;
13f3092b
         case 0x570:
             avctx->pix_fmt = AV_PIX_FMT_GBRAP;
             break;
27b1e63f
         case 0x670:
             avctx->pix_fmt = AV_PIX_FMT_YUV444P;
             break;
ef028212
         case 0x680:
             avctx->pix_fmt = AV_PIX_FMT_YUV444P9;
             break;
         case 0x690:
             avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
             break;
         case 0x6B0:
             avctx->pix_fmt = AV_PIX_FMT_YUV444P12;
             break;
         case 0x6D0:
             avctx->pix_fmt = AV_PIX_FMT_YUV444P14;
             break;
53167ecf
         case 0x6F0:
             avctx->pix_fmt = AV_PIX_FMT_YUV444P16;
             break;
27b1e63f
         case 0x671:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P;
             break;
ef028212
         case 0x681:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P9;
             break;
         case 0x691:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
             break;
         case 0x6B1:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P12;
             break;
         case 0x6D1:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P14;
             break;
53167ecf
         case 0x6F1:
             avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
             break;
27b1e63f
         case 0x672:
             avctx->pix_fmt = AV_PIX_FMT_YUV411P;
             break;
         case 0x674:
             avctx->pix_fmt = AV_PIX_FMT_YUV440P;
             break;
         case 0x675:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P;
             break;
ef028212
         case 0x685:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P9;
             break;
b53aab1a
         case 0x695:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
             break;
ef028212
         case 0x6B5:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P12;
             break;
         case 0x6D5:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P14;
             break;
53167ecf
         case 0x6F5:
             avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
             break;
27b1e63f
         case 0x67A:
             avctx->pix_fmt = AV_PIX_FMT_YUV410P;
             break;
13f3092b
         case 0x770:
             avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
             break;
3d879279
         case 0x780:
             avctx->pix_fmt = AV_PIX_FMT_YUVA444P9;
             break;
         case 0x790:
             avctx->pix_fmt = AV_PIX_FMT_YUVA444P10;
             break;
53167ecf
         case 0x7F0:
             avctx->pix_fmt = AV_PIX_FMT_YUVA444P16;
             break;
13f3092b
         case 0x771:
             avctx->pix_fmt = AV_PIX_FMT_YUVA422P;
             break;
3d879279
         case 0x781:
             avctx->pix_fmt = AV_PIX_FMT_YUVA422P9;
             break;
         case 0x791:
             avctx->pix_fmt = AV_PIX_FMT_YUVA422P10;
             break;
53167ecf
         case 0x7F1:
             avctx->pix_fmt = AV_PIX_FMT_YUVA422P16;
             break;
13f3092b
         case 0x775:
             avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
             break;
3d879279
         case 0x785:
             avctx->pix_fmt = AV_PIX_FMT_YUVA420P9;
             break;
b53aab1a
         case 0x795:
             avctx->pix_fmt = AV_PIX_FMT_YUVA420P10;
             break;
53167ecf
         case 0x7F5:
             avctx->pix_fmt = AV_PIX_FMT_YUVA420P16;
             break;
b53aab1a
         default:
c9d39fc8
             ret = AVERROR_INVALIDDATA;
             goto error;
2ca5ca29
         }
     }
 
e6d1c66d
     ff_huffyuv_common_init(avctx);
27b1e63f
 
def18e54
     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");
c9d39fc8
         ret = AVERROR_INVALIDDATA;
         goto error;
def18e54
     }
a7153444
     if (s->predictor == MEDIAN && avctx->pix_fmt == AV_PIX_FMT_YUV422P &&
         avctx->width % 4) {
296b01d7
         av_log(avctx, AV_LOG_ERROR, "width must be a multiple of 4 "
a7153444
                "for this combination of colorspace and predictor type.\n");
c9d39fc8
         ret = AVERROR_INVALIDDATA;
         goto error;
def18e54
     }
a7153444
 
2793b218
     if ((ret = ff_huffyuv_alloc_temp(s)) < 0) {
def18e54
         ff_huffyuv_common_end(s);
c9d39fc8
         goto error;
def18e54
     }
2ca5ca29
 
     return 0;
c9d39fc8
   error:
     decode_end(avctx);
     return ret;
2ca5ca29
 }
 
 static av_cold int decode_init_thread_copy(AVCodecContext *avctx)
 {
     HYuvContext *s = avctx->priv_data;
d0393d79
     int i, ret;
2ca5ca29
 
2793b218
     if ((ret = ff_huffyuv_alloc_temp(s)) < 0) {
def18e54
         ff_huffyuv_common_end(s);
d0393d79
         return ret;
def18e54
     }
2ca5ca29
 
13f3092b
     for (i = 0; i < 8; i++)
2ca5ca29
         s->vlc[i].table = NULL;
 
27b1e63f
     if (s->version >= 2) {
d0393d79
         if ((ret = read_huffman_tables(s, avctx->extradata + 4,
                                        avctx->extradata_size)) < 0)
             return ret;
2ca5ca29
     } else {
d0393d79
         if ((ret = read_old_huffman_tables(s)) < 0)
             return ret;
2ca5ca29
     }
 
     return 0;
 }
 
35dae622
 /** Subset of GET_VLC for use in hand-roller VLC code */
 #define VLC_INTERN(dst, table, gb, name, bits, max_depth)   \
11b47038
     code = table[index][0];                                 \
     n    = table[index][1];                                 \
     if (max_depth > 1 && n < 0) {                           \
         LAST_SKIP_BITS(name, gb, bits);                     \
         UPDATE_CACHE(name, gb);                             \
                                                             \
         nb_bits = -n;                                       \
         index   = SHOW_UBITS(name, gb, nb_bits) + code;     \
         code    = table[index][0];                          \
         n       = table[index][1];                          \
         if (max_depth > 2 && n < 0) {                       \
             LAST_SKIP_BITS(name, gb, nb_bits);              \
             UPDATE_CACHE(name, gb);                         \
                                                             \
             nb_bits = -n;                                   \
             index   = SHOW_UBITS(name, gb, nb_bits) + code; \
             code    = table[index][0];                      \
             n       = table[index][1];                      \
         }                                                   \
     }                                                       \
     dst = code;                                             \
     LAST_SKIP_BITS(name, gb, n)
 
 
 #define GET_VLC_DUAL(dst0, dst1, name, gb, dtable, table1, table2,  \
7eb5b20a
                      bits, max_depth, OP)                           \
11b47038
     do {                                                            \
         unsigned int index = SHOW_UBITS(name, gb, bits);            \
6848325a
         int          code, n = dtable[index][1];                    \
11b47038
                                                                     \
9dc17919
         if (n<=0) {                                                 \
11b47038
             int nb_bits;                                            \
35dae622
             VLC_INTERN(dst0, table1, gb, name, bits, max_depth);    \
11b47038
                                                                     \
             UPDATE_CACHE(re, gb);                                   \
             index = SHOW_UBITS(name, gb, bits);                     \
35dae622
             VLC_INTERN(dst1, table2, gb, name, bits, max_depth);    \
9dc17919
         } else {                                                    \
             code = dtable[index][0];                                \
             OP(dst0, dst1, code);                                   \
             LAST_SKIP_BITS(name, gb, n);                            \
11b47038
         }                                                           \
     } while (0)
 
7eb5b20a
 #define OP8bits(dst0, dst1, code) dst0 = code>>8; dst1 = code
 
c065f4a0
 #define READ_2PIX(dst0, dst1, plane1)                                   \
c1e7fb60
     UPDATE_CACHE(re, &s->gb);                                           \
     GET_VLC_DUAL(dst0, dst1, re, &s->gb, s->vlc[4+plane1].table,        \
7eb5b20a
                  s->vlc[0].table, s->vlc[plane1].table, VLC_BITS, 3, OP8bits)
2ca5ca29
 
 static void decode_422_bitstream(HYuvContext *s, int count)
 {
f6577bd9
     int i, icount;
11b47038
     OPEN_READER(re, &s->gb);
2ca5ca29
     count /= 2;
 
f6577bd9
     icount = get_bits_left(&s->gb) / (32 * 4);
     if (count >= icount) {
         for (i = 0; i < icount; i++) {
c065f4a0
             READ_2PIX(s->temp[0][2 * i],     s->temp[1][i], 1);
2ca5ca29
             READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2);
         }
ba47d519
         for (; i < count && BITS_LEFT(re, &s->gb) > 0; i++) {
f6577bd9
             READ_2PIX(s->temp[0][2 * i    ], s->temp[1][i], 1);
ba47d519
             if (BITS_LEFT(re, &s->gb) <= 0) break;
f6577bd9
             READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2);
         }
42b6805c
         for (; i < count; i++)
             s->temp[0][2 * i    ] = s->temp[1][i] =
20c7baf8
             s->temp[0][2 * i + 1] = s->temp[2][i] = 0;
2ca5ca29
     } else {
         for (i = 0; i < count; i++) {
c065f4a0
             READ_2PIX(s->temp[0][2 * i],     s->temp[1][i], 1);
2ca5ca29
             READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2);
         }
     }
11b47038
     CLOSE_READER(re, &s->gb);
2ca5ca29
 }
 
7eb5b20a
 #define READ_2PIX_PLANE(dst0, dst1, plane, OP) \
a3702040
     UPDATE_CACHE(re, &s->gb); \
     GET_VLC_DUAL(dst0, dst1, re, &s->gb, s->vlc[4+plane].table, \
7eb5b20a
                  s->vlc[plane].table, s->vlc[plane].table, VLC_BITS, 3, OP)
 
 #define OP14bits(dst0, dst1, code) dst0 = code>>8; dst1 = sign_extend(code, 8)
53167ecf
 
7eb5b20a
 /* TODO instead of restarting the read when the code isn't in the first level
  * of the joint table, jump into the 2nd level of the individual table. */
53167ecf
 #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);\
 }
f75baa6c
 static void decode_plane_bitstream(HYuvContext *s, int width, int plane)
27b1e63f
 {
f75baa6c
     int i, count = width/2;
27b1e63f
 
b53aab1a
     if (s->bps <= 8) {
a3702040
         OPEN_READER(re, &s->gb);
e9c47705
         if (count >= (get_bits_left(&s->gb)) / (32 * 2)) {
ba47d519
             for (i = 0; i < count && BITS_LEFT(re, &s->gb) > 0; i++) {
7eb5b20a
                 READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane, OP8bits);
b53aab1a
             }
         } else {
             for(i=0; i<count; i++){
7eb5b20a
                 READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane, OP8bits);
b53aab1a
             }
27b1e63f
         }
f75baa6c
         if( width&1 && BITS_LEFT(re, &s->gb)>0 ) {
             unsigned int index;
             int nb_bits, code, n;
             UPDATE_CACHE(re, &s->gb);
             index = SHOW_UBITS(re, &s->gb, VLC_BITS);
             VLC_INTERN(s->temp[0][width-1], s->vlc[plane].table,
                        &s->gb, re, VLC_BITS, 3);
         }
a3702040
         CLOSE_READER(re, &s->gb);
53167ecf
     } else if (s->bps <= 14) {
7eb5b20a
         OPEN_READER(re, &s->gb);
e9c47705
         if (count >= (get_bits_left(&s->gb)) / (32 * 2)) {
ba47d519
             for (i = 0; i < count && BITS_LEFT(re, &s->gb) > 0; i++) {
7eb5b20a
                 READ_2PIX_PLANE(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane, OP14bits);
53167ecf
             }
         } else {
             for(i=0; i<count; i++){
7eb5b20a
                 READ_2PIX_PLANE(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane, OP14bits);
53167ecf
             }
         }
f75baa6c
         if( width&1 && BITS_LEFT(re, &s->gb)>0 ) {
             unsigned int index;
             int nb_bits, code, n;
             UPDATE_CACHE(re, &s->gb);
             index = SHOW_UBITS(re, &s->gb, VLC_BITS);
             VLC_INTERN(s->temp16[0][width-1], s->vlc[plane].table,
                        &s->gb, re, VLC_BITS, 3);
         }
7eb5b20a
         CLOSE_READER(re, &s->gb);
27b1e63f
     } else {
e9c47705
         if (count >= (get_bits_left(&s->gb)) / (32 * 2)) {
b53aab1a
             for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
                 READ_2PIX_PLANE16(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
             }
         } else {
             for(i=0; i<count; i++){
                 READ_2PIX_PLANE16(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
             }
27b1e63f
         }
f75baa6c
         if( width&1 && get_bits_left(&s->gb)>0 ) {
             int dst = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;
             s->temp16[0][width-1] = dst + get_bits(&s->gb, 2);
         }
27b1e63f
     }
 }
 
2ca5ca29
 static void decode_gray_bitstream(HYuvContext *s, int count)
 {
     int i;
11b47038
     OPEN_READER(re, &s->gb);
c1e7fb60
     count /= 2;
2ca5ca29
 
e9c47705
     if (count >= (get_bits_left(&s->gb)) / (32 * 2)) {
ba47d519
         for (i = 0; i < count && BITS_LEFT(re, &s->gb) > 0; i++) {
2ca5ca29
             READ_2PIX(s->temp[0][2 * i], s->temp[0][2 * i + 1], 0);
         }
     } else {
c065f4a0
         for (i = 0; i < count; i++) {
2ca5ca29
             READ_2PIX(s->temp[0][2 * i], s->temp[0][2 * i + 1], 0);
         }
     }
11b47038
     CLOSE_READER(re, &s->gb);
2ca5ca29
 }
 
 static av_always_inline void decode_bgr_1(HYuvContext *s, int count,
                                           int decorrelate, int alpha)
 {
     int i;
deadcf5e
     OPEN_READER(re, &s->gb);
 
ba47d519
     for (i = 0; i < count && BITS_LEFT(re, &s->gb) > 0; i++) {
deadcf5e
         unsigned int index;
331b1f7d
         int code, n, nb_bits;
deadcf5e
 
         UPDATE_CACHE(re, &s->gb);
         index = SHOW_UBITS(re, &s->gb, VLC_BITS);
         n     = s->vlc[4].table[index][1];
 
0d632b35
         if (n>0) {
             code  = s->vlc[4].table[index][0];
c065f4a0
             *(uint32_t *) &s->temp[0][4 * i] = s->pix_bgr_map[code];
deadcf5e
             LAST_SKIP_BITS(re, &s->gb, n);
2ca5ca29
         } else {
c1e7fb60
             if (decorrelate) {
35dae622
                 VLC_INTERN(s->temp[0][4 * i + G], s->vlc[1].table,
                            &s->gb, re, VLC_BITS, 3);
deadcf5e
 
                 UPDATE_CACHE(re, &s->gb);
                 index = SHOW_UBITS(re, &s->gb, VLC_BITS);
35dae622
                 VLC_INTERN(code, s->vlc[0].table, &s->gb, re, VLC_BITS, 3);
deadcf5e
                 s->temp[0][4 * i + B] = code + s->temp[0][4 * i + G];
 
                 UPDATE_CACHE(re, &s->gb);
                 index = SHOW_UBITS(re, &s->gb, VLC_BITS);
35dae622
                 VLC_INTERN(code, s->vlc[2].table, &s->gb, re, VLC_BITS, 3);
deadcf5e
                 s->temp[0][4 * i + R] = code + s->temp[0][4 * i + G];
             } else {
35dae622
                 VLC_INTERN(s->temp[0][4 * i + B], s->vlc[0].table,
                            &s->gb, re, VLC_BITS, 3);
deadcf5e
 
                 UPDATE_CACHE(re, &s->gb);
                 index = SHOW_UBITS(re, &s->gb, VLC_BITS);
35dae622
                 VLC_INTERN(s->temp[0][4 * i + G], s->vlc[1].table,
                            &s->gb, re, VLC_BITS, 3);
deadcf5e
 
                 UPDATE_CACHE(re, &s->gb);
                 index = SHOW_UBITS(re, &s->gb, VLC_BITS);
35dae622
                 VLC_INTERN(s->temp[0][4 * i + R], s->vlc[2].table,
                            &s->gb, re, VLC_BITS, 3);
deadcf5e
             }
2ca5ca29
         }
331b1f7d
         if (alpha) {
             UPDATE_CACHE(re, &s->gb);
             index = SHOW_UBITS(re, &s->gb, VLC_BITS);
             VLC_INTERN(s->temp[0][4 * i + A], s->vlc[2].table,
                        &s->gb, re, VLC_BITS, 3);
         } else
             s->temp[0][4 * i + A] = 0;
2ca5ca29
     }
deadcf5e
     CLOSE_READER(re, &s->gb);
2ca5ca29
 }
 
 static void decode_bgr_bitstream(HYuvContext *s, int count)
 {
     if (s->decorrelate) {
c065f4a0
         if (s->bitstream_bpp == 24)
2ca5ca29
             decode_bgr_1(s, count, 1, 0);
         else
             decode_bgr_1(s, count, 1, 1);
     } else {
c065f4a0
         if (s->bitstream_bpp == 24)
2ca5ca29
             decode_bgr_1(s, count, 0, 0);
         else
             decode_bgr_1(s, count, 0, 1);
     }
 }
 
759001c5
 static void draw_slice(HYuvContext *s, AVFrame *frame, int y)
2ca5ca29
 {
     int h, cy, i;
     int offset[AV_NUM_DATA_POINTERS];
 
f929ab05
     if (!s->avctx->draw_horiz_band)
2ca5ca29
         return;
 
c065f4a0
     h  = y - s->last_slice_end;
2ca5ca29
     y -= h;
 
c065f4a0
     if (s->bitstream_bpp == 12)
         cy = y >> 1;
     else
2ca5ca29
         cy = y;
 
759001c5
     offset[0] = frame->linesize[0] * y;
     offset[1] = frame->linesize[1] * cy;
     offset[2] = frame->linesize[2] * cy;
2ca5ca29
     for (i = 3; i < AV_NUM_DATA_POINTERS; i++)
         offset[i] = 0;
     emms_c();
 
759001c5
     s->avctx->draw_horiz_band(s->avctx, frame, offset, y, 3, h);
2ca5ca29
 
     s->last_slice_end = y + h;
 }
 
b53aab1a
 static int left_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, int w, int acc)
 {
     if (s->bps <= 8) {
e2abc0d5
         return s->hdsp.add_hfyu_left_pred(dst, src, w, acc);
b53aab1a
     } else {
7b4c4605
         return s->llviddsp.add_hfyu_left_pred_int16((      uint16_t *)dst, (const uint16_t *)src, s->n-1, w, acc);
b53aab1a
     }
 }
 
 static void add_bytes(HYuvContext *s, uint8_t *dst, uint8_t *src, int w)
 {
     if (s->bps <= 8) {
e2abc0d5
         s->hdsp.add_bytes(dst, src, w);
b53aab1a
     } else {
f70d7eb2
         s->llviddsp.add_int16((uint16_t*)dst, (const uint16_t*)src, s->n - 1, w);
b53aab1a
     }
 }
 
2fd39642
 static void add_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, const uint8_t *diff, int w, int *left, int *left_top)
 {
     if (s->bps <= 8) {
e2abc0d5
         s->hdsp.add_hfyu_median_pred(dst, src, diff, w, left, left_top);
2fd39642
     } else {
550ae6c0
         s->llviddsp.add_hfyu_median_pred_int16((uint16_t *)dst, (const uint16_t *)src, (const uint16_t *)diff, s->n-1, w, left, left_top);
2fd39642
     }
 }
2ca5ca29
 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                         AVPacket *avpkt)
 {
     const uint8_t *buf = avpkt->data;
c065f4a0
     int buf_size       = avpkt->size;
2ca5ca29
     HYuvContext *s = avctx->priv_data;
c065f4a0
     const int width  = s->width;
     const int width2 = s->width >> 1;
2ca5ca29
     const int height = s->height;
     int fake_ystride, fake_ustride, fake_vstride;
759001c5
     ThreadFrame frame = { .f = data };
c065f4a0
     AVFrame *const p = data;
def18e54
     int table_size = 0, ret;
2ca5ca29
 
def18e54
     av_fast_padded_malloc(&s->bitstream_buffer,
2ca5ca29
                    &s->bitstream_buffer_size,
def18e54
                    buf_size);
2ca5ca29
     if (!s->bitstream_buffer)
         return AVERROR(ENOMEM);
 
c67b449b
     s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer,
                       (const uint32_t *) buf, buf_size / 4);
2ca5ca29
 
1ec94b0f
     if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
def18e54
         return ret;
2ca5ca29
 
     if (s->context) {
         table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size);
         if (table_size < 0)
d0393d79
             return table_size;
2ca5ca29
     }
 
c065f4a0
     if ((unsigned) (buf_size - table_size) >= INT_MAX / 8)
def18e54
         return AVERROR_INVALIDDATA;
2ca5ca29
 
d0393d79
     if ((ret = init_get_bits(&s->gb, s->bitstream_buffer + table_size,
                              (buf_size - table_size) * 8)) < 0)
         return ret;
2ca5ca29
 
c065f4a0
     fake_ystride = s->interlaced ? p->linesize[0] * 2 : p->linesize[0];
     fake_ustride = s->interlaced ? p->linesize[1] * 2 : p->linesize[1];
     fake_vstride = s->interlaced ? p->linesize[2] * 2 : p->linesize[2];
2ca5ca29
 
     s->last_slice_end = 0;
 
27b1e63f
     if (s->version > 2) {
         int plane;
         for(plane = 0; plane < 1 + 2*s->chroma + s->alpha; plane++) {
             int left, lefttop, y;
             int w = width;
             int h = height;
             int fake_stride = fake_ystride;
 
             if (s->chroma && (plane == 1 || plane == 2)) {
                 w >>= s->chroma_h_shift;
                 h >>= s->chroma_v_shift;
                 fake_stride = plane == 1 ? fake_ustride : fake_vstride;
             }
 
             switch (s->predictor) {
             case LEFT:
             case PLANE:
                 decode_plane_bitstream(s, w, plane);
b53aab1a
                 left = left_prediction(s, p->data[plane], s->temp[0], w, 0);
27b1e63f
 
                 for (y = 1; y < h; y++) {
                     uint8_t *dst = p->data[plane] + p->linesize[plane]*y;
 
                     decode_plane_bitstream(s, w, plane);
b53aab1a
                     left = left_prediction(s, dst, s->temp[0], w, left);
27b1e63f
                     if (s->predictor == PLANE) {
                         if (y > s->interlaced) {
b53aab1a
                             add_bytes(s, dst, dst - fake_stride, w);
27b1e63f
                         }
                     }
                 }
 
                 break;
             case MEDIAN:
                 decode_plane_bitstream(s, w, plane);
b53aab1a
                 left= left_prediction(s, p->data[plane], s->temp[0], w, 0);
27b1e63f
 
                 y = 1;
 
                 /* second line is left predicted for interlaced case */
                 if (s->interlaced) {
                     decode_plane_bitstream(s, w, plane);
b53aab1a
                     left = left_prediction(s, p->data[plane] + p->linesize[plane], s->temp[0], w, left);
27b1e63f
                     y++;
                 }
 
                 lefttop = p->data[plane][0];
                 decode_plane_bitstream(s, w, plane);
2fd39642
                 add_median_prediction(s, p->data[plane] + fake_stride, p->data[plane], s->temp[0], w, &left, &lefttop);
27b1e63f
                 y++;
 
                 for (; y<h; y++) {
                     uint8_t *dst;
 
                     decode_plane_bitstream(s, w, plane);
 
                     dst = p->data[plane] + p->linesize[plane] * y;
 
2fd39642
                     add_median_prediction(s, dst, dst - fake_stride, s->temp[0], w, &left, &lefttop);
27b1e63f
                 }
 
                 break;
             }
         }
         draw_slice(s, p, height);
     } else if (s->bitstream_bpp < 24) {
2ca5ca29
         int y, cy;
         int lefty, leftu, leftv;
         int lefttopy, lefttopu, lefttopv;
 
         if (s->yuy2) {
             p->data[0][3] = get_bits(&s->gb, 8);
             p->data[0][2] = get_bits(&s->gb, 8);
             p->data[0][1] = get_bits(&s->gb, 8);
             p->data[0][0] = get_bits(&s->gb, 8);
 
             av_log(avctx, AV_LOG_ERROR,
                    "YUY2 output is not implemented yet\n");
def18e54
             return AVERROR_PATCHWELCOME;
2ca5ca29
         } else {
c065f4a0
             leftv         =
             p->data[2][0] = get_bits(&s->gb, 8);
             lefty         =
             p->data[0][1] = get_bits(&s->gb, 8);
             leftu         =
             p->data[1][0] = get_bits(&s->gb, 8);
             p->data[0][0] = get_bits(&s->gb, 8);
2ca5ca29
 
             switch (s->predictor) {
             case LEFT:
             case PLANE:
c065f4a0
                 decode_422_bitstream(s, width - 2);
                 lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + 2, s->temp[0],
                                                    width - 2, lefty);
7c6eb0a1
                 if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
0d439fbe
                     leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + 1, s->temp[1], width2 - 1, leftu);
                     leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + 1, s->temp[2], width2 - 1, leftv);
2ca5ca29
                 }
 
                 for (cy = y = 1; y < s->height; y++, cy++) {
                     uint8_t *ydst, *udst, *vdst;
 
                     if (s->bitstream_bpp == 12) {
                         decode_gray_bitstream(s, width);
 
                         ydst = p->data[0] + p->linesize[0] * y;
 
c065f4a0
                         lefty = s->hdsp.add_hfyu_left_pred(ydst, s->temp[0],
                                                            width, lefty);
2ca5ca29
                         if (s->predictor == PLANE) {
                             if (y > s->interlaced)
0d439fbe
                                 s->hdsp.add_bytes(ydst, ydst - fake_ystride, width);
2ca5ca29
                         }
                         y++;
c065f4a0
                         if (y >= s->height)
                             break;
2ca5ca29
                     }
 
759001c5
                     draw_slice(s, p, y);
2ca5ca29
 
c065f4a0
                     ydst = p->data[0] + p->linesize[0] * y;
                     udst = p->data[1] + p->linesize[1] * cy;
                     vdst = p->data[2] + p->linesize[2] * cy;
2ca5ca29
 
                     decode_422_bitstream(s, width);
c065f4a0
                     lefty = s->hdsp.add_hfyu_left_pred(ydst, s->temp[0],
                                                        width, lefty);
7c6eb0a1
                     if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
0d439fbe
                         leftu = s->hdsp.add_hfyu_left_pred(udst, s->temp[1], width2, leftu);
                         leftv = s->hdsp.add_hfyu_left_pred(vdst, s->temp[2], width2, leftv);
2ca5ca29
                     }
                     if (s->predictor == PLANE) {
                         if (cy > s->interlaced) {
0d439fbe
                             s->hdsp.add_bytes(ydst, ydst - fake_ystride, width);
7c6eb0a1
                             if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
0d439fbe
                                 s->hdsp.add_bytes(udst, udst - fake_ustride, width2);
                                 s->hdsp.add_bytes(vdst, vdst - fake_vstride, width2);
2ca5ca29
                             }
                         }
                     }
                 }
759001c5
                 draw_slice(s, p, height);
2ca5ca29
 
                 break;
             case MEDIAN:
                 /* first line except first 2 pixels is left predicted */
                 decode_422_bitstream(s, width - 2);
c065f4a0
                 lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + 2, s->temp[0],
                                                    width - 2, lefty);
7c6eb0a1
                 if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
0d439fbe
                     leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + 1, s->temp[1], width2 - 1, leftu);
                     leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + 1, s->temp[2], width2 - 1, leftv);
2ca5ca29
                 }
 
                 cy = y = 1;
 
                 /* second line is left predicted for interlaced case */
                 if (s->interlaced) {
                     decode_422_bitstream(s, width);
c065f4a0
                     lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + p->linesize[0],
                                                        s->temp[0], width, lefty);
7c6eb0a1
                     if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
0d439fbe
                         leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + p->linesize[2], s->temp[1], width2, leftu);
                         leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + p->linesize[1], s->temp[2], width2, leftv);
2ca5ca29
                     }
c065f4a0
                     y++;
                     cy++;
2ca5ca29
                 }
 
                 /* next 4 pixels are left predicted too */
                 decode_422_bitstream(s, 4);
c065f4a0
                 lefty = s->hdsp.add_hfyu_left_pred(p->data[0] + fake_ystride,
                                                    s->temp[0], 4, lefty);
7c6eb0a1
                 if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
0d439fbe
                     leftu = s->hdsp.add_hfyu_left_pred(p->data[1] + fake_ustride, s->temp[1], 2, leftu);
                     leftv = s->hdsp.add_hfyu_left_pred(p->data[2] + fake_vstride, s->temp[2], 2, leftv);
2ca5ca29
                 }
 
                 /* next line except the first 4 pixels is median predicted */
                 lefttopy = p->data[0][3];
                 decode_422_bitstream(s, width - 4);
c065f4a0
                 s->hdsp.add_hfyu_median_pred(p->data[0] + fake_ystride + 4,
                                              p->data[0] + 4, s->temp[0],
                                              width - 4, &lefty, &lefttopy);
7c6eb0a1
                 if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
2ca5ca29
                     lefttopu = p->data[1][1];
                     lefttopv = p->data[2][1];
0d439fbe
                     s->hdsp.add_hfyu_median_pred(p->data[1] + fake_ustride + 2, p->data[1] + 2, s->temp[1], width2 - 2, &leftu, &lefttopu);
                     s->hdsp.add_hfyu_median_pred(p->data[2] + fake_vstride + 2, p->data[2] + 2, s->temp[2], width2 - 2, &leftv, &lefttopv);
2ca5ca29
                 }
c065f4a0
                 y++;
                 cy++;
2ca5ca29
 
c065f4a0
                 for (; y < height; y++, cy++) {
2ca5ca29
                     uint8_t *ydst, *udst, *vdst;
 
                     if (s->bitstream_bpp == 12) {
                         while (2 * cy > y) {
                             decode_gray_bitstream(s, width);
                             ydst = p->data[0] + p->linesize[0] * y;
c065f4a0
                             s->hdsp.add_hfyu_median_pred(ydst, ydst - fake_ystride,
                                                          s->temp[0], width,
                                                          &lefty, &lefttopy);
2ca5ca29
                             y++;
                         }
c065f4a0
                         if (y >= height)
                             break;
2ca5ca29
                     }
759001c5
                     draw_slice(s, p, y);
2ca5ca29
 
                     decode_422_bitstream(s, width);
 
                     ydst = p->data[0] + p->linesize[0] * y;
                     udst = p->data[1] + p->linesize[1] * cy;
                     vdst = p->data[2] + p->linesize[2] * cy;
 
c065f4a0
                     s->hdsp.add_hfyu_median_pred(ydst, ydst - fake_ystride,
                                                  s->temp[0], width,
                                                  &lefty, &lefttopy);
7c6eb0a1
                     if (!(s->flags & AV_CODEC_FLAG_GRAY)) {
0d439fbe
                         s->hdsp.add_hfyu_median_pred(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu);
                         s->hdsp.add_hfyu_median_pred(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv);
2ca5ca29
                     }
                 }
 
759001c5
                 draw_slice(s, p, height);
2ca5ca29
                 break;
             }
         }
     } else {
         int y;
25e6310a
         uint8_t left[4];
2ca5ca29
         const int last_line = (height - 1) * p->linesize[0];
 
         if (s->bitstream_bpp == 32) {
c1e7fb60
             left[A] = p->data[0][last_line + A] = get_bits(&s->gb, 8);
             left[R] = p->data[0][last_line + R] = get_bits(&s->gb, 8);
             left[G] = p->data[0][last_line + G] = get_bits(&s->gb, 8);
             left[B] = p->data[0][last_line + B] = get_bits(&s->gb, 8);
2ca5ca29
         } else {
c1e7fb60
             left[R] = p->data[0][last_line + R] = get_bits(&s->gb, 8);
             left[G] = p->data[0][last_line + G] = get_bits(&s->gb, 8);
             left[B] = p->data[0][last_line + B] = get_bits(&s->gb, 8);
             left[A] = p->data[0][last_line + A] = 255;
2ca5ca29
             skip_bits(&s->gb, 8);
         }
 
         if (s->bgr32) {
             switch (s->predictor) {
             case LEFT:
             case PLANE:
                 decode_bgr_bitstream(s, width - 1);
c065f4a0
                 s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + last_line + 4,
c1e7fb60
                                                  s->temp[0], width - 1, left);
2ca5ca29
 
c065f4a0
                 for (y = s->height - 2; y >= 0; y--) { // Yes it is stored upside down.
2ca5ca29
                     decode_bgr_bitstream(s, width);
 
c065f4a0
                     s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + p->linesize[0] * y,
c1e7fb60
                                                      s->temp[0], width, left);
2ca5ca29
                     if (s->predictor == PLANE) {
c065f4a0
                         if (s->bitstream_bpp != 32)
c1e7fb60
                             left[A] = 0;
2f1de5ca
                         if (y < s->height - 1 - s->interlaced) {
0d439fbe
                             s->hdsp.add_bytes(p->data[0] + p->linesize[0] * y,
                                               p->data[0] + p->linesize[0] * y +
2f1de5ca
                                               fake_ystride, 4 * width);
2ca5ca29
                         }
                     }
                 }
                 // just 1 large slice as this is not possible in reverse order
759001c5
                 draw_slice(s, p, height);
2ca5ca29
                 break;
             default:
                 av_log(avctx, AV_LOG_ERROR,
                        "prediction type not supported!\n");
             }
c065f4a0
         } else {
2ca5ca29
             av_log(avctx, AV_LOG_ERROR,
                    "BGR24 output is not implemented yet\n");
def18e54
             return AVERROR_PATCHWELCOME;
2ca5ca29
         }
     }
     emms_c();
 
     *got_frame = 1;
 
     return (get_bits_count(&s->gb) + 31) / 32 * 4 + table_size;
 }
 
 AVCodec ff_huffyuv_decoder = {
     .name             = "huffyuv",
b2bed932
     .long_name        = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"),
2ca5ca29
     .type             = AVMEDIA_TYPE_VIDEO,
     .id               = AV_CODEC_ID_HUFFYUV,
     .priv_data_size   = sizeof(HYuvContext),
     .init             = decode_init,
     .close            = decode_end,
     .decode           = decode_frame,
def97856
     .capabilities     = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                         AV_CODEC_CAP_FRAME_THREADS,
2ca5ca29
     .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
 };
 
 #if CONFIG_FFVHUFF_DECODER
 AVCodec ff_ffvhuff_decoder = {
     .name             = "ffvhuff",
b2bed932
     .long_name        = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"),
2ca5ca29
     .type             = AVMEDIA_TYPE_VIDEO,
     .id               = AV_CODEC_ID_FFVHUFF,
     .priv_data_size   = sizeof(HYuvContext),
     .init             = decode_init,
     .close            = decode_end,
     .decode           = decode_frame,
def97856
     .capabilities     = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                         AV_CODEC_CAP_FRAME_THREADS,
2ca5ca29
     .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
 };
c065f4a0
 #endif /* CONFIG_FFVHUFF_DECODER */