libavcodec/huffyuv.c
11f18faf
 /*
  * huffyuv codec for libavcodec
  *
aaa1e4cd
  * Copyright (c) 2002-2003 Michael Niedermayer <michaelni@gmx.at>
11f18faf
  *
7b94177e
  * see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of
  * the algorithm used
  *
b78e7197
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
11f18faf
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
b78e7197
  * version 2.1 of the License, or (at your option) any later version.
11f18faf
  *
b78e7197
  * FFmpeg is distributed in the hope that it will be useful,
11f18faf
  * 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
b78e7197
  * License along with FFmpeg; if not, write to the Free Software
5509bffa
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
11f18faf
  */
115329f1
 
983e3246
 /**
ba87f080
  * @file
983e3246
  * huffyuv codec for libavcodec.
  */
11f18faf
 
 #include "avcodec.h"
9106a698
 #include "get_bits.h"
b2755007
 #include "put_bits.h"
11f18faf
 #include "dsputil.h"
e9e9139c
 #include "thread.h"
11f18faf
 
 #define VLC_BITS 11
1e491e29
 
63613fe6
 #if HAVE_BIGENDIAN
3ad7dd8c
 #define B 3
 #define G 2
 #define R 1
f267d3ac
 #define A 0
3ad7dd8c
 #else
 #define B 0
 #define G 1
 #define R 2
f267d3ac
 #define A 3
3ad7dd8c
 #endif
 
11f18faf
 typedef enum Predictor{
     LEFT= 0,
     PLANE,
     MEDIAN,
 } Predictor;
115329f1
 
11f18faf
 typedef struct HYuvContext{
     AVCodecContext *avctx;
     Predictor predictor;
     GetBitContext gb;
     PutBitContext pb;
     int interlaced;
     int decorrelate;
     int bitstream_bpp;
     int version;
     int yuy2;                               //use yuy2 instead of 422P
     int bgr32;                              //use bgr32 instead of bgr24
     int width, height;
     int flags;
11087086
     int context;
11f18faf
     int picture_number;
7c5ab7b8
     int last_slice_end;
0ecca7a4
     uint8_t *temp[3];
11f18faf
     uint64_t stats[3][256];
     uint8_t len[3][256];
     uint32_t bits[3][256];
8be6dac8
     uint32_t pix_bgr_map[1<<VLC_BITS];
19716d64
     VLC vlc[6];                             //Y,U,V,YY,YU,YV
492cd3a9
     AVFrame picture;
0ecca7a4
     uint8_t *bitstream_buffer;
f038fe8b
     unsigned int bitstream_buffer_size;
115329f1
     DSPContext dsp;
11f18faf
 }HYuvContext;
 
24def10e
 static const unsigned char classic_shift_luma[] = {
676b385c
   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,10,21,9,23,8,8,199,70,
   69,68, 0
 };
 
24def10e
 static const unsigned char classic_shift_chroma[] = {
676b385c
   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,78,77,44,75,41,40,39,38,37,36,34, 0
 };
 
24def10e
 static const unsigned char classic_add_luma[256] = {
676b385c
     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,
 };
 
24def10e
 static const unsigned char classic_add_chroma[256] = {
676b385c
     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,
 };
 
7c5ab7b8
 static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst, uint8_t *src, int w, int left){
11f18faf
     int i;
7c5ab7b8
     if(w<32){
         for(i=0; i<w; i++){
             const int temp= src[i];
             dst[i]= temp - left;
             left= temp;
         }
         return left;
     }else{
         for(i=0; i<16; i++){
             const int temp= src[i];
             dst[i]= temp - left;
             left= temp;
         }
         s->dsp.diff_bytes(dst+16, src+16, src+15, w-16);
         return src[w-1];
11f18faf
     }
 }
2a250222
 
d2bfaf8a
 static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst, uint8_t *src, int w, int *red, int *green, int *blue){
     int i;
     int r,g,b;
     r= *red;
     g= *green;
     b= *blue;
     for(i=0; i<FFMIN(w,4); i++){
         const int rt= src[i*4+R];
         const int gt= src[i*4+G];
         const int bt= src[i*4+B];
         dst[i*4+R]= rt - r;
         dst[i*4+G]= gt - g;
         dst[i*4+B]= bt - b;
         r = rt;
         g = gt;
         b = bt;
     }
     s->dsp.diff_bytes(dst+16, src+16, src+12, w*4-16);
     *red=   src[(w-1)*4+R];
     *green= src[(w-1)*4+G];
     *blue=  src[(w-1)*4+B];
 }
 
e30004fa
 static int read_len_table(uint8_t *dst, GetBitContext *gb){
11f18faf
     int i, val, repeat;
115329f1
 
11f18faf
     for(i=0; i<256;){
         repeat= get_bits(gb, 3);
         val   = get_bits(gb, 5);
         if(repeat==0)
             repeat= get_bits(gb, 8);
 //printf("%d %d\n", val, repeat);
e30004fa
         if(i+repeat > 256) {
             av_log(NULL, AV_LOG_ERROR, "Error reading huffman table\n");
             return -1;
         }
11f18faf
         while (repeat--)
             dst[i++] = val;
     }
e30004fa
     return 0;
11f18faf
 }
 
22c29c36
 static int generate_bits_table(uint32_t *dst, const uint8_t *len_table){
11f18faf
     int len, index;
     uint32_t bits=0;
 
     for(len=32; len>0; len--){
         for(index=0; index<256; index++){
14b74d38
             if(len_table[index]==len)
                 dst[index]= bits++;
11f18faf
         }
14b74d38
         if(bits & 1){
9b879566
             av_log(NULL, AV_LOG_ERROR, "Error generating huffman table\n");
14b74d38
             return -1;
         }
         bits >>= 1;
11f18faf
     }
     return 0;
 }
 
b250f9c6
 #if CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER
98ef8c32
 typedef struct {
     uint64_t val;
     int name;
fe5c7e58
 } HeapElem;
98ef8c32
 
fe5c7e58
 static void heap_sift(HeapElem *h, int root, int size)
98ef8c32
 {
     while(root*2+1 < size) {
         int child = root*2+1;
         if(child < size-1 && h[child].val > h[child+1].val)
             child++;
         if(h[root].val > h[child].val) {
fe5c7e58
             FFSWAP(HeapElem, h[root], h[child]);
98ef8c32
             root = child;
         } else
             break;
     }
 }
 
95024414
 static void generate_len_table(uint8_t *dst, const uint64_t *stats){
d45b771c
     HeapElem h[256];
     int up[2*256];
     int len[2*256];
11f18faf
     int offset, i, next;
95024414
     int size = 256;
115329f1
 
11f18faf
     for(offset=1; ; offset<<=1){
         for(i=0; i<size; i++){
98ef8c32
             h[i].name = i;
             h[i].val = (stats[i] << 8) + offset;
11f18faf
         }
98ef8c32
         for(i=size/2-1; i>=0; i--)
             heap_sift(h, i, size);
 
         for(next=size; next<size*2-1; next++){
             // merge the two smallest entries, and put it back in the heap
             uint64_t min1v = h[0].val;
             up[h[0].name] = next;
             h[0].val = INT64_MAX;
             heap_sift(h, 0, size);
             up[h[0].name] = next;
             h[0].name = next;
             h[0].val += min1v;
             heap_sift(h, 0, size);
11f18faf
         }
115329f1
 
98ef8c32
         len[2*size-2] = 0;
         for(i=2*size-3; i>=size; i--)
             len[i] = len[up[i]] + 1;
         for(i=0; i<size; i++) {
             dst[i] = len[up[i]] + 1;
2bf4aa2e
             if(dst[i] >= 32) break;
11f18faf
         }
         if(i==size) break;
     }
 }
b250f9c6
 #endif /* CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER */
11f18faf
 
19716d64
 static void generate_joint_tables(HYuvContext *s){
8be6dac8
     uint16_t symbols[1<<VLC_BITS];
     uint16_t bits[1<<VLC_BITS];
     uint8_t len[1<<VLC_BITS];
19716d64
     if(s->bitstream_bpp < 24){
         int p, i, y, u;
         for(p=0; p<3; p++){
             for(i=y=0; y<256; y++){
                 int len0 = s->len[0][y];
                 int limit = VLC_BITS - len0;
f45fcba3
                 if(limit <= 0)
                     continue;
                 for(u=0; u<256; u++){
                     int len1 = s->len[p][u];
                     if(len1 > limit)
                         continue;
                     len[i] = len0 + len1;
                     bits[i] = (s->bits[0][y] << len1) + s->bits[p][u];
                     symbols[i] = (y<<8) + u;
                     if(symbols[i] != 0xffff) // reserved to mean "invalid"
                         i++;
19716d64
                 }
             }
             free_vlc(&s->vlc[3+p]);
acc0e0c8
             init_vlc_sparse(&s->vlc[3+p], VLC_BITS, i, len, 1, 1, bits, 2, 2, symbols, 2, 2, 0);
19716d64
         }
8be6dac8
     }else{
         uint8_t (*map)[4] = (uint8_t(*)[4])s->pix_bgr_map;
         int i, b, g, r, code;
         int p0 = s->decorrelate;
         int p1 = !s->decorrelate;
         // restrict the range to +/-16 becaues that's pretty much guaranteed to
         // cover all the combinations that fit in 11 bits total, and it doesn't
         // matter if we miss a few rare codes.
         for(i=0, g=-16; g<16; g++){
             int len0 = s->len[p0][g&255];
             int limit0 = VLC_BITS - len0;
             if(limit0 < 2)
                 continue;
             for(b=-16; b<16; b++){
                 int len1 = s->len[p1][b&255];
                 int limit1 = limit0 - len1;
                 if(limit1 < 1)
                     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];
                     if(len2 > limit1)
                         continue;
                     len[i] = len0 + len1 + len2;
                     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++;
                 }
             }
         }
         free_vlc(&s->vlc[3]);
         init_vlc(&s->vlc[3], VLC_BITS, i, len, 1, 1, bits, 2, 2, 0);
19716d64
     }
 }
 
22c29c36
 static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length){
11f18faf
     GetBitContext gb;
     int i;
115329f1
 
68f593b4
     init_get_bits(&gb, src, length*8);
115329f1
 
11f18faf
     for(i=0; i<3; i++){
e30004fa
         if(read_len_table(s->len[i], &gb)<0)
             return -1;
11f18faf
         if(generate_bits_table(s->bits[i], s->len[i])<0){
             return -1;
         }
11087086
         free_vlc(&s->vlc[i]);
073c2593
         init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, s->bits[i], 4, 4, 0);
11f18faf
     }
115329f1
 
19716d64
     generate_joint_tables(s);
 
11087086
     return (get_bits_count(&gb)+7)/8;
11f18faf
 }
 
 static int read_old_huffman_tables(HYuvContext *s){
676b385c
 #if 1
11f18faf
     GetBitContext gb;
     int i;
 
68f593b4
     init_get_bits(&gb, classic_shift_luma, sizeof(classic_shift_luma)*8);
e30004fa
     if(read_len_table(s->len[0], &gb)<0)
         return -1;
68f593b4
     init_get_bits(&gb, classic_shift_chroma, sizeof(classic_shift_chroma)*8);
e30004fa
     if(read_len_table(s->len[1], &gb)<0)
         return -1;
115329f1
 
11f18faf
     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];
 
     if(s->bitstream_bpp >= 24){
         memcpy(s->bits[1], s->bits[0], 256*sizeof(uint32_t));
         memcpy(s->len[1] , s->len [0], 256*sizeof(uint8_t));
     }
     memcpy(s->bits[2], s->bits[1], 256*sizeof(uint32_t));
     memcpy(s->len[2] , s->len [1], 256*sizeof(uint8_t));
115329f1
 
11087086
     for(i=0; i<3; i++){
         free_vlc(&s->vlc[i]);
073c2593
         init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, s->bits[i], 4, 4, 0);
11087086
     }
115329f1
 
19716d64
     generate_joint_tables(s);
 
11f18faf
     return 0;
 #else
267f7edc
     av_log(s->avctx, AV_LOG_DEBUG, "v1 huffyuv is not supported \n");
11f18faf
     return -1;
 #endif
 }
 
5ef251e5
 static av_cold void alloc_temp(HYuvContext *s){
ae2f1d46
     int i;
115329f1
 
ae2f1d46
     if(s->bitstream_bpp<24){
         for(i=0; i<3; i++){
             s->temp[i]= av_malloc(s->width + 16);
         }
     }else{
f267d3ac
         s->temp[0]= av_mallocz(4*s->width + 16);
ae2f1d46
     }
 }
 
5ef251e5
 static av_cold int common_init(AVCodecContext *avctx){
11f18faf
     HYuvContext *s = avctx->priv_data;
 
     s->avctx= avctx;
     s->flags= avctx->flags;
115329f1
 
1d98dca3
     dsputil_init(&s->dsp, avctx);
115329f1
 
0ecca7a4
     s->width= avctx->width;
     s->height= avctx->height;
     assert(s->width>0 && s->height>0);
115329f1
 
0ecca7a4
     return 0;
 }
 
b250f9c6
 #if CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER
98a6fff9
 static av_cold int decode_init(AVCodecContext *avctx)
0ecca7a4
 {
     HYuvContext *s = avctx->priv_data;
 
     common_init(avctx);
11087086
     memset(s->vlc, 0, 3*sizeof(VLC));
115329f1
 
492cd3a9
     avctx->coded_frame= &s->picture;
01042d41
     avcodec_get_frame_defaults(&s->picture);
0ecca7a4
     s->interlaced= s->height > 288;
1e491e29
 
11f18faf
 s->bgr32=1;
 //if(avctx->extradata)
 //  printf("extradata:%X, extradata_size:%d\n", *(uint32_t*)avctx->extradata, avctx->extradata_size);
     if(avctx->extradata_size){
dd1c8f3e
         if((avctx->bits_per_coded_sample&7) && avctx->bits_per_coded_sample != 12)
11f18faf
             s->version=1; // do such files exist at all?
         else
             s->version=2;
     }else
         s->version=0;
115329f1
 
11f18faf
     if(s->version==2){
42dd22c4
         int method, interlace;
11f18faf
 
2818bdf2
         if (avctx->extradata_size < 4)
             return -1;
 
11f18faf
         method= ((uint8_t*)avctx->extradata)[0];
         s->decorrelate= method&64 ? 1 : 0;
         s->predictor= method&63;
         s->bitstream_bpp= ((uint8_t*)avctx->extradata)[1];
115329f1
         if(s->bitstream_bpp==0)
dd1c8f3e
             s->bitstream_bpp= avctx->bits_per_coded_sample&~7;
42dd22c4
         interlace= (((uint8_t*)avctx->extradata)[2] & 0x30) >> 4;
         s->interlaced= (interlace==1) ? 1 : (interlace==2) ? 0 : s->interlaced;
11087086
         s->context= ((uint8_t*)avctx->extradata)[2] & 0x40 ? 1 : 0;
115329f1
 
2818bdf2
         if(read_huffman_tables(s, ((uint8_t*)avctx->extradata)+4, avctx->extradata_size-4) < 0)
11f18faf
             return -1;
     }else{
dd1c8f3e
         switch(avctx->bits_per_coded_sample&7){
11f18faf
         case 1:
             s->predictor= LEFT;
             s->decorrelate= 0;
             break;
         case 2:
             s->predictor= LEFT;
             s->decorrelate= 1;
             break;
         case 3:
             s->predictor= PLANE;
dd1c8f3e
             s->decorrelate= avctx->bits_per_coded_sample >= 24;
11f18faf
             break;
         case 4:
             s->predictor= MEDIAN;
             s->decorrelate= 0;
             break;
         default:
             s->predictor= LEFT; //OLD
             s->decorrelate= 0;
             break;
         }
dd1c8f3e
         s->bitstream_bpp= avctx->bits_per_coded_sample & ~7;
11087086
         s->context= 0;
115329f1
 
11f18faf
         if(read_old_huffman_tables(s) < 0)
             return -1;
     }
115329f1
 
11f18faf
     switch(s->bitstream_bpp){
     case 12:
         avctx->pix_fmt = PIX_FMT_YUV420P;
         break;
     case 16:
         if(s->yuy2){
71e445fc
             avctx->pix_fmt = PIX_FMT_YUYV422;
11f18faf
         }else{
             avctx->pix_fmt = PIX_FMT_YUV422P;
         }
         break;
     case 24:
     case 32:
         if(s->bgr32){
71e445fc
             avctx->pix_fmt = PIX_FMT_RGB32;
11f18faf
         }else{
             avctx->pix_fmt = PIX_FMT_BGR24;
         }
         break;
     default:
         assert(0);
     }
115329f1
 
ae2f1d46
     alloc_temp(s);
115329f1
 
dd1c8f3e
 //    av_log(NULL, AV_LOG_DEBUG, "pred:%d bpp:%d hbpp:%d il:%d\n", s->predictor, s->bitstream_bpp, avctx->bits_per_coded_sample, s->interlaced);
07140e39
 
11f18faf
     return 0;
 }
e9e9139c
 
 static av_cold int decode_init_thread_copy(AVCodecContext *avctx)
 {
     HYuvContext *s = avctx->priv_data;
     int i;
 
     avctx->coded_frame= &s->picture;
     alloc_temp(s);
 
     for (i = 0; i < 6; i++)
         s->vlc[i].table = NULL;
 
     if(s->version==2){
         if(read_huffman_tables(s, ((uint8_t*)avctx->extradata)+4, avctx->extradata_size) < 0)
             return -1;
     }else{
         if(read_old_huffman_tables(s) < 0)
             return -1;
     }
 
     return 0;
 }
b250f9c6
 #endif /* CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER */
11f18faf
 
b250f9c6
 #if CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER
22c29c36
 static int store_table(HYuvContext *s, const uint8_t *len, uint8_t *buf){
11f18faf
     int i;
11087086
     int index= 0;
11f18faf
 
     for(i=0; i<256;){
         int val= len[i];
a003ee9a
         int repeat=0;
115329f1
 
a003ee9a
         for(; i<256 && len[i]==val && repeat<255; i++)
             repeat++;
115329f1
 
a003ee9a
         assert(val < 32 && val >0 && repeat<256 && repeat>0);
11f18faf
         if(repeat>7){
11087086
             buf[index++]= val;
             buf[index++]= repeat;
11f18faf
         }else{
11087086
             buf[index++]= val | (repeat<<5);
11f18faf
         }
     }
115329f1
 
11087086
     return index;
11f18faf
 }
 
98a6fff9
 static av_cold int encode_init(AVCodecContext *avctx)
11f18faf
 {
     HYuvContext *s = avctx->priv_data;
0ecca7a4
     int i, j;
11f18faf
 
0ecca7a4
     common_init(avctx);
115329f1
 
0ecca7a4
     avctx->extradata= av_mallocz(1024*30); // 256*3+4 == 772
     avctx->stats_out= av_mallocz(1024*30); // 21*256*3(%llu ) + 3(\n) + 1(0) = 16132
11f18faf
     s->version=2;
115329f1
 
492cd3a9
     avctx->coded_frame= &s->picture;
115329f1
 
11f18faf
     switch(avctx->pix_fmt){
152ba68c
     case PIX_FMT_YUV420P:
         s->bitstream_bpp= 12;
         break;
11f18faf
     case PIX_FMT_YUV422P:
         s->bitstream_bpp= 16;
         break;
d2bfaf8a
     case PIX_FMT_RGB32:
         s->bitstream_bpp= 24;
         break;
11f18faf
     default:
9b879566
         av_log(avctx, AV_LOG_ERROR, "format not supported\n");
11f18faf
         return -1;
     }
dd1c8f3e
     avctx->bits_per_coded_sample= s->bitstream_bpp;
11f18faf
     s->decorrelate= s->bitstream_bpp >= 24;
     s->predictor= avctx->prediction_method;
ee598f7b
     s->interlaced= avctx->flags&CODEC_FLAG_INTERLACED_ME ? 1 : 0;
11087086
     if(avctx->context_model==1){
         s->context= avctx->context_model;
         if(s->flags & (CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)){
             av_log(avctx, AV_LOG_ERROR, "context=1 is not compatible with 2 pass huffyuv encoding\n");
             return -1;
         }
     }else s->context= 0;
115329f1
 
f37b9768
     if(avctx->codec->id==CODEC_ID_HUFFYUV){
         if(avctx->pix_fmt==PIX_FMT_YUV420P){
             av_log(avctx, AV_LOG_ERROR, "Error: YV12 is not supported by huffyuv; use vcodec=ffvhuff or format=422p\n");
             return -1;
         }
         if(avctx->context_model){
             av_log(avctx, AV_LOG_ERROR, "Error: per-frame huffman tables are not supported by huffyuv; use vcodec=ffvhuff\n");
             return -1;
         }
0ecca7a4
         if(s->interlaced != ( s->height > 288 ))
f37b9768
             av_log(avctx, AV_LOG_INFO, "using huffyuv 2.2.0 or newer interlacing flag\n");
     }
115329f1
 
d2bfaf8a
     if(s->bitstream_bpp>=24 && s->predictor==MEDIAN){
         av_log(avctx, AV_LOG_ERROR, "Error: RGB is incompatible with median predictor\n");
         return -1;
     }
 
     ((uint8_t*)avctx->extradata)[0]= s->predictor | (s->decorrelate << 6);
11f18faf
     ((uint8_t*)avctx->extradata)[1]= s->bitstream_bpp;
42dd22c4
     ((uint8_t*)avctx->extradata)[2]= s->interlaced ? 0x10 : 0x20;
11087086
     if(s->context)
         ((uint8_t*)avctx->extradata)[2]|= 0x40;
11f18faf
     ((uint8_t*)avctx->extradata)[3]= 0;
     s->avctx->extradata_size= 4;
115329f1
 
11f18faf
     if(avctx->stats_in){
         char *p= avctx->stats_in;
115329f1
 
11f18faf
         for(i=0; i<3; i++)
             for(j=0; j<256; j++)
                 s->stats[i][j]= 1;
 
         for(;;){
             for(i=0; i<3; i++){
                 char *next;
 
                 for(j=0; j<256; j++){
                     s->stats[i][j]+= strtol(p, &next, 0);
                     if(next==p) return -1;
                     p=next;
115329f1
                 }
11f18faf
             }
             if(p[0]==0 || p[1]==0 || p[2]==0) break;
         }
     }else{
         for(i=0; i<3; i++)
             for(j=0; j<256; j++){
                 int d= FFMIN(j, 256-j);
115329f1
 
11f18faf
                 s->stats[i][j]= 100000000/(d+1);
             }
     }
115329f1
 
11f18faf
     for(i=0; i<3; i++){
95024414
         generate_len_table(s->len[i], s->stats[i]);
11f18faf
 
         if(generate_bits_table(s->bits[i], s->len[i])<0){
             return -1;
         }
115329f1
 
11087086
         s->avctx->extradata_size+=
         store_table(s, s->len[i], &((uint8_t*)s->avctx->extradata)[s->avctx->extradata_size]);
11f18faf
     }
 
11087086
     if(s->context){
         for(i=0; i<3; i++){
0ecca7a4
             int pels = s->width*s->height / (i?40:10);
11087086
             for(j=0; j<256; j++){
                 int d= FFMIN(j, 256-j);
                 s->stats[i][j]= pels/(d+1);
             }
         }
     }else{
         for(i=0; i<3; i++)
             for(j=0; j<256; j++)
                 s->stats[i][j]= 0;
     }
115329f1
 
dd1c8f3e
 //    printf("pred:%d bpp:%d hbpp:%d il:%d\n", s->predictor, s->bitstream_bpp, avctx->bits_per_coded_sample, s->interlaced);
5fd74135
 
ae2f1d46
     alloc_temp(s);
 
11f18faf
     s->picture_number=0;
5fd74135
 
11f18faf
     return 0;
 }
b250f9c6
 #endif /* CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER */
11f18faf
 
19716d64
 /* 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. */
 #define READ_2PIX(dst0, dst1, plane1){\
acc0e0c8
     uint16_t code = get_vlc2(&s->gb, s->vlc[3+plane1].table, VLC_BITS, 1);\
     if(code != 0xffff){\
         dst0 = code>>8;\
         dst1 = code;\
19716d64
     }else{\
         dst0 = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);\
         dst1 = get_vlc2(&s->gb, s->vlc[plane1].table, VLC_BITS, 3);\
     }\
 }
 
11f18faf
 static void decode_422_bitstream(HYuvContext *s, int count){
     int i;
5fd74135
 
11f18faf
     count/=2;
115329f1
 
6e44ba15
     if(count >= (get_bits_left(&s->gb))/(31*4)){
37458d7e
         for(i=0; i<count && get_bits_count(&s->gb) < s->gb.size_in_bits; i++){
             READ_2PIX(s->temp[0][2*i  ], s->temp[1][i], 1);
             READ_2PIX(s->temp[0][2*i+1], s->temp[2][i], 2);
         }
     }else{
fb6ecd72
         for(i=0; i<count; i++){
             READ_2PIX(s->temp[0][2*i  ], s->temp[1][i], 1);
             READ_2PIX(s->temp[0][2*i+1], s->temp[2][i], 2);
         }
37458d7e
     }
11f18faf
 }
 
152ba68c
 static void decode_gray_bitstream(HYuvContext *s, int count){
     int i;
115329f1
 
152ba68c
     count/=2;
115329f1
 
6e44ba15
     if(count >= (get_bits_left(&s->gb))/(31*2)){
37458d7e
         for(i=0; i<count && get_bits_count(&s->gb) < s->gb.size_in_bits; i++){
             READ_2PIX(s->temp[0][2*i  ], s->temp[0][2*i+1], 0);
         }
     }else{
fb6ecd72
         for(i=0; i<count; i++){
             READ_2PIX(s->temp[0][2*i  ], s->temp[0][2*i+1], 0);
         }
37458d7e
     }
152ba68c
 }
 
b250f9c6
 #if CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER
aa5cfdfb
 static int encode_422_bitstream(HYuvContext *s, int offset, int count){
11f18faf
     int i;
aa5cfdfb
     const uint8_t *y = s->temp[0] + offset;
     const uint8_t *u = s->temp[1] + offset/2;
     const uint8_t *v = s->temp[2] + offset/2;
115329f1
 
0ecca7a4
     if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 2*4*count){
         av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
         return -1;
     }
115329f1
 
bf1a5a46
 #define LOAD4\
aa5cfdfb
             int y0 = y[2*i];\
             int y1 = y[2*i+1];\
             int u0 = u[i];\
             int v0 = v[i];
bf1a5a46
 
11f18faf
     count/=2;
     if(s->flags&CODEC_FLAG_PASS1){
         for(i=0; i<count; i++){
bf1a5a46
             LOAD4;
             s->stats[0][y0]++;
             s->stats[1][u0]++;
             s->stats[0][y1]++;
             s->stats[2][v0]++;
11f18faf
         }
09b0499f
     }
     if(s->avctx->flags2&CODEC_FLAG2_NO_OUTPUT)
         return 0;
     if(s->context){
11087086
         for(i=0; i<count; i++){
bf1a5a46
             LOAD4;
             s->stats[0][y0]++;
             put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);
             s->stats[1][u0]++;
             put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]);
             s->stats[0][y1]++;
             put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
             s->stats[2][v0]++;
             put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]);
11087086
         }
11f18faf
     }else{
         for(i=0; i<count; i++){
bf1a5a46
             LOAD4;
             put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);
             put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]);
             put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
             put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]);
11f18faf
         }
     }
0ecca7a4
     return 0;
11f18faf
 }
 
0ecca7a4
 static int encode_gray_bitstream(HYuvContext *s, int count){
152ba68c
     int i;
115329f1
 
0ecca7a4
     if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 4*count){
         av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
         return -1;
     }
 
bf1a5a46
 #define LOAD2\
             int y0 = s->temp[0][2*i];\
             int y1 = s->temp[0][2*i+1];
 #define STAT2\
             s->stats[0][y0]++;\
             s->stats[0][y1]++;
 #define WRITE2\
             put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);\
             put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
 
152ba68c
     count/=2;
     if(s->flags&CODEC_FLAG_PASS1){
         for(i=0; i<count; i++){
bf1a5a46
             LOAD2;
             STAT2;
152ba68c
         }
09b0499f
     }
     if(s->avctx->flags2&CODEC_FLAG2_NO_OUTPUT)
         return 0;
115329f1
 
09b0499f
     if(s->context){
11087086
         for(i=0; i<count; i++){
bf1a5a46
             LOAD2;
             STAT2;
             WRITE2;
11087086
         }
152ba68c
     }else{
         for(i=0; i<count; i++){
bf1a5a46
             LOAD2;
             WRITE2;
152ba68c
         }
     }
0ecca7a4
     return 0;
152ba68c
 }
b250f9c6
 #endif /* CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER */
152ba68c
 
8be6dac8
 static av_always_inline void decode_bgr_1(HYuvContext *s, int count, int decorrelate, int alpha){
11f18faf
     int i;
8be6dac8
     for(i=0; i<count; i++){
         int code = get_vlc2(&s->gb, s->vlc[3].table, VLC_BITS, 1);
         if(code != -1){
             *(uint32_t*)&s->temp[0][4*i] = s->pix_bgr_map[code];
         }else if(decorrelate){
             s->temp[0][4*i+G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3);
             s->temp[0][4*i+B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3) + s->temp[0][4*i+G];
             s->temp[0][4*i+R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3) + s->temp[0][4*i+G];
11f18faf
         }else{
8be6dac8
             s->temp[0][4*i+B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);
             s->temp[0][4*i+G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3);
             s->temp[0][4*i+R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3);
11f18faf
         }
8be6dac8
         if(alpha)
f267d3ac
             s->temp[0][4*i+A] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3);
8be6dac8
     }
 }
 
 static void decode_bgr_bitstream(HYuvContext *s, int count){
     if(s->decorrelate){
         if(s->bitstream_bpp==24)
             decode_bgr_1(s, count, 1, 0);
         else
             decode_bgr_1(s, count, 1, 1);
11f18faf
     }else{
8be6dac8
         if(s->bitstream_bpp==24)
             decode_bgr_1(s, count, 0, 0);
         else
             decode_bgr_1(s, count, 0, 1);
11f18faf
     }
 }
 
d2bfaf8a
 static int encode_bgr_bitstream(HYuvContext *s, int count){
     int i;
 
     if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 3*4*count){
         av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
         return -1;
     }
 
bf1a5a46
 #define LOAD3\
             int g= s->temp[0][4*i+G];\
             int b= (s->temp[0][4*i+B] - g) & 0xff;\
d2bfaf8a
             int r= (s->temp[0][4*i+R] - g) & 0xff;
bf1a5a46
 #define STAT3\
             s->stats[0][b]++;\
             s->stats[1][g]++;\
d2bfaf8a
             s->stats[2][r]++;
bf1a5a46
 #define WRITE3\
             put_bits(&s->pb, s->len[1][g], s->bits[1][g]);\
             put_bits(&s->pb, s->len[0][b], s->bits[0][b]);\
             put_bits(&s->pb, s->len[2][r], s->bits[2][r]);
 
     if((s->flags&CODEC_FLAG_PASS1) && (s->avctx->flags2&CODEC_FLAG2_NO_OUTPUT)){
         for(i=0; i<count; i++){
             LOAD3;
             STAT3;
d2bfaf8a
         }
     }else if(s->context || (s->flags&CODEC_FLAG_PASS1)){
         for(i=0; i<count; i++){
bf1a5a46
             LOAD3;
             STAT3;
             WRITE3;
d2bfaf8a
         }
     }else{
         for(i=0; i<count; i++){
bf1a5a46
             LOAD3;
             WRITE3;
d2bfaf8a
         }
     }
     return 0;
 }
 
b250f9c6
 #if CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER
7c5ab7b8
 static void draw_slice(HYuvContext *s, int y){
     int h, cy;
7a06ff14
     int offset[4];
115329f1
 
     if(s->avctx->draw_horiz_band==NULL)
7c5ab7b8
         return;
115329f1
 
7c5ab7b8
     h= y - s->last_slice_end;
     y -= h;
115329f1
 
7c5ab7b8
     if(s->bitstream_bpp==12){
         cy= y>>1;
     }else{
         cy= y;
     }
7a06ff14
 
     offset[0] = s->picture.linesize[0]*y;
     offset[1] = s->picture.linesize[1]*cy;
     offset[2] = s->picture.linesize[2]*cy;
     offset[3] = 0;
7c5ab7b8
     emms_c();
 
3bb07d61
     s->avctx->draw_horiz_band(s->avctx, &s->picture, offset, y, 3, h);
115329f1
 
7c5ab7b8
     s->last_slice_end= y + h;
 }
 
7a00bbad
 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt){
     const uint8_t *buf = avpkt->data;
     int buf_size = avpkt->size;
11f18faf
     HYuvContext *s = avctx->priv_data;
     const int width= s->width;
     const int width2= s->width>>1;
     const int height= s->height;
22f3e8be
     int fake_ystride, fake_ustride, fake_vstride;
492cd3a9
     AVFrame * const p= &s->picture;
11087086
     int table_size= 0;
11f18faf
 
492cd3a9
     AVFrame *picture = data;
11f18faf
 
238ef6da
     av_fast_malloc(&s->bitstream_buffer, &s->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
     if (!s->bitstream_buffer)
         return AVERROR(ENOMEM);
11f18faf
 
6ec8eadd
     memset(s->bitstream_buffer + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
fb2cf1bc
     s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer, (const uint32_t*)buf, buf_size/4);
115329f1
 
e20c4069
     if(p->data[0])
e9e9139c
         ff_thread_release_buffer(avctx, p);
e20c4069
 
1e491e29
     p->reference= 0;
e9e9139c
     if(ff_thread_get_buffer(avctx, p) < 0){
9b879566
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
1e491e29
         return -1;
22f3e8be
     }
115329f1
 
11087086
     if(s->context){
         table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size);
         if(table_size < 0)
             return -1;
     }
 
e70e7a4b
     if((unsigned)(buf_size-table_size) >= INT_MAX/8)
         return -1;
 
11087086
     init_get_bits(&s->gb, s->bitstream_buffer+table_size, (buf_size-table_size)*8);
1e491e29
 
     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];
115329f1
 
7c5ab7b8
     s->last_slice_end= 0;
115329f1
 
11f18faf
     if(s->bitstream_bpp<24){
152ba68c
         int y, cy;
11f18faf
         int lefty, leftu, leftv;
         int lefttopy, lefttopu, lefttopv;
115329f1
 
11f18faf
         if(s->yuy2){
1e491e29
             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);
115329f1
 
160d679c
             av_log(avctx, AV_LOG_ERROR, "YUY2 output is not implemented yet\n");
11f18faf
             return -1;
         }else{
115329f1
 
1e491e29
             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);
115329f1
 
11f18faf
             switch(s->predictor){
             case LEFT:
             case PLANE:
                 decode_422_bitstream(s, width-2);
73c6f598
                 lefty= s->dsp.add_hfyu_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty);
11f18faf
                 if(!(s->flags&CODEC_FLAG_GRAY)){
73c6f598
                     leftu= s->dsp.add_hfyu_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu);
                     leftv= s->dsp.add_hfyu_left_prediction(p->data[2] + 1, s->temp[2], width2-1, leftv);
11f18faf
                 }
 
152ba68c
                 for(cy=y=1; y<s->height; y++,cy++){
11f18faf
                     uint8_t *ydst, *udst, *vdst;
115329f1
 
152ba68c
                     if(s->bitstream_bpp==12){
                         decode_gray_bitstream(s, width);
115329f1
 
1e491e29
                         ydst= p->data[0] + p->linesize[0]*y;
152ba68c
 
73c6f598
                         lefty= s->dsp.add_hfyu_left_prediction(ydst, s->temp[0], width, lefty);
152ba68c
                         if(s->predictor == PLANE){
                             if(y>s->interlaced)
                                 s->dsp.add_bytes(ydst, ydst - fake_ystride, width);
                         }
                         y++;
                         if(y>=s->height) break;
                     }
115329f1
 
7c5ab7b8
                     draw_slice(s, y);
115329f1
 
1e491e29
                     ydst= p->data[0] + p->linesize[0]*y;
                     udst= p->data[1] + p->linesize[1]*cy;
                     vdst= p->data[2] + p->linesize[2]*cy;
115329f1
 
152ba68c
                     decode_422_bitstream(s, width);
73c6f598
                     lefty= s->dsp.add_hfyu_left_prediction(ydst, s->temp[0], width, lefty);
11f18faf
                     if(!(s->flags&CODEC_FLAG_GRAY)){
73c6f598
                         leftu= s->dsp.add_hfyu_left_prediction(udst, s->temp[1], width2, leftu);
                         leftv= s->dsp.add_hfyu_left_prediction(vdst, s->temp[2], width2, leftv);
11f18faf
                     }
                     if(s->predictor == PLANE){
152ba68c
                         if(cy>s->interlaced){
11f18faf
                             s->dsp.add_bytes(ydst, ydst - fake_ystride, width);
                             if(!(s->flags&CODEC_FLAG_GRAY)){
                                 s->dsp.add_bytes(udst, udst - fake_ustride, width2);
                                 s->dsp.add_bytes(vdst, vdst - fake_vstride, width2);
                             }
                         }
                     }
                 }
7c5ab7b8
                 draw_slice(s, height);
115329f1
 
11f18faf
                 break;
             case MEDIAN:
                 /* first line except first 2 pixels is left predicted */
                 decode_422_bitstream(s, width-2);
73c6f598
                 lefty= s->dsp.add_hfyu_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty);
11f18faf
                 if(!(s->flags&CODEC_FLAG_GRAY)){
73c6f598
                     leftu= s->dsp.add_hfyu_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu);
                     leftv= s->dsp.add_hfyu_left_prediction(p->data[2] + 1, s->temp[2], width2-1, leftv);
11f18faf
                 }
115329f1
 
152ba68c
                 cy=y=1;
115329f1
 
11f18faf
                 /* second line is left predicted for interlaced case */
                 if(s->interlaced){
                     decode_422_bitstream(s, width);
73c6f598
                     lefty= s->dsp.add_hfyu_left_prediction(p->data[0] + p->linesize[0], s->temp[0], width, lefty);
11f18faf
                     if(!(s->flags&CODEC_FLAG_GRAY)){
73c6f598
                         leftu= s->dsp.add_hfyu_left_prediction(p->data[1] + p->linesize[2], s->temp[1], width2, leftu);
                         leftv= s->dsp.add_hfyu_left_prediction(p->data[2] + p->linesize[1], s->temp[2], width2, leftv);
11f18faf
                     }
152ba68c
                     y++; cy++;
11f18faf
                 }
 
                 /* next 4 pixels are left predicted too */
                 decode_422_bitstream(s, 4);
73c6f598
                 lefty= s->dsp.add_hfyu_left_prediction(p->data[0] + fake_ystride, s->temp[0], 4, lefty);
11f18faf
                 if(!(s->flags&CODEC_FLAG_GRAY)){
73c6f598
                     leftu= s->dsp.add_hfyu_left_prediction(p->data[1] + fake_ustride, s->temp[1], 2, leftu);
                     leftv= s->dsp.add_hfyu_left_prediction(p->data[2] + fake_vstride, s->temp[2], 2, leftv);
11f18faf
                 }
 
                 /* next line except the first 4 pixels is median predicted */
1e491e29
                 lefttopy= p->data[0][3];
11f18faf
                 decode_422_bitstream(s, width-4);
3daa434a
                 s->dsp.add_hfyu_median_prediction(p->data[0] + fake_ystride+4, p->data[0]+4, s->temp[0], width-4, &lefty, &lefttopy);
11f18faf
                 if(!(s->flags&CODEC_FLAG_GRAY)){
1e491e29
                     lefttopu= p->data[1][1];
                     lefttopv= p->data[2][1];
3daa434a
                     s->dsp.add_hfyu_median_prediction(p->data[1] + fake_ustride+2, p->data[1]+2, s->temp[1], width2-2, &leftu, &lefttopu);
                     s->dsp.add_hfyu_median_prediction(p->data[2] + fake_vstride+2, p->data[2]+2, s->temp[2], width2-2, &leftv, &lefttopv);
11f18faf
                 }
152ba68c
                 y++; cy++;
115329f1
 
152ba68c
                 for(; y<height; y++,cy++){
11f18faf
                     uint8_t *ydst, *udst, *vdst;
152ba68c
 
                     if(s->bitstream_bpp==12){
                         while(2*cy > y){
                             decode_gray_bitstream(s, width);
1e491e29
                             ydst= p->data[0] + p->linesize[0]*y;
3daa434a
                             s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy);
152ba68c
                             y++;
                         }
                         if(y>=height) break;
                     }
7c5ab7b8
                     draw_slice(s, y);
152ba68c
 
11f18faf
                     decode_422_bitstream(s, width);
152ba68c
 
1e491e29
                     ydst= p->data[0] + p->linesize[0]*y;
                     udst= p->data[1] + p->linesize[1]*cy;
                     vdst= p->data[2] + p->linesize[2]*cy;
11f18faf
 
3daa434a
                     s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy);
11f18faf
                     if(!(s->flags&CODEC_FLAG_GRAY)){
3daa434a
                         s->dsp.add_hfyu_median_prediction(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu);
                         s->dsp.add_hfyu_median_prediction(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv);
11f18faf
                     }
                 }
7c5ab7b8
 
                 draw_slice(s, height);
11f18faf
                 break;
             }
         }
     }else{
         int y;
f267d3ac
         int leftr, leftg, leftb, lefta;
1e491e29
         const int last_line= (height-1)*p->linesize[0];
115329f1
 
11f18faf
         if(s->bitstream_bpp==32){
f267d3ac
             lefta= p->data[0][last_line+A]= get_bits(&s->gb, 8);
0722ccdb
             leftr= p->data[0][last_line+R]= get_bits(&s->gb, 8);
             leftg= p->data[0][last_line+G]= get_bits(&s->gb, 8);
             leftb= p->data[0][last_line+B]= get_bits(&s->gb, 8);
11f18faf
         }else{
0722ccdb
             leftr= p->data[0][last_line+R]= get_bits(&s->gb, 8);
             leftg= p->data[0][last_line+G]= get_bits(&s->gb, 8);
             leftb= p->data[0][last_line+B]= get_bits(&s->gb, 8);
f267d3ac
             lefta= p->data[0][last_line+A]= 255;
11f18faf
             skip_bits(&s->gb, 8);
         }
115329f1
 
11f18faf
         if(s->bgr32){
             switch(s->predictor){
             case LEFT:
             case PLANE:
                 decode_bgr_bitstream(s, width-1);
f267d3ac
                 s->dsp.add_hfyu_left_prediction_bgr32(p->data[0] + last_line+4, s->temp[0], width-1, &leftr, &leftg, &leftb, &lefta);
11f18faf
 
90b5b51e
                 for(y=s->height-2; y>=0; y--){ //Yes it is stored upside down.
11f18faf
                     decode_bgr_bitstream(s, width);
115329f1
 
f267d3ac
                     s->dsp.add_hfyu_left_prediction_bgr32(p->data[0] + p->linesize[0]*y, s->temp[0], width, &leftr, &leftg, &leftb, &lefta);
11f18faf
                     if(s->predictor == PLANE){
f267d3ac
                         if(s->bitstream_bpp!=32) lefta=0;
fc0be57f
                         if((y&s->interlaced)==0 && y<s->height-1-s->interlaced){
115329f1
                             s->dsp.add_bytes(p->data[0] + p->linesize[0]*y,
1e491e29
                                              p->data[0] + p->linesize[0]*y + fake_ystride, fake_ystride);
11f18faf
                         }
                     }
                 }
160d679c
                 draw_slice(s, height); // just 1 large slice as this is not possible in reverse order
11f18faf
                 break;
             default:
9b879566
                 av_log(avctx, AV_LOG_ERROR, "prediction type not supported!\n");
11f18faf
             }
         }else{
 
160d679c
             av_log(avctx, AV_LOG_ERROR, "BGR24 output is not implemented yet\n");
11f18faf
             return -1;
         }
     }
     emms_c();
115329f1
 
1e491e29
     *picture= *p;
492cd3a9
     *data_size = sizeof(AVFrame);
115329f1
 
1adc29ee
     return (get_bits_count(&s->gb)+31)/32*4 + table_size;
11f18faf
 }
b250f9c6
 #endif /* CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER */
11f18faf
 
0ecca7a4
 static int common_end(HYuvContext *s){
     int i;
115329f1
 
0ecca7a4
     for(i=0; i<3; i++){
         av_freep(&s->temp[i]);
     }
     return 0;
 }
 
b250f9c6
 #if CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER
98a6fff9
 static av_cold int decode_end(AVCodecContext *avctx)
11f18faf
 {
     HYuvContext *s = avctx->priv_data;
     int i;
115329f1
 
0b7f39c9
     if (s->picture.data[0])
         avctx->release_buffer(avctx, &s->picture);
 
0ecca7a4
     common_end(s);
     av_freep(&s->bitstream_buffer);
115329f1
 
7b62bb2b
     for(i=0; i<6; i++){
11f18faf
         free_vlc(&s->vlc[i]);
     }
1e491e29
 
11f18faf
     return 0;
 }
b250f9c6
 #endif /* CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER */
11f18faf
 
b250f9c6
 #if CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER
11f18faf
 static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
     HYuvContext *s = avctx->priv_data;
492cd3a9
     AVFrame *pict = data;
11f18faf
     const int width= s->width;
     const int width2= s->width>>1;
     const int height= s->height;
     const int fake_ystride= s->interlaced ? pict->linesize[0]*2  : pict->linesize[0];
     const int fake_ustride= s->interlaced ? pict->linesize[1]*2  : pict->linesize[1];
     const int fake_vstride= s->interlaced ? pict->linesize[2]*2  : pict->linesize[2];
492cd3a9
     AVFrame * const p= &s->picture;
11087086
     int i, j, size=0;
11f18faf
 
1e491e29
     *p = *pict;
ce5e49b0
     p->pict_type= AV_PICTURE_TYPE_I;
aaa1e4cd
     p->key_frame= 1;
115329f1
 
11087086
     if(s->context){
         for(i=0; i<3; i++){
95024414
             generate_len_table(s->len[i], s->stats[i]);
11087086
             if(generate_bits_table(s->bits[i], s->len[i])<0)
                 return -1;
             size+= store_table(s, s->len[i], &buf[size]);
         }
 
         for(i=0; i<3; i++)
             for(j=0; j<256; j++)
                 s->stats[i][j] >>= 1;
     }
 
     init_put_bits(&s->pb, buf+size, buf_size-size);
 
152ba68c
     if(avctx->pix_fmt == PIX_FMT_YUV422P || avctx->pix_fmt == PIX_FMT_YUV420P){
         int lefty, leftu, leftv, y, cy;
11f18faf
 
1e491e29
         put_bits(&s->pb, 8, leftv= p->data[2][0]);
         put_bits(&s->pb, 8, lefty= p->data[0][1]);
         put_bits(&s->pb, 8, leftu= p->data[1][0]);
         put_bits(&s->pb, 8,        p->data[0][0]);
115329f1
 
fdb699de
         lefty= sub_left_prediction(s, s->temp[0], p->data[0], width , 0);
         leftu= sub_left_prediction(s, s->temp[1], p->data[1], width2, 0);
         leftv= sub_left_prediction(s, s->temp[2], p->data[2], width2, 0);
115329f1
 
fdb699de
         encode_422_bitstream(s, 2, width-2);
115329f1
 
11f18faf
         if(s->predictor==MEDIAN){
             int lefttopy, lefttopu, lefttopv;
152ba68c
             cy=y=1;
11f18faf
             if(s->interlaced){
1e491e29
                 lefty= sub_left_prediction(s, s->temp[0], p->data[0]+p->linesize[0], width , lefty);
                 leftu= sub_left_prediction(s, s->temp[1], p->data[1]+p->linesize[1], width2, leftu);
                 leftv= sub_left_prediction(s, s->temp[2], p->data[2]+p->linesize[2], width2, leftv);
115329f1
 
aa5cfdfb
                 encode_422_bitstream(s, 0, width);
152ba68c
                 y++; cy++;
11f18faf
             }
115329f1
 
1e491e29
             lefty= sub_left_prediction(s, s->temp[0], p->data[0]+fake_ystride, 4, lefty);
07140e39
             leftu= sub_left_prediction(s, s->temp[1], p->data[1]+fake_ustride, 2, leftu);
             leftv= sub_left_prediction(s, s->temp[2], p->data[2]+fake_vstride, 2, leftv);
115329f1
 
aa5cfdfb
             encode_422_bitstream(s, 0, 4);
152ba68c
 
1e491e29
             lefttopy= p->data[0][3];
             lefttopu= p->data[1][1];
             lefttopv= p->data[2][1];
84705403
             s->dsp.sub_hfyu_median_prediction(s->temp[0], p->data[0]+4, p->data[0] + fake_ystride+4, width-4 , &lefty, &lefttopy);
             s->dsp.sub_hfyu_median_prediction(s->temp[1], p->data[1]+2, p->data[1] + fake_ustride+2, width2-2, &leftu, &lefttopu);
             s->dsp.sub_hfyu_median_prediction(s->temp[2], p->data[2]+2, p->data[2] + fake_vstride+2, width2-2, &leftv, &lefttopv);
aa5cfdfb
             encode_422_bitstream(s, 0, width-4);
152ba68c
             y++; cy++;
11f18faf
 
152ba68c
             for(; y<height; y++,cy++){
11f18faf
                 uint8_t *ydst, *udst, *vdst;
115329f1
 
152ba68c
                 if(s->bitstream_bpp==12){
                     while(2*cy > y){
1e491e29
                         ydst= p->data[0] + p->linesize[0]*y;
84705403
                         s->dsp.sub_hfyu_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy);
152ba68c
                         encode_gray_bitstream(s, width);
                         y++;
                     }
                     if(y>=height) break;
                 }
1e491e29
                 ydst= p->data[0] + p->linesize[0]*y;
                 udst= p->data[1] + p->linesize[1]*cy;
                 vdst= p->data[2] + p->linesize[2]*cy;
11f18faf
 
84705403
                 s->dsp.sub_hfyu_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy);
                 s->dsp.sub_hfyu_median_prediction(s->temp[1], udst - fake_ustride, udst, width2, &leftu, &lefttopu);
                 s->dsp.sub_hfyu_median_prediction(s->temp[2], vdst - fake_vstride, vdst, width2, &leftv, &lefttopv);
11f18faf
 
aa5cfdfb
                 encode_422_bitstream(s, 0, width);
11f18faf
             }
         }else{
152ba68c
             for(cy=y=1; y<height; y++,cy++){
11f18faf
                 uint8_t *ydst, *udst, *vdst;
115329f1
 
152ba68c
                 /* encode a luma only line & y++ */
                 if(s->bitstream_bpp==12){
1e491e29
                     ydst= p->data[0] + p->linesize[0]*y;
152ba68c
 
                     if(s->predictor == PLANE && s->interlaced < y){
7c5ab7b8
                         s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width);
152ba68c
 
7c5ab7b8
                         lefty= sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty);
152ba68c
                     }else{
7c5ab7b8
                         lefty= sub_left_prediction(s, s->temp[0], ydst, width , lefty);
152ba68c
                     }
                     encode_gray_bitstream(s, width);
                     y++;
                     if(y>=height) break;
                 }
115329f1
 
1e491e29
                 ydst= p->data[0] + p->linesize[0]*y;
                 udst= p->data[1] + p->linesize[1]*cy;
                 vdst= p->data[2] + p->linesize[2]*cy;
11f18faf
 
152ba68c
                 if(s->predictor == PLANE && s->interlaced < cy){
7c5ab7b8
                     s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width);
                     s->dsp.diff_bytes(s->temp[2], udst, udst - fake_ustride, width2);
ae2f1d46
                     s->dsp.diff_bytes(s->temp[2] + width2, vdst, vdst - fake_vstride, width2);
11f18faf
 
7c5ab7b8
                     lefty= sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty);
                     leftu= sub_left_prediction(s, s->temp[1], s->temp[2], width2, leftu);
ae2f1d46
                     leftv= sub_left_prediction(s, s->temp[2], s->temp[2] + width2, width2, leftv);
11f18faf
                 }else{
7c5ab7b8
                     lefty= sub_left_prediction(s, s->temp[0], ydst, width , lefty);
                     leftu= sub_left_prediction(s, s->temp[1], udst, width2, leftu);
                     leftv= sub_left_prediction(s, s->temp[2], vdst, width2, leftv);
11f18faf
                 }
 
aa5cfdfb
                 encode_422_bitstream(s, 0, width);
11f18faf
             }
115329f1
         }
d2bfaf8a
     }else if(avctx->pix_fmt == PIX_FMT_RGB32){
         uint8_t *data = p->data[0] + (height-1)*p->linesize[0];
         const int stride = -p->linesize[0];
         const int fake_stride = -fake_ystride;
         int y;
         int leftr, leftg, leftb;
 
         put_bits(&s->pb, 8, leftr= data[R]);
         put_bits(&s->pb, 8, leftg= data[G]);
         put_bits(&s->pb, 8, leftb= data[B]);
         put_bits(&s->pb, 8, 0);
 
         sub_left_prediction_bgr32(s, s->temp[0], data+4, width-1, &leftr, &leftg, &leftb);
         encode_bgr_bitstream(s, width-1);
 
         for(y=1; y<s->height; y++){
             uint8_t *dst = data + y*stride;
             if(s->predictor == PLANE && s->interlaced < y){
                 s->dsp.diff_bytes(s->temp[1], dst, dst - fake_stride, width*4);
                 sub_left_prediction_bgr32(s, s->temp[0], s->temp[1], width, &leftr, &leftg, &leftb);
             }else{
                 sub_left_prediction_bgr32(s, s->temp[0], dst, width, &leftr, &leftg, &leftb);
             }
             encode_bgr_bitstream(s, width);
         }
11f18faf
     }else{
9b879566
         av_log(avctx, AV_LOG_ERROR, "Format not supported!\n");
11f18faf
     }
     emms_c();
115329f1
 
11087086
     size+= (put_bits_count(&s->pb)+31)/8;
300a3d0d
     put_bits(&s->pb, 16, 0);
     put_bits(&s->pb, 15, 0);
11087086
     size/= 4;
115329f1
 
11f18faf
     if((s->flags&CODEC_FLAG_PASS1) && (s->picture_number&31)==0){
         int j;
         char *p= avctx->stats_out;
2fc8ea24
         char *end= p + 1024*30;
11f18faf
         for(i=0; i<3; i++){
             for(j=0; j<256; j++){
4733abcb
                 snprintf(p, end-p, "%"PRIu64" ", s->stats[i][j]);
11f18faf
                 p+= strlen(p);
                 s->stats[i][j]= 0;
             }
2fc8ea24
             snprintf(p, end-p, "\n");
11f18faf
             p++;
         }
390f9f31
     } else
         avctx->stats_out[0] = '\0';
09b0499f
     if(!(s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)){
152ba68c
         flush_put_bits(&s->pb);
3d2e8cce
         s->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, size);
11f18faf
     }
115329f1
 
11f18faf
     s->picture_number++;
1e491e29
 
11f18faf
     return size*4;
 }
 
98a6fff9
 static av_cold int encode_end(AVCodecContext *avctx)
11f18faf
 {
0ecca7a4
     HYuvContext *s = avctx->priv_data;
115329f1
 
0ecca7a4
     common_end(s);
11f18faf
 
     av_freep(&avctx->extradata);
     av_freep(&avctx->stats_out);
115329f1
 
11f18faf
     return 0;
 }
b250f9c6
 #endif /* CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER */
11f18faf
 
b250f9c6
 #if CONFIG_HUFFYUV_DECODER
e7e2df27
 AVCodec ff_huffyuv_decoder = {
11f18faf
     "huffyuv",
72415b2a
     AVMEDIA_TYPE_VIDEO,
11f18faf
     CODEC_ID_HUFFYUV,
     sizeof(HYuvContext),
     decode_init,
     NULL,
     decode_end,
     decode_frame,
e9e9139c
     CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_FRAME_THREADS,
bcdb2378
     NULL,
e9e9139c
     .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
fe4bf374
     .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"),
11f18faf
 };
2a43a093
 #endif
11f18faf
 
b250f9c6
 #if CONFIG_FFVHUFF_DECODER
e7e2df27
 AVCodec ff_ffvhuff_decoder = {
f37b9768
     "ffvhuff",
72415b2a
     AVMEDIA_TYPE_VIDEO,
f37b9768
     CODEC_ID_FFVHUFF,
     sizeof(HYuvContext),
     decode_init,
     NULL,
     decode_end,
     decode_frame,
e9e9139c
     CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_FRAME_THREADS,
bcdb2378
     NULL,
e9e9139c
     .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
fe4bf374
     .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"),
f37b9768
 };
62bb489b
 #endif
f37b9768
 
b250f9c6
 #if CONFIG_HUFFYUV_ENCODER
e7e2df27
 AVCodec ff_huffyuv_encoder = {
11f18faf
     "huffyuv",
72415b2a
     AVMEDIA_TYPE_VIDEO,
11f18faf
     CODEC_ID_HUFFYUV,
     sizeof(HYuvContext),
     encode_init,
     encode_frame,
     encode_end,
2ba83017
     .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE},
fe4bf374
     .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"),
11f18faf
 };
f544a5fc
 #endif
5fd74135
 
b250f9c6
 #if CONFIG_FFVHUFF_ENCODER
e7e2df27
 AVCodec ff_ffvhuff_encoder = {
f37b9768
     "ffvhuff",
72415b2a
     AVMEDIA_TYPE_VIDEO,
f37b9768
     CODEC_ID_FFVHUFF,
     sizeof(HYuvContext),
     encode_init,
     encode_frame,
     encode_end,
2ba83017
     .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE},
fe4bf374
     .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"),
f37b9768
 };
f544a5fc
 #endif