diff options
author | Geoffrey McRae <gnif@xbmc.org> | 2012-04-25 15:21:48 +1200 |
---|---|---|
committer | Jonathan Marshall <jmarshall@never.you.mind> | 2012-05-10 09:40:50 +1200 |
commit | 08b78c8fee881cc782060dc3966a8ee9a8398244 (patch) | |
tree | 2bd0f0bb67b44261d5163747b399e8a740229428 | |
parent | 964a1507e91e086f7d838290e1dec96edd457ed7 (diff) |
[AE] dvdplayer: switch to use AE
-rw-r--r-- | xbmc/cores/dvdplayer/DVDAudio.cpp | 171 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDAudio.h | 13 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h | 18 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp | 123 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h | 27 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.cpp | 104 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h | 14 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp | 171 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h | 14 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp | 25 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h | 4 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 17 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 46 | ||||
-rw-r--r-- | xbmc/cores/dvdplayer/DVDPlayerAudio.h | 16 |
14 files changed, 327 insertions, 436 deletions
diff --git a/xbmc/cores/dvdplayer/DVDAudio.cpp b/xbmc/cores/dvdplayer/DVDAudio.cpp index ac26fa7aca..6393deb1c5 100644 --- a/xbmc/cores/dvdplayer/DVDAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDAudio.cpp @@ -26,7 +26,7 @@ #include "DVDClock.h" #include "DVDCodecs/DVDCodecs.h" #include "DVDPlayerAudio.h" -#include "../AudioRenderers/AudioRendererFactory.h" +#include "cores/AudioEngine/AEFactory.h" #include "settings/Settings.h" using namespace std; @@ -34,14 +34,13 @@ using namespace std; CDVDAudio::CDVDAudio(volatile bool &bStop) : m_bStop(bStop) { - m_pAudioDecoder = NULL; + m_pAudioStream = NULL; m_iBufferSize = 0; m_dwPacketSize = 0; m_pBuffer = NULL; m_bPassthrough = false; m_iBitsPerSample = 0; m_iBitrate = 0; - m_iChannels = 0; m_SecondsPerByte = 0.0; m_bPaused = true; } @@ -49,16 +48,13 @@ CDVDAudio::CDVDAudio(volatile bool &bStop) CDVDAudio::~CDVDAudio() { CSingleLock lock (m_critSection); - if (m_pAudioDecoder) - { - m_pAudioDecoder->Deinitialize(); - delete m_pAudioDecoder; - } + if (m_pAudioStream) + CAEFactory::AE->FreeStream(m_pAudioStream); + free(m_pBuffer); } - -bool CDVDAudio::Create(const DVDAudioFrame &audioframe, CodecID codec) +bool CDVDAudio::Create(const DVDAudioFrame &audioframe, CodecID codec, bool needresampler) { CLog::Log(LOGNOTICE, "Creating audio stream (codec id: %i, channels: %i, sample rate: %i, %s)", @@ -69,39 +65,30 @@ bool CDVDAudio::Create(const DVDAudioFrame &audioframe, CodecID codec) ); // if passthrough isset do something else - CSingleLock lock (m_critSection); - - IAudioRenderer::EEncoded encoded = IAudioRenderer::ENCODED_NONE; - if(audioframe.passthrough) - { - switch(codec) { - case CODEC_ID_AC3 : encoded = IAudioRenderer::ENCODED_IEC61937_AC3; break; - case CODEC_ID_EAC3: encoded = IAudioRenderer::ENCODED_IEC61937_EAC3; break; - case CODEC_ID_DTS : encoded = IAudioRenderer::ENCODED_IEC61937_DTS; break; - case CODEC_ID_MP1 : - case CODEC_ID_MP2 : - case CODEC_ID_MP3 : encoded = IAudioRenderer::ENCODED_IEC61937_MPEG; break; - default: encoded = IAudioRenderer::ENCODED_IEC61937_UNKNOWN; break; - } - } + CSingleLock lock(m_critSection); + unsigned int options = needresampler && !audioframe.passthrough ? AESTREAM_FORCE_RESAMPLE : 0; + options |= AESTREAM_AUTOSTART; - m_pAudioDecoder = CAudioRendererFactory::Create(m_pCallback, audioframe.channel_count, audioframe.channel_map, audioframe.sample_rate, audioframe.bits_per_sample, false, false, encoded); - - if (!m_pAudioDecoder) return false; + m_pAudioStream = CAEFactory::AE->MakeStream( + audioframe.data_format, + audioframe.sample_rate, + audioframe.encoded_sample_rate, + audioframe.channel_layout, + options + ); + if (!m_pAudioStream) return false; - m_iChannels = audioframe.channel_count; - m_iBitrate = audioframe.sample_rate; + m_iBitrate = audioframe.sample_rate; m_iBitsPerSample = audioframe.bits_per_sample; - m_bPassthrough = audioframe.passthrough; - if(m_iChannels && m_iBitrate && m_iBitsPerSample) - m_SecondsPerByte = 1.0 / (m_iChannels * m_iBitrate * (m_iBitsPerSample>>3)); + m_bPassthrough = audioframe.passthrough; + m_channelLayout = audioframe.channel_layout; + m_dwPacketSize = m_pAudioStream->GetFrameSize(); + + if(m_channelLayout.Count() && m_iBitrate && m_iBitsPerSample) + m_SecondsPerByte = 1.0 / (m_channelLayout.Count() * m_iBitrate * (m_iBitsPerSample>>3)); else m_SecondsPerByte = 0.0; - m_dwPacketSize = m_pAudioDecoder->GetChunkLen(); - if(m_bPaused) - m_pAudioDecoder->Pause(); - m_iBufferSize = 0; SetDynamicRangeCompression((long)(g_settings.m_currentVideoSettings.m_VolumeAmplification * 100)); @@ -112,18 +99,14 @@ void CDVDAudio::Destroy() { CSingleLock lock (m_critSection); - if (m_pAudioDecoder) - { - m_pAudioDecoder->Stop(); - m_pAudioDecoder->Deinitialize(); - delete m_pAudioDecoder; - } + if (m_pAudioStream) + CAEFactory::AE->FreeStream(m_pAudioStream); + free(m_pBuffer); m_pBuffer = NULL; m_dwPacketSize = 0; - m_pAudioDecoder = NULL; + m_pAudioStream = NULL; m_iBufferSize = 0; - m_iChannels = 0; m_iBitrate = 0; m_iBitsPerSample = 0; m_bPassthrough = false; @@ -132,16 +115,16 @@ void CDVDAudio::Destroy() DWORD CDVDAudio::AddPacketsRenderer(unsigned char* data, DWORD len, CSingleLock &lock) { - if(!m_pAudioDecoder) + if(!m_pAudioStream) return 0; - DWORD bps = m_iChannels * m_iBitrate * (m_iBitsPerSample>>3); + DWORD bps = m_channelLayout.Count() * m_iBitrate * (m_iBitsPerSample>>3); if(!bps) return 0; //Calculate a timeout when this definitely should be done double timeout; - timeout = DVD_SEC_TO_TIME(m_pAudioDecoder->GetDelay() + len * m_SecondsPerByte); + timeout = DVD_SEC_TO_TIME(m_pAudioStream->GetDelay() + len * m_SecondsPerByte); timeout += DVD_SEC_TO_TIME(1.0); timeout += CDVDClock::GetAbsoluteClock(); @@ -149,7 +132,7 @@ DWORD CDVDAudio::AddPacketsRenderer(unsigned char* data, DWORD len, CSingleLock DWORD copied; do { - copied = m_pAudioDecoder->AddPackets(data, len); + copied = m_pAudioStream->AddData(data, len); data += copied; len -= copied; if (len < m_dwPacketSize) @@ -179,15 +162,6 @@ DWORD CDVDAudio::AddPackets(const DVDAudioFrame &audioframe) DWORD total = len; DWORD copied; - // When paused, we need to buffer all data as renderers don't need to accept it - if (m_bPaused) - { - m_pBuffer = (BYTE*)realloc(m_pBuffer, m_iBufferSize + len); - memcpy(m_pBuffer+m_iBufferSize, data, len); - m_iBufferSize += len; - return len; - } - if (m_iBufferSize > 0) // See if there are carryover bytes from the last call. need to add them 1st. { copied = std::min(m_dwPacketSize - m_iBufferSize % m_dwPacketSize, len); // Smaller of either the data provided or the leftover data @@ -229,35 +203,10 @@ DWORD CDVDAudio::AddPackets(const DVDAudioFrame &audioframe) return total; } -double CDVDAudio::AddSilence(double delay) -{ - CLog::Log(LOGDEBUG, "CDVDAudio::AddSilence - %f seconds", delay); - DVDAudioFrame audioframe; - audioframe.passthrough = m_bPassthrough; - audioframe.channel_count = m_iChannels; - audioframe.sample_rate = m_iBitrate; - audioframe.bits_per_sample = m_iBitsPerSample; - audioframe.size = m_iChannels * (m_iBitsPerSample>>3); - audioframe.data = (BYTE*)calloc(1, audioframe.size); - if(audioframe.data == NULL) - return 0.0; - unsigned samples = m_iBitrate * delay; - unsigned added = 0; - for(; added < samples; added++) - { - if(AddPackets(audioframe) != audioframe.size) - break; - } - if(added < samples) - CLog::Log(LOGDEBUG, "CDVDAudio::AddSilence - failed to %d silence samples of %u", samples - added, samples); - free(audioframe.data); - return (double)added / m_iBitrate; -} - void CDVDAudio::Finish() { CSingleLock lock (m_critSection); - if (!m_pAudioDecoder) + if (!m_pAudioStream) return; DWORD silence = m_dwPacketSize - m_iBufferSize % m_dwPacketSize; @@ -280,27 +229,26 @@ void CDVDAudio::Drain() { Finish(); CSingleLock lock (m_critSection); - if (m_pAudioDecoder) - m_pAudioDecoder->WaitCompletion(); + if (m_pAudioStream) + m_pAudioStream->Drain(); } void CDVDAudio::SetVolume(float volume) { CSingleLock lock (m_critSection); - if (m_pAudioDecoder) m_pAudioDecoder->SetCurrentVolume(volume); + if (m_pAudioStream) m_pAudioStream->SetVolume(volume); } void CDVDAudio::SetDynamicRangeCompression(long drc) { - CSingleLock lock (m_critSection); - if (m_pAudioDecoder) m_pAudioDecoder->SetDynamicRangeCompression(drc); + } float CDVDAudio::GetCurrentAttenuation() { CSingleLock lock (m_critSection); - if (m_pAudioDecoder) - return m_pAudioDecoder->GetCurrentAttenuation(); + if (m_pAudioStream) + return m_pAudioStream->GetVolume(); else return 1.0f; } @@ -308,15 +256,13 @@ float CDVDAudio::GetCurrentAttenuation() void CDVDAudio::Pause() { CSingleLock lock (m_critSection); - m_bPaused = true; - if (m_pAudioDecoder) m_pAudioDecoder->Pause(); + if (m_pAudioStream) m_pAudioStream->Pause(); } void CDVDAudio::Resume() { CSingleLock lock (m_critSection); - m_bPaused = false; - if (m_pAudioDecoder) m_pAudioDecoder->Resume(); + if (m_pAudioStream) m_pAudioStream->Resume(); } double CDVDAudio::GetDelay() @@ -324,8 +270,8 @@ double CDVDAudio::GetDelay() CSingleLock lock (m_critSection); double delay = 0.0; - if(m_pAudioDecoder) - delay = m_pAudioDecoder->GetDelay(); + if(m_pAudioStream) + delay = m_pAudioStream->GetDelay(); delay += m_SecondsPerByte * m_iBufferSize; @@ -336,39 +282,46 @@ void CDVDAudio::Flush() { CSingleLock lock (m_critSection); - if (m_pAudioDecoder) + if (m_pAudioStream) { - m_pAudioDecoder->Stop(); - m_pAudioDecoder->Resume(); + m_pAudioStream->Flush(); } m_iBufferSize = 0; } bool CDVDAudio::IsValidFormat(const DVDAudioFrame &audioframe) { - if(!m_pAudioDecoder) + if(!m_pAudioStream) return false; if(audioframe.passthrough != m_bPassthrough) return false; - if(audioframe.channel_count != m_iChannels - || audioframe.sample_rate != m_iBitrate - || audioframe.bits_per_sample != m_iBitsPerSample) + if(m_iBitrate != audioframe.sample_rate + || m_iBitsPerSample != audioframe.bits_per_sample + || m_channelLayout != audioframe.channel_layout) return false; return true; } +void CDVDAudio::SetResampleRatio(double ratio) +{ + CSingleLock lock (m_critSection); + + if(m_pAudioStream) + m_pAudioStream->SetResampleRatio(ratio); +} + double CDVDAudio::GetCacheTime() { CSingleLock lock (m_critSection); - if(!m_pAudioDecoder) + if(!m_pAudioStream) return 0.0; double delay = 0.0; - if(m_pAudioDecoder) - delay = m_pAudioDecoder->GetCacheTime(); + if(m_pAudioStream) + delay = m_pAudioStream->GetCacheTime(); delay += m_SecondsPerByte * m_iBufferSize; @@ -378,7 +331,7 @@ double CDVDAudio::GetCacheTime() double CDVDAudio::GetCacheTotal() { CSingleLock lock (m_critSection); - if(!m_pAudioDecoder) + if(!m_pAudioStream) return 0.0; - return m_pAudioDecoder->GetCacheTotal(); + return m_pAudioStream->GetCacheTotal(); } diff --git a/xbmc/cores/dvdplayer/DVDAudio.h b/xbmc/cores/dvdplayer/DVDAudio.h index 8a51be7580..35529f0a48 100644 --- a/xbmc/cores/dvdplayer/DVDAudio.h +++ b/xbmc/cores/dvdplayer/DVDAudio.h @@ -24,10 +24,11 @@ #if (defined HAVE_CONFIG_H) && (!defined WIN32) #include "config.h" #endif -#include "cores/AudioRenderers/IAudioRenderer.h" #include "threads/CriticalSection.h" #include "PlatformDefs.h" +#include "cores/AudioEngine/Interfaces/AEStream.h" + #ifndef _LINUX enum CodecID; #else @@ -58,11 +59,10 @@ public: float GetCurrentAttenuation(); void Pause(); void Resume(); - bool Create(const DVDAudioFrame &audioframe, CodecID codec); + bool Create(const DVDAudioFrame &audioframe, CodecID codec, bool needresampler); bool IsValidFormat(const DVDAudioFrame &audioframe); void Destroy(); DWORD AddPackets(const DVDAudioFrame &audioframe); - double AddSilence(double delay); double GetDelay(); // returns the time it takes to play a packet if we add one at this time double GetCacheTime(); // returns total amount of data cached in audio output at this time double GetCacheTotal(); // returns total amount the audio device can buffer @@ -70,7 +70,10 @@ public: void Finish(); void Drain(); - IAudioRenderer* m_pAudioDecoder; + void SetSpeed(int iSpeed); + void SetResampleRatio(double ratio); + + IAEStream *m_pAudioStream; protected: DWORD AddPacketsRenderer(unsigned char* data, DWORD len, CSingleLock &lock); BYTE* m_pBuffer; // should be [m_dwPacketSize] @@ -78,11 +81,11 @@ protected: DWORD m_dwPacketSize; CCriticalSection m_critSection; - int m_iChannels; int m_iBitrate; int m_iBitsPerSample; double m_SecondsPerByte; bool m_bPassthrough; + CAEChannelInfo m_channelLayout; bool m_bPaused; volatile bool& m_bStop; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h index 25df2b5d2b..06bbc1ca72 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h @@ -22,7 +22,7 @@ */ #include "system.h" -#include "utils/PCMRemap.h" +#include "cores/AudioEngine/AEAudioFormat.h" #if (defined HAVE_CONFIG_H) && (!defined WIN32) #include "config.h" @@ -76,9 +76,14 @@ public: virtual int GetChannels() = 0; /* + * returns the nr of channels for the encoded audio stream + */ + virtual int GetEncodedChannels() { return 0; } + + /* * returns the channel mapping */ - virtual enum PCMChannels* GetChannelMap() = 0; + virtual CAEChannelInfo GetChannelMap() = 0; /* * returns the samplerate for the decoded audio stream @@ -86,9 +91,14 @@ public: virtual int GetSampleRate() = 0; /* - * returns the bitspersample for the decoded audio stream (eg 16 bits) + * returns the samplerate for the encoded audio stream + */ + virtual int GetEncodedSampleRate() { return 0; } + + /* + * returns the data format for the decoded audio stream (eg AE_FMT_S16LE) */ - virtual int GetBitsPerSample() = 0; + virtual enum AEDataFormat GetDataFormat() = 0; /* * should return the average input bit rate diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp index c55c3923c2..dc90af7636 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp @@ -29,6 +29,7 @@ CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec() { + m_iBufferSize1 = 0; m_iBufferSize2 = 0; m_pBuffer2 = (BYTE*)_aligned_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE, 16); memset(m_pBuffer2, 0, AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); @@ -38,10 +39,10 @@ CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec() m_pConvert = NULL; m_bOpenedCodec = false; - m_channelMap[0] = PCM_INVALID; m_channels = 0; m_layout = 0; - m_pFrame1 = NULL; + + m_bLpcmMode = false; } CDVDAudioCodecFFmpeg::~CDVDAudioCodecFFmpeg() @@ -67,6 +68,12 @@ bool CDVDAudioCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options return false; } +#if defined(TARGET_DARWIN) + int audioMode = g_guiSettings.GetInt("audiooutput.mode"); + if (audioMode == AUDIO_HDMI) + m_bLpcmMode = g_guiSettings.GetBool("audiooutput.multichannellpcm"); +#endif + m_pCodecContext = m_dllAvCodec.avcodec_alloc_context3(pCodec); m_pCodecContext->debug_mv = 0; m_pCodecContext->debug = 0; @@ -151,7 +158,6 @@ int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize) if (iBytesUsed < 0 || !got_frame) { m_iBufferSize1 = 0; - m_iBufferSize2 = 0; return iBytesUsed; } m_iBufferSize1 = m_dllAvUtil.av_samples_get_buffer_size(NULL, m_pCodecContext->channels, m_pFrame1->nb_samples, m_pCodecContext->sample_fmt, 1); @@ -167,8 +173,16 @@ int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize) m_iBuffered += iBytesUsed; else m_iBuffered = 0; + + if(m_bLpcmMode) + ConvertToFloat(); - if(m_pCodecContext->sample_fmt != AV_SAMPLE_FMT_S16 && m_iBufferSize1 > 0) + return iBytesUsed; +} + +void CDVDAudioCodecFFmpeg::ConvertToFloat() +{ + if(m_pCodecContext->sample_fmt != AV_SAMPLE_FMT_FLT && m_iBufferSize1 > 0) { if(m_pConvert && m_pCodecContext->sample_fmt != m_iSampleFormat) { @@ -179,35 +193,33 @@ int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize) if(!m_pConvert) { m_iSampleFormat = m_pCodecContext->sample_fmt; - m_pConvert = m_dllAvCodec.av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, m_pCodecContext->sample_fmt, 1, NULL, 0); + m_pConvert = m_dllAvCodec.av_audio_convert_alloc(AV_SAMPLE_FMT_FLT, 1, m_pCodecContext->sample_fmt, 1, NULL, 0); } if(!m_pConvert) { - CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_S16", m_pCodecContext->sample_fmt); + CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_FLT", m_pCodecContext->sample_fmt); m_iBufferSize1 = 0; m_iBufferSize2 = 0; - return iBytesUsed; + return; } const void *ibuf[6] = { m_pFrame1->data[0] }; void *obuf[6] = { m_pBuffer2 }; int istr[6] = { m_dllAvUtil.av_get_bytes_per_sample(m_pCodecContext->sample_fmt) }; - int ostr[6] = { 2 }; + int ostr[6] = { m_dllAvUtil.av_get_bytes_per_sample(AV_SAMPLE_FMT_FLT) }; int len = m_iBufferSize1 / istr[0]; if(m_dllAvCodec.av_audio_convert(m_pConvert, obuf, ostr, ibuf, istr, len) < 0) { - CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_S16", (int)m_pCodecContext->sample_fmt); + CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_FLT", (int)m_pCodecContext->sample_fmt); m_iBufferSize1 = 0; m_iBufferSize2 = 0; - return iBytesUsed; + return; } m_iBufferSize1 = 0; m_iBufferSize2 = len * ostr[0]; } - - return iBytesUsed; } int CDVDAudioCodecFFmpeg::GetData(BYTE** dst) @@ -217,11 +229,13 @@ int CDVDAudioCodecFFmpeg::GetData(BYTE** dst) *dst = m_pFrame1->data[0]; return m_iBufferSize1; } + if(m_iBufferSize2) { *dst = m_pBuffer2; return m_iBufferSize2; } + return 0; } @@ -240,13 +254,38 @@ int CDVDAudioCodecFFmpeg::GetChannels() int CDVDAudioCodecFFmpeg::GetSampleRate() { - if (m_pCodecContext) return m_pCodecContext->sample_rate; + if (m_pCodecContext) + return m_pCodecContext->sample_rate; return 0; } -int CDVDAudioCodecFFmpeg::GetBitsPerSample() +int CDVDAudioCodecFFmpeg::GetEncodedSampleRate() { - return 16; + if (m_pCodecContext) + return m_pCodecContext->sample_rate; + return 0; +} + +enum AEDataFormat CDVDAudioCodecFFmpeg::GetDataFormat() +{ + if(m_bLpcmMode) + { + return AE_FMT_LPCM; + } + else + { + switch(m_pCodecContext->sample_fmt) + { + case SAMPLE_FMT_U8 : return AE_FMT_U8; + case SAMPLE_FMT_S16: return AE_FMT_S16NE; + case SAMPLE_FMT_S32: return AE_FMT_S32NE; + case SAMPLE_FMT_FLT: return AE_FMT_FLOAT; + case SAMPLE_FMT_DBL: return AE_FMT_DOUBLE; + default: + assert(false); + return AE_FMT_INVALID; + } + } } int CDVDAudioCodecFFmpeg::GetBitRate() @@ -265,7 +304,7 @@ static unsigned count_bits(int64_t value) void CDVDAudioCodecFFmpeg::BuildChannelMap() { - if (m_channels == m_pCodecContext->channels && m_layout == (int64_t)m_pCodecContext->channel_layout) + if (m_channels == m_pCodecContext->channels && m_layout == m_pCodecContext->channel_layout) return; //nothing to do here m_channels = m_pCodecContext->channels; @@ -282,36 +321,32 @@ void CDVDAudioCodecFFmpeg::BuildChannelMap() layout = m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels); } - int index = 0; - if (layout & AV_CH_FRONT_LEFT ) m_channelMap[index++] = PCM_FRONT_LEFT ; - if (layout & AV_CH_FRONT_RIGHT ) m_channelMap[index++] = PCM_FRONT_RIGHT ; - if (layout & AV_CH_FRONT_CENTER ) m_channelMap[index++] = PCM_FRONT_CENTER ; - if (layout & AV_CH_LOW_FREQUENCY ) m_channelMap[index++] = PCM_LOW_FREQUENCY ; - if (layout & AV_CH_BACK_LEFT ) m_channelMap[index++] = PCM_BACK_LEFT ; - if (layout & AV_CH_BACK_RIGHT ) m_channelMap[index++] = PCM_BACK_RIGHT ; - if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ; - if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER; - if (layout & AV_CH_BACK_CENTER ) m_channelMap[index++] = PCM_BACK_CENTER ; - if (layout & AV_CH_SIDE_LEFT ) m_channelMap[index++] = PCM_SIDE_LEFT ; - if (layout & AV_CH_SIDE_RIGHT ) m_channelMap[index++] = PCM_SIDE_RIGHT ; - if (layout & AV_CH_TOP_CENTER ) m_channelMap[index++] = PCM_TOP_CENTER ; - if (layout & AV_CH_TOP_FRONT_LEFT ) m_channelMap[index++] = PCM_TOP_FRONT_LEFT ; - if (layout & AV_CH_TOP_FRONT_CENTER ) m_channelMap[index++] = PCM_TOP_FRONT_CENTER ; - if (layout & AV_CH_TOP_FRONT_RIGHT ) m_channelMap[index++] = PCM_TOP_FRONT_RIGHT ; - if (layout & AV_CH_TOP_BACK_LEFT ) m_channelMap[index++] = PCM_TOP_BACK_LEFT ; - if (layout & AV_CH_TOP_BACK_CENTER ) m_channelMap[index++] = PCM_TOP_BACK_CENTER ; - if (layout & AV_CH_TOP_BACK_RIGHT ) m_channelMap[index++] = PCM_TOP_BACK_RIGHT ; - - //terminate the channel map - m_channelMap[index] = PCM_INVALID; + m_channelLayout.Reset(); + + if (layout & AV_CH_FRONT_LEFT ) m_channelLayout += AE_CH_FL ; + if (layout & AV_CH_FRONT_RIGHT ) m_channelLayout += AE_CH_FR ; + if (layout & AV_CH_FRONT_CENTER ) m_channelLayout += AE_CH_FC ; + if (layout & AV_CH_LOW_FREQUENCY ) m_channelLayout += AE_CH_LFE ; + if (layout & AV_CH_BACK_LEFT ) m_channelLayout += AE_CH_BL ; + if (layout & AV_CH_BACK_RIGHT ) m_channelLayout += AE_CH_BR ; + if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelLayout += AE_CH_FLOC; + if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelLayout += AE_CH_FROC; + if (layout & AV_CH_BACK_CENTER ) m_channelLayout += AE_CH_BC ; + if (layout & AV_CH_SIDE_LEFT ) m_channelLayout += AE_CH_SL ; + if (layout & AV_CH_SIDE_RIGHT ) m_channelLayout += AE_CH_SR ; + if (layout & AV_CH_TOP_CENTER ) m_channelLayout += AE_CH_TC ; + if (layout & AV_CH_TOP_FRONT_LEFT ) m_channelLayout += AE_CH_TFL ; + if (layout & AV_CH_TOP_FRONT_CENTER ) m_channelLayout += AE_CH_TFC ; + if (layout & AV_CH_TOP_FRONT_RIGHT ) m_channelLayout += AE_CH_TFR ; + if (layout & AV_CH_TOP_BACK_LEFT ) m_channelLayout += AE_CH_BL ; + if (layout & AV_CH_TOP_BACK_CENTER ) m_channelLayout += AE_CH_BC ; + if (layout & AV_CH_TOP_BACK_RIGHT ) m_channelLayout += AE_CH_BR ; + + m_channels = m_pCodecContext->channels; } -enum PCMChannels* CDVDAudioCodecFFmpeg::GetChannelMap() +CAEChannelInfo CDVDAudioCodecFFmpeg::GetChannelMap() { BuildChannelMap(); - - if (m_channelMap[0] == PCM_INVALID) - return NULL; - - return m_channelMap; + return m_channelLayout; } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h index 4c01499ca1..749e687836 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h @@ -37,34 +37,37 @@ public: virtual int GetData(BYTE** dst); virtual void Reset(); virtual int GetChannels(); - virtual enum PCMChannels *GetChannelMap(); + virtual CAEChannelInfo GetChannelMap(); virtual int GetSampleRate(); - virtual int GetBitsPerSample(); + virtual int GetEncodedSampleRate(); + virtual enum AEDataFormat GetDataFormat(); virtual const char* GetName() { return "FFmpeg"; } virtual int GetBufferSize() { return m_iBuffered; } virtual int GetBitRate(); protected: - AVCodecContext* m_pCodecContext; - AVAudioConvert* m_pConvert;; - enum AVSampleFormat m_iSampleFormat; - enum PCMChannels m_channelMap[PCM_MAX_CH + 1]; + AVCodecContext* m_pCodecContext; + AVAudioConvert* m_pConvert; + enum AVSampleFormat m_iSampleFormat; + CAEChannelInfo m_channelLayout; + int m_iMapChannels; + bool m_bLpcmMode; AVFrame* m_pFrame1; - int m_iBufferSize1; - - BYTE *m_pBuffer2; - int m_iBufferSize2; + int m_iBufferSize1; + BYTE* m_pBuffer2; + int m_iBufferSize2; bool m_bOpenedCodec; int m_iBuffered; - int m_channels; - int64_t m_layout; + int m_channels; + uint64_t m_layout; DllAvCodec m_dllAvCodec; DllAvUtil m_dllAvUtil; void BuildChannelMap(); + void ConvertToFloat(); }; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.cpp index 7aef7e4be1..40a91360fe 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.cpp @@ -22,21 +22,6 @@ #include "DVDAudioCodecLibMad.h" #include "DVDStreamInfo.h" -static inline signed int scale(mad_fixed_t sample) -{ - /* round */ - sample += (1L << (MAD_F_FRACBITS - 16)); - - /* clip */ - if (sample >= MAD_F_ONE) - sample = MAD_F_ONE - 1; - else if (sample < -MAD_F_ONE) - sample = -MAD_F_ONE; - - /* quantize */ - return sample >> (MAD_F_FRACBITS + 1 - 16); -} - CDVDAudioCodecLibMad::CDVDAudioCodecLibMad() : CDVDAudioCodec() { m_bInitialized = false; @@ -96,15 +81,12 @@ int CDVDAudioCodecLibMad::Decode(BYTE* pData, int iSize) // m_inputBuffer should always have room here for extra bytes int iBytesFree = MAD_INPUT_SIZE - m_iInputBufferSize; - int iBytesUsed = iBytesFree; - if (iBytesUsed > iSize) iBytesUsed = iSize; + int iBytesUsed = std::min(iSize, iBytesFree); // copy data into our buffer for decoding memcpy(m_inputBuffer + m_iInputBufferSize, pData, iBytesUsed); m_iInputBufferSize += iBytesUsed; - - if (m_bInitialized) { m_dll.mad_stream_buffer(&m_stream, pBuffer, m_iInputBufferSize); @@ -134,7 +116,7 @@ int CDVDAudioCodecLibMad::Decode(BYTE* pData, int iSize) if (m_stream.next_frame) { m_iInputBufferSize = m_stream.bufend - m_stream.next_frame; - pBuffer = (BYTE*)m_stream.next_frame; + pBuffer = (BYTE*)m_stream.next_frame; } if (m_iInputBufferSize <= 0) @@ -142,74 +124,50 @@ int CDVDAudioCodecLibMad::Decode(BYTE* pData, int iSize) return iBytesUsed; } - // buffer again after a sync - m_dll.mad_stream_buffer(&m_stream, pBuffer, m_iInputBufferSize); + // buffer again after a sync + m_dll.mad_stream_buffer(&m_stream, pBuffer, m_iInputBufferSize); } else { // decoded some data m_iSourceSampleRate = m_frame.header.samplerate; - m_iSourceChannels = (m_frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? 1 : 2; - m_iSourceBitrate = m_frame.header.bitrate; - - /* - switch (this->frame.header.layer) { - case MAD_LAYER_I: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, - "MPEG audio layer 1 (lib: MAD)"); - break; - case MAD_LAYER_II: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, - "MPEG audio layer 2 (lib: MAD)"); - break; - case MAD_LAYER_III: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, - "MPEG audio layer 3 (lib: MAD)"); - break; - default: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, - "MPEG audio (lib: MAD)"); - } - */ + m_iSourceChannels = (m_frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? 1 : 2; + m_iSourceBitrate = m_frame.header.bitrate; m_dll.mad_synth_frame(&m_synth, &m_frame); { unsigned int nchannels, nsamples; - mad_fixed_t const* left_ch, *right_ch; - struct mad_pcm* pcm = &m_synth.pcm; - unsigned __int16* output = (unsigned __int16*)(m_decodedData + m_iDecodedDataSize); + mad_fixed_t const* left_ch, *right_ch; + struct mad_pcm* pcm = &m_synth.pcm; + float* output = (float*)(m_decodedData + m_iDecodedDataSize); nchannels = pcm->channels; nsamples = pcm->length; - left_ch = pcm->samples[0]; - right_ch = pcm->samples[1]; - - int iSize = nsamples * 2; - if (nchannels == 2) iSize += nsamples * 2; + left_ch = pcm->samples[0]; + right_ch = pcm->samples[1]; + unsigned int iSize = nsamples * sizeof(float) * nchannels; if (iSize < (MAD_DECODED_SIZE - m_iDecodedDataSize)) { - while (nsamples--) - { - // output sample(s) in 16-bit signed little-endian PCM - *output++ = scale(*left_ch++); - - if (nchannels == 2) - { - *output++ = scale(*right_ch++); - } - } - - m_iDecodedDataSize += iSize; - } + while (nsamples--) + { + // output sample(s) in float + *output++ = mad_f_todouble(*left_ch++); + if (nchannels == 2) + { + *output++ = mad_f_todouble(*right_ch++); + } + } + m_iDecodedDataSize += iSize; + } - if (iSize > (MAD_DECODED_SIZE - m_iDecodedDataSize)) + if (iSize > (MAD_DECODED_SIZE - m_iDecodedDataSize)) { // next audio frame is not going to fit bFullOutputBuffer = true; } - } + } } } } @@ -244,13 +202,15 @@ void CDVDAudioCodecLibMad::Reset() } } -enum PCMChannels* CDVDAudioCodecLibMad::GetChannelMap() +CAEChannelInfo CDVDAudioCodecLibMad::GetChannelMap() { - static enum PCMChannels map[2][2] = { - {PCM_FRONT_CENTER}, - {PCM_FRONT_LEFT, PCM_FRONT_RIGHT} + assert(m_iSourceChannels > 0 && m_iSourceChannels < 3); + + static enum AEChannel map[2][3] = { + {AE_CH_FC, AE_CH_NULL}, + {AE_CH_FL, AE_CH_FR, AE_CH_NULL} }; - return map[m_iSourceChannels - 1]; + return CAEChannelInfo(map[m_iSourceChannels -1]); } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h index 314246eb79..d61ae24df9 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h @@ -25,7 +25,7 @@ #include "DllLibMad.h" #define MAD_INPUT_SIZE (8 * 1024) -#define MAD_DECODED_SIZE (16 * MAD_INPUT_SIZE) +#define MAD_DECODED_SIZE (sizeof(float) * MAD_INPUT_SIZE) class CDVDAudioCodecLibMad : public CDVDAudioCodec { @@ -37,12 +37,12 @@ public: virtual int Decode(BYTE* pData, int iSize); virtual int GetData(BYTE** dst); virtual void Reset(); - virtual enum PCMChannels* GetChannelMap(); - virtual int GetChannels() { return m_iSourceChannels; } - virtual int GetSampleRate() { return m_iSourceSampleRate; } - virtual int GetBitsPerSample() { return 16; } - virtual const char* GetName() { return "libmad"; } - virtual int GetBufferSize() { return m_iInputBufferSize; } + virtual CAEChannelInfo GetChannelMap(); + virtual int GetChannels() { return m_iSourceChannels; } + virtual int GetSampleRate() { return m_iSourceSampleRate; } + virtual enum AEDataFormat GetDataFormat() { return AE_FMT_FLOAT; } + virtual const char* GetName() { return "libmad"; } + virtual int GetBufferSize() { return m_iInputBufferSize; } private: diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp index 3fa1102186..1de73c213c 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp @@ -26,8 +26,6 @@ #include "settings/Settings.h" #include "utils/log.h" -#include "Encoders/DVDAudioEncoderFFmpeg.h" - //These values are forced to allow spdif out #define OUT_SAMPLESIZE 16 #define OUT_CHANNELS 2 @@ -58,9 +56,7 @@ CDVDAudioCodecPassthroughFFmpeg::CDVDAudioCodecPassthroughFFmpeg(void) m_SampleRate = 0; m_Codec = NULL; - m_Encoder = NULL; - m_InitEncoder = true; - + /* make enough room for at-least two audio frames */ m_DecodeSize = 0; m_DecodeBuffer = NULL; @@ -290,36 +286,6 @@ bool CDVDAudioCodecPassthroughFFmpeg::SupportsFormat(CDVDStreamInfo &hints) return true; } -bool CDVDAudioCodecPassthroughFFmpeg::SetupEncoder(CDVDStreamInfo &hints) -{ - /* there is no point encoding <= 2 channel sources, and we dont support anything but AC3 at the moment */ - if (hints.channels <= 2 || !m_bSupportsAC3Out) - return false; - - CLog::Log(LOGDEBUG, "CDVDAudioCodecPassthroughFFmpeg::SetupEncoder - Setting up encoder for on the fly transcode"); - - /* we need to decode the incoming audio data, so we can re-encode it as we need it */ - CDVDStreamInfo h(hints); - m_Codec = CDVDFactoryCodec::CreateAudioCodec(h, false); - if (!m_Codec) - { - CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::SetupEncoder - Unable to create a decoder for transcode"); - return false; - } - - /* create and setup the encoder */ - m_Encoder = new CDVDAudioEncoderFFmpeg(); - m_InitEncoder = true; - - /* adjust the hints according to the encorders output */ - hints.codec = m_Encoder->GetCodecID(); - hints.bitrate = m_Encoder->GetBitRate(); - hints.channels = OUT_CHANNELS; - - CLog::Log(LOGDEBUG, "CDVDAudioCodecPassthroughFFmpeg::SetupEncoder - Ready to transcode"); - return true; -} - bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { int audioMode = g_guiSettings.GetInt("audiooutput.mode"); @@ -356,20 +322,9 @@ bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptio /* see if the muxer supports our codec (see spdif.c for supported formats) */ if (!SupportsFormat(hints)) { - /* HDMI can do multichannel LPCM, transcoding would just be silly */ - if (audioMode == AUDIO_HDMI) - { - CLog::Log(LOGINFO, "CDVDAudioCodecPassthroughFFmpeg::Open - Won't transcode for HDMI"); - Dispose(); - return false; - } - - if (!SetupEncoder(hints) || !SupportsFormat(hints)) - { - CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - FFmpeg SPDIF muxer does not support this codec"); - Dispose(); - return false; - } + CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - FFmpeg SPDIF muxer does not support this codec"); + Dispose(); + return false; } else { @@ -383,7 +338,6 @@ bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptio } m_Codec = NULL; - m_Encoder = NULL; } if (!SetupMuxer(hints, "spdif", m_SPDIF)) @@ -393,6 +347,9 @@ bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptio /* we will check the first packet's crc */ m_LostSync = true; + + m_codec = hints.codec; + return true; } @@ -409,9 +366,6 @@ void CDVDAudioCodecPassthroughFFmpeg::Dispose() m_DecodeBuffer = NULL; } - delete m_Encoder; - m_Encoder = NULL; - delete m_Codec; m_Codec = NULL; } @@ -421,76 +375,6 @@ int CDVDAudioCodecPassthroughFFmpeg::Decode(BYTE* pData, int iSize) unsigned int used, fSize; fSize = iSize; - /* if we are transcoding */ - if (m_Encoder) - { - uint8_t *decData; - uint8_t *encData; - - /* if we are decoding */ - used = m_Codec->Decode (pData, iSize); - fSize = m_Codec->GetData(&decData); - - /* we may not get any data for a few frames, this is expected */ - if (fSize == 0) - return used; - - /* now we have data, it is safe to initialize the encoder, as we should now have a channel map */ - if (m_InitEncoder) - { - if (m_Encoder->Initialize(m_Codec->GetChannels(), m_Codec->GetChannelMap(), m_Codec->GetBitsPerSample(), m_Codec->GetSampleRate())) - { - m_InitEncoder = false; - m_EncPacketSize = m_Encoder->GetPacketSize(); - /* allocate enough room for two packets of data */ - m_DecodeBuffer = (uint8_t*)_aligned_malloc(m_EncPacketSize * 2, 16); - m_DecodeSize = 0; - } - else - { - CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Encode - Unable to initialize the encoder for transcode"); - return -1; - } - } - - unsigned int avail, eUsed, eCoded = 0; - avail = fSize + m_DecodeSize; - - while(avail >= m_EncPacketSize) - { - /* append up to one packet of data to the buffer */ - if (m_DecodeSize < m_EncPacketSize) - { - unsigned int copy = (fSize > m_EncPacketSize) ? m_EncPacketSize : fSize; - if (copy) - { - memcpy(m_DecodeBuffer + m_DecodeSize, decData, copy); - m_DecodeSize += copy; - decData += copy; - fSize -= copy; - } - } - - /* encode the data and advance our data pointer */ - eUsed = m_Encoder->Encode(m_DecodeBuffer, m_EncPacketSize); - avail -= eUsed; - - /* shift buffered data along with memmove as the data can overlap */ - m_DecodeSize -= eUsed; - memmove(m_DecodeBuffer, m_DecodeBuffer + eUsed, m_DecodeSize); - - /* output the frame of data */ - while((eCoded = m_Encoder->GetData(&encData))) - WriteFrame(m_SPDIF, encData, eCoded); - } - - /* append any leftover data to the buffer */ - memcpy(m_DecodeBuffer + m_DecodeSize, decData, fSize); - m_DecodeSize += fSize; - - return used; - } - /* if we are muxing into ADTS (AAC) */ int adts_used = 0; if (m_ADTS.m_pFormat) @@ -575,16 +459,17 @@ void CDVDAudioCodecPassthroughFFmpeg::Reset() ResetMuxer(m_SPDIF); ResetMuxer(m_ADTS ); - - if (m_Encoder) - m_Encoder->Reset(); } int CDVDAudioCodecPassthroughFFmpeg::GetChannels() { //Can't return correct channels here as this is used to keep sync. //should probably have some other way to find out this - return OUT_CHANNELS; + switch(m_codec) + { + default: + return 2; + } } int CDVDAudioCodecPassthroughFFmpeg::GetSampleRate() @@ -592,6 +477,23 @@ int CDVDAudioCodecPassthroughFFmpeg::GetSampleRate() return m_SPDIF.m_pStream->codec->sample_rate; } +int CDVDAudioCodecPassthroughFFmpeg::GetEncodedSampleRate() +{ + return m_SPDIF.m_pStream->codec->sample_rate; +} + +enum AEDataFormat CDVDAudioCodecPassthroughFFmpeg::GetDataFormat() +{ + switch(m_codec) + { + case CODEC_ID_AC3: return AE_FMT_AC3; + case CODEC_ID_DTS: return AE_FMT_DTS; + default: + return AE_FMT_INVALID; //Unknown stream type + } +} + + int CDVDAudioCodecPassthroughFFmpeg::GetBitsPerSample() { return OUT_SAMPLESIZE; @@ -731,3 +633,18 @@ unsigned int CDVDAudioCodecPassthroughFFmpeg::SyncAAC(BYTE* pData, unsigned int return iSize; } /* ========================== END SYNC FUNCTIONS ========================== */ + + +CAEChannelInfo CDVDAudioCodecPassthroughFFmpeg::GetChannelMap() +{ + static enum AEChannel map[2][9] = { + {AE_CH_RAW, AE_CH_RAW, AE_CH_NULL}, + {AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_NULL} + }; + + switch(m_codec) + { + default: + return map[0]; + } +} diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h index d16afc8c38..acef62247d 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h @@ -27,11 +27,8 @@ #include "DllAvCodec.h" #include "DllAvUtil.h" -#include "../DVDFactoryCodec.h" #include "DVDAudioCodec.h" -class IDVDAudioEncoder; - class CDVDAudioCodecPassthroughFFmpeg : public CDVDAudioCodec { public: @@ -44,8 +41,10 @@ public: virtual int GetData(BYTE** dst); virtual void Reset(); virtual int GetChannels(); - virtual enum PCMChannels *GetChannelMap() { static enum PCMChannels map[2] = {PCM_FRONT_LEFT, PCM_FRONT_RIGHT}; return map; } - virtual int GetSampleRate(); + virtual CAEChannelInfo GetChannelMap(); + virtual int GetSampleRate(); + virtual int GetEncodedSampleRate(); + virtual enum AEDataFormat GetDataFormat(); virtual int GetBitsPerSample(); virtual bool NeedPassthrough() { return true; } virtual const char* GetName() { return "PassthroughFFmpeg"; } @@ -87,19 +86,16 @@ private: bool m_bSupportsAACOut; CDVDAudioCodec *m_Codec; - IDVDAudioEncoder *m_Encoder; - bool m_InitEncoder; - unsigned int m_EncPacketSize; BYTE *m_DecodeBuffer; unsigned int m_DecodeSize; bool SupportsFormat(CDVDStreamInfo &hints); - bool SetupEncoder (CDVDStreamInfo &hints); uint8_t m_NeededBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE]; unsigned int m_NeededUsed; unsigned int m_Needed; bool m_LostSync; int m_SampleRate; + CodecID m_codec; unsigned int (CDVDAudioCodecPassthroughFFmpeg::*m_pSyncFrame)(BYTE* pData, unsigned int iSize, unsigned int *fSize); unsigned int SyncAC3(BYTE* pData, unsigned int iSize, unsigned int *fSize); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp index ca3d7db544..0f7f605df7 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp @@ -293,18 +293,19 @@ int CDVDAudioCodecPcm::GetChannels() return m_iOutputChannels; } -enum PCMChannels* CDVDAudioCodecPcm::GetChannelMap() +CAEChannelInfo CDVDAudioCodecPcm::GetChannelMap() { - static enum PCMChannels map[8][8] = + assert(m_iOutputChannels > 0 && m_iOutputChannels <= 8); + static enum AEChannel map[8][9] = { - /* MONO */ {PCM_FRONT_CENTER }, - /* STEREO */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT }, - /* 3.0 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER }, - /* 4.0 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_LEFT , PCM_BACK_RIGHT }, - /* 5.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT , PCM_BACK_RIGHT }, - /* 5.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_BACK_LEFT , PCM_BACK_RIGHT }, - /* 7.0 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT , PCM_BACK_RIGHT, PCM_SIDE_LEFT , PCM_SIDE_RIGHT }, - /* 7.1 ? */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_BACK_LEFT , PCM_BACK_RIGHT, PCM_SIDE_LEFT , PCM_SIDE_RIGHT } + /* MONO */ {AE_CH_FC, AE_CH_NULL, }, + /* STEREO */ {AE_CH_FL, AE_CH_FR, AE_CH_NULL, }, + /* 3.0 ? */ {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_NULL, }, + /* 4.0 ? */ {AE_CH_FL, AE_CH_FR, AE_CH_BL, AE_CH_BR , AE_CH_NULL, }, + /* 5.0 */ {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL , AE_CH_BR, AE_CH_NULL }, + /* 5.1 */ {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_NULL, }, + /* 7.0 ? */ {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL , AE_CH_BR, AE_CH_SL, AE_CH_SR, AE_CH_NULL }, + /* 7.1 ? */ {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_SL, AE_CH_SR, AE_CH_NULL} }; return map[m_iOutputChannels - 1]; @@ -315,7 +316,7 @@ int CDVDAudioCodecPcm::GetSampleRate() return m_iSourceSampleRate; } -int CDVDAudioCodecPcm::GetBitsPerSample() +enum AEDataFormat CDVDAudioCodecPcm::GetDataFormat() { - return 16; + return AE_FMT_S16NE; } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h index b7d8f74d73..7ca2d0666b 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h @@ -34,9 +34,9 @@ public: virtual int GetData(BYTE** dst); virtual void Reset(); virtual int GetChannels(); - virtual enum PCMChannels* GetChannelMap(); + virtual CAEChannelInfo GetChannelMap(); virtual int GetSampleRate(); - virtual int GetBitsPerSample(); + virtual enum AEDataFormat GetDataFormat(); virtual const char* GetName() { return "pcm"; } protected: diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp index 983d9bfa62..78b34aad1e 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp @@ -41,7 +41,10 @@ #include "Audio/DVDAudioCodecLibMad.h" #include "Audio/DVDAudioCodecPcm.h" #include "Audio/DVDAudioCodecLPcm.h" +#if defined(TARGET_DARWIN_OSX) || defined(TARGET_DARWIN_IOS) #include "Audio/DVDAudioCodecPassthroughFFmpeg.h" +#endif +#include "Audio/DVDAudioCodecPassthrough.h" #include "Overlay/DVDOverlayCodecSSA.h" #include "Overlay/DVDOverlayCodecText.h" #include "Overlay/DVDOverlayCodecTX3G.h" @@ -270,8 +273,18 @@ CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint, bool p if (passthrough) { - pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options); - if ( pCodec ) return pCodec; +#if defined(TARGET_DARWIN_OSX) || defined(TARGET_DARWIN_IOS) + switch(hint.codec) + { + case CODEC_ID_AC3: + case CODEC_ID_DTS: + pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options ); + if( pCodec ) return pCodec; + break; + } +#endif + pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options ); + if( pCodec ) return pCodec; } switch (hint.codec) diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp index c41095a9c9..97c402b9f9 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp @@ -31,10 +31,18 @@ #include "utils/log.h" #include "utils/TimeUtils.h" #include "utils/MathUtils.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #include <sstream> #include <iomanip> +/* for sync-based resampling */ +#define PROPORTIONAL 20.0 +#define PROPREF 0.01 +#define PROPDIVMIN 2.0 +#define PROPDIVMAX 40.0 +#define INTEGRAL 200.0 + using namespace std; CPTSOutputQueue::CPTSOutputQueue() @@ -226,7 +234,6 @@ void CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints, CDVDAudioCodec* codec ) m_synctype = SYNC_DISCON; m_setsynctype = g_guiSettings.GetInt("videoplayer.synctype"); m_prevsynctype = -1; - m_resampler.SetQuality(g_guiSettings.GetInt("videoplayer.resamplequality")); m_error = 0; m_errorbuff = 0; @@ -277,7 +284,6 @@ void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers) // flush any remaining pts values m_ptsOutput.Flush(); - m_resampler.Flush(); } // decode one audio frame and returns its uncompressed size @@ -328,16 +334,20 @@ int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &audioframe, bool bDropPacket) // get decoded data and the size of it audioframe.size = m_pAudioCodec->GetData(&audioframe.data); - audioframe.pts = m_audioClock; - audioframe.channel_map = m_pAudioCodec->GetChannelMap(); - audioframe.channel_count = m_pAudioCodec->GetChannels(); - audioframe.bits_per_sample = m_pAudioCodec->GetBitsPerSample(); - audioframe.sample_rate = m_pAudioCodec->GetSampleRate(); - audioframe.passthrough = m_pAudioCodec->NeedPassthrough(); + audioframe.pts = m_audioClock; if (audioframe.size <= 0) continue; + audioframe.channel_layout = m_pAudioCodec->GetChannelMap(); + audioframe.channel_count = m_pAudioCodec->GetChannels(); + audioframe.encoded_channel_count = m_pAudioCodec->GetEncodedChannels(); + audioframe.data_format = m_pAudioCodec->GetDataFormat(); + audioframe.bits_per_sample = CAEUtil::DataFormatToBits(audioframe.data_format); + audioframe.sample_rate = m_pAudioCodec->GetSampleRate(); + audioframe.encoded_sample_rate = m_pAudioCodec->GetEncodedSampleRate(); + audioframe.passthrough = m_pAudioCodec->NeedPassthrough(); + if (m_streaminfo.samplerate != audioframe.sample_rate) { // The sample rate has changed or we just got it for the first time @@ -440,7 +450,6 @@ int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &audioframe, bool bDropPacket) m_dvdAudio.Flush(); m_ptsOutput.Flush(); m_ptsInput.Flush(); - m_resampler.Flush(); m_syncclock = true; m_stalled = true; m_started = false; @@ -486,7 +495,6 @@ int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &audioframe, bool bDropPacket) else { m_ptsOutput.Flush(); - m_resampler.Flush(); m_syncclock = true; if (m_speed != DVD_PLAYSPEED_PAUSE) m_dvdAudio.Flush(); @@ -589,7 +597,7 @@ void CDVDPlayerAudio::Process() else m_dvdAudio.Pause(); - if(!m_dvdAudio.Create(audioframe, m_streaminfo.codec)) + if(!m_dvdAudio.Create(audioframe, m_streaminfo.codec, m_setsynctype == SYNC_RESAMPLE)) CLog::Log(LOGERROR, "%s - failed to create audio renderer", __FUNCTION__); } @@ -709,7 +717,6 @@ void CDVDPlayerAudio::HandleSyncError(double duration) m_integral = 0; m_skipdupcount = 0; m_error = 0; - m_resampler.Flush(); m_errortime = CurrentHostCounter(); return; } @@ -822,19 +829,10 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe) proportional = m_error / DVD_TIME_BASE / proportionaldiv; } - m_resampleratio = 1.0 / g_VideoReferenceClock.GetSpeed() + proportional + m_integral; - m_resampler.SetRatio(m_resampleratio); - //add to the resampler - m_resampler.Add(audioframe, audioframe.pts); - //give any packets from the resampler to the audiorenderer - bool packetadded = false; - while(m_resampler.Retrieve(audioframe, audioframe.pts)) - { - m_dvdAudio.AddPackets(audioframe); - packetadded = true; - } - return packetadded; + m_resampleratio = 1.0 / g_VideoReferenceClock.GetSpeed() + proportional + m_integral; + m_dvdAudio.SetResampleRatio(m_resampleratio); + m_dvdAudio.AddPackets(audioframe); } return true; diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.h b/xbmc/cores/dvdplayer/DVDPlayerAudio.h index 43ffdde608..e71bd51f07 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h @@ -28,7 +28,8 @@ #include "DVDDemuxers/DVDDemuxUtils.h" #include "DVDStreamInfo.h" #include "utils/BitstreamStats.h" -#include "DVDPlayerAudioResampler.h" + +#include "cores/AudioEngine/AEAudioFormat.h" #include <list> #include <queue> @@ -54,10 +55,13 @@ typedef struct stDVDAudioFrame unsigned int size; int channel_count; - enum PCMChannels *channel_map; - int bits_per_sample; - int sample_rate; - bool passthrough; + int encoded_channel_count; + CAEChannelInfo channel_layout; + enum AEDataFormat data_format; + int bits_per_sample; + int sample_rate; + int encoded_sample_rate; + bool passthrough; } DVDAudioFrame; class CPTSOutputQueue @@ -182,8 +186,6 @@ protected: double m_duration; // last packets duration bool m_silence; - CDVDPlayerResampler m_resampler; - bool OutputPacket(DVDAudioFrame &audioframe); //SYNC_DISCON, SYNC_SKIPDUP, SYNC_RESAMPLE |