aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey McRae <gnif@xbmc.org>2012-04-25 15:21:48 +1200
committerJonathan Marshall <jmarshall@never.you.mind>2012-05-10 09:40:50 +1200
commit08b78c8fee881cc782060dc3966a8ee9a8398244 (patch)
tree2bd0f0bb67b44261d5163747b399e8a740229428
parent964a1507e91e086f7d838290e1dec96edd457ed7 (diff)
[AE] dvdplayer: switch to use AE
-rw-r--r--xbmc/cores/dvdplayer/DVDAudio.cpp171
-rw-r--r--xbmc/cores/dvdplayer/DVDAudio.h13
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h18
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp123
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h27
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.cpp104
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecLibMad.h14
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp171
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h14
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.cpp25
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPcm.h4
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp17
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayerAudio.cpp46
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayerAudio.h16
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