2 * AVS encoding using the xavs library
3 * Copyright (C) 2010 Amanda, Y.N. Wu <amanda11192003@gmail.com>
5 * This file is part of FFmpeg.
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.
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.
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
31 #include "libavutil/internal.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/opt.h"
35 #define END_OF_STREAM 0x001
37 #define XAVS_PART_I8X8 0x002 /* Analyze i8x8 (requires 8x8 transform) */
38 #define XAVS_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */
39 #define XAVS_PART_B8X8 0x100 /* Analyze b16x8, b*/
41 typedef struct XavsContext
{
63 static void XAVS_log(void *p
, int level
, const char *fmt
, va_list args
)
65 static const int level_map
[] = {
66 [XAVS_LOG_ERROR
] = AV_LOG_ERROR
,
67 [XAVS_LOG_WARNING
] = AV_LOG_WARNING
,
68 [XAVS_LOG_INFO
] = AV_LOG_INFO
,
69 [XAVS_LOG_DEBUG
] = AV_LOG_DEBUG
72 if (level
< 0 || level
> XAVS_LOG_DEBUG
)
75 av_vlog(p
, level_map
[level
], fmt
, args
);
78 static int encode_nals(AVCodecContext
*ctx
, AVPacket
*pkt
,
79 xavs_nal_t
*nals
, int nnal
)
81 XavsContext
*x4
= ctx
->priv_data
;
83 int i
, s
, ret
, size
= x4
->sei_size
+ FF_MIN_BUFFER_SIZE
;
88 for (i
= 0; i
< nnal
; i
++)
89 size
+= nals
[i
].i_payload
;
91 if ((ret
= ff_alloc_packet2(ctx
, pkt
, size
)) < 0)
95 /* Write the SEI as part of the first frame. */
96 if (x4
->sei_size
> 0 && nnal
> 0) {
97 memcpy(p
, x4
->sei
, x4
->sei_size
);
102 for (i
= 0; i
< nnal
; i
++) {
103 s
= xavs_nal_encode(p
, &size
, 1, nals
+ i
);
108 pkt
->size
= p
- pkt
->data
;
113 static int XAVS_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
114 const AVFrame
*frame
, int *got_packet
)
116 XavsContext
*x4
= avctx
->priv_data
;
119 xavs_picture_t pic_out
;
121 x4
->pic
.img
.i_csp
= XAVS_CSP_I420
;
122 x4
->pic
.img
.i_plane
= 3;
125 for (i
= 0; i
< 3; i
++) {
126 x4
->pic
.img
.plane
[i
] = frame
->data
[i
];
127 x4
->pic
.img
.i_stride
[i
] = frame
->linesize
[i
];
130 x4
->pic
.i_pts
= frame
->pts
;
131 x4
->pic
.i_type
= XAVS_TYPE_AUTO
;
132 x4
->pts_buffer
[avctx
->frame_number
% (avctx
->max_b_frames
+1)] = frame
->pts
;
135 if (xavs_encoder_encode(x4
->enc
, &nal
, &nnal
,
136 frame
? &x4
->pic
: NULL
, &pic_out
) < 0)
139 ret
= encode_nals(avctx
, pkt
, nal
, nnal
);
145 if (!frame
&& !(x4
->end_of_stream
)) {
146 if ((ret
= ff_alloc_packet2(avctx
, pkt
, 4)) < 0)
153 pkt
->dts
= 2*x4
->pts_buffer
[(x4
->out_frame_count
-1)%(avctx
->max_b_frames
+1)] -
154 x4
->pts_buffer
[(x4
->out_frame_count
-2)%(avctx
->max_b_frames
+1)];
155 x4
->end_of_stream
= END_OF_STREAM
;
161 avctx
->coded_frame
->pts
= pic_out
.i_pts
;
162 pkt
->pts
= pic_out
.i_pts
;
163 if (avctx
->has_b_frames
) {
164 if (!x4
->out_frame_count
)
165 pkt
->dts
= pkt
->pts
- (x4
->pts_buffer
[1] - x4
->pts_buffer
[0]);
167 pkt
->dts
= x4
->pts_buffer
[(x4
->out_frame_count
-1)%(avctx
->max_b_frames
+1)];
171 switch (pic_out
.i_type
) {
174 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_I
;
177 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_P
;
181 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_B
;
185 /* There is no IDR frame in AVS JiZhun */
186 /* Sequence header is used as a flag */
187 if (pic_out
.i_type
== XAVS_TYPE_I
) {
188 avctx
->coded_frame
->key_frame
= 1;
189 pkt
->flags
|= AV_PKT_FLAG_KEY
;
192 avctx
->coded_frame
->quality
= (pic_out
.i_qpplus1
- 1) * FF_QP2LAMBDA
;
194 x4
->out_frame_count
++;
199 static av_cold
int XAVS_close(AVCodecContext
*avctx
)
201 XavsContext
*x4
= avctx
->priv_data
;
203 av_freep(&avctx
->extradata
);
205 av_freep(&x4
->pts_buffer
);
208 xavs_encoder_close(x4
->enc
);
210 av_frame_free(&avctx
->coded_frame
);
215 static av_cold
int XAVS_init(AVCodecContext
*avctx
)
217 XavsContext
*x4
= avctx
->priv_data
;
220 xavs_param_default(&x4
->params
);
222 x4
->params
.pf_log
= XAVS_log
;
223 x4
->params
.p_log_private
= avctx
;
224 x4
->params
.i_keyint_max
= avctx
->gop_size
;
225 if (avctx
->bit_rate
) {
226 x4
->params
.rc
.i_bitrate
= avctx
->bit_rate
/ 1000;
227 x4
->params
.rc
.i_rc_method
= XAVS_RC_ABR
;
229 x4
->params
.rc
.i_vbv_buffer_size
= avctx
->rc_buffer_size
/ 1000;
230 x4
->params
.rc
.i_vbv_max_bitrate
= avctx
->rc_max_rate
/ 1000;
231 x4
->params
.rc
.b_stat_write
= avctx
->flags
& CODEC_FLAG_PASS1
;
232 if (avctx
->flags
& CODEC_FLAG_PASS2
) {
233 x4
->params
.rc
.b_stat_read
= 1;
236 x4
->params
.rc
.i_rc_method
= XAVS_RC_CRF
;
237 x4
->params
.rc
.f_rf_constant
= x4
->crf
;
238 } else if (x4
->cqp
>= 0) {
239 x4
->params
.rc
.i_rc_method
= XAVS_RC_CQP
;
240 x4
->params
.rc
.i_qp_constant
= x4
->cqp
;
245 x4
->params
.b_aud
= x4
->aud
;
247 x4
->params
.rc
.b_mb_tree
= x4
->mbtree
;
248 if (x4
->direct_pred
>= 0)
249 x4
->params
.analyse
.i_direct_mv_pred
= x4
->direct_pred
;
250 if (x4
->fast_pskip
>= 0)
251 x4
->params
.analyse
.b_fast_pskip
= x4
->fast_pskip
;
252 if (x4
->mixed_refs
>= 0)
253 x4
->params
.analyse
.b_mixed_references
= x4
->mixed_refs
;
254 if (x4
->b_bias
!= INT_MIN
)
255 x4
->params
.i_bframe_bias
= x4
->b_bias
;
256 if (x4
->cplxblur
>= 0)
257 x4
->params
.rc
.f_complexity_blur
= x4
->cplxblur
;
259 x4
->params
.i_bframe
= avctx
->max_b_frames
;
260 /* cabac is not included in AVS JiZhun Profile */
261 x4
->params
.b_cabac
= 0;
263 x4
->params
.i_bframe_adaptive
= avctx
->b_frame_strategy
;
265 avctx
->has_b_frames
= !!avctx
->max_b_frames
;
267 /* AVS doesn't allow B picture as reference */
268 /* The max allowed reference frame number of B is 2 */
269 x4
->params
.i_keyint_min
= avctx
->keyint_min
;
270 if (x4
->params
.i_keyint_min
> x4
->params
.i_keyint_max
)
271 x4
->params
.i_keyint_min
= x4
->params
.i_keyint_max
;
273 x4
->params
.i_scenecut_threshold
= avctx
->scenechange_threshold
;
275 // x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER;
277 x4
->params
.rc
.i_qp_min
= avctx
->qmin
;
278 x4
->params
.rc
.i_qp_max
= avctx
->qmax
;
279 x4
->params
.rc
.i_qp_step
= avctx
->max_qdiff
;
281 x4
->params
.rc
.f_qcompress
= avctx
->qcompress
; /* 0.0 => cbr, 1.0 => constant qp */
282 x4
->params
.rc
.f_qblur
= avctx
->qblur
; /* temporally blur quants */
284 x4
->params
.i_frame_reference
= avctx
->refs
;
286 x4
->params
.i_width
= avctx
->width
;
287 x4
->params
.i_height
= avctx
->height
;
288 x4
->params
.vui
.i_sar_width
= avctx
->sample_aspect_ratio
.num
;
289 x4
->params
.vui
.i_sar_height
= avctx
->sample_aspect_ratio
.den
;
290 /* This is only used for counting the fps */
291 x4
->params
.i_fps_num
= avctx
->time_base
.den
;
292 x4
->params
.i_fps_den
= avctx
->time_base
.num
;
293 x4
->params
.analyse
.inter
= XAVS_ANALYSE_I8x8
|XAVS_ANALYSE_PSUB16x16
| XAVS_ANALYSE_BSUB16x16
;
295 switch (avctx
->me_method
) {
297 x4
->params
.analyse
.i_me_method
= XAVS_ME_DIA
;
300 x4
->params
.analyse
.i_me_method
= XAVS_ME_HEX
;
303 x4
->params
.analyse
.i_me_method
= XAVS_ME_UMH
;
306 x4
->params
.analyse
.i_me_method
= XAVS_ME_ESA
;
309 x4
->params
.analyse
.i_me_method
= XAVS_ME_TESA
;
312 x4
->params
.analyse
.i_me_method
= XAVS_ME_HEX
;
315 x4
->params
.analyse
.i_me_range
= avctx
->me_range
;
316 x4
->params
.analyse
.i_subpel_refine
= avctx
->me_subpel_quality
;
318 x4
->params
.analyse
.b_chroma_me
= avctx
->me_cmp
& FF_CMP_CHROMA
;
319 /* AVS P2 only enables 8x8 transform */
320 x4
->params
.analyse
.b_transform_8x8
= 1; //avctx->flags2 & CODEC_FLAG2_8X8DCT;
322 x4
->params
.analyse
.i_trellis
= avctx
->trellis
;
323 x4
->params
.analyse
.i_noise_reduction
= avctx
->noise_reduction
;
325 if (avctx
->level
> 0)
326 x4
->params
.i_level_idc
= avctx
->level
;
328 x4
->params
.rc
.f_rate_tolerance
=
329 (float)avctx
->bit_rate_tolerance
/avctx
->bit_rate
;
331 if ((avctx
->rc_buffer_size
) &&
332 (avctx
->rc_initial_buffer_occupancy
<= avctx
->rc_buffer_size
)) {
333 x4
->params
.rc
.f_vbv_buffer_init
=
334 (float)avctx
->rc_initial_buffer_occupancy
/ avctx
->rc_buffer_size
;
336 x4
->params
.rc
.f_vbv_buffer_init
= 0.9;
338 /* TAG:do we have MB tree RC method */
339 /* what is the RC method we are now using? Default NO */
340 x4
->params
.rc
.f_ip_factor
= 1 / fabs(avctx
->i_quant_factor
);
341 x4
->params
.rc
.f_pb_factor
= avctx
->b_quant_factor
;
342 x4
->params
.analyse
.i_chroma_qp_offset
= avctx
->chromaoffset
;
344 x4
->params
.analyse
.b_psnr
= avctx
->flags
& CODEC_FLAG_PSNR
;
345 x4
->params
.i_log_level
= XAVS_LOG_DEBUG
;
346 x4
->params
.i_threads
= avctx
->thread_count
;
347 x4
->params
.b_interlaced
= avctx
->flags
& CODEC_FLAG_INTERLACED_DCT
;
349 if (avctx
->flags
& CODEC_FLAG_GLOBAL_HEADER
)
350 x4
->params
.b_repeat_headers
= 0;
352 x4
->enc
= xavs_encoder_open(&x4
->params
);
356 if (!(x4
->pts_buffer
= av_mallocz_array((avctx
->max_b_frames
+1), sizeof(*x4
->pts_buffer
))))
357 return AVERROR(ENOMEM
);
359 avctx
->coded_frame
= av_frame_alloc();
360 if (!avctx
->coded_frame
)
361 return AVERROR(ENOMEM
);
363 /* TAG: Do we have GLOBAL HEADER in AVS */
364 /* We Have PPS and SPS in AVS */
365 if (avctx
->flags
& CODEC_FLAG_GLOBAL_HEADER
) {
367 int nnal
, s
, i
, size
;
370 s
= xavs_encoder_headers(x4
->enc
, &nal
, &nnal
);
372 avctx
->extradata
= p
= av_malloc(s
);
373 for (i
= 0; i
< nnal
; i
++) {
374 /* Don't put the SEI in extradata. */
375 if (nal
[i
].i_type
== NAL_SEI
) {
376 x4
->sei
= av_malloc( 5 + nal
[i
].i_payload
* 4 / 3 );
377 if (xavs_nal_encode(x4
->sei
, &x4
->sei_size
, 1, nal
+ i
) < 0)
382 size
= xavs_nal_encode(p
, &s
, 1, nal
+ i
);
387 avctx
->extradata_size
= p
- avctx
->extradata
;
392 #define OFFSET(x) offsetof(XavsContext, x)
393 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
394 static const AVOption options
[] = {
395 { "crf", "Select the quality for constant quality mode", OFFSET(crf
), AV_OPT_TYPE_FLOAT
, {.dbl
= -1 }, -1, FLT_MAX
, VE
},
396 { "qp", "Constant quantization parameter rate control method",OFFSET(cqp
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, INT_MAX
, VE
},
397 { "b-bias", "Influences how often B-frames are used", OFFSET(b_bias
), AV_OPT_TYPE_INT
, {.i64
= INT_MIN
}, INT_MIN
, INT_MAX
, VE
},
398 { "cplxblur", "Reduce fluctuations in QP (before curve compression)", OFFSET(cplxblur
), AV_OPT_TYPE_FLOAT
, {.dbl
= -1 }, -1, FLT_MAX
, VE
},
399 { "direct-pred", "Direct MV prediction mode", OFFSET(direct_pred
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, INT_MAX
, VE
, "direct-pred" },
400 { "none", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_NONE
}, 0, 0, VE
, "direct-pred" },
401 { "spatial", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_SPATIAL
}, 0, 0, VE
, "direct-pred" },
402 { "temporal", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_TEMPORAL
}, 0, 0, VE
, "direct-pred" },
403 { "auto", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_AUTO
}, 0, 0, VE
, "direct-pred" },
404 { "aud", "Use access unit delimiters.", OFFSET(aud
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, 1, VE
},
405 { "mbtree", "Use macroblock tree ratecontrol.", OFFSET(mbtree
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, 1, VE
},
406 { "mixed-refs", "One reference per partition, as opposed to one reference per macroblock", OFFSET(mixed_refs
), AV_OPT_TYPE_INT
, {.i64
= -1}, -1, 1, VE
},
407 { "fast-pskip", NULL
, OFFSET(fast_pskip
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, 1, VE
},
411 static const AVClass xavs_class
= {
412 .class_name
= "libxavs",
413 .item_name
= av_default_item_name
,
415 .version
= LIBAVUTIL_VERSION_INT
,
418 static const AVCodecDefault xavs_defaults
[] = {
423 AVCodec ff_libxavs_encoder
= {
425 .long_name
= NULL_IF_CONFIG_SMALL("libxavs Chinese AVS (Audio Video Standard)"),
426 .type
= AVMEDIA_TYPE_VIDEO
,
427 .id
= AV_CODEC_ID_CAVS
,
428 .priv_data_size
= sizeof(XavsContext
),
430 .encode2
= XAVS_frame
,
432 .capabilities
= CODEC_CAP_DELAY
| CODEC_CAP_AUTO_THREADS
,
433 .pix_fmts
= (const enum AVPixelFormat
[]) { AV_PIX_FMT_YUV420P
, AV_PIX_FMT_NONE
},
434 .priv_class
= &xavs_class
,
435 .defaults
= xavs_defaults
,