|
@@ -70,11 +70,14 @@ static int choose_encoder(const OptionsContext *o, AVFormatContext *s,
|
|
|
OutputStream *ost, const AVCodec **enc)
|
|
|
{
|
|
|
enum AVMediaType type = ost->type;
|
|
|
- char *codec_name = NULL;
|
|
|
+ const char *codec_name = NULL;
|
|
|
+ int ret;
|
|
|
|
|
|
*enc = NULL;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->codec_names, s, ost->st, &codec_name);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
|
|
|
if (type != AVMEDIA_TYPE_VIDEO &&
|
|
|
type != AVMEDIA_TYPE_AUDIO &&
|
|
@@ -416,12 +419,17 @@ static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc,
|
|
|
OutputStream *ost, char **dst)
|
|
|
{
|
|
|
const char *filters = NULL;
|
|
|
+ int ret;
|
|
|
#if FFMPEG_OPT_FILTER_SCRIPT
|
|
|
const char *filters_script = NULL;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(filter_scripts, str, filters_script, oc, ost->st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->filter_scripts, oc, ost->st, &filters_script);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
#endif
|
|
|
- MATCH_PER_STREAM_OPT(filters, str, filters, oc, ost->st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->filters, oc, ost->st, &filters);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
|
|
|
if (!ost->enc) {
|
|
|
if (
|
|
@@ -586,18 +594,22 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
MuxStream *ms = ms_from_ost(ost);
|
|
|
AVFormatContext *oc = mux->fc;
|
|
|
AVStream *st;
|
|
|
- char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL;
|
|
|
+ const char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL;
|
|
|
int ret = 0;
|
|
|
|
|
|
st = ost->st;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->frame_rates, oc, st, &frame_rate);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) {
|
|
|
av_log(ost, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
|
|
|
return AVERROR(EINVAL);
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->max_frame_rates, oc, st, &max_frame_rate);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) {
|
|
|
av_log(ost, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate);
|
|
|
return AVERROR(EINVAL);
|
|
@@ -608,7 +620,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
return AVERROR(EINVAL);
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->frame_aspect_ratios, oc, st, &frame_aspect_ratio);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (frame_aspect_ratio) {
|
|
|
AVRational q;
|
|
|
if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 ||
|
|
@@ -622,14 +636,16 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
if (ost->enc_ctx) {
|
|
|
AVCodecContext *video_enc = ost->enc_ctx;
|
|
|
const char *p = NULL, *fps_mode = NULL;
|
|
|
- char *frame_size = NULL;
|
|
|
- char *frame_pix_fmt = NULL;
|
|
|
- char *intra_matrix = NULL, *inter_matrix = NULL;
|
|
|
- char *chroma_intra_matrix = NULL;
|
|
|
+ const char *frame_size = NULL;
|
|
|
+ const char *frame_pix_fmt = NULL;
|
|
|
+ const char *intra_matrix = NULL, *inter_matrix = NULL;
|
|
|
+ const char *chroma_intra_matrix = NULL;
|
|
|
int do_pass = 0;
|
|
|
int i;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->frame_sizes, oc, st, &frame_size);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (frame_size) {
|
|
|
ret = av_parse_video_size(&video_enc->width, &video_enc->height, frame_size);
|
|
|
if (ret < 0) {
|
|
@@ -638,7 +654,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->frame_pix_fmts, oc, st, &frame_pix_fmt);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (frame_pix_fmt && *frame_pix_fmt == '+') {
|
|
|
*keep_pix_fmt = 1;
|
|
|
if (!*++frame_pix_fmt)
|
|
@@ -650,7 +668,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
return AVERROR(EINVAL);
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->intra_matrices, oc, st, &intra_matrix);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (intra_matrix) {
|
|
|
if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64)))
|
|
|
return AVERROR(ENOMEM);
|
|
@@ -659,7 +679,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
}
|
|
|
- MATCH_PER_STREAM_OPT(chroma_intra_matrices, str, chroma_intra_matrix, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->chroma_intra_matrices, oc, st, &chroma_intra_matrix);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (chroma_intra_matrix) {
|
|
|
uint16_t *p = av_mallocz(sizeof(*video_enc->chroma_intra_matrix) * 64);
|
|
|
if (!p)
|
|
@@ -669,7 +691,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
}
|
|
|
- MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->inter_matrices, oc, st, &inter_matrix);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (inter_matrix) {
|
|
|
if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64)))
|
|
|
return AVERROR(ENOMEM);
|
|
@@ -678,7 +702,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->rc_overrides, oc, st, &p);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
for (i = 0; p; i++) {
|
|
|
int start, end, q;
|
|
|
int e = sscanf(p, "%d,%d,%d", &start, &end, &q);
|
|
@@ -717,7 +743,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
video_enc->flags |= AV_CODEC_FLAG_PASS2;
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->passlogfiles, oc, st, &ost->logfile_prefix);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (ost->logfile_prefix &&
|
|
|
!(ost->logfile_prefix = av_strdup(ost->logfile_prefix)))
|
|
|
return AVERROR(ENOMEM);
|
|
@@ -778,7 +806,9 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
|
|
|
#else
|
|
|
*vsync_method = VSYNC_AUTO;
|
|
|
#endif
|
|
|
- MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->fps_mode, oc, st, &fps_mode);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (fps_mode) {
|
|
|
ret = parse_and_set_vsync(fps_mode, vsync_method, ost->file->index, ost->index, 0);
|
|
|
if (ret < 0)
|
|
@@ -834,8 +864,9 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
|
|
|
if (ost->enc_ctx) {
|
|
|
AVCodecContext *audio_enc = ost->enc_ctx;
|
|
|
int channels = 0;
|
|
|
- char *layout = NULL;
|
|
|
- char *sample_fmt = NULL;
|
|
|
+ const char *layout = NULL;
|
|
|
+ const char *sample_fmt = NULL;
|
|
|
+ int ret;
|
|
|
|
|
|
MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st);
|
|
|
if (channels) {
|
|
@@ -843,13 +874,17 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
|
|
|
audio_enc->ch_layout.nb_channels = channels;
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->audio_ch_layouts, oc, st, &layout);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (layout && av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) {
|
|
|
av_log(ost, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout);
|
|
|
return AVERROR(EINVAL);
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->sample_fmts, oc, st, &sample_fmt);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (sample_fmt &&
|
|
|
(audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) {
|
|
|
av_log(ost, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt);
|
|
@@ -858,7 +893,9 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
|
|
|
|
|
|
MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(apad, str, ms->apad, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->apad, oc, st, &ms->apad);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -880,9 +917,12 @@ static int new_stream_subtitle(Muxer *mux, const OptionsContext *o,
|
|
|
avcodec_descriptor_get(subtitle_enc->codec_id);
|
|
|
int input_props = 0, output_props = 0;
|
|
|
|
|
|
- char *frame_size = NULL;
|
|
|
+ const char *frame_size = NULL;
|
|
|
+ int ret;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, mux->fc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->frame_sizes, mux->fc, st, &frame_size);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (frame_size) {
|
|
|
int ret = av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size);
|
|
|
if (ret < 0) {
|
|
@@ -1039,8 +1079,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|
|
int threads_manual = 0;
|
|
|
AVRational enc_tb = { 0, 0 };
|
|
|
enum VideoSyncMethod vsync_method = VSYNC_AUTO;
|
|
|
- const char *bsfs = NULL, *time_base = NULL;
|
|
|
- char *filters = NULL, *next, *codec_tag = NULL;
|
|
|
+ const char *bsfs = NULL, *time_base = NULL, *codec_tag = NULL;
|
|
|
+ char *filters = NULL, *next;
|
|
|
double qscale = -1;
|
|
|
|
|
|
st = avformat_new_stream(oc, NULL);
|
|
@@ -1151,9 +1191,9 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|
|
if (ost->enc_ctx) {
|
|
|
AVCodecContext *enc = ost->enc_ctx;
|
|
|
AVIOContext *s = NULL;
|
|
|
- char *buf = NULL, *arg = NULL, *preset = NULL;
|
|
|
+ char *buf = NULL, *arg = NULL;
|
|
|
const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL;
|
|
|
- const char *enc_time_base = NULL;
|
|
|
+ const char *enc_time_base = NULL, *preset = NULL;
|
|
|
|
|
|
ret = filter_codec_opts(o->g->codec_opts, enc->codec_id,
|
|
|
oc, st, enc->codec, &encoder_opts,
|
|
@@ -1161,7 +1201,9 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|
|
if (ret < 0)
|
|
|
goto fail;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->presets, oc, st, &preset);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
|
|
|
MATCH_PER_STREAM_OPT(autoscale, i, autoscale, oc, st);
|
|
|
if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) {
|
|
@@ -1194,43 +1236,57 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->enc_stats_pre, oc, st, &enc_stats_pre);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
if (enc_stats_pre &&
|
|
|
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
|
|
|
const char *format = "{fidx} {sidx} {n} {t}";
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->enc_stats_pre_fmt, oc, st, &format);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
|
|
|
ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format);
|
|
|
if (ret < 0)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->enc_stats_post, oc, st, &enc_stats_post);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
if (enc_stats_post &&
|
|
|
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
|
|
|
const char *format = "{fidx} {sidx} {n} {t}";
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->enc_stats_post_fmt, oc, st, &format);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
|
|
|
ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format);
|
|
|
if (ret < 0)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->mux_stats, oc, st, &mux_stats);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
if (mux_stats &&
|
|
|
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
|
|
|
const char *format = "{fidx} {sidx} {n} {t}";
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->mux_stats_fmt, oc, st, &format);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
|
|
|
ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format);
|
|
|
if (ret < 0)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->enc_time_bases, oc, st, &enc_time_base);
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
if (enc_time_base && type == AVMEDIA_TYPE_SUBTITLE)
|
|
|
av_log(ost, AV_LOG_WARNING,
|
|
|
"-enc_time_base not supported for subtitles, ignoring\n");
|
|
@@ -1293,7 +1349,9 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|
|
ost->bitexact = !!(ost->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT);
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->time_bases, oc, st, &time_base);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (time_base) {
|
|
|
AVRational q;
|
|
|
if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
|
|
@@ -1318,7 +1376,9 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|
|
ms->copy_prior_start = -1;
|
|
|
MATCH_PER_STREAM_OPT(copy_prior_start, i, ms->copy_prior_start, oc ,st);
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->bitstream_filters, oc, st, &bsfs);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (bsfs && *bsfs) {
|
|
|
ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx);
|
|
|
if (ret < 0) {
|
|
@@ -1327,7 +1387,9 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->codec_tags, oc, st, &codec_tag);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
if (codec_tag) {
|
|
|
uint32_t tag = strtol(codec_tag, &next, 0);
|
|
|
if (*next) {
|
|
@@ -2943,7 +3005,9 @@ static int set_dispositions(Muxer *mux, const OptionsContext *o)
|
|
|
|
|
|
nb_streams[ost->type + 1]++;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT_CLEAN(disposition, str, dispositions[i], ctx, ost->st, goto finish);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->disposition, ctx, ost->st, &dispositions[i]);
|
|
|
+ if (ret < 0)
|
|
|
+ goto finish;
|
|
|
|
|
|
have_manual |= !!dispositions[i];
|
|
|
|
|
@@ -3088,8 +3152,12 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o)
|
|
|
for (int i = 0; i < mux->of.nb_streams; i++) {
|
|
|
OutputStream *ost = mux->of.streams[i];
|
|
|
const char *forced_keyframes = NULL;
|
|
|
+ int ret;
|
|
|
|
|
|
- MATCH_PER_STREAM_OPT(forced_key_frames, str, forced_keyframes, mux->fc, ost->st);
|
|
|
+ ret = opt_match_per_stream_str(ost, &o->forced_key_frames,
|
|
|
+ mux->fc, ost->st, &forced_keyframes);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
|
|
|
if (!(ost->type == AVMEDIA_TYPE_VIDEO &&
|
|
|
ost->enc_ctx && forced_keyframes))
|