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