4xm.c 22.7 KB
Newer Older
Michael Niedermayer's avatar
Michael Niedermayer committed
1 2 3 4
/*
 * 4XM codec
 * Copyright (c) 2003 Michael Niedermayer
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
Michael Niedermayer's avatar
Michael Niedermayer committed
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Michael Niedermayer's avatar
Michael Niedermayer committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Michael Niedermayer's avatar
Michael Niedermayer committed
13 14 15 16 17
 * 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
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Michael Niedermayer's avatar
Michael Niedermayer committed
20
 */
21

Michael Niedermayer's avatar
Michael Niedermayer committed
22 23 24 25
/**
 * @file 4xm.c
 * 4XM codec.
 */
26

Michael Niedermayer's avatar
Michael Niedermayer committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"

//#undef NDEBUG
//#include <assert.h>

#define BLOCK_TYPE_VLC_BITS 5
#define ACDC_VLC_BITS 9

#define CFRAME_BUFFER_COUNT 100

static const uint8_t block_type_tab[4][8][2]={
  {   //{8,4,2}x{8,4,2}
    { 0,1}, { 2,2}, { 6,3}, {14,4}, {30,5}, {31,5}, { 0,0}
  },{ //{8,4}x1
    { 0,1}, { 0,0}, { 2,2}, { 6,3}, {14,4}, {15,4}, { 0,0}
  },{ //1x{8,4}
    { 0,1}, { 2,2}, { 0,0}, { 6,3}, {14,4}, {15,4}, { 0,0}
  },{ //1x2, 2x1
    { 0,1}, { 0,0}, { 0,0}, { 2,2}, { 6,3}, {14,4}, {15,4}
  }
};

static const uint8_t size2index[4][4]={
  {-1, 3, 1, 1},
  { 3, 0, 0, 0},
  { 2, 0, 0, 0},
  { 2, 0, 0, 0},
};

static const int8_t mv[256][2]={
{  0,  0},{  0, -1},{ -1,  0},{  1,  0},{  0,  1},{ -1, -1},{  1, -1},{ -1,  1},
{  1,  1},{  0, -2},{ -2,  0},{  2,  0},{  0,  2},{ -1, -2},{  1, -2},{ -2, -1},
{  2, -1},{ -2,  1},{  2,  1},{ -1,  2},{  1,  2},{ -2, -2},{  2, -2},{ -2,  2},
{  2,  2},{  0, -3},{ -3,  0},{  3,  0},{  0,  3},{ -1, -3},{  1, -3},{ -3, -1},
{  3, -1},{ -3,  1},{  3,  1},{ -1,  3},{  1,  3},{ -2, -3},{  2, -3},{ -3, -2},
{  3, -2},{ -3,  2},{  3,  2},{ -2,  3},{  2,  3},{  0, -4},{ -4,  0},{  4,  0},
{  0,  4},{ -1, -4},{  1, -4},{ -4, -1},{  4, -1},{  4,  1},{ -1,  4},{  1,  4},
{ -3, -3},{ -3,  3},{  3,  3},{ -2, -4},{ -4, -2},{  4, -2},{ -4,  2},{ -2,  4},
{  2,  4},{ -3, -4},{  3, -4},{  4, -3},{ -5,  0},{ -4,  3},{ -3,  4},{  3,  4},
{ -1, -5},{ -5, -1},{ -5,  1},{ -1,  5},{ -2, -5},{  2, -5},{  5, -2},{  5,  2},
{ -4, -4},{ -4,  4},{ -3, -5},{ -5, -3},{ -5,  3},{  3,  5},{ -6,  0},{  0,  6},
{ -6, -1},{ -6,  1},{  1,  6},{  2, -6},{ -6,  2},{  2,  6},{ -5, -4},{  5,  4},
{  4,  5},{ -6, -3},{  6,  3},{ -7,  0},{ -1, -7},{  5, -5},{ -7,  1},{ -1,  7},
{  4, -6},{  6,  4},{ -2, -7},{ -7,  2},{ -3, -7},{  7, -3},{  3,  7},{  6, -5},
{  0, -8},{ -1, -8},{ -7, -4},{ -8,  1},{  4,  7},{  2, -8},{ -2,  8},{  6,  6},
{ -8,  3},{  5, -7},{ -5,  7},{  8, -4},{  0, -9},{ -9, -1},{  1,  9},{  7, -6},
{ -7,  6},{ -5, -8},{ -5,  8},{ -9,  3},{  9, -4},{  7, -7},{  8, -6},{  6,  8},
{ 10,  1},{-10,  2},{  9, -5},{ 10, -3},{ -8, -7},{-10, -4},{  6, -9},{-11,  0},
{ 11,  1},{-11, -2},{ -2, 11},{  7, -9},{ -7,  9},{ 10,  6},{ -4, 11},{  8, -9},
{  8,  9},{  5, 11},{  7,-10},{ 12, -3},{ 11,  6},{ -9, -9},{  8, 10},{  5, 12},
{-11,  7},{ 13,  2},{  6,-12},{ 10,  9},{-11,  8},{ -7, 12},{  0, 14},{ 14, -2},
{ -9, 11},{ -6, 13},{-14, -4},{ -5,-14},{  5, 14},{-15, -1},{-14, -6},{  3,-15},
{ 11,-11},{ -7, 14},{ -5, 15},{  8,-14},{ 15,  6},{  3, 16},{  7,-15},{-16,  5},
{  0, 17},{-16, -6},{-10, 14},{-16,  7},{ 12, 13},{-16,  8},{-17,  6},{-18,  3},
{ -7, 17},{ 15, 11},{ 16, 10},{  2,-19},{  3,-19},{-11,-16},{-18,  8},{-19, -6},
{  2,-20},{-17,-11},{-10,-18},{  8, 19},{-21, -1},{-20,  7},{ -4, 21},{ 21,  5},
{ 15, 16},{  2,-22},{-10,-20},{-22,  5},{ 20,-11},{ -7,-22},{-12, 20},{ 23, -5},
{ 13,-20},{ 24, -2},{-15, 19},{-11, 22},{ 16, 19},{ 23,-10},{-18,-18},{ -9,-24},
{ 24,-10},{ -3, 26},{-23, 13},{-18,-20},{ 17, 21},{ -4, 27},{ 27,  6},{  1,-28},
{-11, 26},{-17,-23},{  7, 28},{ 11,-27},{ 29,  5},{-23,-19},{-28,-11},{-21, 22},
{-30,  7},{-17, 26},{-27, 16},{ 13, 29},{ 19,-26},{ 10,-31},{-14,-30},{ 20,-27},
{-29, 18},{-16,-31},{-28,-22},{ 21,-30},{-25, 28},{ 26,-29},{ 25,-32},{-32,-32}
};

// this is simply the scaled down elementwise product of the standard jpeg quantizer table and the AAN premul table
static const uint8_t dequant_table[64]={
 16, 15, 13, 19, 24, 31, 28, 17,
 17, 23, 25, 31, 36, 63, 45, 21,
 18, 24, 27, 37, 52, 59, 49, 20,
 16, 28, 34, 40, 60, 80, 51, 20,
 18, 31, 48, 66, 68, 86, 56, 21,
 19, 38, 56, 59, 64, 64, 48, 20,
 27, 48, 55, 55, 56, 51, 35, 15,
 20, 35, 34, 32, 31, 22, 15,  8,
};

static VLC block_type_vlc[4];


typedef struct CFrameBuffer{
109 110
    unsigned int allocated_size;
    unsigned int size;
Michael Niedermayer's avatar
Michael Niedermayer committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    int id;
    uint8_t *data;
}CFrameBuffer;

typedef struct FourXContext{
    AVCodecContext *avctx;
    DSPContext dsp;
    AVFrame current_picture, last_picture;
    GetBitContext pre_gb;          ///< ac/dc prefix
    GetBitContext gb;
    uint8_t *bytestream;
    uint16_t *wordstream;
    int mv[256];
    VLC pre_vlc;
    int last_dc;
126
    DECLARE_ALIGNED_8(DCTELEM, block[6][64]);
Michael Niedermayer's avatar
Michael Niedermayer committed
127
    uint8_t *bitstream_buffer;
128
    unsigned int bitstream_buffer_size;
Michael Niedermayer's avatar
Michael Niedermayer committed
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    CFrameBuffer cfrm[CFRAME_BUFFER_COUNT];
} FourXContext;


#define FIX_1_082392200  70936
#define FIX_1_414213562  92682
#define FIX_1_847759065 121095
#define FIX_2_613125930 171254

#define MULTIPLY(var,const)  (((var)*(const)) >> 16)

static void idct(DCTELEM block[64]){
    int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
    int tmp10, tmp11, tmp12, tmp13;
    int z5, z10, z11, z12, z13;
    int i;
    int temp[64];
146

Michael Niedermayer's avatar
Michael Niedermayer committed
147 148 149 150 151 152 153 154 155 156 157
    for(i=0; i<8; i++){
        tmp10 = block[8*0 + i] + block[8*4 + i];
        tmp11 = block[8*0 + i] - block[8*4 + i];

        tmp13 =          block[8*2 + i] + block[8*6 + i];
        tmp12 = MULTIPLY(block[8*2 + i] - block[8*6 + i], FIX_1_414213562) - tmp13;

        tmp0 = tmp10 + tmp13;
        tmp3 = tmp10 - tmp13;
        tmp1 = tmp11 + tmp12;
        tmp2 = tmp11 - tmp12;
158

Michael Niedermayer's avatar
Michael Niedermayer committed
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
        z13 = block[8*5 + i] + block[8*3 + i];
        z10 = block[8*5 + i] - block[8*3 + i];
        z11 = block[8*1 + i] + block[8*7 + i];
        z12 = block[8*1 + i] - block[8*7 + i];

        tmp7  =          z11 + z13;
        tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562);

        z5    = MULTIPLY(z10 + z12, FIX_1_847759065);
        tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5;
        tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5;

        tmp6 = tmp12 - tmp7;
        tmp5 = tmp11 - tmp6;
        tmp4 = tmp10 + tmp5;

        temp[8*0 + i] = tmp0 + tmp7;
        temp[8*7 + i] = tmp0 - tmp7;
        temp[8*1 + i] = tmp1 + tmp6;
        temp[8*6 + i] = tmp1 - tmp6;
        temp[8*2 + i] = tmp2 + tmp5;
        temp[8*5 + i] = tmp2 - tmp5;
        temp[8*4 + i] = tmp3 + tmp4;
        temp[8*3 + i] = tmp3 - tmp4;
    }
184

Michael Niedermayer's avatar
Michael Niedermayer committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
    for(i=0; i<8*8; i+=8){
        tmp10 = temp[0 + i] + temp[4 + i];
        tmp11 = temp[0 + i] - temp[4 + i];

        tmp13 = temp[2 + i] + temp[6 + i];
        tmp12 = MULTIPLY(temp[2 + i] - temp[6 + i], FIX_1_414213562) - tmp13;

        tmp0 = tmp10 + tmp13;
        tmp3 = tmp10 - tmp13;
        tmp1 = tmp11 + tmp12;
        tmp2 = tmp11 - tmp12;

        z13 = temp[5 + i] + temp[3 + i];
        z10 = temp[5 + i] - temp[3 + i];
        z11 = temp[1 + i] + temp[7 + i];
        z12 = temp[1 + i] - temp[7 + i];

        tmp7 = z11 + z13;
        tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562);

        z5 = MULTIPLY(z10 + z12, FIX_1_847759065);
        tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5;
        tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5;

        tmp6 = tmp12 - tmp7;
        tmp5 = tmp11 - tmp6;
        tmp4 = tmp10 + tmp5;

        block[0 + i] = (tmp0 + tmp7)>>6;
        block[7 + i] = (tmp0 - tmp7)>>6;
        block[1 + i] = (tmp1 + tmp6)>>6;
        block[6 + i] = (tmp1 - tmp6)>>6;
        block[2 + i] = (tmp2 + tmp5)>>6;
        block[5 + i] = (tmp2 - tmp5)>>6;
        block[4 + i] = (tmp3 + tmp4)>>6;
        block[3 + i] = (tmp3 - tmp4)>>6;
    }
}

static void init_vlcs(FourXContext *f){
    int i;

227
    for(i=0; i<4; i++){
228
        init_vlc(&block_type_vlc[i], BLOCK_TYPE_VLC_BITS, 7,
229 230
                 &block_type_tab[i][0][1], 2, 1,
                 &block_type_tab[i][0][0], 2, 1, 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
    }
}

static void init_mv(FourXContext *f){
    int i;

    for(i=0; i<256; i++){
        f->mv[i] = mv[i][0] + mv[i][1]*f->current_picture.linesize[0]/2;
    }
}

static inline void mcdc(uint16_t *dst, uint16_t *src, int log2w, int h, int stride, int scale, int dc){
   int i;
   dc*= 0x10001;

   switch(log2w){
   case 0:
        for(i=0; i<h; i++){
            dst[0] = scale*src[0] + dc;
            if(scale) src += stride;
            dst += stride;
        }
        break;
    case 1:
        for(i=0; i<h; i++){
            ((uint32_t*)dst)[0] = scale*((uint32_t*)src)[0] + dc;
            if(scale) src += stride;
            dst += stride;
        }
        break;
    case 2:
        for(i=0; i<h; i++){
            ((uint32_t*)dst)[0] = scale*((uint32_t*)src)[0] + dc;
            ((uint32_t*)dst)[1] = scale*((uint32_t*)src)[1] + dc;
            if(scale) src += stride;
            dst += stride;
        }
        break;
    case 3:
        for(i=0; i<h; i++){
            ((uint32_t*)dst)[0] = scale*((uint32_t*)src)[0] + dc;
            ((uint32_t*)dst)[1] = scale*((uint32_t*)src)[1] + dc;
            ((uint32_t*)dst)[2] = scale*((uint32_t*)src)[2] + dc;
            ((uint32_t*)dst)[3] = scale*((uint32_t*)src)[3] + dc;
            if(scale) src += stride;
            dst += stride;
        }
        break;
    default: assert(0);
    }
}

static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int log2w, int log2h, int stride){
    const int index= size2index[log2h][log2w];
    const int h= 1<<log2h;
    int code= get_vlc2(&f->gb, block_type_vlc[index].table, BLOCK_TYPE_VLC_BITS, 1);
287

Michael Niedermayer's avatar
Michael Niedermayer committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
    assert(code>=0 && code<=6);

    if(code == 0){
        src += f->mv[ *f->bytestream++ ];
        mcdc(dst, src, log2w, h, stride, 1, 0);
    }else if(code == 1){
        log2h--;
        decode_p_block(f, dst                  , src                  , log2w, log2h, stride);
        decode_p_block(f, dst + (stride<<log2h), src + (stride<<log2h), log2w, log2h, stride);
    }else if(code == 2){
        log2w--;
        decode_p_block(f, dst             , src             , log2w, log2h, stride);
        decode_p_block(f, dst + (1<<log2w), src + (1<<log2w), log2w, log2h, stride);
    }else if(code == 4){
        src += f->mv[ *f->bytestream++ ];
        mcdc(dst, src, log2w, h, stride, 1, le2me_16(*f->wordstream++));
    }else if(code == 5){
        mcdc(dst, src, log2w, h, stride, 0, le2me_16(*f->wordstream++));
    }else if(code == 6){
        if(log2w){
            dst[0] = le2me_16(*f->wordstream++);
            dst[1] = le2me_16(*f->wordstream++);
        }else{
            dst[0     ] = le2me_16(*f->wordstream++);
            dst[stride] = le2me_16(*f->wordstream++);
        }
    }
}

static int get32(void *p){
    return le2me_32(*(uint32_t*)p);
}

static int decode_p_frame(FourXContext *f, uint8_t *buf, int length){
    int x, y;
    const int width= f->avctx->width;
    const int height= f->avctx->height;
    uint16_t *src= (uint16_t*)f->last_picture.data[0];
    uint16_t *dst= (uint16_t*)f->current_picture.data[0];
    const int stride= f->current_picture.linesize[0]>>1;
328 329 330
    const unsigned int bitstream_size= get32(buf+8);
    const unsigned int bytestream_size= get32(buf+16);
    const unsigned int wordstream_size= get32(buf+12);
331

332 333 334 335 336
    if(bitstream_size+ bytestream_size+ wordstream_size + 20 != length
       || bitstream_size  > (1<<26)
       || bytestream_size > (1<<26)
       || wordstream_size > (1<<26)
       ){
337
        av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size,
Michael Niedermayer's avatar
Michael Niedermayer committed
338
        bitstream_size+ bytestream_size+ wordstream_size - length);
339 340
        return -1;
    }
341

Michael Niedermayer's avatar
Michael Niedermayer committed
342 343 344 345 346 347
    f->bitstream_buffer= av_fast_realloc(f->bitstream_buffer, &f->bitstream_buffer_size, bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE);
    f->dsp.bswap_buf((uint32_t*)f->bitstream_buffer, (uint32_t*)(buf + 20), bitstream_size/4);
    init_get_bits(&f->gb, f->bitstream_buffer, 8*bitstream_size);

    f->wordstream= (uint16_t*)(buf + 20 + bitstream_size);
    f->bytestream= buf + 20 + bitstream_size + wordstream_size;
348

Michael Niedermayer's avatar
Michael Niedermayer committed
349
    init_mv(f);
350

Michael Niedermayer's avatar
Michael Niedermayer committed
351 352 353 354
    for(y=0; y<height; y+=8){
        for(x=0; x<width; x+=8){
            decode_p_block(f, dst + x, src + x, 3, 3, stride);
        }
355 356
        src += 8*stride;
        dst += 8*stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
357
    }
358

Michael Niedermayer's avatar
Michael Niedermayer committed
359
    if(bitstream_size != (get_bits_count(&f->gb)+31)/32*4)
360 361
        av_log(f->avctx, AV_LOG_ERROR, " %d %td %td bytes left\n",
            bitstream_size - (get_bits_count(&f->gb)+31)/32*4,
Michael Niedermayer's avatar
Michael Niedermayer committed
362 363 364
            bytestream_size - (f->bytestream - (buf + 20 + bitstream_size + wordstream_size)),
            wordstream_size - (((uint8_t*)f->wordstream) - (buf + 20 + bitstream_size))
        );
365

Michael Niedermayer's avatar
Michael Niedermayer committed
366 367 368 369 370 371 372 373 374 375 376 377 378
    return 0;
}

/**
 * decode block and dequantize.
 * Note this is allmost identical to mjpeg
 */
static int decode_i_block(FourXContext *f, DCTELEM *block){
    int code, i, j, level, val;

    /* DC coef */
    val = get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3);
    if (val>>4){
379
        av_log(f->avctx, AV_LOG_ERROR, "error dc run != 0\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
380 381 382 383 384 385 386 387 388 389 390 391
    }

    if(val)
        val = get_xbits(&f->gb, val);

    val = val * dequant_table[0] + f->last_dc;
    f->last_dc =
    block[0] = val;
    /* AC coefs */
    i = 1;
    for(;;) {
        code = get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3);
392

Michael Niedermayer's avatar
Michael Niedermayer committed
393 394 395 396 397 398 399 400 401
        /* EOB */
        if (code == 0)
            break;
        if (code == 0xf0) {
            i += 16;
        } else {
            level = get_xbits(&f->gb, code & 0xf);
            i += code >> 4;
            if (i >= 64) {
402
                av_log(f->avctx, AV_LOG_ERROR, "run %d oveflow\n", i);
Michael Niedermayer's avatar
Michael Niedermayer committed
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
                return 0;
            }

            j= ff_zigzag_direct[i];
            block[j] = level * dequant_table[j];
            i++;
            if (i >= 64)
                break;
        }
    }

    return 0;
}

static inline void idct_put(FourXContext *f, int x, int y){
    DCTELEM (*block)[64]= f->block;
    int stride= f->current_picture.linesize[0]>>1;
    int i;
    uint16_t *dst = ((uint16_t*)f->current_picture.data[0]) + y * stride + x;
422

423 424 425 426
    for(i=0; i<4; i++){
        block[i][0] += 0x80*8*8;
        idct(block[i]);
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
427

428 429 430
    if(!(f->avctx->flags&CODEC_FLAG_GRAY)){
        for(i=4; i<6; i++) idct(block[i]);
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
431

432 433 434 435
/* Note transform is:
y= ( 1b + 4g + 2r)/14
cb=( 3b - 2g - 1r)/14
cr=(-1b - 4g + 5r)/14
436
*/
Michael Niedermayer's avatar
Michael Niedermayer committed
437 438 439
    for(y=0; y<8; y++){
        for(x=0; x<8; x++){
            DCTELEM *temp= block[(x>>2) + 2*(y>>2)] + 2*(x&3) + 2*8*(y&3); //FIXME optimize
440 441
            int cb= block[4][x + 8*y];
            int cr= block[5][x + 8*y];
Michael Niedermayer's avatar
Michael Niedermayer committed
442 443
            int cg= (cb + cr)>>1;
            int y;
444

445
            cb+=cb;
446

Michael Niedermayer's avatar
Michael Niedermayer committed
447
            y = temp[0];
448
            dst[0       ]= ((y+cb)>>3) + (((y-cg)&0xFC)<<3) + (((y+cr)&0xF8)<<8);
Michael Niedermayer's avatar
Michael Niedermayer committed
449
            y = temp[1];
450
            dst[1       ]= ((y+cb)>>3) + (((y-cg)&0xFC)<<3) + (((y+cr)&0xF8)<<8);
Michael Niedermayer's avatar
Michael Niedermayer committed
451
            y = temp[8];
452
            dst[  stride]= ((y+cb)>>3) + (((y-cg)&0xFC)<<3) + (((y+cr)&0xF8)<<8);
Michael Niedermayer's avatar
Michael Niedermayer committed
453
            y = temp[9];
454
            dst[1+stride]= ((y+cb)>>3) + (((y-cg)&0xFC)<<3) + (((y+cr)&0xF8)<<8);
Michael Niedermayer's avatar
Michael Niedermayer committed
455 456 457 458 459 460 461 462
            dst += 2;
        }
        dst += 2*stride - 2*8;
    }
}

static int decode_i_mb(FourXContext *f){
    int i;
463

Michael Niedermayer's avatar
Michael Niedermayer committed
464
    f->dsp.clear_blocks(f->block[0]);
465

Michael Niedermayer's avatar
Michael Niedermayer committed
466 467 468 469
    for(i=0; i<6; i++){
        if(decode_i_block(f, f->block[i]) < 0)
            return -1;
    }
470

Michael Niedermayer's avatar
Michael Niedermayer committed
471 472 473 474 475 476 477 478 479 480 481 482
    return 0;
}

static uint8_t *read_huffman_tables(FourXContext *f, uint8_t * const buf){
    int frequency[512];
    uint8_t flag[512];
    int up[512];
    uint8_t len_tab[257];
    int bits_tab[257];
    int start, end;
    uint8_t *ptr= buf;
    int j;
483

Michael Niedermayer's avatar
Michael Niedermayer committed
484 485 486 487 488 489 490
    memset(frequency, 0, sizeof(frequency));
    memset(up, -1, sizeof(up));

    start= *ptr++;
    end= *ptr++;
    for(;;){
        int i;
491

Michael Niedermayer's avatar
Michael Niedermayer committed
492 493 494 495 496
        for(i=start; i<=end; i++){
            frequency[i]= *ptr++;
        }
        start= *ptr++;
        if(start==0) break;
497

Michael Niedermayer's avatar
Michael Niedermayer committed
498 499 500 501
        end= *ptr++;
    }
    frequency[256]=1;

502
    while((ptr - buf)&3) ptr++; // 4byte align
Michael Niedermayer's avatar
Michael Niedermayer committed
503 504

    for(j=257; j<512; j++){
505 506
        int min_freq[2]= {256*256, 256*256};
        int smallest[2]= {0, 0};
Michael Niedermayer's avatar
Michael Niedermayer committed
507 508 509
        int i;
        for(i=0; i<j; i++){
            if(frequency[i] == 0) continue;
510 511 512 513 514 515 516
            if(frequency[i] < min_freq[1]){
                if(frequency[i] < min_freq[0]){
                    min_freq[1]= min_freq[0]; smallest[1]= smallest[0];
                    min_freq[0]= frequency[i];smallest[0]= i;
                }else{
                    min_freq[1]= frequency[i];smallest[1]= i;
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
517 518
            }
        }
519
        if(min_freq[1] == 256*256) break;
520

521
        frequency[j]= min_freq[0] + min_freq[1];
Michael Niedermayer's avatar
Michael Niedermayer committed
522 523
        flag[ smallest[0] ]= 0;
        flag[ smallest[1] ]= 1;
524
        up[ smallest[0] ]=
Michael Niedermayer's avatar
Michael Niedermayer committed
525 526 527 528 529 530 531 532 533 534 535 536
        up[ smallest[1] ]= j;
        frequency[ smallest[0] ]= frequency[ smallest[1] ]= 0;
    }

    for(j=0; j<257; j++){
        int node;
        int len=0;
        int bits=0;

        for(node= j; up[node] != -1; node= up[node]){
            bits += flag[node]<<len;
            len++;
537
            if(len > 31) av_log(f->avctx, AV_LOG_ERROR, "vlc length overflow\n"); //can this happen at all ?
Michael Niedermayer's avatar
Michael Niedermayer committed
538
        }
539

Michael Niedermayer's avatar
Michael Niedermayer committed
540 541 542
        bits_tab[j]= bits;
        len_tab[j]= len;
    }
543 544

    init_vlc(&f->pre_vlc, ACDC_VLC_BITS, 257,
Michael Niedermayer's avatar
Michael Niedermayer committed
545
             len_tab , 1, 1,
546
             bits_tab, 4, 4, 0);
547

Michael Niedermayer's avatar
Michael Niedermayer committed
548 549 550 551 552 553 554 555 556
    return ptr;
}

static int decode_i_frame(FourXContext *f, uint8_t *buf, int length){
    int x, y;
    const int width= f->avctx->width;
    const int height= f->avctx->height;
    uint16_t *dst= (uint16_t*)f->current_picture.data[0];
    const int stride= f->current_picture.linesize[0]>>1;
557
    const unsigned int bitstream_size= get32(buf);
Falk Hüffner's avatar
Falk Hüffner committed
558
    const int token_count __attribute__((unused)) = get32(buf + bitstream_size + 8);
559
    unsigned int prestream_size= 4*get32(buf + bitstream_size + 4);
Michael Niedermayer's avatar
Michael Niedermayer committed
560
    uint8_t *prestream= buf + bitstream_size + 12;
561

562 563 564
    if(prestream_size + bitstream_size + 12 != length
       || bitstream_size > (1<<26)
       || prestream_size > (1<<26)){
565
        av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d %d\n", prestream_size, bitstream_size, length);
566 567
        return -1;
    }
568

Michael Niedermayer's avatar
Michael Niedermayer committed
569 570 571 572 573
    prestream= read_huffman_tables(f, prestream);

    init_get_bits(&f->gb, buf + 4, 8*bitstream_size);

    prestream_size= length + buf - prestream;
574

Michael Niedermayer's avatar
Michael Niedermayer committed
575 576 577 578 579
    f->bitstream_buffer= av_fast_realloc(f->bitstream_buffer, &f->bitstream_buffer_size, prestream_size + FF_INPUT_BUFFER_PADDING_SIZE);
    f->dsp.bswap_buf((uint32_t*)f->bitstream_buffer, (uint32_t*)prestream, prestream_size/4);
    init_get_bits(&f->pre_gb, f->bitstream_buffer, 8*prestream_size);

    f->last_dc= 0*128*8*8;
580

Michael Niedermayer's avatar
Michael Niedermayer committed
581 582 583 584 585 586 587
    for(y=0; y<height; y+=16){
        for(x=0; x<width; x+=16){
            if(decode_i_mb(f) < 0)
                return -1;

            idct_put(f, x, y);
        }
588
        dst += 16*stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
589 590 591
    }

    if(get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3) != 256)
592
        av_log(f->avctx, AV_LOG_ERROR, "end mismatch\n");
593

Michael Niedermayer's avatar
Michael Niedermayer committed
594 595 596
    return 0;
}

597
static int decode_frame(AVCodecContext *avctx,
Michael Niedermayer's avatar
Michael Niedermayer committed
598 599 600 601 602 603 604 605 606
                        void *data, int *data_size,
                        uint8_t *buf, int buf_size)
{
    FourXContext * const f = avctx->priv_data;
    AVFrame *picture = data;
    AVFrame *p, temp;
    int i, frame_4cc, frame_size;

    frame_4cc= get32(buf);
607
    if(buf_size != get32(buf+4)+8 || buf_size < 20){
608
        av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n", buf_size, get32(buf+4));
Michael Niedermayer's avatar
Michael Niedermayer committed
609 610 611 612 613 614 615 616 617 618 619
    }

    if(frame_4cc == ff_get_fourcc("cfrm")){
        int free_index=-1;
        const int data_size= buf_size - 20;
        const int id= get32(buf+12);
        const int whole_size= get32(buf+16);
        CFrameBuffer *cfrm;

        for(i=0; i<CFRAME_BUFFER_COUNT; i++){
            if(f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number)
620
                av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n", f->cfrm[i].id);
Michael Niedermayer's avatar
Michael Niedermayer committed
621
        }
622

Michael Niedermayer's avatar
Michael Niedermayer committed
623 624 625 626 627 628 629 630 631 632
        for(i=0; i<CFRAME_BUFFER_COUNT; i++){
            if(f->cfrm[i].id   == id) break;
            if(f->cfrm[i].size == 0 ) free_index= i;
        }

        if(i>=CFRAME_BUFFER_COUNT){
            i= free_index;
            f->cfrm[i].id= id;
        }
        cfrm= &f->cfrm[i];
633

Michael Niedermayer's avatar
Michael Niedermayer committed
634
        cfrm->data= av_fast_realloc(cfrm->data, &cfrm->allocated_size, cfrm->size + data_size + FF_INPUT_BUFFER_PADDING_SIZE);
635 636 637 638
        if(!cfrm->data){ //explicit check needed as memcpy below might not catch a NULL
            av_log(f->avctx, AV_LOG_ERROR, "realloc falure");
            return -1;
        }
639

Michael Niedermayer's avatar
Michael Niedermayer committed
640 641
        memcpy(cfrm->data + cfrm->size, buf+20, data_size);
        cfrm->size += data_size;
642

Michael Niedermayer's avatar
Michael Niedermayer committed
643 644 645
        if(cfrm->size >= whole_size){
            buf= cfrm->data;
            frame_size= cfrm->size;
646

Michael Niedermayer's avatar
Michael Niedermayer committed
647
            if(id != avctx->frame_number){
648
                av_log(f->avctx, AV_LOG_ERROR, "cframe id mismatch %d %d\n", id, avctx->frame_number);
Michael Niedermayer's avatar
Michael Niedermayer committed
649
            }
650

Michael Niedermayer's avatar
Michael Niedermayer committed
651 652 653 654 655 656 657
            cfrm->size= cfrm->id= 0;
            frame_4cc= ff_get_fourcc("pfrm");
        }else
            return buf_size;
    }else{
        buf= buf + 12;
        frame_size= buf_size - 12;
658
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673

    temp= f->current_picture;
    f->current_picture= f->last_picture;
    f->last_picture= temp;

    p= &f->current_picture;
    avctx->coded_frame= p;

    avctx->flags |= CODEC_FLAG_EMU_EDGE; // alternatively we would have to use our own buffer management

    if(p->data[0])
        avctx->release_buffer(avctx, p);

    p->reference= 1;
    if(avctx->get_buffer(avctx, p) < 0){
674
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
675 676 677 678 679 680 681 682 683 684 685 686
        return -1;
    }

    if(frame_4cc == ff_get_fourcc("ifrm")){
        p->pict_type= I_TYPE;
        if(decode_i_frame(f, buf, frame_size) < 0)
            return -1;
    }else if(frame_4cc == ff_get_fourcc("pfrm")){
        p->pict_type= P_TYPE;
        if(decode_p_frame(f, buf, frame_size) < 0)
            return -1;
    }else if(frame_4cc == ff_get_fourcc("snd_")){
687
        av_log(avctx, AV_LOG_ERROR, "ignoring snd_ chunk length:%d\n", buf_size);
Michael Niedermayer's avatar
Michael Niedermayer committed
688
    }else{
689
        av_log(avctx, AV_LOG_ERROR, "ignoring unknown chunk length:%d\n", buf_size);
Michael Niedermayer's avatar
Michael Niedermayer committed
690 691 692 693 694 695 696 697
    }

    p->key_frame= p->pict_type == I_TYPE;

    *picture= *p;
    *data_size = sizeof(AVPicture);

    emms_c();
698

Michael Niedermayer's avatar
Michael Niedermayer committed
699 700 701 702 703 704 705 706 707 708 709 710 711 712
    return buf_size;
}


static void common_init(AVCodecContext *avctx){
    FourXContext * const f = avctx->priv_data;

    dsputil_init(&f->dsp, avctx);

    f->avctx= avctx;
}

static int decode_init(AVCodecContext *avctx){
    FourXContext * const f = avctx->priv_data;
713

Michael Niedermayer's avatar
Michael Niedermayer committed
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
    common_init(avctx);
    init_vlcs(f);

    avctx->pix_fmt= PIX_FMT_RGB565;

    return 0;
}


static int decode_end(AVCodecContext *avctx){
    FourXContext * const f = avctx->priv_data;
    int i;

    av_freep(&f->bitstream_buffer);
    f->bitstream_buffer_size=0;
    for(i=0; i<CFRAME_BUFFER_COUNT; i++){
        av_freep(&f->cfrm[i].data);
        f->cfrm[i].allocated_size= 0;
    }
    free_vlc(&f->pre_vlc);
734

Michael Niedermayer's avatar
Michael Niedermayer committed
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
    return 0;
}

AVCodec fourxm_decoder = {
    "4xm",
    CODEC_TYPE_VIDEO,
    CODEC_ID_4XM,
    sizeof(FourXContext),
    decode_init,
    NULL,
    decode_end,
    decode_frame,
    /*CODEC_CAP_DR1,*/
};