ffmpeg / libavcodec / libxavs.c @ b9f9e59a
History | View | Annotate | Download (11.7 KB)
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",
|
341 |
.type = AVMEDIA_TYPE_VIDEO, |
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 |
|