asv1.c 19.8 KB
Newer Older
Michael Niedermayer's avatar
Michael Niedermayer committed
1
/*
Michael Niedermayer's avatar
Michael Niedermayer committed
2
 * ASUS V1/V2 codec
Michael Niedermayer's avatar
Michael Niedermayer committed
3 4
 * 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
/**
 * @file asv1.c
Michael Niedermayer's avatar
Michael Niedermayer committed
24
 * ASUS V1/V2 codec.
Michael Niedermayer's avatar
Michael Niedermayer committed
25
 */
26

Michael Niedermayer's avatar
Michael Niedermayer committed
27
#include "avcodec.h"
28
#include "bitstream.h"
Michael Niedermayer's avatar
Michael Niedermayer committed
29
#include "dsputil.h"
30
#include "mpeg12data.h"
Michael Niedermayer's avatar
Michael Niedermayer committed
31 32 33 34

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

Michael Niedermayer's avatar
Michael Niedermayer committed
35 36
#define VLC_BITS 6
#define ASV2_LEVEL_VLC_BITS 10
37

Michael Niedermayer's avatar
Michael Niedermayer committed
38 39 40 41 42 43 44 45 46 47 48 49
typedef struct ASV1Context{
    AVCodecContext *avctx;
    DSPContext dsp;
    AVFrame picture;
    PutBitContext pb;
    GetBitContext gb;
    ScanTable scantable;
    int inv_qscale;
    int mb_width;
    int mb_height;
    int mb_width2;
    int mb_height2;
50
    DECLARE_ALIGNED_16(DCTELEM, block[6][64]);
51 52
    DECLARE_ALIGNED_8(uint16_t, intra_matrix[64]);
    DECLARE_ALIGNED_8(int, q_intra_matrix[64]);
Michael Niedermayer's avatar
Michael Niedermayer committed
53
    uint8_t *bitstream_buffer;
54
    unsigned int bitstream_buffer_size;
Michael Niedermayer's avatar
Michael Niedermayer committed
55 56 57 58 59 60 61 62
} ASV1Context;

static const uint8_t scantab[64]={
    0x00,0x08,0x01,0x09,0x10,0x18,0x11,0x19,
    0x02,0x0A,0x03,0x0B,0x12,0x1A,0x13,0x1B,
    0x04,0x0C,0x05,0x0D,0x20,0x28,0x21,0x29,
    0x06,0x0E,0x07,0x0F,0x14,0x1C,0x15,0x1D,
    0x22,0x2A,0x23,0x2B,0x30,0x38,0x31,0x39,
Michael Niedermayer's avatar
Michael Niedermayer committed
63 64 65 66 67 68
    0x16,0x1E,0x17,0x1F,0x24,0x2C,0x25,0x2D,
    0x32,0x3A,0x33,0x3B,0x26,0x2E,0x27,0x2F,
    0x34,0x3C,0x35,0x3D,0x36,0x3E,0x37,0x3F,
};


Michael Niedermayer's avatar
Michael Niedermayer committed
69
static const uint8_t ccp_tab[17][2]={
Michael Niedermayer's avatar
Michael Niedermayer committed
70 71
    {0x2,2}, {0x7,5}, {0xB,5}, {0x3,5},
    {0xD,5}, {0x5,5}, {0x9,5}, {0x1,5},
72
    {0xE,5}, {0x6,5}, {0xA,5}, {0x2,5},
Michael Niedermayer's avatar
Michael Niedermayer committed
73
    {0xC,5}, {0x4,5}, {0x8,5}, {0x3,2},
Michael Niedermayer's avatar
Michael Niedermayer committed
74 75 76 77 78 79 80
    {0xF,5}, //EOB
};

static const uint8_t level_tab[7][2]={
    {3,4}, {3,3}, {3,2}, {0,3}, {2,2}, {2,3}, {2,4}
};

Michael Niedermayer's avatar
Michael Niedermayer committed
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 109
static const uint8_t dc_ccp_tab[8][2]={
    {0x1,2}, {0xD,4}, {0xF,4}, {0xC,4},
    {0x5,3}, {0xE,4}, {0x4,3}, {0x0,2},
};

static const uint8_t ac_ccp_tab[16][2]={
    {0x00,2}, {0x3B,6}, {0x0A,4}, {0x3A,6},
    {0x02,3}, {0x39,6}, {0x3C,6}, {0x38,6},
    {0x03,3}, {0x3D,6}, {0x08,4}, {0x1F,5},
    {0x09,4}, {0x0B,4}, {0x0D,4}, {0x0C,4},
};

static const uint8_t asv2_level_tab[63][2]={
    {0x3F,10},{0x2F,10},{0x37,10},{0x27,10},{0x3B,10},{0x2B,10},{0x33,10},{0x23,10},
    {0x3D,10},{0x2D,10},{0x35,10},{0x25,10},{0x39,10},{0x29,10},{0x31,10},{0x21,10},
    {0x1F, 8},{0x17, 8},{0x1B, 8},{0x13, 8},{0x1D, 8},{0x15, 8},{0x19, 8},{0x11, 8},
    {0x0F, 6},{0x0B, 6},{0x0D, 6},{0x09, 6},
    {0x07, 4},{0x05, 4},
    {0x03, 2},
    {0x00, 5},
    {0x02, 2},
    {0x04, 4},{0x06, 4},
    {0x08, 6},{0x0C, 6},{0x0A, 6},{0x0E, 6},
    {0x10, 8},{0x18, 8},{0x14, 8},{0x1C, 8},{0x12, 8},{0x1A, 8},{0x16, 8},{0x1E, 8},
    {0x20,10},{0x30,10},{0x28,10},{0x38,10},{0x24,10},{0x34,10},{0x2C,10},{0x3C,10},
    {0x22,10},{0x32,10},{0x2A,10},{0x3A,10},{0x26,10},{0x36,10},{0x2E,10},{0x3E,10},
};


Michael Niedermayer's avatar
Michael Niedermayer committed
110 111
static VLC ccp_vlc;
static VLC level_vlc;
Michael Niedermayer's avatar
Michael Niedermayer committed
112 113 114
static VLC dc_ccp_vlc;
static VLC ac_ccp_vlc;
static VLC asv2_level_vlc;
Michael Niedermayer's avatar
Michael Niedermayer committed
115

116
static av_cold void init_vlcs(ASV1Context *a){
Michael Niedermayer's avatar
Michael Niedermayer committed
117 118 119 120 121
    static int done = 0;

    if (!done) {
        done = 1;

122
        init_vlc(&ccp_vlc, VLC_BITS, 17,
Michael Niedermayer's avatar
Michael Niedermayer committed
123
                 &ccp_tab[0][1], 2, 1,
124
                 &ccp_tab[0][0], 2, 1, 1);
125
        init_vlc(&dc_ccp_vlc, VLC_BITS, 8,
Michael Niedermayer's avatar
Michael Niedermayer committed
126
                 &dc_ccp_tab[0][1], 2, 1,
127
                 &dc_ccp_tab[0][0], 2, 1, 1);
128
        init_vlc(&ac_ccp_vlc, VLC_BITS, 16,
Michael Niedermayer's avatar
Michael Niedermayer committed
129
                 &ac_ccp_tab[0][1], 2, 1,
130
                 &ac_ccp_tab[0][0], 2, 1, 1);
131
        init_vlc(&level_vlc,  VLC_BITS, 7,
Michael Niedermayer's avatar
Michael Niedermayer committed
132
                 &level_tab[0][1], 2, 1,
133
                 &level_tab[0][0], 2, 1, 1);
134
        init_vlc(&asv2_level_vlc, ASV2_LEVEL_VLC_BITS, 63,
Michael Niedermayer's avatar
Michael Niedermayer committed
135
                 &asv2_level_tab[0][1], 2, 1,
136
                 &asv2_level_tab[0][0], 2, 1, 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
137 138 139
    }
}

Michael Niedermayer's avatar
Michael Niedermayer committed
140 141
//FIXME write a reversed bitstream reader to avoid the double reverse
static inline int asv2_get_bits(GetBitContext *gb, int n){
142
    return ff_reverse[ get_bits(gb, n) << (8-n) ];
Michael Niedermayer's avatar
Michael Niedermayer committed
143 144
}

Michael Niedermayer's avatar
Michael Niedermayer committed
145
static inline void asv2_put_bits(PutBitContext *pb, int n, int v){
146
    put_bits(pb, n, ff_reverse[ v << (8-n) ]);
Michael Niedermayer's avatar
Michael Niedermayer committed
147 148
}

Michael Niedermayer's avatar
Michael Niedermayer committed
149
static inline int asv1_get_level(GetBitContext *gb){
Michael Niedermayer's avatar
Michael Niedermayer committed
150 151 152 153 154 155
    int code= get_vlc2(gb, level_vlc.table, VLC_BITS, 1);

    if(code==3) return get_sbits(gb, 8);
    else        return code - 3;
}

Michael Niedermayer's avatar
Michael Niedermayer committed
156 157 158 159 160 161 162 163
static inline int asv2_get_level(GetBitContext *gb){
    int code= get_vlc2(gb, asv2_level_vlc.table, ASV2_LEVEL_VLC_BITS, 1);

    if(code==31) return (int8_t)asv2_get_bits(gb, 8);
    else         return code - 31;
}

static inline void asv1_put_level(PutBitContext *pb, int level){
Michael Niedermayer's avatar
Michael Niedermayer committed
164 165 166 167 168
    unsigned int index= level + 3;

    if(index <= 6) put_bits(pb, level_tab[index][1], level_tab[index][0]);
    else{
        put_bits(pb, level_tab[3][1], level_tab[3][0]);
169
        put_sbits(pb, 8, level);
Michael Niedermayer's avatar
Michael Niedermayer committed
170 171 172
    }
}

Michael Niedermayer's avatar
Michael Niedermayer committed
173 174 175 176 177 178 179 180 181 182
static inline void asv2_put_level(PutBitContext *pb, int level){
    unsigned int index= level + 31;

    if(index <= 62) put_bits(pb, asv2_level_tab[index][1], asv2_level_tab[index][0]);
    else{
        put_bits(pb, asv2_level_tab[31][1], asv2_level_tab[31][0]);
        asv2_put_bits(pb, 8, level&0xFF);
    }
}

Michael Niedermayer's avatar
Michael Niedermayer committed
183
static inline int asv1_decode_block(ASV1Context *a, DCTELEM block[64]){
Michael Niedermayer's avatar
Michael Niedermayer committed
184 185 186
    int i;

    block[0]= 8*get_bits(&a->gb, 8);
187

Michael Niedermayer's avatar
Michael Niedermayer committed
188 189 190 191 192 193
    for(i=0; i<11; i++){
        const int ccp= get_vlc2(&a->gb, ccp_vlc.table, VLC_BITS, 1);

        if(ccp){
            if(ccp == 16) break;
            if(ccp < 0 || i>=10){
194
                av_log(a->avctx, AV_LOG_ERROR, "coded coeff pattern damaged\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
195 196 197
                return -1;
            }

Michael Niedermayer's avatar
Michael Niedermayer committed
198 199 200 201
            if(ccp&8) block[a->scantable.permutated[4*i+0]]= (asv1_get_level(&a->gb) * a->intra_matrix[4*i+0])>>4;
            if(ccp&4) block[a->scantable.permutated[4*i+1]]= (asv1_get_level(&a->gb) * a->intra_matrix[4*i+1])>>4;
            if(ccp&2) block[a->scantable.permutated[4*i+2]]= (asv1_get_level(&a->gb) * a->intra_matrix[4*i+2])>>4;
            if(ccp&1) block[a->scantable.permutated[4*i+3]]= (asv1_get_level(&a->gb) * a->intra_matrix[4*i+3])>>4;
Michael Niedermayer's avatar
Michael Niedermayer committed
202 203 204 205 206 207
        }
    }

    return 0;
}

Michael Niedermayer's avatar
Michael Niedermayer committed
208 209 210 211
static inline int asv2_decode_block(ASV1Context *a, DCTELEM block[64]){
    int i, count, ccp;

    count= asv2_get_bits(&a->gb, 4);
212

Michael Niedermayer's avatar
Michael Niedermayer committed
213
    block[0]= 8*asv2_get_bits(&a->gb, 8);
214

Michael Niedermayer's avatar
Michael Niedermayer committed
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    ccp= get_vlc2(&a->gb, dc_ccp_vlc.table, VLC_BITS, 1);
    if(ccp){
        if(ccp&4) block[a->scantable.permutated[1]]= (asv2_get_level(&a->gb) * a->intra_matrix[1])>>4;
        if(ccp&2) block[a->scantable.permutated[2]]= (asv2_get_level(&a->gb) * a->intra_matrix[2])>>4;
        if(ccp&1) block[a->scantable.permutated[3]]= (asv2_get_level(&a->gb) * a->intra_matrix[3])>>4;
    }

    for(i=1; i<count+1; i++){
        const int ccp= get_vlc2(&a->gb, ac_ccp_vlc.table, VLC_BITS, 1);

        if(ccp){
            if(ccp&8) block[a->scantable.permutated[4*i+0]]= (asv2_get_level(&a->gb) * a->intra_matrix[4*i+0])>>4;
            if(ccp&4) block[a->scantable.permutated[4*i+1]]= (asv2_get_level(&a->gb) * a->intra_matrix[4*i+1])>>4;
            if(ccp&2) block[a->scantable.permutated[4*i+2]]= (asv2_get_level(&a->gb) * a->intra_matrix[4*i+2])>>4;
            if(ccp&1) block[a->scantable.permutated[4*i+3]]= (asv2_get_level(&a->gb) * a->intra_matrix[4*i+3])>>4;
        }
    }
232

Michael Niedermayer's avatar
Michael Niedermayer committed
233 234 235
    return 0;
}

Michael Niedermayer's avatar
Michael Niedermayer committed
236
static inline void asv1_encode_block(ASV1Context *a, DCTELEM block[64]){
Michael Niedermayer's avatar
Michael Niedermayer committed
237 238
    int i;
    int nc_count=0;
239

Michael Niedermayer's avatar
Michael Niedermayer committed
240 241
    put_bits(&a->pb, 8, (block[0] + 32)>>6);
    block[0]= 0;
242

Michael Niedermayer's avatar
Michael Niedermayer committed
243 244 245 246
    for(i=0; i<10; i++){
        const int index= scantab[4*i];
        int ccp=0;

Michael Niedermayer's avatar
Michael Niedermayer committed
247 248 249 250
        if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8;
        if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4;
        if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2;
        if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1;
Michael Niedermayer's avatar
Michael Niedermayer committed
251 252

        if(ccp){
253
            for(;nc_count; nc_count--)
Michael Niedermayer's avatar
Michael Niedermayer committed
254 255 256
                put_bits(&a->pb, ccp_tab[0][1], ccp_tab[0][0]);

            put_bits(&a->pb, ccp_tab[ccp][1], ccp_tab[ccp][0]);
257

Michael Niedermayer's avatar
Michael Niedermayer committed
258 259 260 261
            if(ccp&8) asv1_put_level(&a->pb, block[index + 0]);
            if(ccp&4) asv1_put_level(&a->pb, block[index + 8]);
            if(ccp&2) asv1_put_level(&a->pb, block[index + 1]);
            if(ccp&1) asv1_put_level(&a->pb, block[index + 9]);
Michael Niedermayer's avatar
Michael Niedermayer committed
262 263 264 265 266 267 268
        }else{
            nc_count++;
        }
    }
    put_bits(&a->pb, ccp_tab[16][1], ccp_tab[16][0]);
}

Michael Niedermayer's avatar
Michael Niedermayer committed
269 270 271
static inline void asv2_encode_block(ASV1Context *a, DCTELEM block[64]){
    int i;
    int count=0;
272

Michael Niedermayer's avatar
Michael Niedermayer committed
273 274 275
    for(count=63; count>3; count--){
        const int index= scantab[count];

276
        if( (block[index]*a->q_intra_matrix[index] + (1<<15))>>16 )
Michael Niedermayer's avatar
Michael Niedermayer committed
277 278
            break;
    }
279

Michael Niedermayer's avatar
Michael Niedermayer committed
280 281 282 283 284
    count >>= 2;

    asv2_put_bits(&a->pb, 4, count);
    asv2_put_bits(&a->pb, 8, (block[0] + 32)>>6);
    block[0]= 0;
285

Michael Niedermayer's avatar
Michael Niedermayer committed
286 287 288 289 290 291 292 293 294
    for(i=0; i<=count; i++){
        const int index= scantab[4*i];
        int ccp=0;

        if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8;
        if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4;
        if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2;
        if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1;

295
        assert(i || ccp<8);
Michael Niedermayer's avatar
Michael Niedermayer committed
296 297 298 299 300 301 302 303 304 305 306 307
        if(i) put_bits(&a->pb, ac_ccp_tab[ccp][1], ac_ccp_tab[ccp][0]);
        else  put_bits(&a->pb, dc_ccp_tab[ccp][1], dc_ccp_tab[ccp][0]);

        if(ccp){
            if(ccp&8) asv2_put_level(&a->pb, block[index + 0]);
            if(ccp&4) asv2_put_level(&a->pb, block[index + 8]);
            if(ccp&2) asv2_put_level(&a->pb, block[index + 1]);
            if(ccp&1) asv2_put_level(&a->pb, block[index + 9]);
        }
    }
}

Michael Niedermayer's avatar
Michael Niedermayer committed
308 309 310 311
static inline int decode_mb(ASV1Context *a, DCTELEM block[6][64]){
    int i;

    a->dsp.clear_blocks(block[0]);
312

Michael Niedermayer's avatar
Michael Niedermayer committed
313 314
    if(a->avctx->codec_id == CODEC_ID_ASV1){
        for(i=0; i<6; i++){
315
            if( asv1_decode_block(a, block[i]) < 0)
Michael Niedermayer's avatar
Michael Niedermayer committed
316 317 318 319
                return -1;
        }
    }else{
        for(i=0; i<6; i++){
320
            if( asv2_decode_block(a, block[i]) < 0)
Michael Niedermayer's avatar
Michael Niedermayer committed
321 322
                return -1;
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
323 324 325 326
    }
    return 0;
}

327
static inline int encode_mb(ASV1Context *a, DCTELEM block[6][64]){
Michael Niedermayer's avatar
Michael Niedermayer committed
328
    int i;
329

330 331 332 333
    if(a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < 30*16*16*3/2/8){
        av_log(a->avctx, AV_LOG_ERROR, "encoded frame too large\n");
        return -1;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
334

Michael Niedermayer's avatar
Michael Niedermayer committed
335 336 337 338 339 340
    if(a->avctx->codec_id == CODEC_ID_ASV1){
        for(i=0; i<6; i++)
            asv1_encode_block(a, block[i]);
    }else{
        for(i=0; i<6; i++)
            asv2_encode_block(a, block[i]);
Michael Niedermayer's avatar
Michael Niedermayer committed
341
    }
342
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
343
}
344

Michael Niedermayer's avatar
Michael Niedermayer committed
345 346 347
static inline void idct_put(ASV1Context *a, int mb_x, int mb_y){
    DCTELEM (*block)[64]= a->block;
    int linesize= a->picture.linesize[0];
348

Michael Niedermayer's avatar
Michael Niedermayer committed
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
    uint8_t *dest_y  = a->picture.data[0] + (mb_y * 16* linesize              ) + mb_x * 16;
    uint8_t *dest_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8;
    uint8_t *dest_cr = a->picture.data[2] + (mb_y * 8 * a->picture.linesize[2]) + mb_x * 8;

    a->dsp.idct_put(dest_y                 , linesize, block[0]);
    a->dsp.idct_put(dest_y              + 8, linesize, block[1]);
    a->dsp.idct_put(dest_y + 8*linesize    , linesize, block[2]);
    a->dsp.idct_put(dest_y + 8*linesize + 8, linesize, block[3]);

    if(!(a->avctx->flags&CODEC_FLAG_GRAY)){
        a->dsp.idct_put(dest_cb, a->picture.linesize[1], block[4]);
        a->dsp.idct_put(dest_cr, a->picture.linesize[2], block[5]);
    }
}

static inline void dct_get(ASV1Context *a, int mb_x, int mb_y){
    DCTELEM (*block)[64]= a->block;
    int linesize= a->picture.linesize[0];
    int i;
368

Michael Niedermayer's avatar
Michael Niedermayer committed
369 370 371 372 373 374 375 376 377 378
    uint8_t *ptr_y  = a->picture.data[0] + (mb_y * 16* linesize              ) + mb_x * 16;
    uint8_t *ptr_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8;
    uint8_t *ptr_cr = a->picture.data[2] + (mb_y * 8 * a->picture.linesize[2]) + mb_x * 8;

    a->dsp.get_pixels(block[0], ptr_y                 , linesize);
    a->dsp.get_pixels(block[1], ptr_y              + 8, linesize);
    a->dsp.get_pixels(block[2], ptr_y + 8*linesize    , linesize);
    a->dsp.get_pixels(block[3], ptr_y + 8*linesize + 8, linesize);
    for(i=0; i<4; i++)
        a->dsp.fdct(block[i]);
379

Michael Niedermayer's avatar
Michael Niedermayer committed
380 381 382 383 384 385 386 387
    if(!(a->avctx->flags&CODEC_FLAG_GRAY)){
        a->dsp.get_pixels(block[4], ptr_cb, a->picture.linesize[1]);
        a->dsp.get_pixels(block[5], ptr_cr, a->picture.linesize[2]);
        for(i=4; i<6; i++)
            a->dsp.fdct(block[i]);
    }
}

388
static int decode_frame(AVCodecContext *avctx,
Michael Niedermayer's avatar
Michael Niedermayer committed
389
                        void *data, int *data_size,
Michael Niedermayer's avatar
Michael Niedermayer committed
390
                        const uint8_t *buf, int buf_size)
Michael Niedermayer's avatar
Michael Niedermayer committed
391 392 393 394 395 396 397 398 399 400 401
{
    ASV1Context * const a = avctx->priv_data;
    AVFrame *picture = data;
    AVFrame * const p= (AVFrame*)&a->picture;
    int mb_x, mb_y;

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

    p->reference= 0;
    if(avctx->get_buffer(avctx, p) < 0){
402
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
403 404
        return -1;
    }
405
    p->pict_type= FF_I_TYPE;
Michael Niedermayer's avatar
Michael Niedermayer committed
406 407 408
    p->key_frame= 1;

    a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
409

Michael Niedermayer's avatar
Michael Niedermayer committed
410
    if(avctx->codec_id == CODEC_ID_ASV1)
Michael Niedermayer's avatar
Michael Niedermayer committed
411
        a->dsp.bswap_buf((uint32_t*)a->bitstream_buffer, (const uint32_t*)buf, buf_size/4);
Michael Niedermayer's avatar
Michael Niedermayer committed
412 413 414
    else{
        int i;
        for(i=0; i<buf_size; i++)
415
            a->bitstream_buffer[i]= ff_reverse[ buf[i] ];
Michael Niedermayer's avatar
Michael Niedermayer committed
416 417
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
418 419 420 421 422 423
    init_get_bits(&a->gb, a->bitstream_buffer, buf_size*8);

    for(mb_y=0; mb_y<a->mb_height2; mb_y++){
        for(mb_x=0; mb_x<a->mb_width2; mb_x++){
            if( decode_mb(a, a->block) <0)
                return -1;
424

Michael Niedermayer's avatar
Michael Niedermayer committed
425 426 427 428 429 430 431 432 433
            idct_put(a, mb_x, mb_y);
        }
    }

    if(a->mb_width2 != a->mb_width){
        mb_x= a->mb_width2;
        for(mb_y=0; mb_y<a->mb_height2; mb_y++){
            if( decode_mb(a, a->block) <0)
                return -1;
434

Michael Niedermayer's avatar
Michael Niedermayer committed
435 436 437 438 439 440 441 442 443
            idct_put(a, mb_x, mb_y);
        }
    }

    if(a->mb_height2 != a->mb_height){
        mb_y= a->mb_height2;
        for(mb_x=0; mb_x<a->mb_width; mb_x++){
            if( decode_mb(a, a->block) <0)
                return -1;
444

Michael Niedermayer's avatar
Michael Niedermayer committed
445 446 447
            idct_put(a, mb_x, mb_y);
        }
    }
448
#if 0
Michael Niedermayer's avatar
Michael Niedermayer committed
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
int i;
printf("%d %d\n", 8*buf_size, get_bits_count(&a->gb));
for(i=get_bits_count(&a->gb); i<8*buf_size; i++){
    printf("%d", get_bits1(&a->gb));
}

for(i=0; i<s->avctx->extradata_size; i++){
    printf("%c\n", ((uint8_t*)s->avctx->extradata)[i]);
}
#endif

    *picture= *(AVFrame*)&a->picture;
    *data_size = sizeof(AVPicture);

    emms_c();
464

Michael Niedermayer's avatar
Michael Niedermayer committed
465 466 467
    return (get_bits_count(&a->gb)+31)/32*4;
}

468
#if defined(CONFIG_ASV1_ENCODER) || defined(CONFIG_ASV2_ENCODER)
Michael Niedermayer's avatar
Michael Niedermayer committed
469 470 471 472 473 474 475
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
    ASV1Context * const a = avctx->priv_data;
    AVFrame *pict = data;
    AVFrame * const p= (AVFrame*)&a->picture;
    int size;
    int mb_x, mb_y;

476
    init_put_bits(&a->pb, buf, buf_size);
477

Michael Niedermayer's avatar
Michael Niedermayer committed
478
    *p = *pict;
479
    p->pict_type= FF_I_TYPE;
Michael Niedermayer's avatar
Michael Niedermayer committed
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
    p->key_frame= 1;

    for(mb_y=0; mb_y<a->mb_height2; mb_y++){
        for(mb_x=0; mb_x<a->mb_width2; mb_x++){
            dct_get(a, mb_x, mb_y);
            encode_mb(a, a->block);
        }
    }

    if(a->mb_width2 != a->mb_width){
        mb_x= a->mb_width2;
        for(mb_y=0; mb_y<a->mb_height2; mb_y++){
            dct_get(a, mb_x, mb_y);
            encode_mb(a, a->block);
        }
    }

    if(a->mb_height2 != a->mb_height){
        mb_y= a->mb_height2;
        for(mb_x=0; mb_x<a->mb_width; mb_x++){
            dct_get(a, mb_x, mb_y);
            encode_mb(a, a->block);
        }
    }
    emms_c();
505

Michael Niedermayer's avatar
Michael Niedermayer committed
506
    align_put_bits(&a->pb);
507
    while(put_bits_count(&a->pb)&31)
Michael Niedermayer's avatar
Michael Niedermayer committed
508
        put_bits(&a->pb, 8, 0);
509

510
    size= put_bits_count(&a->pb)/32;
511

Michael Niedermayer's avatar
Michael Niedermayer committed
512 513 514 515 516
    if(avctx->codec_id == CODEC_ID_ASV1)
        a->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, size);
    else{
        int i;
        for(i=0; i<4*size; i++)
517
            buf[i]= ff_reverse[ buf[i] ];
Michael Niedermayer's avatar
Michael Niedermayer committed
518
    }
519

Michael Niedermayer's avatar
Michael Niedermayer committed
520 521
    return size*4;
}
522
#endif /* defined(CONFIG_ASV1_ENCODER) || defined(CONFIG_ASV2_ENCODER) */
Michael Niedermayer's avatar
Michael Niedermayer committed
523

524
static av_cold void common_init(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
525 526 527 528 529 530 531 532 533 534 535 536 537
    ASV1Context * const a = avctx->priv_data;

    dsputil_init(&a->dsp, avctx);

    a->mb_width   = (avctx->width  + 15) / 16;
    a->mb_height  = (avctx->height + 15) / 16;
    a->mb_width2  = (avctx->width  + 0) / 16;
    a->mb_height2 = (avctx->height + 0) / 16;

    avctx->coded_frame= (AVFrame*)&a->picture;
    a->avctx= avctx;
}

538
static av_cold int decode_init(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
539 540 541
    ASV1Context * const a = avctx->priv_data;
    AVFrame *p= (AVFrame*)&a->picture;
    int i;
Michael Niedermayer's avatar
Michael Niedermayer committed
542
    const int scale= avctx->codec_id == CODEC_ID_ASV1 ? 1 : 2;
543

Michael Niedermayer's avatar
Michael Niedermayer committed
544 545 546
    common_init(avctx);
    init_vlcs(a);
    ff_init_scantable(a->dsp.idct_permutation, &a->scantable, scantab);
547
    avctx->pix_fmt= PIX_FMT_YUV420P;
Michael Niedermayer's avatar
Michael Niedermayer committed
548

Michael Niedermayer's avatar
Michael Niedermayer committed
549
    a->inv_qscale= ((uint8_t*)avctx->extradata)[0];
Michael Niedermayer's avatar
Michael Niedermayer committed
550
    if(a->inv_qscale == 0){
551
        av_log(avctx, AV_LOG_ERROR, "illegal qscale 0\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
552 553 554 555
        if(avctx->codec_id == CODEC_ID_ASV1)
            a->inv_qscale= 6;
        else
            a->inv_qscale= 10;
Michael Niedermayer's avatar
Michael Niedermayer committed
556 557 558 559
    }

    for(i=0; i<64; i++){
        int index= scantab[i];
Michael Niedermayer's avatar
Michael Niedermayer committed
560

Michael Niedermayer's avatar
Michael Niedermayer committed
561
        a->intra_matrix[i]= 64*scale*ff_mpeg1_default_intra_matrix[index] / a->inv_qscale;
Michael Niedermayer's avatar
Michael Niedermayer committed
562 563 564
    }

    p->qstride= a->mb_width;
565
    p->qscale_table= av_malloc( p->qstride * a->mb_height);
Michael Niedermayer's avatar
Michael Niedermayer committed
566 567
    p->quality= (32*scale + a->inv_qscale/2)/a->inv_qscale;
    memset(p->qscale_table, p->quality, p->qstride*a->mb_height);
Michael Niedermayer's avatar
Michael Niedermayer committed
568 569 570 571

    return 0;
}

572
#if defined(CONFIG_ASV1_ENCODER) || defined(CONFIG_ASV2_ENCODER)
573
static av_cold int encode_init(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
574 575
    ASV1Context * const a = avctx->priv_data;
    int i;
Michael Niedermayer's avatar
Michael Niedermayer committed
576 577
    const int scale= avctx->codec_id == CODEC_ID_ASV1 ? 1 : 2;

Michael Niedermayer's avatar
Michael Niedermayer committed
578
    common_init(avctx);
579

Michael Niedermayer's avatar
Michael Niedermayer committed
580 581
    if(avctx->global_quality == 0) avctx->global_quality= 4*FF_QUALITY_SCALE;

Michael Niedermayer's avatar
Michael Niedermayer committed
582
    a->inv_qscale= (32*scale*FF_QUALITY_SCALE +  avctx->global_quality/2) / avctx->global_quality;
583

Michael Niedermayer's avatar
Michael Niedermayer committed
584 585 586 587
    avctx->extradata= av_mallocz(8);
    avctx->extradata_size=8;
    ((uint32_t*)avctx->extradata)[0]= le2me_32(a->inv_qscale);
    ((uint32_t*)avctx->extradata)[1]= le2me_32(ff_get_fourcc("ASUS"));
588

Michael Niedermayer's avatar
Michael Niedermayer committed
589
    for(i=0; i<64; i++){
Michael Niedermayer's avatar
Michael Niedermayer committed
590
        int q= 32*scale*ff_mpeg1_default_intra_matrix[i];
Michael Niedermayer's avatar
Michael Niedermayer committed
591 592 593 594 595
        a->q_intra_matrix[i]= ((a->inv_qscale<<16) + q/2) / q;
    }

    return 0;
}
596
#endif /* defined(CONFIG_ASV1_ENCODER) || defined(CONFIG_ASV2_ENCODER) */
Michael Niedermayer's avatar
Michael Niedermayer committed
597

598
static av_cold int decode_end(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
599 600 601 602 603
    ASV1Context * const a = avctx->priv_data;

    av_freep(&a->bitstream_buffer);
    av_freep(&a->picture.qscale_table);
    a->bitstream_buffer_size=0;
604

Michael Niedermayer's avatar
Michael Niedermayer committed
605 606 607 608 609 610 611 612 613 614 615 616 617
    return 0;
}

AVCodec asv1_decoder = {
    "asv1",
    CODEC_TYPE_VIDEO,
    CODEC_ID_ASV1,
    sizeof(ASV1Context),
    decode_init,
    NULL,
    decode_end,
    decode_frame,
    CODEC_CAP_DR1,
618
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V1"),
Michael Niedermayer's avatar
Michael Niedermayer committed
619 620
};

Michael Niedermayer's avatar
Michael Niedermayer committed
621 622 623 624 625 626 627 628 629 630
AVCodec asv2_decoder = {
    "asv2",
    CODEC_TYPE_VIDEO,
    CODEC_ID_ASV2,
    sizeof(ASV1Context),
    decode_init,
    NULL,
    decode_end,
    decode_frame,
    CODEC_CAP_DR1,
631
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V2"),
Michael Niedermayer's avatar
Michael Niedermayer committed
632 633
};

634
#ifdef CONFIG_ASV1_ENCODER
Michael Niedermayer's avatar
Michael Niedermayer committed
635 636 637 638 639 640 641 642
AVCodec asv1_encoder = {
    "asv1",
    CODEC_TYPE_VIDEO,
    CODEC_ID_ASV1,
    sizeof(ASV1Context),
    encode_init,
    encode_frame,
    //encode_end,
643
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
644
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V1"),
Michael Niedermayer's avatar
Michael Niedermayer committed
645
};
646
#endif
647

648
#ifdef CONFIG_ASV2_ENCODER
Michael Niedermayer's avatar
Michael Niedermayer committed
649 650 651 652 653 654 655 656
AVCodec asv2_encoder = {
    "asv2",
    CODEC_TYPE_VIDEO,
    CODEC_ID_ASV2,
    sizeof(ASV1Context),
    encode_init,
    encode_frame,
    //encode_end,
657
    .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
658
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V2"),
Michael Niedermayer's avatar
Michael Niedermayer committed
659
};
660
#endif