Commit 0140d3f0 authored by Baptiste Coudurier's avatar Baptiste Coudurier

In libx264 wrapper, add -preset and -tune options

parent abf8342a
...@@ -365,8 +365,9 @@ void set_context_opts(void *ctx, void *opts_ctx, int flags, AVCodec *codec) ...@@ -365,8 +365,9 @@ void set_context_opts(void *ctx, void *opts_ctx, int flags, AVCodec *codec)
/* We need to use a differnt system to pass options to the private context because /* We need to use a differnt system to pass options to the private context because
it is not known which codec and thus context kind that will be when parsing options it is not known which codec and thus context kind that will be when parsing options
we thus use opt_values directly instead of opts_ctx */ we thus use opt_values directly instead of opts_ctx */
if(!str && priv_ctx && av_get_string(priv_ctx, opt_names[i], &opt, buf, sizeof(buf))){ if(!str && priv_ctx) {
av_set_string3(priv_ctx, opt_names[i], opt_values[i], 1, NULL); if (av_find_opt(priv_ctx, opt_names[i], NULL, flags, flags))
av_set_string3(priv_ctx, opt_names[i], opt_values[i], 0, NULL);
} }
} }
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "libavutil/opt.h"
#include "avcodec.h" #include "avcodec.h"
#include <x264.h> #include <x264.h>
#include <math.h> #include <math.h>
...@@ -27,12 +28,17 @@ ...@@ -27,12 +28,17 @@
#include <string.h> #include <string.h>
typedef struct X264Context { typedef struct X264Context {
AVClass *class;
x264_param_t params; x264_param_t params;
x264_t *enc; x264_t *enc;
x264_picture_t pic; x264_picture_t pic;
uint8_t *sei; uint8_t *sei;
int sei_size; int sei_size;
AVFrame out_pic; AVFrame out_pic;
const char *preset;
const char *tune;
const char *profile;
int fastfirstpass;
} X264Context; } X264Context;
static void X264_log(void *p, int level, const char *fmt, va_list args) static void X264_log(void *p, int level, const char *fmt, va_list args)
...@@ -163,32 +169,7 @@ static av_cold int X264_init(AVCodecContext *avctx) ...@@ -163,32 +169,7 @@ static av_cold int X264_init(AVCodecContext *avctx)
x4->sei_size = 0; x4->sei_size = 0;
x264_param_default(&x4->params); x264_param_default(&x4->params);
x4->params.pf_log = X264_log;
x4->params.p_log_private = avctx;
x4->params.i_keyint_max = avctx->gop_size; x4->params.i_keyint_max = avctx->gop_size;
x4->params.b_intra_refresh = avctx->flags2 & CODEC_FLAG2_INTRA_REFRESH;
x4->params.rc.i_bitrate = avctx->bit_rate / 1000;
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 {
if (avctx->crf) {
x4->params.rc.i_rc_method = X264_RC_CRF;
x4->params.rc.f_rf_constant = avctx->crf;
x4->params.rc.f_rf_constant_max = avctx->crf_max;
} else if (avctx->cqp > -1) {
x4->params.rc.i_rc_method = X264_RC_CQP;
x4->params.rc.i_qp_constant = avctx->cqp;
}
}
// if neither crf nor cqp modes are selected we have to enable the RC
// we do it this way because we cannot check if the bitrate has been set
if (!(avctx->crf || (avctx->cqp > -1)))
x4->params.rc.i_rc_method = X264_RC_ABR;
x4->params.i_bframe = avctx->max_b_frames; x4->params.i_bframe = avctx->max_b_frames;
x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC; x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC;
...@@ -217,13 +198,6 @@ static av_cold int X264_init(AVCodecContext *avctx) ...@@ -217,13 +198,6 @@ static av_cold int X264_init(AVCodecContext *avctx)
x4->params.i_frame_reference = avctx->refs; x4->params.i_frame_reference = avctx->refs;
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;
x4->params.analyse.inter = 0; x4->params.analyse.inter = 0;
if (avctx->partitions) { if (avctx->partitions) {
if (avctx->partitions & X264_PART_I4X4) if (avctx->partitions & X264_PART_I4X4)
...@@ -277,20 +251,65 @@ static av_cold int X264_init(AVCodecContext *avctx) ...@@ -277,20 +251,65 @@ static av_cold int X264_init(AVCodecContext *avctx)
if (avctx->level > 0) if (avctx->level > 0)
x4->params.i_level_idc = avctx->level; x4->params.i_level_idc = avctx->level;
x4->params.rc.b_mb_tree = !!(avctx->flags2 & CODEC_FLAG2_MBTREE);
x4->params.rc.f_ip_factor = 1 / fabs(avctx->i_quant_factor);
x4->params.rc.f_pb_factor = avctx->b_quant_factor;
x4->params.analyse.i_chroma_qp_offset = avctx->chromaoffset;
if (x4->preset || x4->tune) {
if (x264_param_default_preset(&x4->params, x4->preset, x4->tune) < 0)
return -1;
}
if (x4->fastfirstpass)
x264_param_apply_fastfirstpass(&x4->params);
if (x4->profile)
if (x264_param_apply_profile(&x4->params, x4->profile) < 0)
return -1;
x4->params.pf_log = X264_log;
x4->params.p_log_private = avctx;
x4->params.i_log_level = X264_LOG_DEBUG;
x4->params.b_intra_refresh = avctx->flags2 & CODEC_FLAG2_INTRA_REFRESH;
x4->params.rc.i_bitrate = avctx->bit_rate / 1000;
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 {
if (avctx->crf) {
x4->params.rc.i_rc_method = X264_RC_CRF;
x4->params.rc.f_rf_constant = avctx->crf;
x4->params.rc.f_rf_constant_max = avctx->crf_max;
} else if (avctx->cqp > -1) {
x4->params.rc.i_rc_method = X264_RC_CQP;
x4->params.rc.i_qp_constant = avctx->cqp;
}
}
// if neither crf nor cqp modes are selected we have to enable the RC
// we do it this way because we cannot check if the bitrate has been set
if (!(avctx->crf || (avctx->cqp > -1)))
x4->params.rc.i_rc_method = X264_RC_ABR;
if (avctx->rc_buffer_size && avctx->rc_initial_buffer_occupancy && if (avctx->rc_buffer_size && avctx->rc_initial_buffer_occupancy &&
(avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) { (avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) {
x4->params.rc.f_vbv_buffer_init = x4->params.rc.f_vbv_buffer_init =
(float)avctx->rc_initial_buffer_occupancy / avctx->rc_buffer_size; (float)avctx->rc_initial_buffer_occupancy / avctx->rc_buffer_size;
} }
x4->params.rc.b_mb_tree = !!(avctx->flags2 & CODEC_FLAG2_MBTREE); x4->params.i_width = avctx->width;
x4->params.rc.f_ip_factor = 1 / fabs(avctx->i_quant_factor); x4->params.i_height = avctx->height;
x4->params.rc.f_pb_factor = avctx->b_quant_factor; x4->params.vui.i_sar_width = avctx->sample_aspect_ratio.num;
x4->params.analyse.i_chroma_qp_offset = avctx->chromaoffset; 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;
x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR; x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR;
x4->params.analyse.b_ssim = avctx->flags2 & CODEC_FLAG2_SSIM; x4->params.analyse.b_ssim = avctx->flags2 & CODEC_FLAG2_SSIM;
x4->params.i_log_level = X264_LOG_DEBUG;
x4->params.b_aud = avctx->flags2 & CODEC_FLAG2_AUD; x4->params.b_aud = avctx->flags2 & CODEC_FLAG2_AUD;
...@@ -305,6 +324,11 @@ static av_cold int X264_init(AVCodecContext *avctx) ...@@ -305,6 +324,11 @@ static av_cold int X264_init(AVCodecContext *avctx)
if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER)
x4->params.b_repeat_headers = 0; x4->params.b_repeat_headers = 0;
// update AVCodecContext with x264 parameters
avctx->has_b_frames = x4->params.i_bframe_pyramid ? 2 : !!x4->params.i_bframe;
avctx->bit_rate = x4->params.rc.i_bitrate*1000;
avctx->crf = x4->params.rc.f_rf_constant;
x4->enc = x264_encoder_open(&x4->params); x4->enc = x264_encoder_open(&x4->params);
if (!x4->enc) if (!x4->enc)
return -1; return -1;
...@@ -328,6 +352,19 @@ static av_cold int X264_init(AVCodecContext *avctx) ...@@ -328,6 +352,19 @@ static av_cold int X264_init(AVCodecContext *avctx)
return 0; return 0;
} }
#define OFFSET(x) offsetof(X264Context,x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{"preset", "Set the encoding preset", OFFSET(preset), FF_OPT_TYPE_STRING, 0, 0, 0, VE},
{"tune", "Tune the encoding params", OFFSET(tune), FF_OPT_TYPE_STRING, 0, 0, 0, VE},
{"fastfirstpass", "Use fast settings when encoding first pass", OFFSET(fastfirstpass), FF_OPT_TYPE_INT, 1, 0, 1, VE},
{"profile", "Set profile restrictions", OFFSET(profile), FF_OPT_TYPE_STRING, 0, 0, 0, VE},
{ NULL },
};
static const AVClass class = { "libx264", av_default_item_name, options, LIBAVUTIL_VERSION_INT };
AVCodec ff_libx264_encoder = { AVCodec ff_libx264_encoder = {
.name = "libx264", .name = "libx264",
.type = AVMEDIA_TYPE_VIDEO, .type = AVMEDIA_TYPE_VIDEO,
...@@ -339,4 +376,5 @@ AVCodec ff_libx264_encoder = { ...@@ -339,4 +376,5 @@ AVCodec ff_libx264_encoder = {
.capabilities = CODEC_CAP_DELAY, .capabilities = CODEC_CAP_DELAY,
.pix_fmts = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_YUVJ420P, PIX_FMT_NONE }, .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_YUVJ420P, PIX_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
.priv_class = &class,
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment