2005-03-09 05:04:56 +02:00
/*
* H .264 encoding using the x264 library
2007-07-05 23:08:51 +03:00
* Copyright ( C ) 2005 Mans Rullgard < mans @ mansr . com >
2005-03-09 05:04:56 +02:00
*
2011-03-18 19:35:10 +02:00
* This file is part of Libav .
2006-10-07 18:30:46 +03:00
*
2011-03-18 19:35:10 +02:00
* Libav is free software ; you can redistribute it and / or
2005-03-09 05:04:56 +02:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
2006-10-07 18:30:46 +03:00
* version 2.1 of the License , or ( at your option ) any later version .
2005-03-09 05:04:56 +02:00
*
2011-03-18 19:35:10 +02:00
* Libav is distributed in the hope that it will be useful ,
2005-03-09 05:04:56 +02:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2011-03-18 19:35:10 +02:00
* License along with Libav ; if not , write to the Free Software
2006-01-13 00:43:26 +02:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2005-03-09 05:04:56 +02:00
*/
2012-08-06 16:49:32 +03:00
# include "libavutil/internal.h"
2011-04-17 02:50:50 +03:00
# include "libavutil/opt.h"
2012-08-06 16:49:32 +03:00
# include "libavutil/mem.h"
2011-10-05 22:09:51 +03:00
# include "libavutil/pixdesc.h"
2005-03-09 05:04:56 +02:00
# include "avcodec.h"
2011-08-20 17:59:47 +03:00
# include "internal.h"
2005-03-09 05:04:56 +02:00
# include <x264.h>
2011-08-22 08:55:34 +03:00
# include <float.h>
2005-07-10 03:22:13 +03:00
# include <math.h>
2005-12-29 09:24:23 +02:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2005-03-09 05:04:56 +02:00
typedef struct X264Context {
2011-04-17 02:50:50 +03:00
AVClass * class ;
2009-09-29 21:03:30 +03:00
x264_param_t params ;
x264_t * enc ;
x264_picture_t pic ;
uint8_t * sei ;
int sei_size ;
AVFrame out_pic ;
2011-04-17 02:50:50 +03:00
char * preset ;
char * tune ;
char * profile ;
int fastfirstpass ;
2011-08-22 08:55:34 +03:00
float crf ;
2011-08-22 08:55:34 +03:00
float crf_max ;
2011-08-22 08:55:34 +03:00
int cqp ;
2011-08-22 08:55:34 +03:00
int aq_mode ;
2011-08-22 08:55:34 +03:00
float aq_strength ;
2011-08-27 08:52:03 +03:00
char * psy_rd ;
2011-08-27 11:16:14 +03:00
int psy ;
2011-08-22 08:55:34 +03:00
int rc_lookahead ;
2011-08-22 08:55:34 +03:00
int weightp ;
2011-08-22 08:55:34 +03:00
int weightb ;
2011-08-22 08:55:34 +03:00
int ssim ;
2011-08-22 08:55:34 +03:00
int intra_refresh ;
2011-09-01 14:15:09 +03:00
int b_bias ;
2011-08-22 08:55:34 +03:00
int b_pyramid ;
2011-08-22 08:55:34 +03:00
int mixed_refs ;
2011-08-22 08:55:34 +03:00
int dct8x8 ;
2011-08-22 08:55:34 +03:00
int fast_pskip ;
2011-08-22 08:55:34 +03:00
int aud ;
2011-08-27 11:16:14 +03:00
int mbtree ;
2011-09-01 14:15:09 +03:00
char * deblock ;
2011-09-01 14:15:09 +03:00
float cplxblur ;
2011-09-01 14:15:09 +03:00
char * partitions ;
2011-09-01 14:15:09 +03:00
int direct_pred ;
2011-09-16 05:30:10 +03:00
int slice_max_size ;
2012-03-12 19:20:20 +03:00
char * stats ;
2012-09-21 10:20:09 +03:00
int nal_hrd ;
2005-03-09 05:04:56 +02:00
} X264Context ;
2009-09-29 21:03:30 +03:00
static void X264_log ( void * p , int level , const char * fmt , va_list args )
2005-03-09 05:04:56 +02:00
{
static const int level_map [ ] = {
2005-12-22 03:10:11 +02:00
[ X264_LOG_ERROR ] = AV_LOG_ERROR ,
2007-07-12 11:22:28 +03:00
[ X264_LOG_WARNING ] = AV_LOG_WARNING ,
2005-12-22 03:10:11 +02:00
[ X264_LOG_INFO ] = AV_LOG_INFO ,
[ X264_LOG_DEBUG ] = AV_LOG_DEBUG
2005-03-09 05:04:56 +02:00
} ;
2009-09-29 21:03:30 +03:00
if ( level < 0 | | level > X264_LOG_DEBUG )
2005-12-22 03:10:11 +02:00
return ;
2005-03-09 05:04:56 +02:00
av_vlog ( p , level_map [ level ] , fmt , args ) ;
}
2012-02-06 09:39:23 +03:00
static int encode_nals ( AVCodecContext * ctx , AVPacket * pkt ,
x264_nal_t * nals , int nnal )
2005-03-09 05:04:56 +02:00
{
2009-07-01 02:45:01 +03:00
X264Context * x4 = ctx - > priv_data ;
2012-02-06 09:39:23 +03:00
uint8_t * p ;
int i , size = x4 - > sei_size , ret ;
if ( ! nnal )
return 0 ;
for ( i = 0 ; i < nnal ; i + + )
size + = nals [ i ] . i_payload ;
if ( ( ret = ff_alloc_packet ( pkt , size ) ) < 0 )
return ret ;
p = pkt - > data ;
2009-07-01 02:45:01 +03:00
/* Write the SEI as part of the first frame. */
2009-09-29 21:03:30 +03:00
if ( x4 - > sei_size > 0 & & nnal > 0 ) {
2009-07-01 02:45:01 +03:00
memcpy ( p , x4 - > sei , x4 - > sei_size ) ;
p + = x4 - > sei_size ;
x4 - > sei_size = 0 ;
}
2005-03-09 05:04:56 +02:00
2009-09-29 21:03:30 +03:00
for ( i = 0 ; i < nnal ; i + + ) {
2009-09-23 12:03:26 +03:00
memcpy ( p , nals [ i ] . p_payload , nals [ i ] . i_payload ) ;
p + = nals [ i ] . i_payload ;
2005-03-09 05:04:56 +02:00
}
2012-02-06 09:39:23 +03:00
return 1 ;
2005-03-09 05:04:56 +02:00
}
2012-02-06 09:39:23 +03:00
static int X264_frame ( AVCodecContext * ctx , AVPacket * pkt , const AVFrame * frame ,
int * got_packet )
2005-03-09 05:04:56 +02:00
{
X264Context * x4 = ctx - > priv_data ;
x264_nal_t * nal ;
2012-02-06 09:39:23 +03:00
int nnal , i , ret ;
2005-03-09 05:04:56 +02:00
x264_picture_t pic_out ;
2010-06-02 23:05:27 +03:00
x264_picture_init ( & x4 - > pic ) ;
2011-10-09 20:34:20 +03:00
x4 - > pic . img . i_csp = x4 - > params . i_csp ;
2011-10-05 22:09:51 +03:00
if ( x264_bit_depth > 8 )
x4 - > pic . img . i_csp | = X264_CSP_HIGH_DEPTH ;
2005-03-09 05:04:56 +02:00
x4 - > pic . img . i_plane = 3 ;
2009-09-29 21:03:30 +03:00
if ( frame ) {
for ( i = 0 ; i < 3 ; i + + ) {
x4 - > pic . img . plane [ i ] = frame - > data [ i ] ;
2006-11-01 20:19:20 +02:00
x4 - > pic . img . i_stride [ i ] = frame - > linesize [ i ] ;
}
2005-03-09 05:04:56 +02:00
2009-09-29 21:03:30 +03:00
x4 - > pic . i_pts = frame - > pts ;
2010-10-25 17:40:00 +03:00
x4 - > pic . i_type =
2011-04-29 19:53:57 +03:00
frame - > pict_type = = AV_PICTURE_TYPE_I ? X264_TYPE_KEYFRAME :
frame - > pict_type = = AV_PICTURE_TYPE_P ? X264_TYPE_P :
frame - > pict_type = = AV_PICTURE_TYPE_B ? X264_TYPE_B :
2010-10-25 17:40:00 +03:00
X264_TYPE_AUTO ;
2011-01-26 04:07:34 +02:00
if ( x4 - > params . b_tff ! = frame - > top_field_first ) {
x4 - > params . b_tff = frame - > top_field_first ;
x264_encoder_reconfig ( x4 - > enc , & x4 - > params ) ;
}
2012-07-08 17:33:47 +03:00
if ( x4 - > params . vui . i_sar_height ! = ctx - > sample_aspect_ratio . den | |
x4 - > params . vui . i_sar_width ! = ctx - > sample_aspect_ratio . num ) {
x4 - > params . vui . i_sar_height = ctx - > sample_aspect_ratio . den ;
x4 - > params . vui . i_sar_width = ctx - > sample_aspect_ratio . num ;
x264_encoder_reconfig ( x4 - > enc , & x4 - > params ) ;
}
2006-11-01 20:18:48 +02:00
}
2005-03-09 05:04:56 +02:00
2010-05-19 23:48:29 +03:00
do {
2012-02-01 12:56:14 +03:00
if ( x264_encoder_encode ( x4 - > enc , & nal , & nnal , frame ? & x4 - > pic : NULL , & pic_out ) < 0 )
return - 1 ;
2005-03-09 05:04:56 +02:00
2012-02-06 09:39:23 +03:00
ret = encode_nals ( ctx , pkt , nal , nnal ) ;
if ( ret < 0 )
2012-02-01 12:56:14 +03:00
return - 1 ;
2012-02-06 09:39:23 +03:00
} while ( ! ret & & ! frame & & x264_encoder_delayed_frames ( x4 - > enc ) ) ;
2005-03-09 05:04:56 +02:00
2012-02-06 09:39:23 +03:00
pkt - > pts = pic_out . i_pts ;
pkt - > dts = pic_out . i_dts ;
2005-03-09 05:04:56 +02:00
2009-09-29 21:03:30 +03:00
switch ( pic_out . i_type ) {
2005-03-09 05:04:56 +02:00
case X264_TYPE_IDR :
case X264_TYPE_I :
2011-04-29 19:53:57 +03:00
x4 - > out_pic . pict_type = AV_PICTURE_TYPE_I ;
2005-03-09 05:04:56 +02:00
break ;
case X264_TYPE_P :
2011-04-29 19:53:57 +03:00
x4 - > out_pic . pict_type = AV_PICTURE_TYPE_P ;
2005-03-09 05:04:56 +02:00
break ;
case X264_TYPE_B :
case X264_TYPE_BREF :
2011-04-29 19:53:57 +03:00
x4 - > out_pic . pict_type = AV_PICTURE_TYPE_B ;
2005-03-09 05:04:56 +02:00
break ;
}
2012-02-06 09:39:23 +03:00
pkt - > flags | = AV_PKT_FLAG_KEY * pic_out . b_keyframe ;
if ( ret )
2011-01-30 03:05:42 +02:00
x4 - > out_pic . quality = ( pic_out . i_qpplus1 - 1 ) * FF_QP2LAMBDA ;
2005-03-09 05:04:56 +02:00
2012-02-06 09:39:23 +03:00
* got_packet = ret ;
return 0 ;
2005-03-09 05:04:56 +02:00
}
2009-09-29 21:03:30 +03:00
static av_cold int X264_close ( AVCodecContext * avctx )
2005-03-09 05:04:56 +02:00
{
X264Context * x4 = avctx - > priv_data ;
2008-10-13 16:47:05 +03:00
av_freep ( & avctx - > extradata ) ;
2009-07-01 02:45:01 +03:00
av_free ( x4 - > sei ) ;
2008-10-13 16:47:05 +03:00
2009-09-29 21:03:30 +03:00
if ( x4 - > enc )
2005-12-22 03:10:11 +02:00
x264_encoder_close ( x4 - > enc ) ;
2005-03-09 05:04:56 +02:00
return 0 ;
}
2012-10-06 13:10:34 +03:00
static int convert_pix_fmt ( enum AVPixelFormat pix_fmt )
2011-10-09 20:34:20 +03:00
{
switch ( pix_fmt ) {
2012-10-06 13:10:34 +03:00
case AV_PIX_FMT_YUV420P :
case AV_PIX_FMT_YUVJ420P :
case AV_PIX_FMT_YUV420P9 :
case AV_PIX_FMT_YUV420P10 : return X264_CSP_I420 ;
case AV_PIX_FMT_YUV422P :
case AV_PIX_FMT_YUV422P10 : return X264_CSP_I422 ;
case AV_PIX_FMT_YUV444P :
case AV_PIX_FMT_YUV444P9 :
case AV_PIX_FMT_YUV444P10 : return X264_CSP_I444 ;
2011-10-09 20:34:20 +03:00
} ;
return 0 ;
}
2011-09-01 14:15:09 +03:00
# define PARSE_X264_OPT(name, var)\
if ( x4 - > var & & x264_param_parse ( & x4 - > params , name , x4 - > var ) < 0 ) { \
av_log ( avctx , AV_LOG_ERROR , " Error parsing option '%s' with value '%s'. \n " , name , x4 - > var ) ; \
return AVERROR ( EINVAL ) ; \
}
2009-09-29 21:03:30 +03:00
static av_cold int X264_init ( AVCodecContext * avctx )
2005-03-09 05:04:56 +02:00
{
X264Context * x4 = avctx - > priv_data ;
x264_param_default ( & x4 - > params ) ;
2009-12-09 02:38:22 +02:00
x4 - > params . b_deblocking_filter = avctx - > flags & CODEC_FLAG_LOOP_FILTER ;
2005-03-19 14:27:10 +02:00
2011-04-17 02:50:50 +03:00
if ( x4 - > preset | | x4 - > tune )
if ( x264_param_default_preset ( & x4 - > params , x4 - > preset , x4 - > tune ) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " Error setting preset/tune %s/%s. \n " , x4 - > preset , x4 - > tune ) ;
return AVERROR ( EINVAL ) ;
}
2011-09-07 09:27:28 +03:00
if ( avctx - > level > 0 )
x4 - > params . i_level_idc = avctx - > level ;
2011-04-17 02:50:50 +03:00
x4 - > params . pf_log = X264_log ;
x4 - > params . p_log_private = avctx ;
x4 - > params . i_log_level = X264_LOG_DEBUG ;
2011-10-09 20:34:20 +03:00
x4 - > params . i_csp = convert_pix_fmt ( avctx - > pix_fmt ) ;
2011-04-17 02:50:50 +03:00
2011-08-20 17:59:47 +03:00
if ( avctx - > bit_rate ) {
x4 - > params . rc . i_bitrate = avctx - > bit_rate / 1000 ;
x4 - > params . rc . i_rc_method = X264_RC_ABR ;
}
2011-04-17 02:50:50 +03:00
x4 - > params . rc . i_vbv_buffer_size = avctx - > rc_buffer_size / 1000 ;
x4 - > params . rc . i_vbv_max_bitrate = avctx - > rc_max_rate / 1000 ;
x4 - > params . rc . b_stat_write = avctx - > flags & CODEC_FLAG_PASS1 ;
if ( avctx - > flags & CODEC_FLAG_PASS2 ) {
x4 - > params . rc . b_stat_read = 1 ;
} else {
2011-08-22 08:55:34 +03:00
if ( x4 - > crf > = 0 ) {
x4 - > params . rc . i_rc_method = X264_RC_CRF ;
x4 - > params . rc . f_rf_constant = x4 - > crf ;
2011-08-22 08:55:34 +03:00
} else if ( x4 - > cqp > = 0 ) {
x4 - > params . rc . i_rc_method = X264_RC_CQP ;
x4 - > params . rc . i_qp_constant = x4 - > cqp ;
2011-08-22 08:55:34 +03:00
}
2011-08-22 08:55:34 +03:00
if ( x4 - > crf_max > = 0 )
x4 - > params . rc . f_rf_constant_max = x4 - > crf_max ;
2011-04-17 02:50:50 +03:00
}
2011-02-06 15:10:15 +02:00
if ( avctx - > rc_buffer_size & & avctx - > rc_initial_buffer_occupancy & &
2009-09-29 21:03:30 +03:00
( avctx - > rc_initial_buffer_occupancy < = avctx - > rc_buffer_size ) ) {
2005-12-29 09:24:23 +02:00
x4 - > params . rc . f_vbv_buffer_init =
2009-09-29 21:03:30 +03:00
( float ) avctx - > rc_initial_buffer_occupancy / avctx - > rc_buffer_size ;
2011-02-06 15:10:15 +02:00
}
2005-12-29 09:24:23 +02:00
2009-09-29 21:03:30 +03:00
x4 - > params . rc . f_ip_factor = 1 / fabs ( avctx - > i_quant_factor ) ;
x4 - > params . rc . f_pb_factor = avctx - > b_quant_factor ;
2005-12-29 09:24:23 +02:00
x4 - > params . analyse . i_chroma_qp_offset = avctx - > chromaoffset ;
2011-09-07 10:13:02 +03:00
if ( avctx - > me_method = = ME_EPZS )
x4 - > params . analyse . i_me_method = X264_ME_DIA ;
else if ( avctx - > me_method = = ME_HEX )
x4 - > params . analyse . i_me_method = X264_ME_HEX ;
else if ( avctx - > me_method = = ME_UMH )
x4 - > params . analyse . i_me_method = X264_ME_UMH ;
else if ( avctx - > me_method = = ME_FULL )
x4 - > params . analyse . i_me_method = X264_ME_ESA ;
else if ( avctx - > me_method = = ME_TESA )
x4 - > params . analyse . i_me_method = X264_ME_TESA ;
2011-09-01 13:59:29 +03:00
if ( avctx - > gop_size > = 0 )
x4 - > params . i_keyint_max = avctx - > gop_size ;
if ( avctx - > max_b_frames > = 0 )
x4 - > params . i_bframe = avctx - > max_b_frames ;
if ( avctx - > scenechange_threshold > = 0 )
x4 - > params . i_scenecut_threshold = avctx - > scenechange_threshold ;
if ( avctx - > qmin > = 0 )
x4 - > params . rc . i_qp_min = avctx - > qmin ;
if ( avctx - > qmax > = 0 )
x4 - > params . rc . i_qp_max = avctx - > qmax ;
if ( avctx - > max_qdiff > = 0 )
x4 - > params . rc . i_qp_step = avctx - > max_qdiff ;
if ( avctx - > qblur > = 0 )
x4 - > params . rc . f_qblur = avctx - > qblur ; /* temporally blur quants */
if ( avctx - > qcompress > = 0 )
x4 - > params . rc . f_qcompress = avctx - > qcompress ; /* 0.0 => cbr, 1.0 => constant qp */
if ( avctx - > refs > = 0 )
x4 - > params . i_frame_reference = avctx - > refs ;
2011-09-07 10:13:02 +03:00
if ( avctx - > trellis > = 0 )
x4 - > params . analyse . i_trellis = avctx - > trellis ;
if ( avctx - > me_range > = 0 )
x4 - > params . analyse . i_me_range = avctx - > me_range ;
if ( avctx - > noise_reduction > = 0 )
x4 - > params . analyse . i_noise_reduction = avctx - > noise_reduction ;
if ( avctx - > me_subpel_quality > = 0 )
x4 - > params . analyse . i_subpel_refine = avctx - > me_subpel_quality ;
if ( avctx - > b_frame_strategy > = 0 )
x4 - > params . i_bframe_adaptive = avctx - > b_frame_strategy ;
if ( avctx - > keyint_min > = 0 )
x4 - > params . i_keyint_min = avctx - > keyint_min ;
if ( avctx - > coder_type > = 0 )
x4 - > params . b_cabac = avctx - > coder_type = = FF_CODER_TYPE_AC ;
if ( avctx - > me_cmp > = 0 )
x4 - > params . analyse . b_chroma_me = avctx - > me_cmp & FF_CMP_CHROMA ;
2011-09-01 13:59:29 +03:00
2011-08-22 08:55:34 +03:00
if ( x4 - > aq_mode > = 0 )
x4 - > params . rc . i_aq_mode = x4 - > aq_mode ;
2011-08-22 08:55:34 +03:00
if ( x4 - > aq_strength > = 0 )
x4 - > params . rc . f_aq_strength = x4 - > aq_strength ;
2011-09-01 14:15:09 +03:00
PARSE_X264_OPT ( " psy-rd " , psy_rd ) ;
PARSE_X264_OPT ( " deblock " , deblock ) ;
2011-09-01 14:15:09 +03:00
PARSE_X264_OPT ( " partitions " , partitions ) ;
2012-03-12 19:20:20 +03:00
PARSE_X264_OPT ( " stats " , stats ) ;
2011-08-27 11:16:14 +03:00
if ( x4 - > psy > = 0 )
x4 - > params . analyse . b_psy = x4 - > psy ;
2011-08-22 08:55:34 +03:00
if ( x4 - > rc_lookahead > = 0 )
x4 - > params . rc . i_lookahead = x4 - > rc_lookahead ;
2011-08-22 08:55:34 +03:00
if ( x4 - > weightp > = 0 )
x4 - > params . analyse . i_weighted_pred = x4 - > weightp ;
2011-08-22 08:55:34 +03:00
if ( x4 - > weightb > = 0 )
x4 - > params . analyse . b_weighted_bipred = x4 - > weightb ;
2011-09-01 14:15:09 +03:00
if ( x4 - > cplxblur > = 0 )
x4 - > params . rc . f_complexity_blur = x4 - > cplxblur ;
2011-08-22 08:55:34 +03:00
2011-08-22 08:55:34 +03:00
if ( x4 - > ssim > = 0 )
x4 - > params . analyse . b_ssim = x4 - > ssim ;
2011-08-22 08:55:34 +03:00
if ( x4 - > intra_refresh > = 0 )
x4 - > params . b_intra_refresh = x4 - > intra_refresh ;
2011-09-01 14:15:09 +03:00
if ( x4 - > b_bias ! = INT_MIN )
x4 - > params . i_bframe_bias = x4 - > b_bias ;
2011-08-22 08:55:34 +03:00
if ( x4 - > b_pyramid > = 0 )
x4 - > params . i_bframe_pyramid = x4 - > b_pyramid ;
2011-08-22 08:55:34 +03:00
if ( x4 - > mixed_refs > = 0 )
x4 - > params . analyse . b_mixed_references = x4 - > mixed_refs ;
2011-08-22 08:55:34 +03:00
if ( x4 - > dct8x8 > = 0 )
x4 - > params . analyse . b_transform_8x8 = x4 - > dct8x8 ;
2011-08-22 08:55:34 +03:00
if ( x4 - > fast_pskip > = 0 )
x4 - > params . analyse . b_fast_pskip = x4 - > fast_pskip ;
2011-08-22 08:55:34 +03:00
if ( x4 - > aud > = 0 )
x4 - > params . b_aud = x4 - > aud ;
2011-08-27 11:16:14 +03:00
if ( x4 - > mbtree > = 0 )
x4 - > params . rc . b_mb_tree = x4 - > mbtree ;
2011-09-01 14:15:09 +03:00
if ( x4 - > direct_pred > = 0 )
x4 - > params . analyse . i_direct_mv_pred = x4 - > direct_pred ;
2011-08-22 08:55:34 +03:00
2011-09-16 05:30:10 +03:00
if ( x4 - > slice_max_size > = 0 )
x4 - > params . i_slice_max_size = x4 - > slice_max_size ;
2011-04-17 02:50:50 +03:00
if ( x4 - > fastfirstpass )
x264_param_apply_fastfirstpass ( & x4 - > params ) ;
2012-09-19 20:51:29 +03:00
if ( x4 - > nal_hrd > = 0 )
x4 - > params . i_nal_hrd = x4 - > nal_hrd ;
2011-04-17 02:50:50 +03:00
if ( x4 - > profile )
if ( x264_param_apply_profile ( & x4 - > params , x4 - > profile ) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " Error setting profile %s. \n " , x4 - > profile ) ;
return AVERROR ( EINVAL ) ;
}
x4 - > params . i_width = avctx - > width ;
x4 - > params . i_height = avctx - > height ;
x4 - > params . vui . i_sar_width = avctx - > sample_aspect_ratio . num ;
x4 - > params . vui . i_sar_height = avctx - > sample_aspect_ratio . den ;
x4 - > params . i_fps_num = x4 - > params . i_timebase_den = avctx - > time_base . den ;
x4 - > params . i_fps_den = x4 - > params . i_timebase_num = avctx - > time_base . num ;
2009-12-09 02:38:22 +02:00
x4 - > params . analyse . b_psnr = avctx - > flags & CODEC_FLAG_PSNR ;
2005-12-29 09:24:23 +02:00
2009-09-29 21:03:30 +03:00
x4 - > params . i_threads = avctx - > thread_count ;
2012-03-05 22:54:17 +03:00
if ( avctx - > thread_type )
x4 - > params . b_sliced_threads = avctx - > thread_type = = FF_THREAD_SLICE ;
2005-05-30 23:34:02 +03:00
2009-12-09 02:38:22 +02:00
x4 - > params . b_interlaced = avctx - > flags & CODEC_FLAG_INTERLACED_DCT ;
2008-06-04 03:56:36 +03:00
2011-05-10 16:11:45 +03:00
x4 - > params . b_open_gop = ! ( avctx - > flags & CODEC_FLAG_CLOSED_GOP ) ;
2010-10-22 21:09:14 +03:00
x4 - > params . i_slice_count = avctx - > slices ;
2012-10-06 13:10:34 +03:00
x4 - > params . vui . b_fullrange = avctx - > pix_fmt = = AV_PIX_FMT_YUVJ420P ;
2010-12-07 11:51:27 +02:00
2009-09-29 21:03:30 +03:00
if ( avctx - > flags & CODEC_FLAG_GLOBAL_HEADER )
2006-01-20 23:20:46 +02:00
x4 - > params . b_repeat_headers = 0 ;
2011-04-17 02:50:50 +03:00
// update AVCodecContext with x264 parameters
avctx - > has_b_frames = x4 - > params . i_bframe ?
x4 - > params . i_bframe_pyramid ? 2 : 1 : 0 ;
2012-01-14 00:41:16 +03:00
if ( avctx - > max_b_frames < 0 )
avctx - > max_b_frames = 0 ;
2011-04-17 02:50:50 +03:00
avctx - > bit_rate = x4 - > params . rc . i_bitrate * 1000 ;
2005-03-09 05:04:56 +02:00
x4 - > enc = x264_encoder_open ( & x4 - > params ) ;
2009-09-29 21:03:30 +03:00
if ( ! x4 - > enc )
2005-03-09 05:04:56 +02:00
return - 1 ;
avctx - > coded_frame = & x4 - > out_pic ;
2009-09-29 21:03:30 +03:00
if ( avctx - > flags & CODEC_FLAG_GLOBAL_HEADER ) {
2006-01-24 12:33:14 +02:00
x264_nal_t * nal ;
2012-02-06 09:34:57 +03:00
uint8_t * p ;
2010-03-25 21:25:21 +02:00
int nnal , s , i ;
2006-01-20 23:20:46 +02:00
2009-09-23 12:03:26 +03:00
s = x264_encoder_headers ( x4 - > enc , & nal , & nnal ) ;
2012-02-06 09:34:57 +03:00
avctx - > extradata = p = av_malloc ( s ) ;
2006-01-20 23:20:46 +02:00
2012-02-06 09:34:57 +03:00
for ( i = 0 ; i < nnal ; i + + ) {
/* Don't put the SEI in extradata. */
if ( nal [ i ] . i_type = = NAL_SEI ) {
2010-03-25 21:25:21 +02:00
av_log ( avctx , AV_LOG_INFO , " %s \n " , nal [ i ] . p_payload + 25 ) ;
2012-02-06 09:34:57 +03:00
x4 - > sei_size = nal [ i ] . i_payload ;
x4 - > sei = av_malloc ( x4 - > sei_size ) ;
memcpy ( x4 - > sei , nal [ i ] . p_payload , nal [ i ] . i_payload ) ;
continue ;
}
memcpy ( p , nal [ i ] . p_payload , nal [ i ] . i_payload ) ;
p + = nal [ i ] . i_payload ;
}
avctx - > extradata_size = p - avctx - > extradata ;
2006-01-20 23:20:46 +02:00
}
2005-03-09 05:04:56 +02:00
return 0 ;
}
2012-10-06 13:10:34 +03:00
static const enum AVPixelFormat pix_fmts_8bit [ ] = {
AV_PIX_FMT_YUV420P ,
AV_PIX_FMT_YUVJ420P ,
AV_PIX_FMT_YUV422P ,
AV_PIX_FMT_YUV444P ,
AV_PIX_FMT_NONE
2011-10-05 22:09:51 +03:00
} ;
2012-10-06 13:10:34 +03:00
static const enum AVPixelFormat pix_fmts_9bit [ ] = {
AV_PIX_FMT_YUV420P9 ,
AV_PIX_FMT_YUV444P9 ,
AV_PIX_FMT_NONE
2011-10-05 22:09:51 +03:00
} ;
2012-10-06 13:10:34 +03:00
static const enum AVPixelFormat pix_fmts_10bit [ ] = {
AV_PIX_FMT_YUV420P10 ,
AV_PIX_FMT_YUV422P10 ,
AV_PIX_FMT_YUV444P10 ,
AV_PIX_FMT_NONE
2011-10-05 22:09:51 +03:00
} ;
static av_cold void X264_init_static ( AVCodec * codec )
{
if ( x264_bit_depth = = 8 )
codec - > pix_fmts = pix_fmts_8bit ;
else if ( x264_bit_depth = = 9 )
codec - > pix_fmts = pix_fmts_9bit ;
else if ( x264_bit_depth = = 10 )
codec - > pix_fmts = pix_fmts_10bit ;
}
2011-04-17 02:50:50 +03:00
# define OFFSET(x) offsetof(X264Context, x)
# define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options [ ] = {
2011-10-04 08:38:01 +03:00
{ " preset " , " Set the encoding preset (cf. x264 --fullhelp) " , OFFSET ( preset ) , AV_OPT_TYPE_STRING , { . str = " medium " } , 0 , 0 , VE } ,
{ " tune " , " Tune the encoding params (cf. x264 --fullhelp) " , OFFSET ( tune ) , AV_OPT_TYPE_STRING , { 0 } , 0 , 0 , VE } ,
{ " profile " , " Set profile restrictions (cf. x264 --fullhelp) " , OFFSET ( profile ) , AV_OPT_TYPE_STRING , { 0 } , 0 , 0 , VE } ,
2012-08-31 13:22:31 +03:00
{ " fastfirstpass " , " Use fast settings when encoding first pass " , OFFSET ( fastfirstpass ) , AV_OPT_TYPE_INT , { . i64 = 1 } , 0 , 1 , VE } ,
2012-08-31 13:34:23 +03:00
{ " crf " , " Select the quality for constant quality mode " , OFFSET ( crf ) , AV_OPT_TYPE_FLOAT , { . dbl = - 1 } , - 1 , FLT_MAX , VE } ,
{ " crf_max " , " In CRF mode, prevents VBV from lowering quality beyond this point. " , OFFSET ( crf_max ) , AV_OPT_TYPE_FLOAT , { . dbl = - 1 } , - 1 , FLT_MAX , VE } ,
2012-08-31 13:22:31 +03:00
{ " qp " , " Constant quantization parameter rate control method " , OFFSET ( cqp ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE } ,
{ " aq-mode " , " AQ method " , OFFSET ( aq_mode ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE , " aq_mode " } ,
2012-08-31 12:45:52 +03:00
{ " none " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_AQ_NONE } , INT_MIN , INT_MAX , VE , " aq_mode " } ,
{ " variance " , " Variance AQ (complexity mask) " , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_AQ_VARIANCE } , INT_MIN , INT_MAX , VE , " aq_mode " } ,
{ " autovariance " , " Auto-variance AQ (experimental) " , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_AQ_AUTOVARIANCE } , INT_MIN , INT_MAX , VE , " aq_mode " } ,
2012-08-31 13:34:23 +03:00
{ " aq-strength " , " AQ strength. Reduces blocking and blurring in flat and textured areas. " , OFFSET ( aq_strength ) , AV_OPT_TYPE_FLOAT , { . dbl = - 1 } , - 1 , FLT_MAX , VE } ,
2012-08-31 13:22:31 +03:00
{ " psy " , " Use psychovisual optimizations. " , OFFSET ( psy ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
2011-10-04 08:38:01 +03:00
{ " psy-rd " , " Strength of psychovisual optimization, in <psy-rd>:<psy-trellis> format. " , OFFSET ( psy_rd ) , AV_OPT_TYPE_STRING , { 0 } , 0 , 0 , VE } ,
2012-08-31 13:22:31 +03:00
{ " rc-lookahead " , " Number of frames to look ahead for frametype and ratecontrol " , OFFSET ( rc_lookahead ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE } ,
{ " weightb " , " Weighted prediction for B-frames. " , OFFSET ( weightb ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " weightp " , " Weighted prediction analysis method. " , OFFSET ( weightp ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE , " weightp " } ,
2012-08-31 12:45:52 +03:00
{ " none " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_WEIGHTP_NONE } , INT_MIN , INT_MAX , VE , " weightp " } ,
{ " simple " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_WEIGHTP_SIMPLE } , INT_MIN , INT_MAX , VE , " weightp " } ,
{ " smart " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_WEIGHTP_SMART } , INT_MIN , INT_MAX , VE , " weightp " } ,
2012-08-31 13:22:31 +03:00
{ " ssim " , " Calculate and print SSIM stats. " , OFFSET ( ssim ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " intra-refresh " , " Use Periodic Intra Refresh instead of IDR frames. " , OFFSET ( intra_refresh ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " b-bias " , " Influences how often B-frames are used " , OFFSET ( b_bias ) , AV_OPT_TYPE_INT , { . i64 = INT_MIN } , INT_MIN , INT_MAX , VE } ,
{ " b-pyramid " , " Keep some B-frames as references. " , OFFSET ( b_pyramid ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE , " b_pyramid " } ,
2012-08-31 12:45:52 +03:00
{ " none " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_B_PYRAMID_NONE } , INT_MIN , INT_MAX , VE , " b_pyramid " } ,
{ " strict " , " Strictly hierarchical pyramid " , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_B_PYRAMID_STRICT } , INT_MIN , INT_MAX , VE , " b_pyramid " } ,
{ " normal " , " Non-strict (not Blu-ray compatible) " , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_B_PYRAMID_NORMAL } , INT_MIN , INT_MAX , VE , " b_pyramid " } ,
2012-08-31 13:22:31 +03:00
{ " 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 } ,
{ " 8x8dct " , " High profile 8x8 transform. " , OFFSET ( dct8x8 ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " fast-pskip " , NULL , OFFSET ( fast_pskip ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " aud " , " Use access unit delimiters. " , OFFSET ( aud ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
{ " mbtree " , " Use macroblock tree ratecontrol. " , OFFSET ( mbtree ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , 1 , VE } ,
2011-10-04 08:38:01 +03:00
{ " deblock " , " Loop filter parameters, in <alpha:beta> form. " , OFFSET ( deblock ) , AV_OPT_TYPE_STRING , { 0 } , 0 , 0 , VE } ,
2012-08-31 13:34:23 +03:00
{ " cplxblur " , " Reduce fluctuations in QP (before curve compression) " , OFFSET ( cplxblur ) , AV_OPT_TYPE_FLOAT , { . dbl = - 1 } , - 1 , FLT_MAX , VE } ,
2011-09-01 14:15:09 +03:00
{ " partitions " , " A comma-separated list of partitions to consider. "
2011-10-04 08:38:01 +03:00
" Possible values: p8x8, p4x4, b8x8, i8x8, i4x4, none, all " , OFFSET ( partitions ) , AV_OPT_TYPE_STRING , { 0 } , 0 , 0 , VE } ,
2012-08-31 13:22:31 +03:00
{ " direct-pred " , " Direct MV prediction mode " , OFFSET ( direct_pred ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE , " direct-pred " } ,
2012-08-31 12:45:52 +03:00
{ " none " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_DIRECT_PRED_NONE } , 0 , 0 , VE , " direct-pred " } ,
{ " spatial " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_DIRECT_PRED_SPATIAL } , 0 , 0 , VE , " direct-pred " } ,
{ " temporal " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_DIRECT_PRED_TEMPORAL } , 0 , 0 , VE , " direct-pred " } ,
{ " auto " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_DIRECT_PRED_AUTO } , 0 , 0 , VE , " direct-pred " } ,
2012-08-31 13:22:31 +03:00
{ " slice-max-size " , " Limit the size of each slice in bytes " , OFFSET ( slice_max_size ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE } ,
2012-03-12 19:20:20 +03:00
{ " stats " , " Filename for 2 pass stats " , OFFSET ( stats ) , AV_OPT_TYPE_STRING , { 0 } , 0 , 0 , VE } ,
2012-09-19 20:51:29 +03:00
{ " nal-hrd " , " Signal HRD information (requires vbv-bufsize; "
" cbr not allowed in .mp4) " , OFFSET ( nal_hrd ) , AV_OPT_TYPE_INT , { . i64 = - 1 } , - 1 , INT_MAX , VE , " nal-hrd " } ,
{ " none " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_NAL_HRD_NONE } , INT_MIN , INT_MAX , VE , " nal-hrd " } ,
{ " vbr " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_NAL_HRD_VBR } , INT_MIN , INT_MAX , VE , " nal-hrd " } ,
{ " cbr " , NULL , 0 , AV_OPT_TYPE_CONST , { . i64 = X264_NAL_HRD_CBR } , INT_MIN , INT_MAX , VE , " nal-hrd " } ,
2011-04-17 02:50:50 +03:00
{ NULL } ,
} ;
static const AVClass class = {
. class_name = " libx264 " ,
. item_name = av_default_item_name ,
. option = options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
2011-08-20 17:59:47 +03:00
static const AVCodecDefault x264_defaults [ ] = {
{ " b " , " 0 " } ,
2011-09-01 13:59:29 +03:00
{ " bf " , " -1 " } ,
{ " g " , " -1 " } ,
{ " qmin " , " -1 " } ,
{ " qmax " , " -1 " } ,
{ " qdiff " , " -1 " } ,
{ " qblur " , " -1 " } ,
{ " qcomp " , " -1 " } ,
{ " refs " , " -1 " } ,
{ " sc_threshold " , " -1 " } ,
2011-09-07 10:13:02 +03:00
{ " trellis " , " -1 " } ,
{ " nr " , " -1 " } ,
{ " me_range " , " -1 " } ,
{ " me_method " , " -1 " } ,
{ " subq " , " -1 " } ,
{ " b_strategy " , " -1 " } ,
{ " keyint_min " , " -1 " } ,
{ " coder " , " -1 " } ,
{ " cmp " , " -1 " } ,
2011-08-31 20:26:01 +03:00
{ " threads " , AV_STRINGIFY ( X264_THREADS_AUTO ) } ,
2012-03-05 22:54:17 +03:00
{ " thread_type " , " 0 " } ,
2012-09-22 21:41:16 +03:00
{ " flags " , " +cgop " } ,
2011-08-20 17:59:47 +03:00
{ NULL } ,
} ;
2011-01-25 23:40:11 +02:00
AVCodec ff_libx264_encoder = {
2012-04-06 19:19:39 +03:00
. name = " libx264 " ,
. type = AVMEDIA_TYPE_VIDEO ,
2012-08-05 12:11:04 +03:00
. id = AV_CODEC_ID_H264 ,
2012-04-06 19:19:39 +03:00
. priv_data_size = sizeof ( X264Context ) ,
. init = X264_init ,
. encode2 = X264_frame ,
. close = X264_close ,
. capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS ,
. long_name = NULL_IF_CONFIG_SMALL ( " libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 " ) ,
. priv_class = & class ,
. defaults = x264_defaults ,
2011-10-05 22:09:51 +03:00
. init_static_data = X264_init_static ,
2005-03-09 05:04:56 +02:00
} ;