2005-03-09 03:04:56 +00:00
/*
* H.264 encoding using the x264 library
2007-07-05 20:08:51 +00:00
* Copyright (C) 2005 Mans Rullgard <mans@mansr.com>
2005-03-09 03:04:56 +00:00
*
2011-03-18 17:35:10 +00:00
* This file is part of Libav.
2006-10-07 15:30:46 +00:00
*
2011-03-18 17:35:10 +00:00
* Libav is free software; you can redistribute it and/or
2005-03-09 03:04:56 +00:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
2006-10-07 15:30:46 +00:00
* version 2.1 of the License, or (at your option) any later version.
2005-03-09 03:04:56 +00:00
*
2011-03-18 17:35:10 +00:00
* Libav is distributed in the hope that it will be useful,
2005-03-09 03:04:56 +00: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 17:35:10 +00:00
* License along with Libav; if not, write to the Free Software
2006-01-12 22:43:26 +00:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2005-03-09 03:04:56 +00:00
*/
2012-08-06 16:49:32 +03:00
#include "libavutil/internal.h"
2011-04-16 16:50:50 -07:00
#include "libavutil/opt.h"
2012-08-06 16:49:32 +03:00
#include "libavutil/mem.h"
2011-10-05 21:09:51 +02:00
#include "libavutil/pixdesc.h"
2005-03-09 03:04:56 +00:00
#include "avcodec.h"
2011-08-20 16:59:47 +02:00
#include "internal.h"
2005-03-09 03:04:56 +00:00
#include <x264.h>
2011-08-22 07:55:34 +02:00
#include <float.h>
2005-07-10 00:22:13 +00:00
#include <math.h>
2005-12-29 07:24:23 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2005-03-09 03:04:56 +00:00
typedef struct X264Context {
2011-04-16 16:50:50 -07:00
AVClass * class ;
2009-09-29 18:03:30 +00:00
x264_param_t params ;
x264_t * enc ;
x264_picture_t pic ;
uint8_t * sei ;
int sei_size ;
AVFrame out_pic ;
2011-04-16 16:50:50 -07:00
char * preset ;
char * tune ;
char * profile ;
int fastfirstpass ;
2011-08-22 07:55:34 +02:00
float crf ;
2011-08-22 07:55:34 +02:00
float crf_max ;
2011-08-22 07:55:34 +02:00
int cqp ;
2011-08-22 07:55:34 +02:00
int aq_mode ;
2011-08-22 07:55:34 +02:00
float aq_strength ;
2011-08-27 07:52:03 +02:00
char * psy_rd ;
2011-08-27 10:16:14 +02:00
int psy ;
2011-08-22 07:55:34 +02:00
int rc_lookahead ;
2011-08-22 07:55:34 +02:00
int weightp ;
2011-08-22 07:55:34 +02:00
int weightb ;
2011-08-22 07:55:34 +02:00
int ssim ;
2011-08-22 07:55:34 +02:00
int intra_refresh ;
2011-09-01 13:15:09 +02:00
int b_bias ;
2011-08-22 07:55:34 +02:00
int b_pyramid ;
2011-08-22 07:55:34 +02:00
int mixed_refs ;
2011-08-22 07:55:34 +02:00
int dct8x8 ;
2011-08-22 07:55:34 +02:00
int fast_pskip ;
2011-08-22 07:55:34 +02:00
int aud ;
2011-08-27 10:16:14 +02:00
int mbtree ;
2011-09-01 13:15:09 +02:00
char * deblock ;
2011-09-01 13:15:09 +02:00
float cplxblur ;
2011-09-01 13:15:09 +02:00
char * partitions ;
2011-09-01 13:15:09 +02:00
int direct_pred ;
2011-09-16 04:30:10 +02:00
int slice_max_size ;
2012-03-12 17:20:20 +01:00
char * stats ;
2012-09-21 09:20:09 +02:00
int nal_hrd ;
2005-03-09 03:04:56 +00:00
} X264Context ;
2009-09-29 18:03:30 +00:00
static void X264_log ( void * p , int level , const char * fmt , va_list args )
2005-03-09 03:04:56 +00:00
{
static const int level_map [] = {
2005-12-22 01:10:11 +00:00
[ X264_LOG_ERROR ] = AV_LOG_ERROR ,
2007-07-12 08:22:28 +00:00
[ X264_LOG_WARNING ] = AV_LOG_WARNING ,
2005-12-22 01:10:11 +00:00
[ X264_LOG_INFO ] = AV_LOG_INFO ,
[ X264_LOG_DEBUG ] = AV_LOG_DEBUG
2005-03-09 03:04:56 +00:00
};
2009-09-29 18:03:30 +00:00
if ( level < 0 || level > X264_LOG_DEBUG )
2005-12-22 01:10:11 +00:00
return ;
2005-03-09 03:04:56 +00:00
av_vlog ( p , level_map [ level ], fmt , args );
}
2012-02-06 07:39:23 +01:00
static int encode_nals ( AVCodecContext * ctx , AVPacket * pkt ,
x264_nal_t * nals , int nnal )
2005-03-09 03:04:56 +00:00
{
2009-06-30 23:45:01 +00:00
X264Context * x4 = ctx -> priv_data ;
2012-02-06 07:39:23 +01: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-06-30 23:45:01 +00:00
/* Write the SEI as part of the first frame. */
2009-09-29 18:03:30 +00:00
if ( x4 -> sei_size > 0 && nnal > 0 ) {
2009-06-30 23:45:01 +00:00
memcpy ( p , x4 -> sei , x4 -> sei_size );
p += x4 -> sei_size ;
x4 -> sei_size = 0 ;
}
2005-03-09 03:04:56 +00:00
2009-09-29 18:03:30 +00:00
for ( i = 0 ; i < nnal ; i ++ ){
2009-09-23 09:03:26 +00:00
memcpy ( p , nals [ i ]. p_payload , nals [ i ]. i_payload );
p += nals [ i ]. i_payload ;
2005-03-09 03:04:56 +00:00
}
2012-02-06 07:39:23 +01:00
return 1 ;
2005-03-09 03:04:56 +00:00
}
2012-02-06 07:39:23 +01:00
static int X264_frame ( AVCodecContext * ctx , AVPacket * pkt , const AVFrame * frame ,
int * got_packet )
2005-03-09 03:04:56 +00:00
{
X264Context * x4 = ctx -> priv_data ;
x264_nal_t * nal ;
2012-02-06 07:39:23 +01:00
int nnal , i , ret ;
2005-03-09 03:04:56 +00:00
x264_picture_t pic_out ;
2010-06-02 20:05:27 +00:00
x264_picture_init ( & x4 -> pic );
2011-10-09 19:34:20 +02:00
x4 -> pic . img . i_csp = x4 -> params . i_csp ;
2011-10-05 21:09:51 +02:00
if ( x264_bit_depth > 8 )
x4 -> pic . img . i_csp |= X264_CSP_HIGH_DEPTH ;
2005-03-09 03:04:56 +00:00
x4 -> pic . img . i_plane = 3 ;
2009-09-29 18:03:30 +00:00
if ( frame ) {
for ( i = 0 ; i < 3 ; i ++ ) {
x4 -> pic . img . plane [ i ] = frame -> data [ i ];
2006-11-01 18:19:20 +00:00
x4 -> pic . img . i_stride [ i ] = frame -> linesize [ i ];
}
2005-03-09 03:04:56 +00:00
2009-09-29 18:03:30 +00:00
x4 -> pic . i_pts = frame -> pts ;
2010-10-25 14:40:00 +00:00
x4 -> pic . i_type =
2011-04-29 18:53:57 +02: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 14:40:00 +00:00
X264_TYPE_AUTO ;
2011-01-25 18:07:34 -08: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 18:18:48 +00:00
}
2005-03-09 03:04:56 +00:00
2010-05-19 20:48:29 +00:00
do {
2012-02-01 10:56:14 +01:00
if ( x264_encoder_encode ( x4 -> enc , & nal , & nnal , frame ? & x4 -> pic : NULL , & pic_out ) < 0 )
return - 1 ;
2005-03-09 03:04:56 +00:00
2012-02-06 07:39:23 +01:00
ret = encode_nals ( ctx , pkt , nal , nnal );
if ( ret < 0 )
2012-02-01 10:56:14 +01:00
return - 1 ;
2012-02-06 07:39:23 +01:00
} while ( ! ret && ! frame && x264_encoder_delayed_frames ( x4 -> enc ));
2005-03-09 03:04:56 +00:00
2012-02-06 07:39:23 +01:00
pkt -> pts = pic_out . i_pts ;
pkt -> dts = pic_out . i_dts ;
2005-03-09 03:04:56 +00:00
2009-09-29 18:03:30 +00:00
switch ( pic_out . i_type ) {
2005-03-09 03:04:56 +00:00
case X264_TYPE_IDR :
case X264_TYPE_I :
2011-04-29 18:53:57 +02:00
x4 -> out_pic . pict_type = AV_PICTURE_TYPE_I ;
2005-03-09 03:04:56 +00:00
break ;
case X264_TYPE_P :
2011-04-29 18:53:57 +02:00
x4 -> out_pic . pict_type = AV_PICTURE_TYPE_P ;
2005-03-09 03:04:56 +00:00
break ;
case X264_TYPE_B :
case X264_TYPE_BREF :
2011-04-29 18:53:57 +02:00
x4 -> out_pic . pict_type = AV_PICTURE_TYPE_B ;
2005-03-09 03:04:56 +00:00
break ;
}
2012-02-06 07:39:23 +01:00
pkt -> flags |= AV_PKT_FLAG_KEY * pic_out . b_keyframe ;
if ( ret )
2011-01-29 17:05:42 -08:00
x4 -> out_pic . quality = ( pic_out . i_qpplus1 - 1 ) * FF_QP2LAMBDA ;
2005-03-09 03:04:56 +00:00
2012-02-06 07:39:23 +01:00
* got_packet = ret ;
return 0 ;
2005-03-09 03:04:56 +00:00
}
2009-09-29 18:03:30 +00:00
static av_cold int X264_close ( AVCodecContext * avctx )
2005-03-09 03:04:56 +00:00
{
X264Context * x4 = avctx -> priv_data ;
2008-10-13 13:47:05 +00:00
av_freep ( & avctx -> extradata );
2009-06-30 23:45:01 +00:00
av_free ( x4 -> sei );
2008-10-13 13:47:05 +00:00
2009-09-29 18:03:30 +00:00
if ( x4 -> enc )
2005-12-22 01:10:11 +00:00
x264_encoder_close ( x4 -> enc );
2005-03-09 03:04:56 +00:00
return 0 ;
}
2012-10-06 12:10:34 +02:00
static int convert_pix_fmt ( enum AVPixelFormat pix_fmt )
2011-10-09 19:34:20 +02:00
{
switch ( pix_fmt ) {
2012-10-06 12:10:34 +02: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 19:34:20 +02:00
};
return 0 ;
}
2011-09-01 13:15:09 +02: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 18:03:30 +00:00
static av_cold int X264_init ( AVCodecContext * avctx )
2005-03-09 03:04:56 +00:00
{
X264Context * x4 = avctx -> priv_data ;
x264_param_default ( & x4 -> params );
2009-12-09 00:38:22 +00:00
x4 -> params . b_deblocking_filter = avctx -> flags & CODEC_FLAG_LOOP_FILTER ;
2005-03-19 12:27:10 +00:00
2011-04-16 16:50:50 -07: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 08:27:28 +02:00
if ( avctx -> level > 0 )
x4 -> params . i_level_idc = avctx -> level ;
2011-04-16 16:50:50 -07:00
x4 -> params . pf_log = X264_log ;
x4 -> params . p_log_private = avctx ;
x4 -> params . i_log_level = X264_LOG_DEBUG ;
2011-10-09 19:34:20 +02:00
x4 -> params . i_csp = convert_pix_fmt ( avctx -> pix_fmt );
2011-04-16 16:50:50 -07:00
2011-08-20 16:59:47 +02: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-16 16:50:50 -07: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 07:55:34 +02: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 07:55:34 +02: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 07:55:34 +02:00
}
2011-08-22 07:55:34 +02:00
if ( x4 -> crf_max >= 0 )
x4 -> params . rc . f_rf_constant_max = x4 -> crf_max ;
2011-04-16 16:50:50 -07:00
}
2011-02-06 05:10:15 -08:00
if ( avctx -> rc_buffer_size && avctx -> rc_initial_buffer_occupancy &&
2009-09-29 18:03:30 +00:00
( avctx -> rc_initial_buffer_occupancy <= avctx -> rc_buffer_size )) {
2005-12-29 07:24:23 +00:00
x4 -> params . rc . f_vbv_buffer_init =
2009-09-29 18:03:30 +00:00
( float ) avctx -> rc_initial_buffer_occupancy / avctx -> rc_buffer_size ;
2011-02-06 05:10:15 -08:00
}
2005-12-29 07:24:23 +00:00
2009-09-29 18:03:30 +00: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 07:24:23 +00:00
x4 -> params . analyse . i_chroma_qp_offset = avctx -> chromaoffset ;
2011-09-07 09:13:02 +02: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 12:59:29 +02: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 09:13:02 +02: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 12:59:29 +02:00
2011-08-22 07:55:34 +02:00
if ( x4 -> aq_mode >= 0 )
x4 -> params . rc . i_aq_mode = x4 -> aq_mode ;
2011-08-22 07:55:34 +02:00
if ( x4 -> aq_strength >= 0 )
x4 -> params . rc . f_aq_strength = x4 -> aq_strength ;
2011-09-01 13:15:09 +02:00
PARSE_X264_OPT ( "psy-rd" , psy_rd );
PARSE_X264_OPT ( "deblock" , deblock );
2011-09-01 13:15:09 +02:00
PARSE_X264_OPT ( "partitions" , partitions );
2012-03-12 17:20:20 +01:00
PARSE_X264_OPT ( "stats" , stats );
2011-08-27 10:16:14 +02:00
if ( x4 -> psy >= 0 )
x4 -> params . analyse . b_psy = x4 -> psy ;
2011-08-22 07:55:34 +02:00
if ( x4 -> rc_lookahead >= 0 )
x4 -> params . rc . i_lookahead = x4 -> rc_lookahead ;
2011-08-22 07:55:34 +02:00
if ( x4 -> weightp >= 0 )
x4 -> params . analyse . i_weighted_pred = x4 -> weightp ;
2011-08-22 07:55:34 +02:00
if ( x4 -> weightb >= 0 )
x4 -> params . analyse . b_weighted_bipred = x4 -> weightb ;
2011-09-01 13:15:09 +02:00
if ( x4 -> cplxblur >= 0 )
x4 -> params . rc . f_complexity_blur = x4 -> cplxblur ;
2011-08-22 07:55:34 +02:00
2011-08-22 07:55:34 +02:00
if ( x4 -> ssim >= 0 )
x4 -> params . analyse . b_ssim = x4 -> ssim ;
2011-08-22 07:55:34 +02:00
if ( x4 -> intra_refresh >= 0 )
x4 -> params . b_intra_refresh = x4 -> intra_refresh ;
2011-09-01 13:15:09 +02:00
if ( x4 -> b_bias != INT_MIN )
x4 -> params . i_bframe_bias = x4 -> b_bias ;
2011-08-22 07:55:34 +02:00
if ( x4 -> b_pyramid >= 0 )
x4 -> params . i_bframe_pyramid = x4 -> b_pyramid ;
2011-08-22 07:55:34 +02:00
if ( x4 -> mixed_refs >= 0 )
x4 -> params . analyse . b_mixed_references = x4 -> mixed_refs ;
2011-08-22 07:55:34 +02:00
if ( x4 -> dct8x8 >= 0 )
x4 -> params . analyse . b_transform_8x8 = x4 -> dct8x8 ;
2011-08-22 07:55:34 +02:00
if ( x4 -> fast_pskip >= 0 )
x4 -> params . analyse . b_fast_pskip = x4 -> fast_pskip ;
2011-08-22 07:55:34 +02:00
if ( x4 -> aud >= 0 )
x4 -> params . b_aud = x4 -> aud ;
2011-08-27 10:16:14 +02:00
if ( x4 -> mbtree >= 0 )
x4 -> params . rc . b_mb_tree = x4 -> mbtree ;
2011-09-01 13:15:09 +02:00
if ( x4 -> direct_pred >= 0 )
x4 -> params . analyse . i_direct_mv_pred = x4 -> direct_pred ;
2011-08-22 07:55:34 +02:00
2011-09-16 04:30:10 +02:00
if ( x4 -> slice_max_size >= 0 )
x4 -> params . i_slice_max_size = x4 -> slice_max_size ;
2011-04-16 16:50:50 -07:00
if ( x4 -> fastfirstpass )
x264_param_apply_fastfirstpass ( & x4 -> params );
2012-09-19 13:51:29 -04:00
if ( x4 -> nal_hrd >= 0 )
x4 -> params . i_nal_hrd = x4 -> nal_hrd ;
2011-04-16 16:50:50 -07: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 00:38:22 +00:00
x4 -> params . analyse . b_psnr = avctx -> flags & CODEC_FLAG_PSNR ;
2005-12-29 07:24:23 +00:00
2009-09-29 18:03:30 +00:00
x4 -> params . i_threads = avctx -> thread_count ;
2012-03-05 21:54:17 +02:00
if ( avctx -> thread_type )
x4 -> params . b_sliced_threads = avctx -> thread_type == FF_THREAD_SLICE ;
2005-05-30 20:34:02 +00:00
2009-12-09 00:38:22 +00:00
x4 -> params . b_interlaced = avctx -> flags & CODEC_FLAG_INTERLACED_DCT ;
2008-06-04 00:56:36 +00:00
2011-05-10 15:11:45 +02:00
x4 -> params . b_open_gop = ! ( avctx -> flags & CODEC_FLAG_CLOSED_GOP );
2010-10-22 18:09:14 +00:00
x4 -> params . i_slice_count = avctx -> slices ;
2012-10-06 12:10:34 +02:00
x4 -> params . vui . b_fullrange = avctx -> pix_fmt == AV_PIX_FMT_YUVJ420P ;
2010-12-07 09:51:27 +00:00
2009-09-29 18:03:30 +00:00
if ( avctx -> flags & CODEC_FLAG_GLOBAL_HEADER )
2006-01-20 21:20:46 +00:00
x4 -> params . b_repeat_headers = 0 ;
2011-04-16 16:50:50 -07:00
// update AVCodecContext with x264 parameters
avctx -> has_b_frames = x4 -> params . i_bframe ?
x4 -> params . i_bframe_pyramid ? 2 : 1 : 0 ;
2012-01-13 23:41:16 +02:00
if ( avctx -> max_b_frames < 0 )
avctx -> max_b_frames = 0 ;
2011-04-16 16:50:50 -07:00
avctx -> bit_rate = x4 -> params . rc . i_bitrate * 1000 ;
2005-03-09 03:04:56 +00:00
x4 -> enc = x264_encoder_open ( & x4 -> params );
2009-09-29 18:03:30 +00:00
if ( ! x4 -> enc )
2005-03-09 03:04:56 +00:00
return - 1 ;
avctx -> coded_frame = & x4 -> out_pic ;
2009-09-29 18:03:30 +00:00
if ( avctx -> flags & CODEC_FLAG_GLOBAL_HEADER ) {
2006-01-24 10:33:14 +00:00
x264_nal_t * nal ;
2012-02-06 07:34:57 +01:00
uint8_t * p ;
2010-03-25 19:25:21 +00:00
int nnal , s , i ;
2006-01-20 21:20:46 +00:00
2009-09-23 09:03:26 +00:00
s = x264_encoder_headers ( x4 -> enc , & nal , & nnal );
2012-02-06 07:34:57 +01:00
avctx -> extradata = p = av_malloc ( s );
2006-01-20 21:20:46 +00:00
2012-02-06 07:34:57 +01:00
for ( i = 0 ; i < nnal ; i ++ ) {
/* Don't put the SEI in extradata. */
if ( nal [ i ]. i_type == NAL_SEI ) {
2010-03-25 19:25:21 +00:00
av_log ( avctx , AV_LOG_INFO , "%s \n " , nal [ i ]. p_payload + 25 );
2012-02-06 07:34:57 +01: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 21:20:46 +00:00
}
2005-03-09 03:04:56 +00:00
return 0 ;
}
2012-10-06 12:10:34 +02: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 21:09:51 +02:00
};
2012-10-06 12:10:34 +02:00
static const enum AVPixelFormat pix_fmts_9bit [] = {
AV_PIX_FMT_YUV420P9 ,
AV_PIX_FMT_YUV444P9 ,
AV_PIX_FMT_NONE
2011-10-05 21:09:51 +02:00
};
2012-10-06 12:10:34 +02: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 21:09:51 +02: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-16 16:50:50 -07: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 07:38:01 +02: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 07:38:01 +02: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 07:38:01 +02: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 13:15:09 +02:00
{ "partitions" , "A comma-separated list of partitions to consider. "
2011-10-04 07:38:01 +02: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 17:20:20 +01:00
{ "stats" , "Filename for 2 pass stats" , OFFSET ( stats ), AV_OPT_TYPE_STRING , { 0 }, 0 , 0 , VE },
2012-09-19 13:51:29 -04: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-16 16:50:50 -07:00
{ NULL },
};
static const AVClass class = {
. class_name = "libx264" ,
. item_name = av_default_item_name ,
. option = options ,
. version = LIBAVUTIL_VERSION_INT ,
};
2011-08-20 16:59:47 +02:00
static const AVCodecDefault x264_defaults [] = {
{ "b" , "0" },
2011-09-01 12:59:29 +02:00
{ "bf" , "-1" },
{ "g" , "-1" },
{ "qmin" , "-1" },
{ "qmax" , "-1" },
{ "qdiff" , "-1" },
{ "qblur" , "-1" },
{ "qcomp" , "-1" },
{ "refs" , "-1" },
{ "sc_threshold" , "-1" },
2011-09-07 09:13:02 +02: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 19:26:01 +02:00
{ "threads" , AV_STRINGIFY ( X264_THREADS_AUTO ) },
2012-03-05 21:54:17 +02:00
{ "thread_type" , "0" },
2012-09-22 14:41:16 -04:00
{ "flags" , "+cgop" },
2011-08-20 16:59:47 +02:00
{ NULL },
};
2011-01-25 21:40:11 +00:00
AVCodec ff_libx264_encoder = {
2012-04-06 19:19:39 +03:00
. name = "libx264" ,
. type = AVMEDIA_TYPE_VIDEO ,
2012-08-05 11:11:04 +02: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 21:09:51 +02:00
. init_static_data = X264_init_static ,
2005-03-09 03:04:56 +00:00
};