1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-11-23 21:54:53 +02:00

fftools/ffmpeg: replace MATCH_PER_STREAM_OPT(.., str, ..) with a function

This has multiple advantages:
* The macro has multiple parameters that often have similar or identical
  values, yet very different meanings (one is the name of the
  OptionsContext member where the parsed options are stored, the other
  the name of the variable into which the result is written); this
  change makes each of these explicit.

* The macro returns on failure, which may cause leaks - this was the
  reason for adding MATCH_PER_STREAM_OPT_CLEAN(), also ost_add()
  currently leaks encoder_opts. The new function returns failure to its
  caller, which decides how to deal with it. While that adds a lot of
  error checks/forwards for now, those will be reduced in following
  commits.

* new code is type- and const- correct

Invocations of MATCH_PER_STREAM_OPT() with other types will be converted
in following commits.
This commit is contained in:
Anton Khirnov
2024-08-06 11:11:41 +02:00
parent 82085a3e0a
commit e218bde9f9
7 changed files with 242 additions and 70 deletions

View File

@@ -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))