summaryrefslogtreecommitdiffstats
path: root/audio/decode/ad_lavc.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-05-12 21:47:55 +0200
committerwm4 <wm4@nowhere>2013-05-12 21:47:55 +0200
commite6e5a7b221ef2fcdd5a1982d6fdcb627100447d2 (patch)
tree08b54ef9bb771434fc7fbe9185793503d3ba314c /audio/decode/ad_lavc.c
parent6a83ef1552de4a1a71da49e45647ce1a4ce64e53 (diff)
parent48f94311516dc1426644b3e68b2a48c22727e1e7 (diff)
downloadmpv-e6e5a7b221ef2fcdd5a1982d6fdcb627100447d2.tar.bz2
mpv-e6e5a7b221ef2fcdd5a1982d6fdcb627100447d2.tar.xz
Merge branch 'audio_changes'
Conflicts: audio/out/ao_lavc.c
Diffstat (limited to 'audio/decode/ad_lavc.c')
-rw-r--r--audio/decode/ad_lavc.c85
1 files changed, 53 insertions, 32 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index 248df307d7..8abc0a6035 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -32,9 +32,11 @@
#include "core/codecs.h"
#include "core/mp_msg.h"
#include "core/options.h"
+#include "core/av_opts.h"
#include "ad_internal.h"
#include "audio/reorder_ch.h"
+#include "audio/fmt-conversion.h"
#include "compat/mpbswap.h"
#include "compat/libav.h"
@@ -49,6 +51,16 @@ struct priv {
int output_left;
int unitsize;
int previous_data_left; // input demuxer packet data
+ bool force_channel_map;
+};
+
+#define OPT_BASE_STRUCT struct MPOpts
+
+const m_option_t ad_lavc_decode_opts_conf[] = {
+ OPT_FLOATRANGE("ac3drc", ad_lavc_param.ac3drc, 0, 0, 2),
+ OPT_FLAG("downmix", ad_lavc_param.downmix, 0),
+ OPT_STRING("o", ad_lavc_param.avopt, 0),
+ {0}
};
struct pcm_map
@@ -144,17 +156,9 @@ static int preinit(sh_audio_t *sh)
static int setup_format(sh_audio_t *sh_audio,
const AVCodecContext *lavc_context)
{
- int sample_format = sh_audio->sample_format;
- switch (av_get_packed_sample_fmt(lavc_context->sample_fmt)) {
- case AV_SAMPLE_FMT_U8: sample_format = AF_FORMAT_U8; break;
- case AV_SAMPLE_FMT_S16: sample_format = AF_FORMAT_S16_NE; break;
- case AV_SAMPLE_FMT_S32: sample_format = AF_FORMAT_S32_NE; break;
- case AV_SAMPLE_FMT_FLT: sample_format = AF_FORMAT_FLOAT_NE; break;
- default:
- mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Unsupported sample format\n");
- sample_format = AF_FORMAT_UNKNOWN;
- }
-
+ struct priv *priv = sh_audio->context;
+ int sample_format =
+ af_from_avformat(av_get_packed_sample_fmt(lavc_context->sample_fmt));
bool broken_srate = false;
int samplerate = lavc_context->sample_rate;
int container_samplerate = sh_audio->container_out_samplerate;
@@ -166,10 +170,20 @@ 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 (priv->force_channel_map) {
+ if (lavc_chmap.num == sh_audio->channels.num)
+ lavc_chmap = sh_audio->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;
@@ -198,41 +212,59 @@ static void set_from_wf(AVCodecContext *avctx, WAVEFORMATEX *wf)
static int init(sh_audio_t *sh_audio, const char *decoder)
{
- struct MPOpts *opts = sh_audio->opts;
+ struct MPOpts *mpopts = sh_audio->opts;
+ struct ad_lavc_param *opts = &mpopts->ad_lavc_param;
AVCodecContext *lavc_context;
AVCodec *lavc_codec;
+ struct priv *ctx = talloc_zero(NULL, struct priv);
+ sh_audio->context = ctx;
+
if (sh_audio->wf && strcmp(decoder, "pcm") == 0) {
decoder = find_pcm_decoder(tag_map, sh_audio->format,
sh_audio->wf->wBitsPerSample);
} else if (sh_audio->wf && strcmp(decoder, "mp-pcm") == 0) {
decoder = find_pcm_decoder(af_map, sh_audio->format, 0);
+ ctx->force_channel_map = true;
}
lavc_codec = avcodec_find_decoder_by_name(decoder);
if (!lavc_codec) {
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR,
"Cannot find codec '%s' in libavcodec...\n", decoder);
+ uninit(sh_audio);
return 0;
}
- struct priv *ctx = talloc_zero(NULL, struct priv);
- sh_audio->context = ctx;
lavc_context = avcodec_alloc_context3(lavc_codec);
ctx->avctx = lavc_context;
ctx->avframe = avcodec_alloc_frame();
lavc_context->codec_type = AVMEDIA_TYPE_AUDIO;
lavc_context->codec_id = lavc_codec->id;
- lavc_context->request_channels = opts->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->drc_level,
+ av_opt_set_double(lavc_context, "drc_scale", opts->ac3drc,
AV_OPT_SEARCH_CHILDREN);
+ if (opts->avopt) {
+ if (parse_avopts(lavc_context, opts->avopt) < 0) {
+ mp_msg(MSGT_DECVIDEO, MSGL_ERR,
+ "ad_lavc: setting AVOptions '%s' failed.\n", opts->avopt);
+ uninit(sh_audio);
+ return 0;
+ }
+ }
+
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);
@@ -279,13 +311,9 @@ static int init(sh_audio_t *sh_audio, const char *decoder)
if (sh_audio->wf && sh_audio->wf->nAvgBytesPerSec)
sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
- switch (av_get_packed_sample_fmt(lavc_context->sample_fmt)) {
- case AV_SAMPLE_FMT_U8:
- case AV_SAMPLE_FMT_S16:
- case AV_SAMPLE_FMT_S32:
- case AV_SAMPLE_FMT_FLT:
- break;
- default:
+ int af_sample_fmt =
+ af_from_avformat(av_get_packed_sample_fmt(lavc_context->sample_fmt));
+ if (af_sample_fmt == AF_FORMAT_UNKNOWN) {
uninit(sh_audio);
return 0;
}
@@ -442,13 +470,6 @@ static int decode_audio(sh_audio_t *sh_audio, unsigned char *buf, int minlen,
memcpy(buf, priv->output, size);
priv->output += size;
priv->output_left -= size;
- if (avctx->channels >= 5) {
- int samplesize = av_get_bytes_per_sample(avctx->sample_fmt);
- reorder_channel_nch(buf, AF_CHANNEL_LAYOUT_LAVC_DEFAULT,
- AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
- avctx->channels,
- size / samplesize, samplesize);
- }
if (len < 0)
len = size;
else