mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
Merge commit 'ba7397baef796ca3991fe1c921bc91054407c48b'
* commit 'ba7397baef796ca3991fe1c921bc91054407c48b': avconv: factor out initializing stream parameters for encoding Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
This commit is contained in:
commit
6b449a1290
626
ffmpeg.c
626
ffmpeg.c
@ -2720,9 +2720,17 @@ static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
|
||||
|
||||
static int init_input_stream(int ist_index, char *error, int error_len)
|
||||
{
|
||||
int ret;
|
||||
int i, ret;
|
||||
InputStream *ist = input_streams[ist_index];
|
||||
|
||||
for (i = 0; i < ist->nb_filters; i++) {
|
||||
ret = ifilter_parameters_from_decoder(ist->filters[i], ist->dec_ctx);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ist->decoding_needed) {
|
||||
AVCodec *codec = ist->dec;
|
||||
if (!codec) {
|
||||
@ -2927,6 +2935,9 @@ static int init_output_stream_streamcopy(OutputStream *ost)
|
||||
// copy timebase while removing common factors
|
||||
ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1});
|
||||
|
||||
// copy disposition
|
||||
ost->st->disposition = ist->st->disposition;
|
||||
|
||||
if (ist->st->nb_side_data) {
|
||||
ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data,
|
||||
sizeof(*ist->st->side_data));
|
||||
@ -3015,6 +3026,274 @@ static int init_output_stream_streamcopy(OutputStream *ost)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_encoder_id(OutputFile *of, OutputStream *ost)
|
||||
{
|
||||
AVDictionaryEntry *e;
|
||||
|
||||
uint8_t *encoder_string;
|
||||
int encoder_string_len;
|
||||
int format_flags = 0;
|
||||
int codec_flags = 0;
|
||||
|
||||
if (av_dict_get(ost->st->metadata, "encoder", NULL, 0))
|
||||
return;
|
||||
|
||||
e = av_dict_get(of->opts, "fflags", NULL, 0);
|
||||
if (e) {
|
||||
const AVOption *o = av_opt_find(of->ctx, "fflags", NULL, 0, 0);
|
||||
if (!o)
|
||||
return;
|
||||
av_opt_eval_flags(of->ctx, o, e->value, &format_flags);
|
||||
}
|
||||
e = av_dict_get(ost->encoder_opts, "flags", NULL, 0);
|
||||
if (e) {
|
||||
const AVOption *o = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0);
|
||||
if (!o)
|
||||
return;
|
||||
av_opt_eval_flags(ost->enc_ctx, o, e->value, &codec_flags);
|
||||
}
|
||||
|
||||
encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(ost->enc->name) + 2;
|
||||
encoder_string = av_mallocz(encoder_string_len);
|
||||
if (!encoder_string)
|
||||
exit_program(1);
|
||||
|
||||
if (!(format_flags & AVFMT_FLAG_BITEXACT) && !(codec_flags & AV_CODEC_FLAG_BITEXACT))
|
||||
av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
|
||||
else
|
||||
av_strlcpy(encoder_string, "Lavc ", encoder_string_len);
|
||||
av_strlcat(encoder_string, ost->enc->name, encoder_string_len);
|
||||
av_dict_set(&ost->st->metadata, "encoder", encoder_string,
|
||||
AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
|
||||
}
|
||||
|
||||
static void parse_forced_key_frames(char *kf, OutputStream *ost,
|
||||
AVCodecContext *avctx)
|
||||
{
|
||||
char *p;
|
||||
int n = 1, i, size, index = 0;
|
||||
int64_t t, *pts;
|
||||
|
||||
for (p = kf; *p; p++)
|
||||
if (*p == ',')
|
||||
n++;
|
||||
size = n;
|
||||
pts = av_malloc_array(size, sizeof(*pts));
|
||||
if (!pts) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
p = kf;
|
||||
for (i = 0; i < n; i++) {
|
||||
char *next = strchr(p, ',');
|
||||
|
||||
if (next)
|
||||
*next++ = 0;
|
||||
|
||||
if (!memcmp(p, "chapters", 8)) {
|
||||
|
||||
AVFormatContext *avf = output_files[ost->file_index]->ctx;
|
||||
int j;
|
||||
|
||||
if (avf->nb_chapters > INT_MAX - size ||
|
||||
!(pts = av_realloc_f(pts, size += avf->nb_chapters - 1,
|
||||
sizeof(*pts)))) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"Could not allocate forced key frames array.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0;
|
||||
t = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
|
||||
|
||||
for (j = 0; j < avf->nb_chapters; j++) {
|
||||
AVChapter *c = avf->chapters[j];
|
||||
av_assert1(index < size);
|
||||
pts[index++] = av_rescale_q(c->start, c->time_base,
|
||||
avctx->time_base) + t;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
t = parse_time_or_die("force_key_frames", p, 1);
|
||||
av_assert1(index < size);
|
||||
pts[index++] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
|
||||
|
||||
}
|
||||
|
||||
p = next;
|
||||
}
|
||||
|
||||
av_assert0(index == size);
|
||||
qsort(pts, size, sizeof(*pts), compare_int64);
|
||||
ost->forced_kf_count = size;
|
||||
ost->forced_kf_pts = pts;
|
||||
}
|
||||
|
||||
static int init_output_stream_encode(OutputStream *ost)
|
||||
{
|
||||
InputStream *ist = get_input_stream(ost);
|
||||
AVCodecContext *enc_ctx = ost->enc_ctx;
|
||||
AVCodecContext *dec_ctx = NULL;
|
||||
AVFormatContext *oc = output_files[ost->file_index]->ctx;
|
||||
int j, ret;
|
||||
|
||||
set_encoder_id(output_files[ost->file_index], ost);
|
||||
|
||||
if (ist) {
|
||||
ost->st->disposition = ist->st->disposition;
|
||||
|
||||
dec_ctx = ist->dec_ctx;
|
||||
|
||||
enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
|
||||
} else {
|
||||
for (j = 0; j < oc->nb_streams; j++) {
|
||||
AVStream *st = oc->streams[j];
|
||||
if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type)
|
||||
break;
|
||||
}
|
||||
if (j == oc->nb_streams)
|
||||
if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ||
|
||||
ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
ost->st->disposition = AV_DISPOSITION_DEFAULT;
|
||||
}
|
||||
|
||||
if ((enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
|
||||
enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
|
||||
filtergraph_is_simple(ost->filter->graph)) {
|
||||
FilterGraph *fg = ost->filter->graph;
|
||||
|
||||
if (configure_filtergraph(fg)) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (!ost->frame_rate.num)
|
||||
ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter);
|
||||
if (ist && !ost->frame_rate.num)
|
||||
ost->frame_rate = ist->framerate;
|
||||
if (ist && !ost->frame_rate.num)
|
||||
ost->frame_rate = ist->st->r_frame_rate;
|
||||
if (ist && !ost->frame_rate.num) {
|
||||
ost->frame_rate = (AVRational){25, 1};
|
||||
av_log(NULL, AV_LOG_WARNING,
|
||||
"No information "
|
||||
"about the input framerate is available. Falling "
|
||||
"back to a default value of 25fps for output stream #%d:%d. Use the -r option "
|
||||
"if you want a different framerate.\n",
|
||||
ost->file_index, ost->index);
|
||||
}
|
||||
// ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1};
|
||||
if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
|
||||
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
|
||||
ost->frame_rate = ost->enc->supported_framerates[idx];
|
||||
}
|
||||
// reduce frame rate for mpeg4 to be within the spec limits
|
||||
if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) {
|
||||
av_reduce(&ost->frame_rate.num, &ost->frame_rate.den,
|
||||
ost->frame_rate.num, ost->frame_rate.den, 65535);
|
||||
}
|
||||
}
|
||||
|
||||
switch (enc_ctx->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
|
||||
if (dec_ctx)
|
||||
enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample,
|
||||
av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3);
|
||||
enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
|
||||
enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout;
|
||||
enc_ctx->channels = avfilter_link_get_channels(ost->filter->filter->inputs[0]);
|
||||
enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
enc_ctx->time_base = av_inv_q(ost->frame_rate);
|
||||
if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
|
||||
enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base;
|
||||
if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
|
||||
&& (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
|
||||
av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
|
||||
"Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
|
||||
}
|
||||
for (j = 0; j < ost->forced_kf_count; j++)
|
||||
ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j],
|
||||
AV_TIME_BASE_Q,
|
||||
enc_ctx->time_base);
|
||||
|
||||
enc_ctx->width = ost->filter->filter->inputs[0]->w;
|
||||
enc_ctx->height = ost->filter->filter->inputs[0]->h;
|
||||
enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio =
|
||||
ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option
|
||||
av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) :
|
||||
ost->filter->filter->inputs[0]->sample_aspect_ratio;
|
||||
if (!strncmp(ost->enc->name, "libx264", 7) &&
|
||||
enc_ctx->pix_fmt == AV_PIX_FMT_NONE &&
|
||||
ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P)
|
||||
av_log(NULL, AV_LOG_WARNING,
|
||||
"No pixel format specified, %s for H.264 encoding chosen.\n"
|
||||
"Use -pix_fmt yuv420p for compatibility with outdated media players.\n",
|
||||
av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format));
|
||||
if (!strncmp(ost->enc->name, "mpeg2video", 10) &&
|
||||
enc_ctx->pix_fmt == AV_PIX_FMT_NONE &&
|
||||
ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P)
|
||||
av_log(NULL, AV_LOG_WARNING,
|
||||
"No pixel format specified, %s for MPEG-2 encoding chosen.\n"
|
||||
"Use -pix_fmt yuv420p for compatibility with outdated media players.\n",
|
||||
av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format));
|
||||
enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format;
|
||||
if (dec_ctx)
|
||||
enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample,
|
||||
av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth);
|
||||
|
||||
ost->st->avg_frame_rate = ost->frame_rate;
|
||||
|
||||
if (!dec_ctx ||
|
||||
enc_ctx->width != dec_ctx->width ||
|
||||
enc_ctx->height != dec_ctx->height ||
|
||||
enc_ctx->pix_fmt != dec_ctx->pix_fmt) {
|
||||
enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample;
|
||||
}
|
||||
|
||||
if (ost->forced_keyframes) {
|
||||
if (!strncmp(ost->forced_keyframes, "expr:", 5)) {
|
||||
ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5,
|
||||
forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Invalid force_key_frames expression '%s'\n", ost->forced_keyframes+5);
|
||||
return ret;
|
||||
}
|
||||
ost->forced_keyframes_expr_const_values[FKF_N] = 0;
|
||||
ost->forced_keyframes_expr_const_values[FKF_N_FORCED] = 0;
|
||||
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN;
|
||||
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN;
|
||||
|
||||
// Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
|
||||
// parse it only for static kf timings
|
||||
} else if(strncmp(ost->forced_keyframes, "source", 6)) {
|
||||
parse_forced_key_frames(ost->forced_keyframes, ost, ost->enc_ctx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
enc_ctx->time_base = (AVRational){1, 1000};
|
||||
if (!enc_ctx->width) {
|
||||
enc_ctx->width = input_streams[ost->source_index]->st->codecpar->width;
|
||||
enc_ctx->height = input_streams[ost->source_index]->st->codecpar->height;
|
||||
}
|
||||
break;
|
||||
case AVMEDIA_TYPE_DATA:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_output_stream(OutputStream *ost, char *error, int error_len)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -3024,6 +3303,10 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
|
||||
AVCodecContext *dec = NULL;
|
||||
InputStream *ist;
|
||||
|
||||
ret = init_output_stream_encode(ost);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ist = get_input_stream(ost)))
|
||||
dec = ist->dec_ctx;
|
||||
if (dec && dec->subtitle_header) {
|
||||
@ -3118,6 +3401,38 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// parse user provided disposition, and update stream values
|
||||
if (ost->disposition) {
|
||||
static const AVOption opts[] = {
|
||||
{ "disposition" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
|
||||
{ "default" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "flags" },
|
||||
{ "dub" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "flags" },
|
||||
{ "original" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "flags" },
|
||||
{ "comment" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "flags" },
|
||||
{ "lyrics" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "flags" },
|
||||
{ "karaoke" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "flags" },
|
||||
{ "forced" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "flags" },
|
||||
{ "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" },
|
||||
{ "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" },
|
||||
{ "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" },
|
||||
{ "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" },
|
||||
{ "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" },
|
||||
{ "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" },
|
||||
{ NULL },
|
||||
};
|
||||
static const AVClass class = {
|
||||
.class_name = "",
|
||||
.item_name = av_default_item_name,
|
||||
.option = opts,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
const AVClass *pclass = &class;
|
||||
|
||||
ret = av_opt_eval_flags(&pclass, &opts[0], ost->disposition, &ost->st->disposition);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize bitstream filters for the output stream
|
||||
* needs to be done here, because the codec id for streamcopy is not
|
||||
* known until now */
|
||||
@ -3134,69 +3449,6 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void parse_forced_key_frames(char *kf, OutputStream *ost,
|
||||
AVCodecContext *avctx)
|
||||
{
|
||||
char *p;
|
||||
int n = 1, i, size, index = 0;
|
||||
int64_t t, *pts;
|
||||
|
||||
for (p = kf; *p; p++)
|
||||
if (*p == ',')
|
||||
n++;
|
||||
size = n;
|
||||
pts = av_malloc_array(size, sizeof(*pts));
|
||||
if (!pts) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
|
||||
p = kf;
|
||||
for (i = 0; i < n; i++) {
|
||||
char *next = strchr(p, ',');
|
||||
|
||||
if (next)
|
||||
*next++ = 0;
|
||||
|
||||
if (!memcmp(p, "chapters", 8)) {
|
||||
|
||||
AVFormatContext *avf = output_files[ost->file_index]->ctx;
|
||||
int j;
|
||||
|
||||
if (avf->nb_chapters > INT_MAX - size ||
|
||||
!(pts = av_realloc_f(pts, size += avf->nb_chapters - 1,
|
||||
sizeof(*pts)))) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"Could not allocate forced key frames array.\n");
|
||||
exit_program(1);
|
||||
}
|
||||
t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0;
|
||||
t = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
|
||||
|
||||
for (j = 0; j < avf->nb_chapters; j++) {
|
||||
AVChapter *c = avf->chapters[j];
|
||||
av_assert1(index < size);
|
||||
pts[index++] = av_rescale_q(c->start, c->time_base,
|
||||
avctx->time_base) + t;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
t = parse_time_or_die("force_key_frames", p, 1);
|
||||
av_assert1(index < size);
|
||||
pts[index++] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
|
||||
|
||||
}
|
||||
|
||||
p = next;
|
||||
}
|
||||
|
||||
av_assert0(index == size);
|
||||
qsort(pts, size, sizeof(*pts), compare_int64);
|
||||
ost->forced_kf_count = size;
|
||||
ost->forced_kf_pts = pts;
|
||||
}
|
||||
|
||||
static void report_new_stream(int input_index, AVPacket *pkt)
|
||||
{
|
||||
InputFile *file = input_files[input_index];
|
||||
@ -3212,47 +3464,6 @@ static void report_new_stream(int input_index, AVPacket *pkt)
|
||||
file->nb_streams_warn = pkt->stream_index + 1;
|
||||
}
|
||||
|
||||
static void set_encoder_id(OutputFile *of, OutputStream *ost)
|
||||
{
|
||||
AVDictionaryEntry *e;
|
||||
|
||||
uint8_t *encoder_string;
|
||||
int encoder_string_len;
|
||||
int format_flags = 0;
|
||||
int codec_flags = 0;
|
||||
|
||||
if (av_dict_get(ost->st->metadata, "encoder", NULL, 0))
|
||||
return;
|
||||
|
||||
e = av_dict_get(of->opts, "fflags", NULL, 0);
|
||||
if (e) {
|
||||
const AVOption *o = av_opt_find(of->ctx, "fflags", NULL, 0, 0);
|
||||
if (!o)
|
||||
return;
|
||||
av_opt_eval_flags(of->ctx, o, e->value, &format_flags);
|
||||
}
|
||||
e = av_dict_get(ost->encoder_opts, "flags", NULL, 0);
|
||||
if (e) {
|
||||
const AVOption *o = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0);
|
||||
if (!o)
|
||||
return;
|
||||
av_opt_eval_flags(ost->enc_ctx, o, e->value, &codec_flags);
|
||||
}
|
||||
|
||||
encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(ost->enc->name) + 2;
|
||||
encoder_string = av_mallocz(encoder_string_len);
|
||||
if (!encoder_string)
|
||||
exit_program(1);
|
||||
|
||||
if (!(format_flags & AVFMT_FLAG_BITEXACT) && !(codec_flags & AV_CODEC_FLAG_BITEXACT))
|
||||
av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
|
||||
else
|
||||
av_strlcpy(encoder_string, "Lavc ", encoder_string_len);
|
||||
av_strlcat(encoder_string, ost->enc->name, encoder_string_len);
|
||||
av_dict_set(&ost->st->metadata, "encoder", encoder_string,
|
||||
AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
|
||||
}
|
||||
|
||||
static int transcode_init(void)
|
||||
{
|
||||
int ret = 0, i, j, k;
|
||||
@ -3284,41 +3495,11 @@ static int transcode_init(void)
|
||||
input_streams[j + ifile->ist_index]->start = av_gettime_relative();
|
||||
}
|
||||
|
||||
/* for each output stream, we compute the right encoding parameters */
|
||||
/* hwaccel transcoding */
|
||||
for (i = 0; i < nb_output_streams; i++) {
|
||||
ost = output_streams[i];
|
||||
oc = output_files[ost->file_index]->ctx;
|
||||
ist = get_input_stream(ost);
|
||||
|
||||
if (ost->attachment_filename)
|
||||
continue;
|
||||
|
||||
if (ist) {
|
||||
ost->st->disposition = ist->st->disposition;
|
||||
} else {
|
||||
for (j=0; j<oc->nb_streams; j++) {
|
||||
AVStream *st = oc->streams[j];
|
||||
if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type)
|
||||
break;
|
||||
}
|
||||
if (j == oc->nb_streams)
|
||||
if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ||
|
||||
ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
ost->st->disposition = AV_DISPOSITION_DEFAULT;
|
||||
}
|
||||
|
||||
if (!ost->stream_copy) {
|
||||
AVCodecContext *enc_ctx = ost->enc_ctx;
|
||||
AVCodecContext *dec_ctx = NULL;
|
||||
|
||||
set_encoder_id(output_files[ost->file_index], ost);
|
||||
|
||||
if (ist) {
|
||||
dec_ctx = ist->dec_ctx;
|
||||
|
||||
enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
|
||||
}
|
||||
|
||||
#if CONFIG_LIBMFX
|
||||
if (qsv_transcode_init(ost))
|
||||
exit_program(1);
|
||||
@ -3328,179 +3509,6 @@ static int transcode_init(void)
|
||||
if (cuvid_transcode_init(ost))
|
||||
exit_program(1);
|
||||
#endif
|
||||
|
||||
if ((enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
|
||||
enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
|
||||
filtergraph_is_simple(ost->filter->graph)) {
|
||||
FilterGraph *fg = ost->filter->graph;
|
||||
|
||||
if (dec_ctx) {
|
||||
ret = ifilter_parameters_from_decoder(fg->inputs[0],
|
||||
dec_ctx);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n");
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (configure_filtergraph(fg)) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
|
||||
exit_program(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (!ost->frame_rate.num)
|
||||
ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter);
|
||||
if (ist && !ost->frame_rate.num)
|
||||
ost->frame_rate = ist->framerate;
|
||||
if (ist && !ost->frame_rate.num)
|
||||
ost->frame_rate = ist->st->r_frame_rate;
|
||||
if (ist && !ost->frame_rate.num) {
|
||||
ost->frame_rate = (AVRational){25, 1};
|
||||
av_log(NULL, AV_LOG_WARNING,
|
||||
"No information "
|
||||
"about the input framerate is available. Falling "
|
||||
"back to a default value of 25fps for output stream #%d:%d. Use the -r option "
|
||||
"if you want a different framerate.\n",
|
||||
ost->file_index, ost->index);
|
||||
}
|
||||
// ost->frame_rate = ist->st->avg_frame_rate.num ? ist->st->avg_frame_rate : (AVRational){25, 1};
|
||||
if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
|
||||
int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
|
||||
ost->frame_rate = ost->enc->supported_framerates[idx];
|
||||
}
|
||||
// reduce frame rate for mpeg4 to be within the spec limits
|
||||
if (enc_ctx->codec_id == AV_CODEC_ID_MPEG4) {
|
||||
av_reduce(&ost->frame_rate.num, &ost->frame_rate.den,
|
||||
ost->frame_rate.num, ost->frame_rate.den, 65535);
|
||||
}
|
||||
}
|
||||
|
||||
switch (enc_ctx->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
|
||||
if (dec_ctx)
|
||||
enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample,
|
||||
av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3);
|
||||
enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
|
||||
enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout;
|
||||
enc_ctx->channels = avfilter_link_get_channels(ost->filter->filter->inputs[0]);
|
||||
enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
enc_ctx->time_base = av_inv_q(ost->frame_rate);
|
||||
if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
|
||||
enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base;
|
||||
if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
|
||||
&& (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
|
||||
av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
|
||||
"Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
|
||||
}
|
||||
for (j = 0; j < ost->forced_kf_count; j++)
|
||||
ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j],
|
||||
AV_TIME_BASE_Q,
|
||||
enc_ctx->time_base);
|
||||
|
||||
enc_ctx->width = ost->filter->filter->inputs[0]->w;
|
||||
enc_ctx->height = ost->filter->filter->inputs[0]->h;
|
||||
enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio =
|
||||
ost->frame_aspect_ratio.num ? // overridden by the -aspect cli option
|
||||
av_mul_q(ost->frame_aspect_ratio, (AVRational){ enc_ctx->height, enc_ctx->width }) :
|
||||
ost->filter->filter->inputs[0]->sample_aspect_ratio;
|
||||
if (!strncmp(ost->enc->name, "libx264", 7) &&
|
||||
enc_ctx->pix_fmt == AV_PIX_FMT_NONE &&
|
||||
ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P)
|
||||
av_log(NULL, AV_LOG_WARNING,
|
||||
"No pixel format specified, %s for H.264 encoding chosen.\n"
|
||||
"Use -pix_fmt yuv420p for compatibility with outdated media players.\n",
|
||||
av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format));
|
||||
if (!strncmp(ost->enc->name, "mpeg2video", 10) &&
|
||||
enc_ctx->pix_fmt == AV_PIX_FMT_NONE &&
|
||||
ost->filter->filter->inputs[0]->format != AV_PIX_FMT_YUV420P)
|
||||
av_log(NULL, AV_LOG_WARNING,
|
||||
"No pixel format specified, %s for MPEG-2 encoding chosen.\n"
|
||||
"Use -pix_fmt yuv420p for compatibility with outdated media players.\n",
|
||||
av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format));
|
||||
enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format;
|
||||
if (dec_ctx)
|
||||
enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample,
|
||||
av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth);
|
||||
|
||||
ost->st->avg_frame_rate = ost->frame_rate;
|
||||
|
||||
if (!dec_ctx ||
|
||||
enc_ctx->width != dec_ctx->width ||
|
||||
enc_ctx->height != dec_ctx->height ||
|
||||
enc_ctx->pix_fmt != dec_ctx->pix_fmt) {
|
||||
enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample;
|
||||
}
|
||||
|
||||
if (ost->forced_keyframes) {
|
||||
if (!strncmp(ost->forced_keyframes, "expr:", 5)) {
|
||||
ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5,
|
||||
forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Invalid force_key_frames expression '%s'\n", ost->forced_keyframes+5);
|
||||
return ret;
|
||||
}
|
||||
ost->forced_keyframes_expr_const_values[FKF_N] = 0;
|
||||
ost->forced_keyframes_expr_const_values[FKF_N_FORCED] = 0;
|
||||
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN;
|
||||
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN;
|
||||
|
||||
// Don't parse the 'forced_keyframes' in case of 'keep-source-keyframes',
|
||||
// parse it only for static kf timings
|
||||
} else if(strncmp(ost->forced_keyframes, "source", 6)) {
|
||||
parse_forced_key_frames(ost->forced_keyframes, ost, ost->enc_ctx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
enc_ctx->time_base = (AVRational){1, 1000};
|
||||
if (!enc_ctx->width) {
|
||||
enc_ctx->width = input_streams[ost->source_index]->st->codecpar->width;
|
||||
enc_ctx->height = input_streams[ost->source_index]->st->codecpar->height;
|
||||
}
|
||||
break;
|
||||
case AVMEDIA_TYPE_DATA:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ost->disposition) {
|
||||
static const AVOption opts[] = {
|
||||
{ "disposition" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
|
||||
{ "default" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "flags" },
|
||||
{ "dub" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "flags" },
|
||||
{ "original" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "flags" },
|
||||
{ "comment" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "flags" },
|
||||
{ "lyrics" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "flags" },
|
||||
{ "karaoke" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "flags" },
|
||||
{ "forced" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "flags" },
|
||||
{ "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" },
|
||||
{ "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" },
|
||||
{ "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" },
|
||||
{ "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" },
|
||||
{ "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" },
|
||||
{ "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" },
|
||||
{ NULL },
|
||||
};
|
||||
static const AVClass class = {
|
||||
.class_name = "",
|
||||
.item_name = av_default_item_name,
|
||||
.option = opts,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
const AVClass *pclass = &class;
|
||||
|
||||
ret = av_opt_eval_flags(&pclass, &opts[0], ost->disposition, &ost->st->disposition);
|
||||
if (ret < 0)
|
||||
goto dump_format;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user