From 09cf1f5c858207b0fdb7c50435d4b15edf132470 Mon Sep 17 00:00:00 2001 From: Johns Date: Tue, 7 Feb 2012 17:08:59 +0100 Subject: [PATCH] Fix bug: alsa+ffmpeg use different channel layout. --- ChangeLog | 1 + codec.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/ChangeLog b/ChangeLog index 89cc3d2..6ce31ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ User johns Date: + Fix bug: alsa and ffmpeg use different channel layout. Support more LPCM sample rates and number of channels. Quick&dirty support for mpeg LPCM streams. Workaround for text2skin undrawn OSD areas. diff --git a/codec.c b/codec.c index 9f4c976..a514a33 100644 --- a/codec.c +++ b/codec.c @@ -739,6 +739,62 @@ void CodecSetAudioPassthrough(int mask) (void)mask; } +/** +** Reorder audio frame. +** +** ffmpeg L R C Ls Rs -> alsa L R Ls Rs C +** ffmpeg L R C LFE Ls Rs -> alsa L R Ls Rs C LFE +** ffmpeg L R C LFE Ls Rs Rl Rr -> alsa L R Ls Rs C LFE Rl Rr +*/ +static void CodecReorderAudioFrame(int16_t * buf, int size, int channels) +{ + int i; + int c; + int ls; + int rs; + int lfe; + + switch (channels) { + case 5: + size /= 2; + for (i = 0; i < size; i += 5) { + c = buf[i + 2]; + ls = buf[i + 3]; + rs = buf[i + 4]; + buf[i + 2] = ls; + buf[i + 3] = rs; + buf[i + 4] = c; + } + break; + case 6: + size /= 2; + for (i = 0; i < size; i += 6) { + c = buf[i + 2]; + ls = buf[i + 3]; + rs = buf[i + 4]; + lfe = buf[i + 5]; + buf[i + 2] = ls; + buf[i + 3] = rs; + buf[i + 4] = c; + buf[i + 5] = lfe; + } + break; + case 8: + size /= 2; + for (i = 0; i < size; i += 8) { + c = buf[i + 2]; + ls = buf[i + 3]; + rs = buf[i + 4]; + lfe = buf[i + 5]; + buf[i + 2] = ls; + buf[i + 3] = rs; + buf[i + 4] = c; + buf[i + 5] = lfe; + } + break; + } +} + #ifdef USE_AVPARSER /** @@ -817,6 +873,8 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt) int err; int isAC3; + // FIXME: use swr_convert from swresample + // FIXME: tell ac3 decoder to use downmix if (audio_decoder->ReSample) { audio_resample_close(audio_decoder->ReSample); audio_decoder->ReSample = NULL; @@ -893,6 +951,8 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt) audio_decoder->HwChannels * av_get_bytes_per_sample(audio_ctx->sample_fmt); Debug(4, "codec/audio: %d -> %d\n", buf_sz, outlen); + CodecReorderAudioFrame(outbuf, outlen, + audio_decoder->HwChannels); AudioEnqueue(outbuf, outlen); } } else { @@ -971,6 +1031,8 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt) // True HD? #endif #endif + CodecReorderAudioFrame(buf, buf_sz, + audio_decoder->HwChannels); AudioEnqueue(buf, buf_sz); } }