Mercurial > libavcodec.hg
annotate libxavs.c @ 12522:776789af0304 libavcodec
Move AVOptions from libavcodec to libavutil
author | michael |
---|---|
date | Sun, 26 Sep 2010 14:25:22 +0000 |
parents | 34beb0af8204 |
children |
rev | line source |
---|---|
12281 | 1 /* |
2 * AVS encoding using the xavs library | |
3 * Copyright (C) 2010 Amanda, Y.N. Wu <amanda11192003@gmail.com> | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * 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 | |
20 */ | |
21 | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 #include <math.h> | |
26 #include <stdint.h> | |
27 #include <xavs.h> | |
28 #include "avcodec.h" | |
29 | |
30 #define END_OF_STREAM 0x001 | |
31 | |
32 #define XAVS_PART_I8X8 0x002 /* Analyze i8x8 (requires 8x8 transform) */ | |
33 #define XAVS_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */ | |
34 #define XAVS_PART_B8X8 0x100 /* Analyze b16x8, b*/ | |
35 | |
36 typedef struct XavsContext { | |
37 xavs_param_t params; | |
38 xavs_t *enc; | |
39 xavs_picture_t pic; | |
40 uint8_t *sei; | |
41 int sei_size; | |
42 AVFrame out_pic; | |
43 int end_of_stream; | |
44 } XavsContext; | |
45 | |
46 static void XAVS_log(void *p, int level, const char *fmt, va_list args) | |
47 { | |
48 static const int level_map[] = { | |
49 [XAVS_LOG_ERROR] = AV_LOG_ERROR, | |
50 [XAVS_LOG_WARNING] = AV_LOG_WARNING, | |
51 [XAVS_LOG_INFO] = AV_LOG_INFO, | |
52 [XAVS_LOG_DEBUG] = AV_LOG_DEBUG | |
53 }; | |
54 | |
55 if (level < 0 || level > XAVS_LOG_DEBUG) | |
56 return; | |
57 | |
58 av_vlog(p, level_map[level], fmt, args); | |
59 } | |
60 | |
61 static int encode_nals(AVCodecContext *ctx, uint8_t *buf, | |
62 int size, xavs_nal_t *nals, | |
63 int nnal, int skip_sei) | |
64 { | |
65 XavsContext *x4 = ctx->priv_data; | |
66 uint8_t *p = buf; | |
67 int i, s; | |
68 | |
69 /* Write the SEI as part of the first frame. */ | |
70 if (x4->sei_size > 0 && nnal > 0) { | |
71 memcpy(p, x4->sei, x4->sei_size); | |
72 p += x4->sei_size; | |
73 x4->sei_size = 0; | |
74 } | |
75 | |
76 for (i = 0; i < nnal; i++) { | |
77 /* Don't put the SEI in extradata. */ | |
78 if (skip_sei && nals[i].i_type == NAL_SEI) { | |
79 x4->sei = av_malloc( 5 + nals[i].i_payload * 4 / 3 ); | |
80 if (xavs_nal_encode(x4->sei, &x4->sei_size, 1, nals + i) < 0) | |
81 return -1; | |
82 | |
83 continue; | |
84 } | |
85 s = xavs_nal_encode(p, &size, 1, nals + i); | |
86 if (s < 0) | |
87 return -1; | |
88 p += s; | |
89 } | |
90 | |
91 return p - buf; | |
92 } | |
93 | |
94 static int XAVS_frame(AVCodecContext *ctx, uint8_t *buf, | |
95 int bufsize, void *data) | |
96 { | |
97 XavsContext *x4 = ctx->priv_data; | |
98 AVFrame *frame = data; | |
99 xavs_nal_t *nal; | |
100 int nnal, i; | |
101 xavs_picture_t pic_out; | |
102 | |
103 x4->pic.img.i_csp = XAVS_CSP_I420; | |
104 x4->pic.img.i_plane = 3; | |
105 | |
106 if (frame) { | |
107 for (i = 0; i < 3; i++) { | |
108 x4->pic.img.plane[i] = frame->data[i]; | |
109 x4->pic.img.i_stride[i] = frame->linesize[i]; | |
110 } | |
111 | |
112 x4->pic.i_pts = frame->pts; | |
113 x4->pic.i_type = XAVS_TYPE_AUTO; | |
114 } | |
115 | |
116 if (xavs_encoder_encode(x4->enc, &nal, &nnal, | |
117 frame? &x4->pic: NULL, &pic_out) < 0) | |
118 return -1; | |
119 | |
120 bufsize = encode_nals(ctx, buf, bufsize, nal, nnal, 0); | |
121 | |
122 if (bufsize < 0) | |
123 return -1; | |
124 | |
125 if (!bufsize && !frame && !(x4->end_of_stream)){ | |
126 buf[bufsize] = 0x0; | |
127 buf[bufsize+1] = 0x0; | |
128 buf[bufsize+2] = 0x01; | |
129 buf[bufsize+3] = 0xb1; | |
130 bufsize += 4; | |
131 x4->end_of_stream = END_OF_STREAM; | |
132 return bufsize; | |
133 } | |
134 /* FIXME: libxavs now provides DTS */ | |
135 /* but AVFrame doesn't have a field for it. */ | |
136 x4->out_pic.pts = pic_out.i_pts; | |
137 | |
138 switch (pic_out.i_type) { | |
139 case XAVS_TYPE_IDR: | |
140 case XAVS_TYPE_I: | |
141 x4->out_pic.pict_type = FF_I_TYPE; | |
142 break; | |
143 case XAVS_TYPE_P: | |
144 x4->out_pic.pict_type = FF_P_TYPE; | |
145 break; | |
146 case XAVS_TYPE_B: | |
147 case XAVS_TYPE_BREF: | |
148 x4->out_pic.pict_type = FF_B_TYPE; | |
149 break; | |
150 } | |
151 | |
152 /* There is no IDR frame in AVS JiZhun */ | |
153 /* Sequence header is used as a flag */ | |
154 x4->out_pic.key_frame = pic_out.i_type == XAVS_TYPE_I; | |
155 | |
156 x4->out_pic.quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; | |
157 | |
158 return bufsize; | |
159 } | |
160 | |
161 static av_cold int XAVS_close(AVCodecContext *avctx) | |
162 { | |
163 XavsContext *x4 = avctx->priv_data; | |
164 | |
165 av_freep(&avctx->extradata); | |
166 av_free(x4->sei); | |
167 | |
168 if (x4->enc) | |
169 xavs_encoder_close(x4->enc); | |
170 | |
171 return 0; | |
172 } | |
173 | |
174 static av_cold int XAVS_init(AVCodecContext *avctx) | |
175 { | |
176 XavsContext *x4 = avctx->priv_data; | |
177 | |
178 x4->sei_size = 0; | |
179 xavs_param_default(&x4->params); | |
180 | |
181 x4->params.pf_log = XAVS_log; | |
182 x4->params.p_log_private = avctx; | |
183 x4->params.i_keyint_max = avctx->gop_size; | |
184 x4->params.rc.i_bitrate = avctx->bit_rate / 1000; | |
185 x4->params.rc.i_vbv_buffer_size = avctx->rc_buffer_size / 1000; | |
186 x4->params.rc.i_vbv_max_bitrate = avctx->rc_max_rate / 1000; | |
187 x4->params.rc.b_stat_write = avctx->flags & CODEC_FLAG_PASS1; | |
188 if (avctx->flags & CODEC_FLAG_PASS2) { | |
189 x4->params.rc.b_stat_read = 1; | |
190 } else { | |
191 if (avctx->crf) { | |
192 x4->params.rc.i_rc_method = XAVS_RC_CRF; | |
193 x4->params.rc.f_rf_constant = avctx->crf; | |
194 } else if (avctx->cqp > -1) { | |
195 x4->params.rc.i_rc_method = XAVS_RC_CQP; | |
196 x4->params.rc.i_qp_constant = avctx->cqp; | |
197 } | |
198 } | |
199 | |
200 /* if neither crf nor cqp modes are selected we have to enable the RC */ | |
201 /* we do it this way because we cannot check if the bitrate has been set */ | |
202 if (!(avctx->crf || (avctx->cqp > -1))) | |
203 x4->params.rc.i_rc_method = XAVS_RC_ABR; | |
204 | |
205 x4->params.i_bframe = avctx->max_b_frames; | |
206 /* cabac is not included in AVS JiZhun Profile */ | |
207 x4->params.b_cabac = 0; | |
208 | |
209 x4->params.i_bframe_adaptive = avctx->b_frame_strategy; | |
210 x4->params.i_bframe_bias = avctx->bframebias; | |
211 | |
212 avctx->has_b_frames = !!avctx->max_b_frames; | |
213 | |
214 /* AVS doesn't allow B picture as reference */ | |
215 /* The max allowed reference frame number of B is 2 */ | |
216 x4->params.i_keyint_min = avctx->keyint_min; | |
217 if (x4->params.i_keyint_min > x4->params.i_keyint_max) | |
218 x4->params.i_keyint_min = x4->params.i_keyint_max; | |
219 | |
220 x4->params.i_scenecut_threshold = avctx->scenechange_threshold; | |
221 | |
222 // x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; | |
223 x4->params.i_deblocking_filter_alphac0 = avctx->deblockalpha; | |
224 x4->params.i_deblocking_filter_beta = avctx->deblockbeta; | |
225 | |
226 x4->params.rc.i_qp_min = avctx->qmin; | |
227 x4->params.rc.i_qp_max = avctx->qmax; | |
228 x4->params.rc.i_qp_step = avctx->max_qdiff; | |
229 | |
230 x4->params.rc.f_qcompress = avctx->qcompress; /* 0.0 => cbr, 1.0 => constant qp */ | |
231 x4->params.rc.f_qblur = avctx->qblur; /* temporally blur quants */ | |
232 x4->params.rc.f_complexity_blur = avctx->complexityblur; | |
233 | |
234 x4->params.i_frame_reference = avctx->refs; | |
235 | |
236 x4->params.i_width = avctx->width; | |
237 x4->params.i_height = avctx->height; | |
238 x4->params.vui.i_sar_width = avctx->sample_aspect_ratio.num; | |
239 x4->params.vui.i_sar_height = avctx->sample_aspect_ratio.den; | |
240 /* This is only used for counting the fps */ | |
241 x4->params.i_fps_num = avctx->time_base.den; | |
242 x4->params.i_fps_den = avctx->time_base.num; | |
243 x4->params.analyse.inter = XAVS_ANALYSE_I8x8 |XAVS_ANALYSE_PSUB16x16| XAVS_ANALYSE_BSUB16x16; | |
244 if (avctx->partitions) { | |
245 if (avctx->partitions & XAVS_PART_I8X8) | |
246 x4->params.analyse.inter |= XAVS_ANALYSE_I8x8; | |
247 | |
248 if (avctx->partitions & XAVS_PART_P8X8) | |
249 x4->params.analyse.inter |= XAVS_ANALYSE_PSUB16x16; | |
250 | |
251 if (avctx->partitions & XAVS_PART_B8X8) | |
252 x4->params.analyse.inter |= XAVS_ANALYSE_BSUB16x16; | |
253 } | |
254 | |
255 x4->params.analyse.i_direct_mv_pred = avctx->directpred; | |
256 | |
257 x4->params.analyse.b_weighted_bipred = avctx->flags2 & CODEC_FLAG2_WPRED; | |
258 | |
259 switch (avctx->me_method) { | |
260 case ME_EPZS: | |
261 x4->params.analyse.i_me_method = XAVS_ME_DIA; | |
262 break; | |
263 case ME_HEX: | |
264 x4->params.analyse.i_me_method = XAVS_ME_HEX; | |
265 break; | |
266 case ME_UMH: | |
267 x4->params.analyse.i_me_method = XAVS_ME_UMH; | |
268 break; | |
269 case ME_FULL: | |
270 x4->params.analyse.i_me_method = XAVS_ME_ESA; | |
271 break; | |
272 case ME_TESA: | |
273 x4->params.analyse.i_me_method = XAVS_ME_TESA; | |
274 break; | |
275 default: | |
276 x4->params.analyse.i_me_method = XAVS_ME_HEX; | |
277 } | |
278 | |
279 x4->params.analyse.i_me_range = avctx->me_range; | |
280 x4->params.analyse.i_subpel_refine = avctx->me_subpel_quality; | |
281 | |
282 x4->params.analyse.b_mixed_references = avctx->flags2 & CODEC_FLAG2_MIXED_REFS; | |
283 x4->params.analyse.b_chroma_me = avctx->me_cmp & FF_CMP_CHROMA; | |
284 /* AVS P2 only enables 8x8 transform */ | |
285 x4->params.analyse.b_transform_8x8 = 1; //avctx->flags2 & CODEC_FLAG2_8X8DCT; | |
286 x4->params.analyse.b_fast_pskip = avctx->flags2 & CODEC_FLAG2_FASTPSKIP; | |
287 | |
288 x4->params.analyse.i_trellis = avctx->trellis; | |
289 x4->params.analyse.i_noise_reduction = avctx->noise_reduction; | |
290 | |
291 if (avctx->level > 0) | |
292 x4->params.i_level_idc = avctx->level; | |
293 | |
294 x4->params.rc.f_rate_tolerance = | |
295 (float)avctx->bit_rate_tolerance/avctx->bit_rate; | |
296 | |
297 if ((avctx->rc_buffer_size) && | |
298 (avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) { | |
299 x4->params.rc.f_vbv_buffer_init = | |
300 (float)avctx->rc_initial_buffer_occupancy / avctx->rc_buffer_size; | |
301 } else | |
302 x4->params.rc.f_vbv_buffer_init = 0.9; | |
303 | |
304 /* TAG:do we have MB tree RC method */ | |
305 /* what is the RC method we are now using? Default NO */ | |
306 x4->params.rc.b_mb_tree = !!(avctx->flags2 & CODEC_FLAG2_MBTREE); | |
307 x4->params.rc.f_ip_factor = 1 / fabs(avctx->i_quant_factor); | |
308 x4->params.rc.f_pb_factor = avctx->b_quant_factor; | |
309 x4->params.analyse.i_chroma_qp_offset = avctx->chromaoffset; | |
310 | |
311 x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR; | |
312 x4->params.i_log_level = XAVS_LOG_DEBUG; | |
313 x4->params.b_aud = avctx->flags2 & CODEC_FLAG2_AUD; | |
314 x4->params.i_threads = avctx->thread_count; | |
315 x4->params.b_interlaced = avctx->flags & CODEC_FLAG_INTERLACED_DCT; | |
316 | |
317 if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) | |
318 x4->params.b_repeat_headers = 0; | |
319 | |
320 x4->enc = xavs_encoder_open(&x4->params); | |
321 if (!x4->enc) | |
322 return -1; | |
323 | |
324 avctx->coded_frame = &x4->out_pic; | |
325 /* TAG: Do we have GLOBAL HEADER in AVS */ | |
326 /* We Have PPS and SPS in AVS */ | |
327 if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { | |
328 xavs_nal_t *nal; | |
329 int nnal, s; | |
330 | |
331 s = xavs_encoder_headers(x4->enc, &nal, &nnal); | |
332 | |
333 avctx->extradata = av_malloc(s); | |
334 avctx->extradata_size = encode_nals(avctx, avctx->extradata, s, nal, nnal, 1); | |
335 } | |
336 return 0; | |
337 } | |
338 | |
339 AVCodec libxavs_encoder = { | |
340 .name = "libxavs", | |
12516
34beb0af8204
Replace deprecated CODEC_TYPE_AUDIO and CODEC_TYPE_VIDEO with the
stefano
parents:
12281
diff
changeset
|
341 .type = AVMEDIA_TYPE_VIDEO, |
12281 | 342 .id = CODEC_ID_CAVS, |
343 .priv_data_size = sizeof(XavsContext), | |
344 .init = XAVS_init, | |
345 .encode = XAVS_frame, | |
346 .close = XAVS_close, | |
347 .capabilities = CODEC_CAP_DELAY, | |
348 .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_NONE }, | |
349 .long_name = NULL_IF_CONFIG_SMALL("libxavs - the Chinese Audio Video Standard Encoder"), | |
350 }; | |
351 |