diff --git a/ffmpeg.c b/ffmpeg.c index a34862468d..bd7e6c1dfa 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -49,6 +49,7 @@ #include "libavutil/libm.h" #include "libavutil/imgutils.h" #include "libavutil/timestamp.h" +#include "libavutil/bprint.h" #include "libavformat/os_support.h" #include "libswresample/swresample.h" @@ -294,6 +295,10 @@ typedef struct OutputStream { int forced_kf_count; int forced_kf_index; + /* audio only */ + int audio_channels_map[SWR_CH_MAX]; /* list of the channels id to pick from the source stream */ + int audio_channels_mapped; /* number of channels in audio_channels_map */ + FILE *logfile; OutputFilter *filter; @@ -870,25 +875,46 @@ static int configure_audio_filters(FilterGraph *fg, AVFilterContext **in_filter, *out_filter = format; } - if (audio_volume != 256) { - AVFilterContext *volume; - char args[256]; +#define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \ + AVFilterContext *filt_ctx; \ + \ + av_log(NULL, AV_LOG_WARNING, opt_name " has been deprecated. " \ + "Use the " filter_name " filter instead " \ + "(-af " filter_name "=%s).\n", arg); \ + \ + ret = avfilter_graph_create_filter(&filt_ctx, \ + avfilter_get_by_name(filter_name), \ + filter_name, arg, NULL, fg->graph); \ + if (ret < 0) \ + return ret; \ + \ + ret = avfilter_link(*in_filter, 0, filt_ctx, 0); \ + if (ret < 0) \ + return ret; \ + \ + *in_filter = filt_ctx; \ +} while (0) + + if (ost->audio_channels_mapped) { + int i; + AVBPrint pan_buf; - snprintf(args, sizeof(args), "%lf", audio_volume / 256.); - av_log(NULL, AV_LOG_WARNING, "-vol has been deprecated. Used the " - "volume audio filter instead (-af volume=%s).\n", args); + av_bprint_init(&pan_buf, 256, 8192); + av_bprintf(&pan_buf, "0x%"PRIx64, + av_get_default_channel_layout(ost->audio_channels_mapped)); + for (i = 0; i < ost->audio_channels_mapped; i++) + if (ost->audio_channels_map[i] != -1) + av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]); - ret = avfilter_graph_create_filter(&volume, - avfilter_get_by_name("volume"), - "volume", args, NULL, fg->graph); - if (ret < 0) - return ret; + AUTO_INSERT_FILTER("-map_channel", "pan", pan_buf.str); + av_bprint_finalize(&pan_buf, NULL); + } - ret = avfilter_link(*in_filter, 0, volume, 0); - if (ret < 0) - return ret; + if (audio_volume != 256) { + char args[256]; - *in_filter = volume; + snprintf(args, sizeof(args), "%lf", audio_volume / 256.); + AUTO_INSERT_FILTER("-vol", "volume", args); } return 0; @@ -4629,6 +4655,21 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); if (filters) ost->avfilter = av_strdup(filters); + + /* check for channel mapping for this audio stream */ + for (n = 0; n < o->nb_audio_channel_maps; n++) { + AudioChannelMap *map = &o->audio_channel_maps[n]; + InputStream *ist = input_streams[ost->source_index]; + if ((map->channel_idx == -1 || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) && + (map->ofile_idx == -1 || ost->file_index == map->ofile_idx) && + (map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) { + if (ost->audio_channels_mapped < FF_ARRAY_ELEMS(ost->audio_channels_map)) + ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx; + else + av_log(NULL, AV_LOG_FATAL, "Max channel mapping for output %d.%d reached\n", + ost->file_index, ost->st->index); + } + } } return ost; diff --git a/tests/Makefile b/tests/Makefile index 854419389e..a724e06db5 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -55,7 +55,7 @@ include $(SRC_PATH)/tests/fate/image.mak include $(SRC_PATH)/tests/fate/indeo.mak include $(SRC_PATH)/tests/fate/libavcodec.mak include $(SRC_PATH)/tests/fate/libavutil.mak -#include $(SRC_PATH)/tests/fate/mapchan.mak +include $(SRC_PATH)/tests/fate/mapchan.mak include $(SRC_PATH)/tests/fate/lossless-audio.mak include $(SRC_PATH)/tests/fate/lossless-video.mak include $(SRC_PATH)/tests/fate/microsoft.mak