asv1.c 20.1 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
 * This file is part of Libav.
6
 *
7
 * Libav 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
 * Libav 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 Libav; 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
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 "libavutil/common.h"
29
#include "put_bits.h"
Michael Niedermayer's avatar
Michael Niedermayer committed
30
#include "dsputil.h"
31
#include "mpeg12data.h"
Michael Niedermayer's avatar
Michael Niedermayer committed
32 33 34 35

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
39 40 41 42 43 44 45 46 47 48 49 50
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;
51
    DECLARE_ALIGNED(16, DCTELEM, block)[6][64];
52 53
    uint16_t intra_matrix[64];
    int q_intra_matrix[64];
Michael Niedermayer's avatar
Michael Niedermayer committed
54
    uint8_t *bitstream_buffer;
55
    unsigned int bitstream_buffer_size;
Michael Niedermayer's avatar
Michael Niedermayer committed
56 57 58 59 60 61 62 63
} 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
64 65 66 67 68 69
    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
70
static const uint8_t ccp_tab[17][2]={
Michael Niedermayer's avatar
Michael Niedermayer committed
71 72
    {0x2,2}, {0x7,5}, {0xB,5}, {0x3,5},
    {0xD,5}, {0x5,5}, {0x9,5}, {0x1,5},
73
    {0xE,5}, {0x6,5}, {0xA,5}, {0x2,5},
Michael Niedermayer's avatar
Michael Niedermayer committed
74
    {0xC,5}, {0x4,5}, {0x8,5}, {0x3,2},
Michael Niedermayer's avatar
Michael Niedermayer committed
75 76 77 78 79 80 81
    {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
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 110
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
111 112
static VLC ccp_vlc;
static VLC level_vlc;
Michael Niedermayer's avatar
Michael Niedermayer committed
113 114 115
static VLC dc_ccp_vlc;
static VLC ac_ccp_vlc;
static VLC asv2_level_vlc;
Michael Niedermayer's avatar
Michael Niedermayer committed
116

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

    if (!done) {
        done = 1;

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
150
static inline int asv1_get_level(GetBitContext *gb){
Michael Niedermayer's avatar
Michael Niedermayer committed
151 152 153 154 155 156
    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
157 158 159 160 161 162 163 164
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
165 166 167 168 169
    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]);
170
        put_sbits(pb, 8, level);
Michael Niedermayer's avatar
Michael Niedermayer committed
171 172 173
    }
}

Michael Niedermayer's avatar
Michael Niedermayer committed
174 175 176 177 178 179 180 181 182 183
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
184
static inline int asv1_decode_block(ASV1Context *a, DCTELEM block[64]){
Michael Niedermayer's avatar
Michael Niedermayer committed
185 186 187
    int i;

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

Michael Niedermayer's avatar
Michael Niedermayer committed
189 190 191 192 193 194
    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){
195
                av_log(a->avctx, AV_LOG_ERROR, "coded coeff pattern damaged\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
196 197 198
                return -1;
            }

Michael Niedermayer's avatar
Michael Niedermayer committed
199 200 201 202
            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
203 204 205 206 207 208
        }
    }

    return 0;
}

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
    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;
        }
    }
233

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

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
248 249 250 251
        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
252 253

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
259 260 261 262
            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
263 264 265 266 267 268 269
        }else{
            nc_count++;
        }
    }
    put_bits(&a->pb, ccp_tab[16][1], ccp_tab[16][0]);
}

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

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

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
287 288 289 290 291 292 293 294 295
    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;

296
        assert(i || ccp<8);
Michael Niedermayer's avatar
Michael Niedermayer committed
297 298 299 300 301 302 303 304 305 306 307 308
        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
309 310 311 312
static inline int decode_mb(ASV1Context *a, DCTELEM block[6][64]){
    int i;

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

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

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

331 332 333 334
    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
335

Michael Niedermayer's avatar
Michael Niedermayer committed
336 337 338 339 340 341
    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
342
    }
343
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
344
}
345

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

Michael Niedermayer's avatar
Michael Niedermayer committed
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
    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;
369

Michael Niedermayer's avatar
Michael Niedermayer committed
370 371 372 373 374 375 376 377 378 379
    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]);
380

Michael Niedermayer's avatar
Michael Niedermayer committed
381 382 383 384 385 386 387 388
    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]);
    }
}

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

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

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

411 412 413
    av_fast_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!a->bitstream_buffer)
        return AVERROR(ENOMEM);
414

Michael Niedermayer's avatar
Michael Niedermayer committed
415
    if(avctx->codec_id == CODEC_ID_ASV1)
Michael Niedermayer's avatar
Michael Niedermayer committed
416
        a->dsp.bswap_buf((uint32_t*)a->bitstream_buffer, (const uint32_t*)buf, buf_size/4);
Michael Niedermayer's avatar
Michael Niedermayer committed
417 418 419
    else{
        int i;
        for(i=0; i<buf_size; i++)
420
            a->bitstream_buffer[i]= av_reverse[ buf[i] ];
Michael Niedermayer's avatar
Michael Niedermayer committed
421 422
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
423 424 425 426 427 428
    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;
429

Michael Niedermayer's avatar
Michael Niedermayer committed
430 431 432 433 434 435 436 437 438
            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;
439

Michael Niedermayer's avatar
Michael Niedermayer committed
440 441 442 443 444 445 446 447 448
            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;
449

Michael Niedermayer's avatar
Michael Niedermayer committed
450 451 452 453 454 455 456 457
            idct_put(a, mb_x, mb_y);
        }
    }

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

    emms_c();
458

Michael Niedermayer's avatar
Michael Niedermayer committed
459 460 461
    return (get_bits_count(&a->gb)+31)/32*4;
}

462
#if CONFIG_ASV1_ENCODER || CONFIG_ASV2_ENCODER
Michael Niedermayer's avatar
Michael Niedermayer committed
463 464 465
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
    ASV1Context * const a = avctx->priv_data;
    AVFrame *pict = data;
466
    AVFrame * const p= &a->picture;
Michael Niedermayer's avatar
Michael Niedermayer committed
467 468 469
    int size;
    int mb_x, mb_y;

470
    init_put_bits(&a->pb, buf, buf_size);
471

Michael Niedermayer's avatar
Michael Niedermayer committed
472
    *p = *pict;
473
    p->pict_type= AV_PICTURE_TYPE_I;
Michael Niedermayer's avatar
Michael Niedermayer committed
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
    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();
499

500
    avpriv_align_put_bits(&a->pb);
501
    while(put_bits_count(&a->pb)&31)
Michael Niedermayer's avatar
Michael Niedermayer committed
502
        put_bits(&a->pb, 8, 0);
503

504
    size= put_bits_count(&a->pb)/32;
505

Michael Niedermayer's avatar
Michael Niedermayer committed
506 507 508 509 510
    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++)
511
            buf[i]= av_reverse[ buf[i] ];
Michael Niedermayer's avatar
Michael Niedermayer committed
512
    }
513

Michael Niedermayer's avatar
Michael Niedermayer committed
514 515
    return size*4;
}
516
#endif /* CONFIG_ASV1_ENCODER || CONFIG_ASV2_ENCODER */
Michael Niedermayer's avatar
Michael Niedermayer committed
517

518
static av_cold void common_init(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
519 520 521 522 523 524 525 526 527
    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;

528
    avctx->coded_frame= &a->picture;
Michael Niedermayer's avatar
Michael Niedermayer committed
529 530 531
    a->avctx= avctx;
}

532
static av_cold int decode_init(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
533
    ASV1Context * const a = avctx->priv_data;
534
    AVFrame *p= &a->picture;
Michael Niedermayer's avatar
Michael Niedermayer committed
535
    int i;
Michael Niedermayer's avatar
Michael Niedermayer committed
536
    const int scale= avctx->codec_id == CODEC_ID_ASV1 ? 1 : 2;
537

Michael Niedermayer's avatar
Michael Niedermayer committed
538 539 540
    common_init(avctx);
    init_vlcs(a);
    ff_init_scantable(a->dsp.idct_permutation, &a->scantable, scantab);
541
    avctx->pix_fmt= PIX_FMT_YUV420P;
Michael Niedermayer's avatar
Michael Niedermayer committed
542

543
    a->inv_qscale= avctx->extradata[0];
Michael Niedermayer's avatar
Michael Niedermayer committed
544
    if(a->inv_qscale == 0){
545
        av_log(avctx, AV_LOG_ERROR, "illegal qscale 0\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
546 547 548 549
        if(avctx->codec_id == CODEC_ID_ASV1)
            a->inv_qscale= 6;
        else
            a->inv_qscale= 10;
Michael Niedermayer's avatar
Michael Niedermayer committed
550 551 552 553
    }

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

Michael Niedermayer's avatar
Michael Niedermayer committed
555
        a->intra_matrix[i]= 64*scale*ff_mpeg1_default_intra_matrix[index] / a->inv_qscale;
Michael Niedermayer's avatar
Michael Niedermayer committed
556 557 558
    }

    p->qstride= a->mb_width;
559
    p->qscale_table= av_malloc( p->qstride * a->mb_height);
Michael Niedermayer's avatar
Michael Niedermayer committed
560 561
    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
562 563 564 565

    return 0;
}

566
#if CONFIG_ASV1_ENCODER || CONFIG_ASV2_ENCODER
567
static av_cold int encode_init(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
568 569
    ASV1Context * const a = avctx->priv_data;
    int i;
Michael Niedermayer's avatar
Michael Niedermayer committed
570 571
    const int scale= avctx->codec_id == CODEC_ID_ASV1 ? 1 : 2;

Michael Niedermayer's avatar
Michael Niedermayer committed
572
    common_init(avctx);
573

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
578 579
    avctx->extradata= av_mallocz(8);
    avctx->extradata_size=8;
580 581
    ((uint32_t*)avctx->extradata)[0]= av_le2ne32(a->inv_qscale);
    ((uint32_t*)avctx->extradata)[1]= av_le2ne32(AV_RL32("ASUS"));
582

Michael Niedermayer's avatar
Michael Niedermayer committed
583
    for(i=0; i<64; i++){
Michael Niedermayer's avatar
Michael Niedermayer committed
584
        int q= 32*scale*ff_mpeg1_default_intra_matrix[i];
Michael Niedermayer's avatar
Michael Niedermayer committed
585 586 587 588 589
        a->q_intra_matrix[i]= ((a->inv_qscale<<16) + q/2) / q;
    }

    return 0;
}
590
#endif /* CONFIG_ASV1_ENCODER || CONFIG_ASV2_ENCODER */
Michael Niedermayer's avatar
Michael Niedermayer committed
591

592
static av_cold int decode_end(AVCodecContext *avctx){
Michael Niedermayer's avatar
Michael Niedermayer committed
593 594 595 596 597
    ASV1Context * const a = avctx->priv_data;

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

599 600 601
    if(a->picture.data[0])
        avctx->release_buffer(avctx, &a->picture);

Michael Niedermayer's avatar
Michael Niedermayer committed
602 603 604
    return 0;
}

605
AVCodec ff_asv1_decoder = {
606 607 608 609 610 611 612 613
    .name           = "asv1",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_ASV1,
    .priv_data_size = sizeof(ASV1Context),
    .init           = decode_init,
    .close          = decode_end,
    .decode         = decode_frame,
    .capabilities   = CODEC_CAP_DR1,
614
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V1"),
Michael Niedermayer's avatar
Michael Niedermayer committed
615 616
};

617
AVCodec ff_asv2_decoder = {
618 619 620 621 622 623 624 625
    .name           = "asv2",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_ASV2,
    .priv_data_size = sizeof(ASV1Context),
    .init           = decode_init,
    .close          = decode_end,
    .decode         = decode_frame,
    .capabilities   = CODEC_CAP_DR1,
626
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V2"),
Michael Niedermayer's avatar
Michael Niedermayer committed
627 628
};

629
#if CONFIG_ASV1_ENCODER
630
AVCodec ff_asv1_encoder = {
631 632 633 634 635 636
    .name           = "asv1",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_ASV1,
    .priv_data_size = sizeof(ASV1Context),
    .init           = encode_init,
    .encode         = encode_frame,
Michael Niedermayer's avatar
Michael Niedermayer committed
637
    //encode_end,
638
    .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
639
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V1"),
Michael Niedermayer's avatar
Michael Niedermayer committed
640
};
641
#endif
642

643
#if CONFIG_ASV2_ENCODER
644
AVCodec ff_asv2_encoder = {
645 646 647 648 649 650
    .name           = "asv2",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_ASV2,
    .priv_data_size = sizeof(ASV1Context),
    .init           = encode_init,
    .encode         = encode_frame,
Michael Niedermayer's avatar
Michael Niedermayer committed
651
    //encode_end,
652
    .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
653
    .long_name= NULL_IF_CONFIG_SMALL("ASUS V2"),
Michael Niedermayer's avatar
Michael Niedermayer committed
654
};
655
#endif