core: use channel map on demuxer level too

This helps passing the channel layout correctly from decoder to audio
filter chain. (Because that part "reuses" the demuxer level codec
parameters, which is very disgusting.)

Note that ffmpeg stuff already passed the channel layout via
mp_copy_lav_codec_headers(). So other than easier dealing with the
demuxer/decoder parameters mess, there's no real advantage to doing
this.

Make the --channels option accept a channel map. Since simple numbers
map to standard layouts with the given number of channels, this is
downwards compatible. Likewise for demux_rawaudio.
This commit is contained in:
wm4 2013-04-06 22:43:12 +02:00
parent 586b75ad08
commit 4b5cee4617
15 changed files with 69 additions and 54 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.,

View File

@ -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;
};
////////////////////////////////////////////////////////////////////////////

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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",