Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

ActiveAE: check input stream for ffmpeg channel order, remap if it do…

…es not match
  • Loading branch information...
commit 45f2700e13d69af915071e984073a6a91f680ba2 1 parent c982262
@FernetMenta FernetMenta authored
View
3  xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
@@ -1007,6 +1007,9 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt)
(*it)->m_inputBuffers = new CActiveAEBufferPool((*it)->m_format);
(*it)->m_inputBuffers->Create(MAX_CACHE_LEVEL*1000);
(*it)->m_streamSpace = (*it)->m_format.m_frameSize * (*it)->m_format.m_frames;
+
+ // if input format does not follow ffmpeg channel mask, we may need to remap channels
+ (*it)->InitRemapper();
}
if (initSink && (*it)->m_resampleBuffers)
{
View
5 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp
@@ -25,6 +25,9 @@ using namespace ActiveAE;
CActiveAEResample::CActiveAEResample()
{
m_pContext = NULL;
+ m_loaded = false;
+ if (m_dllAvUtil.Load() && m_dllSwResample.Load())
+ m_loaded = true;
}
CActiveAEResample::~CActiveAEResample()
@@ -38,7 +41,7 @@ CActiveAEResample::~CActiveAEResample()
bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality)
{
- if (!m_dllAvUtil.Load() || !m_dllSwResample.Load())
+ if (!m_loaded)
return false;
m_dst_chan_layout = dst_chan_layout;
View
1  xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h
@@ -51,6 +51,7 @@ class CActiveAEResample
protected:
DllAvUtil m_dllAvUtil;
DllSwResample m_dllSwResample;
+ bool m_loaded;
uint64_t m_src_chan_layout, m_dst_chan_layout;
int m_src_rate, m_dst_rate;
int m_src_channels, m_dst_channels;
View
106 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
@@ -56,11 +56,15 @@ CActiveAEStream::CActiveAEStream(AEAudioFormat *format)
m_leftoverBuffer = new uint8_t[m_format.m_frameSize];
m_leftoverBytes = 0;
m_forceResampler = false;
+ m_remapper = NULL;
+ m_remapBuffer = NULL;
}
CActiveAEStream::~CActiveAEStream()
{
delete [] m_leftoverBuffer;
+ delete m_remapper;
+ delete m_remapBuffer;
}
void CActiveAEStream::IncFreeBuffers()
@@ -81,6 +85,105 @@ void CActiveAEStream::ResetFreeBuffers()
m_streamFreeBuffers = 0;
}
+void CActiveAEStream::InitRemapper()
+{
+ // check if input format follows ffmpeg channel mask
+ bool needRemap = false;
+ unsigned int avLast, avCur = 0;
+ for(unsigned int i=0; i<m_format.m_channelLayout.Count(); i++)
+ {
+ avLast = avCur;
+ avCur = CActiveAEResample::GetAVChannel(m_format.m_channelLayout[i]);
+ if(avCur < avLast)
+ {
+ needRemap = true;
+ break;
+ }
+ }
+
+ if(needRemap)
+ {
+ CLog::Log(LOGDEBUG, "CActiveAEStream::%s - initialize remapper", __FUNCTION__);
+
+ m_remapper = new CActiveAEResample();
+ uint64_t avLayout = CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout);
+
+ // build layout according to ffmpeg channel order
+ // we need this for reference
+ CAEChannelInfo ffmpegLayout;
+ ffmpegLayout.Reset();
+ int idx = 0;
+ for(unsigned int i=0; i<m_format.m_channelLayout.Count(); i++)
+ {
+ for(unsigned int j=0; j<m_format.m_channelLayout.Count(); j++)
+ {
+ idx = m_remapper->GetAVChannelIndex(m_format.m_channelLayout[j], avLayout);
+ if (idx == i)
+ {
+ ffmpegLayout += m_format.m_channelLayout[j];
+ break;
+ }
+ }
+ }
+
+ // build remap layout we can pass to resampler as destination layout
+ CAEChannelInfo remapLayout;
+ remapLayout.Reset();
+ for(unsigned int i=0; i<m_format.m_channelLayout.Count(); i++)
+ {
+ for(unsigned int j=0; j<m_format.m_channelLayout.Count(); j++)
+ {
+ idx = m_remapper->GetAVChannelIndex(m_format.m_channelLayout[j], avLayout);
+ if (idx == i)
+ {
+ remapLayout += ffmpegLayout[j];
+ break;
+ }
+ }
+ }
+
+ // initialize resampler for only doing remapping
+ m_remapper->Init(avLayout,
+ m_format.m_channelLayout.Count(),
+ m_format.m_sampleRate,
+ CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
+ CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
+ avLayout,
+ m_format.m_channelLayout.Count(),
+ m_format.m_sampleRate,
+ CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
+ CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
+ false,
+ false,
+ &remapLayout,
+ AE_QUALITY_LOW); // not used for remapping
+
+ // extra sound packet, we can't resample to the same buffer
+ m_remapBuffer = new CSoundPacket(m_inputBuffers->m_allSamples[0]->pkt->config, m_inputBuffers->m_allSamples[0]->pkt->max_nb_samples);
+ }
+}
+
+void CActiveAEStream::RemapBuffer()
+{
+ if(m_remapper)
+ {
+ int samples = m_remapper->Resample(m_remapBuffer->data, m_remapBuffer->max_nb_samples,
+ m_currentBuffer->pkt->data, m_currentBuffer->pkt->nb_samples,
+ 1.0);
+
+ if (samples != m_currentBuffer->pkt->nb_samples)
+ {
+ CLog::Log(LOGERROR, "CActiveAEStream::%s - error remapping", __FUNCTION__);
+ }
+
+ // swap sound packets
+ CSoundPacket *tmp = m_remapBuffer;
+ tmp = m_currentBuffer->pkt;
+ m_currentBuffer->pkt = m_remapBuffer;
+ m_remapBuffer = tmp;
+ }
+}
+
unsigned int CActiveAEStream::GetSpace()
{
CSingleLock lock(m_streamLock);
@@ -150,6 +253,7 @@ unsigned int CActiveAEStream::AddData(void *data, unsigned int size)
MsgStreamSample msgData;
msgData.buffer = m_currentBuffer;
msgData.stream = this;
+ RemapBuffer();
m_streamPort->SendOutMessage(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
m_currentBuffer = NULL;
}
@@ -234,6 +338,7 @@ void CActiveAEStream::Drain(bool wait)
MsgStreamSample msgData;
msgData.buffer = m_currentBuffer;
msgData.stream = this;
+ RemapBuffer();
m_streamPort->SendOutMessage(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
m_currentBuffer = NULL;
}
@@ -248,6 +353,7 @@ void CActiveAEStream::Drain(bool wait)
MsgStreamSample msgData;
msgData.stream = this;
msgData.buffer = *((CSampleBuffer**)msg->data);
+ RemapBuffer();
msg->Reply(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
DecFreeBuffers();
continue;
View
6 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.h
@@ -38,6 +38,8 @@ class CActiveAEStream : public IAEStream
void IncFreeBuffers();
void DecFreeBuffers();
void ResetFreeBuffers();
+ void InitRemapper();
+ void RemapBuffer();
public:
virtual unsigned int GetSpace();
@@ -94,12 +96,14 @@ class CActiveAEStream : public IAEStream
CCriticalSection m_streamLock;
uint8_t *m_leftoverBuffer;
int m_leftoverBytes;
+ CSampleBuffer *m_currentBuffer;
+ CSoundPacket *m_remapBuffer;
+ CActiveAEResample *m_remapper;
// only accessed by engine
CActiveAEBufferPool *m_inputBuffers;
CActiveAEBufferPoolResample *m_resampleBuffers;
std::deque<CSampleBuffer*> m_processingSamples;
- CSampleBuffer *m_currentBuffer;
CActiveAEDataProtocol *m_streamPort;
CEvent m_inMsgEvent;
CCriticalSection *m_statsLock;
Please sign in to comment.
Something went wrong with that request. Please try again.