mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
ffmpeg: replace custom channel_layout code with an SpecifierOpt based one
This is cleaner and allows fine tuning which stream the option is applied to. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
e6e86a3907
commit
bc99e3a9d6
@ -96,6 +96,8 @@ typedef struct OptionsContext {
|
|||||||
|
|
||||||
SpecifierOpt *codec_names;
|
SpecifierOpt *codec_names;
|
||||||
int nb_codec_names;
|
int nb_codec_names;
|
||||||
|
SpecifierOpt *audio_ch_layouts;
|
||||||
|
int nb_audio_ch_layouts;
|
||||||
SpecifierOpt *audio_channels;
|
SpecifierOpt *audio_channels;
|
||||||
int nb_audio_channels;
|
int nb_audio_channels;
|
||||||
SpecifierOpt *audio_sample_rate;
|
SpecifierOpt *audio_sample_rate;
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
|
|
||||||
static const char *const opt_name_codec_names[] = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL};
|
static const char *const opt_name_codec_names[] = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL};
|
||||||
static const char *const opt_name_audio_channels[] = {"ac", NULL};
|
static const char *const opt_name_audio_channels[] = {"ac", NULL};
|
||||||
|
static const char *const opt_name_audio_ch_layouts[] = {"channel_layout", NULL};
|
||||||
static const char *const opt_name_audio_sample_rate[] = {"ar", NULL};
|
static const char *const opt_name_audio_sample_rate[] = {"ar", NULL};
|
||||||
static const char *const opt_name_frame_rates[] = {"r", NULL};
|
static const char *const opt_name_frame_rates[] = {"r", NULL};
|
||||||
static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL};
|
static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL};
|
||||||
@ -1124,6 +1125,14 @@ static int open_input_file(OptionsContext *o, const char *filename)
|
|||||||
av_dict_set_int(&o->g->format_opts, "channels", o->audio_channels[o->nb_audio_channels - 1].u.i, 0);
|
av_dict_set_int(&o->g->format_opts, "channels", o->audio_channels[o->nb_audio_channels - 1].u.i, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (o->nb_audio_ch_layouts) {
|
||||||
|
const AVClass *priv_class;
|
||||||
|
if (file_iformat && (priv_class = file_iformat->priv_class) &&
|
||||||
|
av_opt_find(&priv_class, "ch_layout", NULL, 0,
|
||||||
|
AV_OPT_SEARCH_FAKE_OBJ)) {
|
||||||
|
av_dict_set(&o->g->format_opts, "ch_layout", o->audio_ch_layouts[o->nb_audio_ch_layouts - 1].u.str, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (o->nb_frame_rates) {
|
if (o->nb_frame_rates) {
|
||||||
const AVClass *priv_class;
|
const AVClass *priv_class;
|
||||||
/* set the format-level framerate option;
|
/* set the format-level framerate option;
|
||||||
@ -1946,6 +1955,7 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
|
|||||||
|
|
||||||
if (!ost->stream_copy) {
|
if (!ost->stream_copy) {
|
||||||
int channels = 0;
|
int channels = 0;
|
||||||
|
char *layout = NULL;
|
||||||
char *sample_fmt = NULL;
|
char *sample_fmt = NULL;
|
||||||
|
|
||||||
MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st);
|
MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st);
|
||||||
@ -1954,6 +1964,27 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
|
|||||||
audio_enc->ch_layout.nb_channels = channels;
|
audio_enc->ch_layout.nb_channels = channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st);
|
||||||
|
if (layout) {
|
||||||
|
if (av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) {
|
||||||
|
#if FF_API_OLD_CHANNEL_LAYOUT
|
||||||
|
uint64_t mask;
|
||||||
|
AV_NOWARN_DEPRECATED({
|
||||||
|
mask = av_get_channel_layout(layout);
|
||||||
|
})
|
||||||
|
if (!mask) {
|
||||||
|
#endif
|
||||||
|
av_log(NULL, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout);
|
||||||
|
exit_program(1);
|
||||||
|
#if FF_API_OLD_CHANNEL_LAYOUT
|
||||||
|
}
|
||||||
|
av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n",
|
||||||
|
layout);
|
||||||
|
av_channel_layout_from_mask(&audio_enc->ch_layout, mask);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st);
|
MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st);
|
||||||
if (sample_fmt &&
|
if (sample_fmt &&
|
||||||
(audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) {
|
(audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) {
|
||||||
@ -3235,54 +3266,6 @@ static int opt_timecode(void *optctx, const char *opt, const char *arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int opt_channel_layout(void *optctx, const char *opt, const char *arg)
|
|
||||||
{
|
|
||||||
OptionsContext *o = optctx;
|
|
||||||
char layout_str[32];
|
|
||||||
char *stream_str;
|
|
||||||
char *ac_str;
|
|
||||||
int ret, ac_str_size;
|
|
||||||
AVChannelLayout layout = { 0 };
|
|
||||||
|
|
||||||
ret = av_channel_layout_from_string(&layout, arg);
|
|
||||||
if (ret < 0) {
|
|
||||||
#if FF_API_OLD_CHANNEL_LAYOUT
|
|
||||||
uint64_t mask;
|
|
||||||
AV_NOWARN_DEPRECATED({
|
|
||||||
mask = av_get_channel_layout(arg);
|
|
||||||
})
|
|
||||||
if (!mask) {
|
|
||||||
#endif
|
|
||||||
av_log(NULL, AV_LOG_ERROR, "Unknown channel layout: %s\n", arg);
|
|
||||||
return AVERROR(EINVAL);
|
|
||||||
#if FF_API_OLD_CHANNEL_LAYOUT
|
|
||||||
}
|
|
||||||
av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n",
|
|
||||||
arg);
|
|
||||||
av_channel_layout_from_mask(&layout, mask);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = opt_default_new(o, opt, arg);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* set 'ac' option based on channel layout */
|
|
||||||
snprintf(layout_str, sizeof(layout_str), "%d", layout.nb_channels);
|
|
||||||
stream_str = strchr(opt, ':');
|
|
||||||
ac_str_size = 3 + (stream_str ? strlen(stream_str) : 0);
|
|
||||||
ac_str = av_mallocz(ac_str_size);
|
|
||||||
if (!ac_str)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
av_strlcpy(ac_str, "ac", 3);
|
|
||||||
if (stream_str)
|
|
||||||
av_strlcat(ac_str, stream_str, ac_str_size);
|
|
||||||
ret = parse_option(o, ac_str, layout_str, options);
|
|
||||||
av_free(ac_str);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int opt_audio_qscale(void *optctx, const char *opt, const char *arg)
|
static int opt_audio_qscale(void *optctx, const char *opt, const char *arg)
|
||||||
{
|
{
|
||||||
OptionsContext *o = optctx;
|
OptionsContext *o = optctx;
|
||||||
@ -3827,8 +3810,8 @@ const OptionDef options[] = {
|
|||||||
{ "sample_fmt", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC |
|
{ "sample_fmt", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC |
|
||||||
OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(sample_fmts) },
|
OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(sample_fmts) },
|
||||||
"set sample format", "format" },
|
"set sample format", "format" },
|
||||||
{ "channel_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE |
|
{ "channel_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC |
|
||||||
OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_channel_layout },
|
OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(audio_ch_layouts) },
|
||||||
"set channel layout", "layout" },
|
"set channel layout", "layout" },
|
||||||
{ "af", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_filters },
|
{ "af", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_filters },
|
||||||
"set audio filters", "filter_graph" },
|
"set audio filters", "filter_graph" },
|
||||||
|
Loading…
Reference in New Issue
Block a user