summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/decode/ad_lavc.c18
-rw-r--r--audio/decode/ad_mpg123.c2
-rw-r--r--audio/decode/ad_spdif.c17
-rw-r--r--audio/decode/dec_audio.c18
-rw-r--r--core/cfg-mplayer.h2
-rw-r--r--core/command.c14
-rw-r--r--core/defaultopts.c3
-rw-r--r--core/m_option.h2
-rw-r--r--core/mplayer.c7
-rw-r--r--core/options.h2
-rw-r--r--demux/demux_lavf.c4
-rw-r--r--demux/demux_mkv.c6
-rw-r--r--demux/demux_rawaudio.c13
-rw-r--r--demux/stheader.h5
-rw-r--r--stream/tv.c10
15 files changed, 69 insertions, 54 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 8177d9cde6..4997a66bc4 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -168,10 +168,16 @@ static int setup_format(sh_audio_t *sh_audio,
else if (container_samplerate)
samplerate = container_samplerate;
- if (lavc_context->channels != sh_audio->channels ||
+ struct mp_chmap lavc_chmap;
+ mp_chmap_from_lavc(&lavc_chmap, lavc_context->channel_layout);
+ // No channel layout or layout disagrees with channel count
+ if (lavc_chmap.num != lavc_context->channels)
+ mp_chmap_from_channels(&lavc_chmap, lavc_context->channels);
+
+ if (!mp_chmap_equals(&lavc_chmap, &sh_audio->channels) ||
samplerate != sh_audio->samplerate ||
sample_format != sh_audio->sample_format) {
- sh_audio->channels = lavc_context->channels;
+ sh_audio->channels = lavc_chmap;
sh_audio->samplerate = samplerate;
sh_audio->sample_format = sample_format;
sh_audio->samplesize = af_fmt2bits(sh_audio->sample_format) / 8;
@@ -227,8 +233,11 @@ static int init(sh_audio_t *sh_audio, const char *decoder)
lavc_context->codec_type = AVMEDIA_TYPE_AUDIO;
lavc_context->codec_id = lavc_codec->id;
- if (opts->downmix)
- lavc_context->request_channels = mpopts->audio_output_channels;
+ if (opts->downmix) {
+ lavc_context->request_channels = mpopts->audio_output_channels.num;
+ lavc_context->request_channel_layout =
+ mp_chmap_to_lavc(&mpopts->audio_output_channels);
+ }
// Always try to set - option only exists for AC3 at the moment
av_opt_set_double(lavc_context, "drc_scale", opts->ac3drc,
@@ -246,6 +255,7 @@ static int init(sh_audio_t *sh_audio, const char *decoder)
lavc_context->codec_tag = sh_audio->format;
lavc_context->sample_rate = sh_audio->samplerate;
lavc_context->bit_rate = sh_audio->i_bps * 8;
+ lavc_context->channel_layout = mp_chmap_to_lavc(&sh_audio->channels);
if (sh_audio->wf)
set_from_wf(lavc_context, sh_audio->wf);
diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c
index 999dc2fbba..45538f42f6 100644
--- a/audio/decode/ad_mpg123.c
+++ b/audio/decode/ad_mpg123.c
@@ -358,7 +358,7 @@ static int init(sh_audio_t *sh, const char *decoder)
con->mean_count = 0;
#endif
con->vbr = (finfo.vbr != MPG123_CBR);
- sh->channels = channels;
+ mp_chmap_from_channels(&sh->channels, channels);
sh->samplerate = rate;
/* Without external force, mpg123 will always choose signed encoding,
* and non-16-bit only on builds that don't support it.
diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
index ad735dde7d..a6f41932e9 100644
--- a/audio/decode/ad_spdif.c
+++ b/audio/decode/ad_spdif.c
@@ -148,19 +148,20 @@ static int init(sh_audio_t *sh, const char *decoder)
}
sh->ds->buffer_pos -= in_size;
+ int num_channels = 0;
switch (lavf_ctx->streams[0]->codec->codec_id) {
case AV_CODEC_ID_AAC:
spdif_ctx->iec61937_packet_size = 16384;
sh->sample_format = AF_FORMAT_IEC61937_LE;
sh->samplerate = srate;
- sh->channels = 2;
+ num_channels = 2;
sh->i_bps = bps;
break;
case AV_CODEC_ID_AC3:
spdif_ctx->iec61937_packet_size = 6144;
sh->sample_format = AF_FORMAT_AC3_LE;
sh->samplerate = srate;
- sh->channels = 2;
+ num_channels = 2;
sh->i_bps = bps;
break;
case AV_CODEC_ID_DTS:
@@ -175,13 +176,13 @@ static int init(sh_audio_t *sh, const char *decoder)
spdif_ctx->iec61937_packet_size = 32768;
sh->sample_format = AF_FORMAT_IEC61937_LE;
sh->samplerate = 192000; // DTS core require 48000
- sh->channels = 2*4;
+ num_channels = 2*4;
sh->i_bps = bps;
} else {
spdif_ctx->iec61937_packet_size = 32768;
sh->sample_format = AF_FORMAT_AC3_LE;
sh->samplerate = srate;
- sh->channels = 2;
+ num_channels = 2;
sh->i_bps = bps;
}
break;
@@ -189,26 +190,28 @@ static int init(sh_audio_t *sh, const char *decoder)
spdif_ctx->iec61937_packet_size = 24576;
sh->sample_format = AF_FORMAT_IEC61937_LE;
sh->samplerate = 192000;
- sh->channels = 2;
+ num_channels = 2;
sh->i_bps = bps;
break;
case AV_CODEC_ID_MP3:
spdif_ctx->iec61937_packet_size = 4608;
sh->sample_format = AF_FORMAT_MPEG2;
sh->samplerate = srate;
- sh->channels = 2;
+ num_channels = 2;
sh->i_bps = bps;
break;
case AV_CODEC_ID_TRUEHD:
spdif_ctx->iec61937_packet_size = 61440;
sh->sample_format = AF_FORMAT_IEC61937_LE;
sh->samplerate = 192000;
- sh->channels = 8;
+ num_channels = 8;
sh->i_bps = bps;
break;
default:
break;
}
+ if (num_channels)
+ mp_chmap_from_channels(&sh->channels, num_channels);
return 1;
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c
index 11232f9271..999a96a10b 100644
--- a/audio/decode/dec_audio.c
+++ b/audio/decode/dec_audio.c
@@ -86,7 +86,7 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder)
sh_audio->initialized = 1;
- if (!sh_audio->channels || !sh_audio->samplerate) {
+ if (mp_chmap_is_empty(&sh_audio->channels) || !sh_audio->samplerate) {
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder did not specify "
"audio format!\n");
uninit_audio(sh_audio); // free buffers
@@ -94,7 +94,7 @@ static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder)
}
if (!sh_audio->o_bps)
- sh_audio->o_bps = sh_audio->channels * sh_audio->samplerate
+ sh_audio->o_bps = sh_audio->channels.num * sh_audio->samplerate
* sh_audio->samplesize;
return 1;
}
@@ -160,14 +160,14 @@ int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders)
sh_audio->gsh->decoder_desc);
mp_msg(MSGT_DECAUDIO, MSGL_V,
"AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n",
- sh_audio->samplerate, sh_audio->channels,
+ sh_audio->samplerate, sh_audio->channels.num,
af_fmt2str_short(sh_audio->sample_format),
sh_audio->i_bps * 8 * 0.001,
((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0,
sh_audio->i_bps, sh_audio->o_bps);
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
"ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n",
- sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels);
+ sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels.num);
} else {
mp_msg(MSGT_DECAUDIO, MSGL_ERR,
"Failed to initialize an audio decoder for codec '%s'.\n",
@@ -207,7 +207,7 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate,
afs = af_new(sh_audio->opts);
// input format: same as codec's output format:
afs->input.rate = in_samplerate;
- mp_audio_set_num_channels(&afs->input, sh_audio->channels);
+ mp_audio_set_channels(&afs->input, &sh_audio->channels);
mp_audio_set_format(&afs->input, sh_audio->sample_format);
// output format: same as ao driver's input format (if missing, fallback to input)
@@ -259,7 +259,7 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len)
// Decode more bytes if needed
int old_samplerate = sh->samplerate;
- int old_channels = sh->channels;
+ struct mp_chmap old_channels = sh->channels;
int old_sample_format = sh->sample_format;
while (sh->a_buffer_len < len) {
unsigned char *buf = sh->a_buffer + sh->a_buffer_len;
@@ -267,7 +267,7 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len)
int maxlen = sh->a_buffer_size - sh->a_buffer_len;
int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen);
int format_change = sh->samplerate != old_samplerate
- || sh->channels != old_channels
+ || !mp_chmap_equals(&sh->channels, &old_channels)
|| sh->sample_format != old_sample_format;
if (ret <= 0 || format_change) {
error = format_change ? -2 : -1;
@@ -285,7 +285,7 @@ static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len)
.rate = sh->samplerate,
};
mp_audio_set_format(&filter_input, sh->sample_format);
- mp_audio_set_num_channels(&filter_input, sh->channels);
+ mp_audio_set_channels(&filter_input, &sh->channels);
struct mp_audio *filter_output = af_play(sh->afilter, &filter_input);
if (!filter_output)
@@ -314,7 +314,7 @@ int decode_audio(sh_audio_t *sh_audio, struct bstr *outbuf, int minlen)
// Indicates that a filter seems to be buffering large amounts of data
int huge_filter_buffer = 0;
// Decoded audio must be cut at boundaries of this many bytes
- int unitsize = sh_audio->channels * sh_audio->samplesize * 16;
+ int unitsize = sh_audio->channels.num * sh_audio->samplesize * 16;
/* Filter output size will be about filter_multiplier times input size.
* If some filter buffers audio in big blocks this might only hold
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index 6e776f6598..5994f24056 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -415,7 +415,7 @@ const m_option_t common_opts[] = {
// force video/audio rate:
OPT_DOUBLE("fps", force_fps, CONF_MIN, 0),
OPT_INTRANGE("srate", force_srate, 0, 1000, 8*48000),
- OPT_INTRANGE("channels", audio_output_channels, 0, 1, 8),
+ OPT_CHMAP("channels", audio_output_channels, CONF_MIN, .min = 1),
OPT_AUDIOFORMAT("format", audio_output_format, 0),
OPT_FLOATRANGE("speed", playback_speed, 0, 0.01, 100.0),
diff --git a/core/command.c b/core/command.c
index 641dfb80e0..115ea9236f 100644
--- a/core/command.c
+++ b/core/command.c
@@ -667,20 +667,10 @@ static int mp_property_channels(m_option_t *prop, int action, void *arg,
return M_PROPERTY_UNAVAILABLE;
switch (action) {
case M_PROPERTY_PRINT:
- switch (mpctx->sh_audio->channels) {
- case 1:
- *(char **) arg = talloc_strdup(NULL, "mono");
- break;
- case 2:
- *(char **) arg = talloc_strdup(NULL, "stereo");
- break;
- default:
- *(char **) arg = talloc_asprintf(NULL, "%d channels",
- mpctx->sh_audio->channels);
- }
+ *(char **) arg = mp_chmap_to_str(&mpctx->sh_audio->channels);
return M_PROPERTY_OK;
case M_PROPERTY_GET:
- *(int *)arg = mpctx->sh_audio->channels;
+ *(int *)arg = mpctx->sh_audio->channels.num;
return M_PROPERTY_OK;
}
return M_PROPERTY_NOT_IMPLEMENTED;
diff --git a/core/defaultopts.c b/core/defaultopts.c
index 75a3b8d226..f1778f2fff 100644
--- a/core/defaultopts.c
+++ b/core/defaultopts.c
@@ -4,6 +4,7 @@
#include "defaultopts.h"
#include "core/options.h"
#include "audio/mixer.h"
+#include "audio/chmap.h"
void set_default_mplayer_options(struct MPOpts *opts)
{
@@ -71,7 +72,7 @@ void set_default_mplayer_options(struct MPOpts *opts)
.audio_display = 1,
.sub_visibility = 1,
.extension_parsing = 1,
- .audio_output_channels = 2,
+ .audio_output_channels = MP_CHMAP_INIT_STEREO,
.audio_output_format = -1, // AF_FORMAT_UNKNOWN
.playback_speed = 1.,
.movie_aspect = -1.,
diff --git a/core/m_option.h b/core/m_option.h
index 66e7208801..e365b3eedc 100644
--- a/core/m_option.h
+++ b/core/m_option.h
@@ -25,6 +25,7 @@
#include "config.h"
#include "core/bstr.h"
+#include "audio/chmap.h"
// m_option allows to parse, print and copy data of various types.
@@ -210,6 +211,7 @@ union m_option_value {
struct m_color color;
struct m_geometry geometry;
struct m_geometry size_box;
+ struct mp_chmap chmap;
};
////////////////////////////////////////////////////////////////////////////
diff --git a/core/mplayer.c b/core/mplayer.c
index 3f7df8ef36..665216921e 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -324,7 +324,7 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename)
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
"ID_AUDIO_RATE=%d\n", mpctx->sh_audio->samplerate);
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
- "ID_AUDIO_NCH=%d\n", mpctx->sh_audio->channels);
+ "ID_AUDIO_NCH=%d\n", mpctx->sh_audio->channels.num);
start_pts = ds_get_next_pts(mpctx->sh_audio->ds);
}
if (video_start_pts != MP_NOPTS_VALUE) {
@@ -1563,8 +1563,11 @@ void reinit_audio_chain(struct MPContext *mpctx)
mpctx->ao->samplerate = opts->force_srate;
mpctx->ao->format = opts->audio_output_format;
// Automatic downmix
- if (opts->audio_output_channels == 2 && mpctx->sh_audio->channels != 2)
+ if (mp_chmap_is_stereo(&opts->audio_output_channels) &&
+ !mp_chmap_is_stereo(&mpctx->sh_audio->channels))
+ {
mp_chmap_from_channels(&mpctx->ao->channels, 2);
+ }
}
ao = mpctx->ao;
diff --git a/core/options.h b/core/options.h
index e72778dbde..2af8479316 100644
--- a/core/options.h
+++ b/core/options.h
@@ -150,7 +150,7 @@ typedef struct MPOpts {
double force_fps;
- int audio_output_channels;
+ struct mp_chmap audio_output_channels;
int audio_output_format;
int force_srate;
int dtshd;
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index ba34e7acfa..9bfafe3257 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -341,7 +341,9 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
sh_audio->format = codec->codec_tag;
// probably unneeded
- sh_audio->channels = codec->channels;
+ mp_chmap_from_channels(&sh_audio->channels, codec->channels);
+ if (codec->channel_layout)
+ mp_chmap_from_lavc(&sh_audio->channels, codec->channel_layout);
sh_audio->samplerate = codec->sample_rate;
sh_audio->i_bps = codec->bit_rate / 8;
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index ee39038c77..4452aa9929 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -1393,7 +1393,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track,
sh_a->format = track->a_formattag;
sh_a->wf->wFormatTag = track->a_formattag;
- sh_a->channels = track->a_channels;
+ mp_chmap_from_channels(&sh_a->channels, track->a_channels);
sh_a->wf->nChannels = track->a_channels;
sh_a->samplerate = (uint32_t) track->a_sfreq;
sh_a->container_out_samplerate = track->a_osfreq;
@@ -1411,7 +1411,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track,
free(sh_a->wf);
sh_a->wf = NULL;
} else if (track->a_formattag == 0x0001) { /* PCM || PCM_BE */
- sh_a->wf->nAvgBytesPerSec = sh_a->channels * sh_a->samplerate * 2;
+ sh_a->wf->nAvgBytesPerSec = sh_a->channels.num * sh_a->samplerate * 2;
sh_a->wf->nBlockAlign = sh_a->wf->nAvgBytesPerSec;
if (!strcmp(track->codec_id, MKV_A_PCM_BE))
sh_a->format = mmioFOURCC('t', 'w', 'o', 's');
@@ -1583,7 +1583,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track,
char *data = sh_a->codecdata;
memcpy(data + 0, "TTA1", 4);
AV_WL16(data + 4, 1);
- AV_WL16(data + 6, sh_a->channels);
+ AV_WL16(data + 6, sh_a->channels.num);
AV_WL16(data + 8, sh_a->wf->wBitsPerSample);
AV_WL32(data + 10, sh_a->samplerate);
// Bogus: last frame won't be played.
diff --git a/demux/demux_rawaudio.c b/demux/demux_rawaudio.c
index c6aad60806..3cd2500e03 100644
--- a/demux/demux_rawaudio.c
+++ b/demux/demux_rawaudio.c
@@ -31,12 +31,12 @@
#include "audio/format.h"
-static int channels = 2;
+static struct mp_chmap channels = MP_CHMAP_INIT_STEREO;
static int samplerate = 44100;
static int format = AF_FORMAT_S16_NE;
const m_option_t demux_rawaudio_opts[] = {
- { "channels", &channels, CONF_TYPE_INT,CONF_RANGE,1,8, NULL },
+ { "channels", &channels, &m_option_type_chmap, CONF_MIN, 1 },
{ "rate", &samplerate, CONF_TYPE_INT,CONF_RANGE,1000,8*48000, NULL },
{ "format", &format, CONF_TYPE_AFMT, 0, 0, 0, NULL },
{NULL, NULL, 0, 0, 0, 0, NULL}
@@ -55,11 +55,12 @@ static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) {
sh_audio->format = format;
sh_audio->wf = w = malloc(sizeof(*w));
w->wFormatTag = 0;
- w->nChannels = sh_audio->channels = channels;
+ sh_audio->channels = channels;
+ w->nChannels = sh_audio->channels.num;
w->nSamplesPerSec = sh_audio->samplerate = samplerate;
int samplesize = (af_fmt2bits(format) + 7) / 8;
- w->nAvgBytesPerSec = samplerate * samplesize * channels;
- w->nBlockAlign = channels * samplesize;
+ w->nAvgBytesPerSec = samplerate * samplesize * w->nChannels;
+ w->nBlockAlign = w->nChannels * samplesize;
w->wBitsPerSample = 8 * samplesize;
w->cbSize = 0;
@@ -105,7 +106,7 @@ static void demux_rawaudio_seek(demuxer_t *demuxer,float rel_seek_secs,float aud
else
pos = base + (rel_seek_secs*sh_audio->i_bps);
- pos -= (pos % (sh_audio->channels * sh_audio->samplesize) );
+ pos -= (pos % (sh_audio->channels.num * sh_audio->samplesize) );
stream_seek(s,pos);
// printf("demux_rawaudio: streamtell=%d\n",(int)stream_tell(demuxer->stream));
}
diff --git a/demux/stheader.h b/demux/stheader.h
index 8d1822c99f..488d94c114 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -23,6 +23,7 @@
#include "codec_tags.h"
+#include "audio/chmap.h"
#include "aviheader.h"
#include "ms_hdr.h"
struct MPOpts;
@@ -108,8 +109,8 @@ typedef struct sh_audio {
int samplerate;
int container_out_samplerate;
int samplesize;
- int channels;
- int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec)
+ struct mp_chmap channels;
+ int o_bps; // == samplerate*samplesize*channels.num (uncompr. bytes/sec)
int i_bps; // == bitrate (compressed bytes/sec)
// in buffers:
int audio_in_minsize; // initial size to allocate for a_in_buffer if any
diff --git a/stream/tv.c b/stream/tv.c
index 80dd53e6a1..38368d4925 100644
--- a/stream/tv.c
+++ b/stream/tv.c
@@ -792,23 +792,25 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer)
&sh_audio->samplerate);
funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE,
&sh_audio->samplesize);
+ int nchannels = sh_audio->channels.num;
funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS,
- &sh_audio->channels);
+ &nchannels);
+ mp_chmap_from_channels(&sh_audio->channels, nchannels);
sh_audio->gsh->codec = "mp-pcm";
sh_audio->format = audio_format;
sh_audio->i_bps = sh_audio->o_bps =
sh_audio->samplerate * sh_audio->samplesize *
- sh_audio->channels;
+ sh_audio->channels.num;
// emulate WF for win32 codecs:
sh_audio->wf = malloc(sizeof(*sh_audio->wf));
sh_audio->wf->wFormatTag = sh_audio->format;
- sh_audio->wf->nChannels = sh_audio->channels;
+ sh_audio->wf->nChannels = sh_audio->channels.num;
sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8;
sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
- sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels;
+ sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels.num;
sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps;
mp_tmsg(MSGT_DECVIDEO, MSGL_V, " TV audio: %d channels, %d bits, %d Hz\n",