diff options
author | wm4 <wm4@nowhere> | 2014-09-24 22:55:50 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-09-24 22:55:50 +0200 |
commit | 9ac86d9e994aeb764207f4d0279b3d37266f79e6 (patch) | |
tree | e1d7ca4e241e8dbe551e9a65eb7dd1e0b4008876 /demux/demux_raw.c | |
parent | 8a8f65d73d7009b13571293d1de6284d42a318e8 (diff) | |
download | mpv-9ac86d9e994aeb764207f4d0279b3d37266f79e6.tar.bz2 mpv-9ac86d9e994aeb764207f4d0279b3d37266f79e6.tar.xz |
audio: decouple demux and audio decoder/filter sample formats
For a while, we used this to transfer PCM from demuxer to the filter
chain. We had a special "codec" that mapped what MPlayer used to do
(MPlayer passes the AF sample format over an extra field to ad_pcm,
which specially interprets it).
Do this by providing a mp_set_pcm_codec() function, which describes a
sample format in a generic way, and sets the appropriate demuxer header
fields so that libavcodec interprets it correctly. We use the fact that
libavcodec has separate PCM decoders for each format. These are
systematically named, so we can easily map them.
This has the advantage that we can change the audio filter chain as we
like, without losing features from the "rawaudio" demuxer. In fact, this
commit also gets rid of the audio filter chain formats completely.
Instead have an explicit list of PCM formats. (We could even just have
the user pass libavcodec PCM decoder names directly, but that would be
annoying in other ways.)
Diffstat (limited to 'demux/demux_raw.c')
-rw-r--r-- | demux/demux_raw.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/demux/demux_raw.c b/demux/demux_raw.c index 552c74a2a3..6faea6e61d 100644 --- a/demux/demux_raw.c +++ b/demux/demux_raw.c @@ -29,7 +29,7 @@ #include "stream/stream.h" #include "demux.h" #include "stheader.h" -#include "audio/format.h" +#include "codec_tags.h" #include "video/img_format.h" #include "video/img_fourcc.h" @@ -40,16 +40,37 @@ struct demux_rawaudio_opts { struct mp_chmap channels; int samplerate; int aformat; - int endian; }; +// Ad-hoc schema to systematically encode the format as int +#define PCM(sign, is_float, bits, is_be) \ + ((sign) | ((is_float) << 1) | ((is_be) << 2) | ((bits) << 3)) +#define NE (BYTE_ORDER == BIG_ENDIAN) + #define OPT_BASE_STRUCT struct demux_rawaudio_opts const struct m_sub_options demux_rawaudio_conf = { .opts = (const m_option_t[]) { OPT_CHMAP("channels", channels, CONF_MIN, .min = 1), OPT_INTRANGE("rate", samplerate, 0, 1000, 8 * 48000), - OPT_AUDIOFORMAT("format", aformat, 0), - OPT_CHOICE("endian", endian, 0, ({"native", 0}, {"le", 1}, {"be", 2})), + OPT_CHOICE("format", aformat, 0, + ({"u8", PCM(0, 0, 8, 0)}, + {"s8", PCM(1, 0, 8, 0)}, + {"u16le", PCM(0, 0, 16, 0)}, {"u16be", PCM(0, 0, 16, 1)}, + {"s16le", PCM(1, 0, 16, 0)}, {"u16be", PCM(1, 0, 16, 1)}, + {"u24le", PCM(0, 0, 24, 0)}, {"u24be", PCM(0, 0, 24, 1)}, + {"s24le", PCM(1, 0, 24, 0)}, {"s24be", PCM(1, 0, 24, 1)}, + {"u32le", PCM(0, 0, 32, 0)}, {"u32be", PCM(0, 0, 32, 1)}, + {"s32le", PCM(1, 0, 32, 0)}, {"s32be", PCM(1, 0, 32, 1)}, + {"floatle", PCM(0, 1, 32, 0)}, {"floatbe", PCM(0, 1, 32, 1)}, + {"doublele",PCM(0, 1, 64, 0)}, {"doublebe", PCM(0, 1, 64, 1)}, + {"u16", PCM(0, 0, 16, NE)}, + {"s16", PCM(1, 0, 16, NE)}, + {"u24", PCM(0, 0, 24, NE)}, + {"s24", PCM(1, 0, 24, NE)}, + {"u32", PCM(0, 0, 32, NE)}, + {"s32", PCM(1, 0, 32, NE)}, + {"float", PCM(0, 1, 32, NE)}, + {"double", PCM(0, 1, 64, NE)})), {0} }, .size = sizeof(struct demux_rawaudio_opts), @@ -57,11 +78,13 @@ const struct m_sub_options demux_rawaudio_conf = { // Note that currently, stream_cdda expects exactly these parameters! .channels = MP_CHMAP_INIT_STEREO, .samplerate = 44100, - .aformat = AF_FORMAT_S16, - .endian = 0, + .aformat = PCM(1, 0, 16, NE), // s16 }, }; +#undef PCM +#undef NE + struct demux_rawvideo_opts { int vformat; int mp_format; @@ -105,32 +128,20 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check) struct demux_rawaudio_opts *opts = demuxer->opts->demux_rawaudio; struct sh_stream *sh; sh_audio_t *sh_audio; - MP_WAVEFORMATEX *w; if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE) return -1; - if (AF_FORMAT_IS_SPECIAL(opts->aformat)) - return -1; - sh = new_sh_stream(demuxer, STREAM_AUDIO); sh_audio = sh->audio; - sh->codec = "mp-pcm"; - sh->format = opts->aformat; - sh_audio->wf = w = talloc_zero(sh, MP_WAVEFORMATEX); - w->wFormatTag = 0; sh_audio->channels = opts->channels; - w->nChannels = sh_audio->channels.num; - w->nSamplesPerSec = sh_audio->samplerate = opts->samplerate; - int samplesize = af_fmt2bps(opts->aformat); - w->nAvgBytesPerSec = sh_audio->samplerate * samplesize * w->nChannels; - w->nBlockAlign = w->nChannels * samplesize; - w->wBitsPerSample = 8 * samplesize; - w->cbSize = 0; - int machine_endian = BYTE_ORDER == BIG_ENDIAN ? 2 : 1; - int endian = opts->endian ? opts->endian : machine_endian; - // wav usually implies little endian - sh_audio->big_endian = endian == 2; + sh_audio->force_channels = true; + sh_audio->samplerate = opts->samplerate; + + int f = opts->aformat; + // See PCM(): sign float bits endian + mp_set_pcm_codec(sh, f & 1, f & 2, f >> 3, f & 4); + int samplesize = ((f >> 3) + 7) / 8; struct priv *p = talloc_ptrtype(demuxer, p); demuxer->priv = p; |