~ubuntu-branches/ubuntu/saucy/gst-libav1.0/saucy-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libavcodec/asvenc.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-07-30 09:00:15 UTC
  • mfrom: (1.1.16) (7.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130730090015-sc1ou2yssu7q5w4e
Tags: 1.1.3-1
* New upstream development snapshot:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.1.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2003 Michael Niedermayer
 
3
 *
 
4
 * This file is part of Libav.
 
5
 *
 
6
 * Libav is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2.1 of the License, or (at your option) any later version.
 
10
 *
 
11
 * Libav is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with Libav; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
19
 */
 
20
 
 
21
/**
 
22
 * @file
 
23
 * ASUS V1/V2 encoder.
 
24
 */
 
25
 
 
26
#include "libavutil/attributes.h"
 
27
#include "libavutil/mem.h"
 
28
 
 
29
#include "asv.h"
 
30
#include "avcodec.h"
 
31
#include "mathops.h"
 
32
#include "mpeg12data.h"
 
33
 
 
34
static inline void asv2_put_bits(PutBitContext *pb, int n, int v){
 
35
    put_bits(pb, n, ff_reverse[ v << (8-n) ]);
 
36
}
 
37
 
 
38
static inline void asv1_put_level(PutBitContext *pb, int level){
 
39
    unsigned int index= level + 3;
 
40
 
 
41
    if(index <= 6) put_bits(pb, ff_asv_level_tab[index][1], ff_asv_level_tab[index][0]);
 
42
    else{
 
43
        put_bits(pb, ff_asv_level_tab[3][1], ff_asv_level_tab[3][0]);
 
44
        put_sbits(pb, 8, level);
 
45
    }
 
46
}
 
47
 
 
48
static inline void asv2_put_level(PutBitContext *pb, int level){
 
49
    unsigned int index= level + 31;
 
50
 
 
51
    if(index <= 62) put_bits(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]);
 
52
    else{
 
53
        put_bits(pb, ff_asv2_level_tab[31][1], ff_asv2_level_tab[31][0]);
 
54
        asv2_put_bits(pb, 8, level&0xFF);
 
55
    }
 
56
}
 
57
 
 
58
static inline void asv1_encode_block(ASV1Context *a, DCTELEM block[64]){
 
59
    int i;
 
60
    int nc_count=0;
 
61
 
 
62
    put_bits(&a->pb, 8, (block[0] + 32)>>6);
 
63
    block[0]= 0;
 
64
 
 
65
    for(i=0; i<10; i++){
 
66
        const int index = ff_asv_scantab[4*i];
 
67
        int ccp=0;
 
68
 
 
69
        if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8;
 
70
        if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4;
 
71
        if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2;
 
72
        if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1;
 
73
 
 
74
        if(ccp){
 
75
            for(;nc_count; nc_count--)
 
76
                put_bits(&a->pb, ff_asv_ccp_tab[0][1], ff_asv_ccp_tab[0][0]);
 
77
 
 
78
            put_bits(&a->pb, ff_asv_ccp_tab[ccp][1], ff_asv_ccp_tab[ccp][0]);
 
79
 
 
80
            if(ccp&8) asv1_put_level(&a->pb, block[index + 0]);
 
81
            if(ccp&4) asv1_put_level(&a->pb, block[index + 8]);
 
82
            if(ccp&2) asv1_put_level(&a->pb, block[index + 1]);
 
83
            if(ccp&1) asv1_put_level(&a->pb, block[index + 9]);
 
84
        }else{
 
85
            nc_count++;
 
86
        }
 
87
    }
 
88
    put_bits(&a->pb, ff_asv_ccp_tab[16][1], ff_asv_ccp_tab[16][0]);
 
89
}
 
90
 
 
91
static inline void asv2_encode_block(ASV1Context *a, DCTELEM block[64]){
 
92
    int i;
 
93
    int count=0;
 
94
 
 
95
    for(count=63; count>3; count--){
 
96
        const int index = ff_asv_scantab[count];
 
97
 
 
98
        if( (block[index]*a->q_intra_matrix[index] + (1<<15))>>16 )
 
99
            break;
 
100
    }
 
101
 
 
102
    count >>= 2;
 
103
 
 
104
    asv2_put_bits(&a->pb, 4, count);
 
105
    asv2_put_bits(&a->pb, 8, (block[0] + 32)>>6);
 
106
    block[0]= 0;
 
107
 
 
108
    for(i=0; i<=count; i++){
 
109
        const int index = ff_asv_scantab[4*i];
 
110
        int ccp=0;
 
111
 
 
112
        if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8;
 
113
        if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4;
 
114
        if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2;
 
115
        if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1;
 
116
 
 
117
        assert(i || ccp<8);
 
118
        if(i) put_bits(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]);
 
119
        else  put_bits(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]);
 
120
 
 
121
        if(ccp){
 
122
            if(ccp&8) asv2_put_level(&a->pb, block[index + 0]);
 
123
            if(ccp&4) asv2_put_level(&a->pb, block[index + 8]);
 
124
            if(ccp&2) asv2_put_level(&a->pb, block[index + 1]);
 
125
            if(ccp&1) asv2_put_level(&a->pb, block[index + 9]);
 
126
        }
 
127
    }
 
128
}
 
129
 
 
130
#define MAX_MB_SIZE (30*16*16*3/2/8)
 
131
 
 
132
static inline int encode_mb(ASV1Context *a, DCTELEM block[6][64]){
 
133
    int i;
 
134
 
 
135
    if (a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < MAX_MB_SIZE) {
 
136
        av_log(a->avctx, AV_LOG_ERROR, "encoded frame too large\n");
 
137
        return -1;
 
138
    }
 
139
 
 
140
    if(a->avctx->codec_id == AV_CODEC_ID_ASV1){
 
141
        for(i=0; i<6; i++)
 
142
            asv1_encode_block(a, block[i]);
 
143
    }else{
 
144
        for(i=0; i<6; i++)
 
145
            asv2_encode_block(a, block[i]);
 
146
    }
 
147
    return 0;
 
148
}
 
149
 
 
150
static inline void dct_get(ASV1Context *a, int mb_x, int mb_y){
 
151
    DCTELEM (*block)[64]= a->block;
 
152
    int linesize= a->picture.linesize[0];
 
153
    int i;
 
154
 
 
155
    uint8_t *ptr_y  = a->picture.data[0] + (mb_y * 16* linesize              ) + mb_x * 16;
 
156
    uint8_t *ptr_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8;
 
157
    uint8_t *ptr_cr = a->picture.data[2] + (mb_y * 8 * a->picture.linesize[2]) + mb_x * 8;
 
158
 
 
159
    a->dsp.get_pixels(block[0], ptr_y                 , linesize);
 
160
    a->dsp.get_pixels(block[1], ptr_y              + 8, linesize);
 
161
    a->dsp.get_pixels(block[2], ptr_y + 8*linesize    , linesize);
 
162
    a->dsp.get_pixels(block[3], ptr_y + 8*linesize + 8, linesize);
 
163
    for(i=0; i<4; i++)
 
164
        a->dsp.fdct(block[i]);
 
165
 
 
166
    if(!(a->avctx->flags&CODEC_FLAG_GRAY)){
 
167
        a->dsp.get_pixels(block[4], ptr_cb, a->picture.linesize[1]);
 
168
        a->dsp.get_pixels(block[5], ptr_cr, a->picture.linesize[2]);
 
169
        for(i=4; i<6; i++)
 
170
            a->dsp.fdct(block[i]);
 
171
    }
 
172
}
 
173
 
 
174
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
175
                        const AVFrame *pict, int *got_packet)
 
176
{
 
177
    ASV1Context * const a = avctx->priv_data;
 
178
    AVFrame * const p= &a->picture;
 
179
    int size, ret;
 
180
    int mb_x, mb_y;
 
181
 
 
182
    if (!pkt->data &&
 
183
        (ret = av_new_packet(pkt, a->mb_height*a->mb_width*MAX_MB_SIZE +
 
184
                                  FF_MIN_BUFFER_SIZE)) < 0) {
 
185
        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
 
186
        return ret;
 
187
    }
 
188
 
 
189
    init_put_bits(&a->pb, pkt->data, pkt->size);
 
190
 
 
191
    *p = *pict;
 
192
    p->pict_type= AV_PICTURE_TYPE_I;
 
193
    p->key_frame= 1;
 
194
 
 
195
    for(mb_y=0; mb_y<a->mb_height2; mb_y++){
 
196
        for(mb_x=0; mb_x<a->mb_width2; mb_x++){
 
197
            dct_get(a, mb_x, mb_y);
 
198
            encode_mb(a, a->block);
 
199
        }
 
200
    }
 
201
 
 
202
    if(a->mb_width2 != a->mb_width){
 
203
        mb_x= a->mb_width2;
 
204
        for(mb_y=0; mb_y<a->mb_height2; mb_y++){
 
205
            dct_get(a, mb_x, mb_y);
 
206
            encode_mb(a, a->block);
 
207
        }
 
208
    }
 
209
 
 
210
    if(a->mb_height2 != a->mb_height){
 
211
        mb_y= a->mb_height2;
 
212
        for(mb_x=0; mb_x<a->mb_width; mb_x++){
 
213
            dct_get(a, mb_x, mb_y);
 
214
            encode_mb(a, a->block);
 
215
        }
 
216
    }
 
217
    emms_c();
 
218
 
 
219
    avpriv_align_put_bits(&a->pb);
 
220
    while(put_bits_count(&a->pb)&31)
 
221
        put_bits(&a->pb, 8, 0);
 
222
 
 
223
    size= put_bits_count(&a->pb)/32;
 
224
 
 
225
    if(avctx->codec_id == AV_CODEC_ID_ASV1)
 
226
        a->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size);
 
227
    else{
 
228
        int i;
 
229
        for(i=0; i<4*size; i++)
 
230
            pkt->data[i] = ff_reverse[pkt->data[i]];
 
231
    }
 
232
 
 
233
    pkt->size   = size*4;
 
234
    pkt->flags |= AV_PKT_FLAG_KEY;
 
235
    *got_packet = 1;
 
236
 
 
237
    return 0;
 
238
}
 
239
 
 
240
static av_cold int encode_init(AVCodecContext *avctx){
 
241
    ASV1Context * const a = avctx->priv_data;
 
242
    int i;
 
243
    const int scale= avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2;
 
244
 
 
245
    ff_asv_common_init(avctx);
 
246
 
 
247
    if(avctx->global_quality == 0) avctx->global_quality= 4*FF_QUALITY_SCALE;
 
248
 
 
249
    a->inv_qscale= (32*scale*FF_QUALITY_SCALE +  avctx->global_quality/2) / avctx->global_quality;
 
250
 
 
251
    avctx->extradata= av_mallocz(8);
 
252
    avctx->extradata_size=8;
 
253
    ((uint32_t*)avctx->extradata)[0]= av_le2ne32(a->inv_qscale);
 
254
    ((uint32_t*)avctx->extradata)[1]= av_le2ne32(AV_RL32("ASUS"));
 
255
 
 
256
    for(i=0; i<64; i++){
 
257
        int q= 32*scale*ff_mpeg1_default_intra_matrix[i];
 
258
        a->q_intra_matrix[i]= ((a->inv_qscale<<16) + q/2) / q;
 
259
    }
 
260
 
 
261
    return 0;
 
262
}
 
263
 
 
264
#if CONFIG_ASV1_ENCODER
 
265
AVCodec ff_asv1_encoder = {
 
266
    .name           = "asv1",
 
267
    .type           = AVMEDIA_TYPE_VIDEO,
 
268
    .id             = AV_CODEC_ID_ASV1,
 
269
    .priv_data_size = sizeof(ASV1Context),
 
270
    .init           = encode_init,
 
271
    .encode2        = encode_frame,
 
272
    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
 
273
                                                    AV_PIX_FMT_NONE },
 
274
    .long_name      = NULL_IF_CONFIG_SMALL("ASUS V1"),
 
275
};
 
276
#endif
 
277
 
 
278
#if CONFIG_ASV2_ENCODER
 
279
AVCodec ff_asv2_encoder = {
 
280
    .name           = "asv2",
 
281
    .type           = AVMEDIA_TYPE_VIDEO,
 
282
    .id             = AV_CODEC_ID_ASV2,
 
283
    .priv_data_size = sizeof(ASV1Context),
 
284
    .init           = encode_init,
 
285
    .encode2        = encode_frame,
 
286
    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
 
287
                                                    AV_PIX_FMT_NONE },
 
288
    .long_name      = NULL_IF_CONFIG_SMALL("ASUS V2"),
 
289
};
 
290
#endif