2 * AVS encoding using the xavs library
3 * Copyright (C) 2010 Amanda, Y.N. Wu <amanda11192003@gmail.com>
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; 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
{
61 int scenechange_threshold
;
68 static void XAVS_log(void *p
, int level
, const char *fmt
, va_list args
)
70 static const int level_map
[] = {
71 [XAVS_LOG_ERROR
] = AV_LOG_ERROR
,
72 [XAVS_LOG_WARNING
] = AV_LOG_WARNING
,
73 [XAVS_LOG_INFO
] = AV_LOG_INFO
,
74 [XAVS_LOG_DEBUG
] = AV_LOG_DEBUG
77 if (level
< 0 || level
> XAVS_LOG_DEBUG
)
80 av_vlog(p
, level_map
[level
], fmt
, args
);
83 static int encode_nals(AVCodecContext
*ctx
, AVPacket
*pkt
,
84 xavs_nal_t
*nals
, int nnal
)
86 XavsContext
*x4
= ctx
->priv_data
;
88 int i
, s
, ret
, size
= x4
->sei_size
+ AV_INPUT_BUFFER_MIN_SIZE
;
93 for (i
= 0; i
< nnal
; i
++)
94 size
+= nals
[i
].i_payload
;
96 if ((ret
= ff_alloc_packet(pkt
, size
)) < 0) {
97 av_log(ctx
, AV_LOG_ERROR
, "Error getting output packet of size %d.\n", size
);
102 /* Write the SEI as part of the first frame. */
103 if (x4
->sei_size
> 0 && nnal
> 0) {
104 memcpy(p
, x4
->sei
, x4
->sei_size
);
109 for (i
= 0; i
< nnal
; i
++) {
110 s
= xavs_nal_encode(p
, &size
, 1, nals
+ i
);
115 pkt
->size
= p
- pkt
->data
;
120 static int XAVS_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
121 const AVFrame
*frame
, int *got_packet
)
123 XavsContext
*x4
= avctx
->priv_data
;
126 xavs_picture_t pic_out
;
129 x4
->pic
.img
.i_csp
= XAVS_CSP_I420
;
130 x4
->pic
.img
.i_plane
= 3;
133 for (i
= 0; i
< 3; i
++) {
134 x4
->pic
.img
.plane
[i
] = frame
->data
[i
];
135 x4
->pic
.img
.i_stride
[i
] = frame
->linesize
[i
];
138 x4
->pic
.i_pts
= frame
->pts
;
139 x4
->pic
.i_type
= XAVS_TYPE_AUTO
;
140 x4
->pts_buffer
[avctx
->frame_number
% (avctx
->max_b_frames
+1)] = frame
->pts
;
143 if (xavs_encoder_encode(x4
->enc
, &nal
, &nnal
,
144 frame
? &x4
->pic
: NULL
, &pic_out
) < 0)
147 ret
= encode_nals(avctx
, pkt
, nal
, nnal
);
153 if (!frame
&& !(x4
->end_of_stream
)) {
154 if ((ret
= ff_alloc_packet(pkt
, 4)) < 0)
161 pkt
->dts
= 2*x4
->pts_buffer
[(x4
->out_frame_count
-1)%(avctx
->max_b_frames
+1)] -
162 x4
->pts_buffer
[(x4
->out_frame_count
-2)%(avctx
->max_b_frames
+1)];
163 x4
->end_of_stream
= END_OF_STREAM
;
169 #if FF_API_CODED_FRAME
170 FF_DISABLE_DEPRECATION_WARNINGS
171 avctx
->coded_frame
->pts
= pic_out
.i_pts
;
172 FF_ENABLE_DEPRECATION_WARNINGS
174 pkt
->pts
= pic_out
.i_pts
;
175 if (avctx
->has_b_frames
) {
176 if (!x4
->out_frame_count
)
177 pkt
->dts
= pkt
->pts
- (x4
->pts_buffer
[1] - x4
->pts_buffer
[0]);
179 pkt
->dts
= x4
->pts_buffer
[(x4
->out_frame_count
-1)%(avctx
->max_b_frames
+1)];
183 #if FF_API_CODED_FRAME
184 FF_DISABLE_DEPRECATION_WARNINGS
185 switch (pic_out
.i_type
) {
188 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_I
;
191 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_P
;
195 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_B
;
198 FF_ENABLE_DEPRECATION_WARNINGS
201 /* There is no IDR frame in AVS JiZhun */
202 /* Sequence header is used as a flag */
203 if (pic_out
.i_type
== XAVS_TYPE_I
) {
204 #if FF_API_CODED_FRAME
205 FF_DISABLE_DEPRECATION_WARNINGS
206 avctx
->coded_frame
->key_frame
= 1;
207 FF_ENABLE_DEPRECATION_WARNINGS
209 pkt
->flags
|= AV_PKT_FLAG_KEY
;
212 #if FF_API_CODED_FRAME
213 FF_DISABLE_DEPRECATION_WARNINGS
214 avctx
->coded_frame
->quality
= (pic_out
.i_qpplus1
- 1) * FF_QP2LAMBDA
;
215 FF_ENABLE_DEPRECATION_WARNINGS
218 sd
= av_packet_new_side_data(pkt
, AV_PKT_DATA_QUALITY_FACTOR
, sizeof(int));
220 return AVERROR(ENOMEM
);
221 *(int *)sd
= (pic_out
.i_qpplus1
- 1) * FF_QP2LAMBDA
;
223 x4
->out_frame_count
++;
228 static av_cold
int XAVS_close(AVCodecContext
*avctx
)
230 XavsContext
*x4
= avctx
->priv_data
;
232 av_freep(&avctx
->extradata
);
234 av_freep(&x4
->pts_buffer
);
237 xavs_encoder_close(x4
->enc
);
242 static av_cold
int XAVS_init(AVCodecContext
*avctx
)
244 XavsContext
*x4
= avctx
->priv_data
;
247 xavs_param_default(&x4
->params
);
249 x4
->params
.pf_log
= XAVS_log
;
250 x4
->params
.p_log_private
= avctx
;
251 x4
->params
.i_keyint_max
= avctx
->gop_size
;
252 if (avctx
->bit_rate
) {
253 x4
->params
.rc
.i_bitrate
= avctx
->bit_rate
/ 1000;
254 x4
->params
.rc
.i_rc_method
= XAVS_RC_ABR
;
256 x4
->params
.rc
.i_vbv_buffer_size
= avctx
->rc_buffer_size
/ 1000;
257 x4
->params
.rc
.i_vbv_max_bitrate
= avctx
->rc_max_rate
/ 1000;
258 x4
->params
.rc
.b_stat_write
= avctx
->flags
& AV_CODEC_FLAG_PASS1
;
259 if (avctx
->flags
& AV_CODEC_FLAG_PASS2
) {
260 x4
->params
.rc
.b_stat_read
= 1;
263 x4
->params
.rc
.i_rc_method
= XAVS_RC_CRF
;
264 x4
->params
.rc
.f_rf_constant
= x4
->crf
;
265 } else if (x4
->cqp
>= 0) {
266 x4
->params
.rc
.i_rc_method
= XAVS_RC_CQP
;
267 x4
->params
.rc
.i_qp_constant
= x4
->cqp
;
272 x4
->params
.b_aud
= x4
->aud
;
274 x4
->params
.rc
.b_mb_tree
= x4
->mbtree
;
275 if (x4
->direct_pred
>= 0)
276 x4
->params
.analyse
.i_direct_mv_pred
= x4
->direct_pred
;
277 if (x4
->fast_pskip
>= 0)
278 x4
->params
.analyse
.b_fast_pskip
= x4
->fast_pskip
;
279 if (x4
->motion_est
>= 0)
280 x4
->params
.analyse
.i_me_method
= x4
->motion_est
;
281 if (x4
->mixed_refs
>= 0)
282 x4
->params
.analyse
.b_mixed_references
= x4
->mixed_refs
;
283 if (x4
->b_bias
!= INT_MIN
)
284 x4
->params
.i_bframe_bias
= x4
->b_bias
;
285 if (x4
->cplxblur
>= 0)
286 x4
->params
.rc
.f_complexity_blur
= x4
->cplxblur
;
288 x4
->params
.i_bframe
= avctx
->max_b_frames
;
289 /* cabac is not included in AVS JiZhun Profile */
290 x4
->params
.b_cabac
= 0;
292 #if FF_API_PRIVATE_OPT
293 FF_DISABLE_DEPRECATION_WARNINGS
294 if (avctx
->b_frame_strategy
)
295 x4
->b_frame_strategy
= avctx
->b_frame_strategy
;
296 FF_ENABLE_DEPRECATION_WARNINGS
299 x4
->params
.i_bframe_adaptive
= x4
->b_frame_strategy
;
301 avctx
->has_b_frames
= !!avctx
->max_b_frames
;
303 /* AVS doesn't allow B picture as reference */
304 /* The max allowed reference frame number of B is 2 */
305 x4
->params
.i_keyint_min
= avctx
->keyint_min
;
306 if (x4
->params
.i_keyint_min
> x4
->params
.i_keyint_max
)
307 x4
->params
.i_keyint_min
= x4
->params
.i_keyint_max
;
309 #if FF_API_PRIVATE_OPT
310 FF_DISABLE_DEPRECATION_WARNINGS
311 if (avctx
->scenechange_threshold
)
312 x4
->scenechange_threshold
= avctx
->scenechange_threshold
;
313 FF_ENABLE_DEPRECATION_WARNINGS
316 x4
->params
.i_scenecut_threshold
= x4
->scenechange_threshold
;
318 // x4->params.b_deblocking_filter = avctx->flags & AV_CODEC_FLAG_LOOP_FILTER;
320 x4
->params
.rc
.i_qp_min
= avctx
->qmin
;
321 x4
->params
.rc
.i_qp_max
= avctx
->qmax
;
322 x4
->params
.rc
.i_qp_step
= avctx
->max_qdiff
;
324 x4
->params
.rc
.f_qcompress
= avctx
->qcompress
; /* 0.0 => cbr, 1.0 => constant qp */
325 x4
->params
.rc
.f_qblur
= avctx
->qblur
; /* temporally blur quants */
327 x4
->params
.i_frame_reference
= avctx
->refs
;
329 x4
->params
.i_width
= avctx
->width
;
330 x4
->params
.i_height
= avctx
->height
;
331 x4
->params
.vui
.i_sar_width
= avctx
->sample_aspect_ratio
.num
;
332 x4
->params
.vui
.i_sar_height
= avctx
->sample_aspect_ratio
.den
;
333 /* This is only used for counting the fps */
334 x4
->params
.i_fps_num
= avctx
->time_base
.den
;
335 x4
->params
.i_fps_den
= avctx
->time_base
.num
;
336 x4
->params
.analyse
.inter
= XAVS_ANALYSE_I8x8
|XAVS_ANALYSE_PSUB16x16
| XAVS_ANALYSE_BSUB16x16
;
338 x4
->params
.analyse
.i_me_range
= avctx
->me_range
;
339 x4
->params
.analyse
.i_subpel_refine
= avctx
->me_subpel_quality
;
341 x4
->params
.analyse
.b_chroma_me
= avctx
->me_cmp
& FF_CMP_CHROMA
;
342 /* AVS P2 only enables 8x8 transform */
343 x4
->params
.analyse
.b_transform_8x8
= 1; //avctx->flags2 & AV_CODEC_FLAG2_8X8DCT;
345 x4
->params
.analyse
.i_trellis
= avctx
->trellis
;
347 #if FF_API_PRIVATE_OPT
348 FF_DISABLE_DEPRECATION_WARNINGS
349 if (avctx
->noise_reduction
>= 0)
350 x4
->noise_reduction
= avctx
->noise_reduction
;
351 FF_ENABLE_DEPRECATION_WARNINGS
354 x4
->params
.analyse
.i_noise_reduction
= x4
->noise_reduction
;
356 if (avctx
->level
> 0)
357 x4
->params
.i_level_idc
= avctx
->level
;
359 if (avctx
->bit_rate
> 0)
360 x4
->params
.rc
.f_rate_tolerance
=
361 (float)avctx
->bit_rate_tolerance
/ avctx
->bit_rate
;
363 if ((avctx
->rc_buffer_size
) &&
364 (avctx
->rc_initial_buffer_occupancy
<= avctx
->rc_buffer_size
)) {
365 x4
->params
.rc
.f_vbv_buffer_init
=
366 (float)avctx
->rc_initial_buffer_occupancy
/ avctx
->rc_buffer_size
;
368 x4
->params
.rc
.f_vbv_buffer_init
= 0.9;
370 /* TAG:do we have MB tree RC method */
371 /* what is the RC method we are now using? Default NO */
372 x4
->params
.rc
.f_ip_factor
= 1 / fabs(avctx
->i_quant_factor
);
373 x4
->params
.rc
.f_pb_factor
= avctx
->b_quant_factor
;
375 #if FF_API_PRIVATE_OPT
376 FF_DISABLE_DEPRECATION_WARNINGS
377 if (avctx
->chromaoffset
)
378 x4
->chroma_offset
= avctx
->chromaoffset
;
379 FF_ENABLE_DEPRECATION_WARNINGS
382 x4
->params
.analyse
.i_chroma_qp_offset
= x4
->chroma_offset
;
384 x4
->params
.analyse
.b_psnr
= avctx
->flags
& AV_CODEC_FLAG_PSNR
;
385 x4
->params
.i_log_level
= XAVS_LOG_DEBUG
;
386 x4
->params
.i_threads
= avctx
->thread_count
;
387 x4
->params
.b_interlaced
= avctx
->flags
& AV_CODEC_FLAG_INTERLACED_DCT
;
389 if (avctx
->flags
& AV_CODEC_FLAG_GLOBAL_HEADER
)
390 x4
->params
.b_repeat_headers
= 0;
392 x4
->enc
= xavs_encoder_open(&x4
->params
);
396 if (!(x4
->pts_buffer
= av_mallocz((avctx
->max_b_frames
+1) * sizeof(*x4
->pts_buffer
))))
397 return AVERROR(ENOMEM
);
399 /* TAG: Do we have GLOBAL HEADER in AVS */
400 /* We Have PPS and SPS in AVS */
401 if (avctx
->flags
& AV_CODEC_FLAG_GLOBAL_HEADER
) {
403 int nnal
, s
, i
, size
;
406 s
= xavs_encoder_headers(x4
->enc
, &nal
, &nnal
);
408 avctx
->extradata
= p
= av_malloc(s
);
409 for (i
= 0; i
< nnal
; i
++) {
410 /* Don't put the SEI in extradata. */
411 if (nal
[i
].i_type
== NAL_SEI
) {
412 x4
->sei
= av_malloc( 5 + nal
[i
].i_payload
* 4 / 3 );
413 if (xavs_nal_encode(x4
->sei
, &x4
->sei_size
, 1, nal
+ i
) < 0)
418 size
= xavs_nal_encode(p
, &s
, 1, nal
+ i
);
423 avctx
->extradata_size
= p
- avctx
->extradata
;
428 #define OFFSET(x) offsetof(XavsContext, x)
429 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
430 static const AVOption options
[] = {
431 { "crf", "Select the quality for constant quality mode", OFFSET(crf
), AV_OPT_TYPE_FLOAT
, {-1 }, -1, FLT_MAX
, VE
},
432 { "qp", "Constant quantization parameter rate control method",OFFSET(cqp
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, INT_MAX
, VE
},
433 { "b-bias", "Influences how often B-frames are used", OFFSET(b_bias
), AV_OPT_TYPE_INT
, {.i64
= INT_MIN
}, INT_MIN
, INT_MAX
, VE
},
434 { "cplxblur", "Reduce fluctuations in QP (before curve compression)", OFFSET(cplxblur
), AV_OPT_TYPE_FLOAT
, {-1 }, -1, FLT_MAX
, VE
},
435 { "direct-pred", "Direct MV prediction mode", OFFSET(direct_pred
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, INT_MAX
, VE
, "direct-pred" },
436 { "none", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_NONE
}, 0, 0, VE
, "direct-pred" },
437 { "spatial", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_SPATIAL
}, 0, 0, VE
, "direct-pred" },
438 { "temporal", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_TEMPORAL
}, 0, 0, VE
, "direct-pred" },
439 { "auto", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_DIRECT_PRED_AUTO
}, 0, 0, VE
, "direct-pred" },
440 { "aud", "Use access unit delimiters.", OFFSET(aud
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, 1, VE
},
441 { "mbtree", "Use macroblock tree ratecontrol.", OFFSET(mbtree
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, 1, VE
},
442 { "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
},
443 { "fast-pskip", NULL
, OFFSET(fast_pskip
), AV_OPT_TYPE_INT
, {.i64
= -1 }, -1, 1, VE
},
444 { "motion-est", "Set motion estimation method", OFFSET(motion_est
), AV_OPT_TYPE_INT
, { .i64
= -1 }, -1, XAVS_ME_TESA
, VE
, "motion-est"},
445 { "dia", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_ME_DIA
}, INT_MIN
, INT_MAX
, VE
, "motion-est" },
446 { "hex", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_ME_HEX
}, INT_MIN
, INT_MAX
, VE
, "motion-est" },
447 { "umh", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_ME_UMH
}, INT_MIN
, INT_MAX
, VE
, "motion-est" },
448 { "esa", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_ME_ESA
}, INT_MIN
, INT_MAX
, VE
, "motion-est" },
449 { "tesa", NULL
, 0, AV_OPT_TYPE_CONST
, { .i64
= XAVS_ME_TESA
}, INT_MIN
, INT_MAX
, VE
, "motion-est" },
450 { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy
), AV_OPT_TYPE_INT
, {.i64
= 0 }, 0, 2, VE
},
451 { "chromaoffset", "QP difference between chroma and luma", OFFSET(chroma_offset
), AV_OPT_TYPE_INT
, {.i64
= 0 }, INT_MIN
, INT_MAX
, VE
},
452 { "sc_threshold", "Scene change threshold", OFFSET(scenechange_threshold
), AV_OPT_TYPE_INT
, {.i64
= 0 }, 0, INT_MAX
, VE
},
453 { "noise_reduction", "Noise reduction", OFFSET(noise_reduction
), AV_OPT_TYPE_INT
, {.i64
= 0 }, 0, INT_MAX
, VE
},
458 static const AVClass
class = {
459 .class_name
= "libxavs",
460 .item_name
= av_default_item_name
,
462 .version
= LIBAVUTIL_VERSION_INT
,
465 static const AVCodecDefault xavs_defaults
[] = {
470 AVCodec ff_libxavs_encoder
= {
472 .long_name
= NULL_IF_CONFIG_SMALL("libxavs Chinese AVS (Audio Video Standard)"),
473 .type
= AVMEDIA_TYPE_VIDEO
,
474 .id
= AV_CODEC_ID_CAVS
,
475 .priv_data_size
= sizeof(XavsContext
),
477 .encode2
= XAVS_frame
,
479 .capabilities
= AV_CODEC_CAP_DELAY
| AV_CODEC_CAP_AUTO_THREADS
,
480 .pix_fmts
= (const enum AVPixelFormat
[]) { AV_PIX_FMT_YUV420P
, AV_PIX_FMT_NONE
},
481 .priv_class
= &class,
482 .defaults
= xavs_defaults
,
483 .wrapper_name
= "libxavs",