2 * Copyright (C) 2010-2013 Team XBMC
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "ActiveAEBuffer.h"
22 #include "cores/AudioEngine/AEFactory.h"
23 #include "cores/AudioEngine/Engines/ActiveAE/ActiveAE.h"
24 #include "cores/AudioEngine/Utils/AEUtil.h"
26 using namespace ActiveAE;
28 /* typecast AE to CActiveAE */
29 #define AE (*((CActiveAE*)CAEFactory::GetEngine()))
31 CSoundPacket::CSoundPacket(SampleConfig conf, int samples) : config(conf)
33 data = AE.AllocSoundSample(config, samples, bytes_per_sample, planes, linesize);
34 max_nb_samples = samples;
38 CSoundPacket::~CSoundPacket()
41 AE.FreeSoundSample(data);
44 CSampleBuffer::CSampleBuffer() : pkt(NULL), pool(NULL)
49 CSampleBuffer::~CSampleBuffer()
54 CSampleBuffer* CSampleBuffer::Acquire()
60 void CSampleBuffer::Return()
63 if (pool && refCount <= 0)
64 pool->ReturnBuffer(this);
67 CActiveAEBufferPool::CActiveAEBufferPool(AEAudioFormat format)
70 if (AE_IS_RAW(m_format.m_dataFormat))
71 m_format.m_dataFormat = AE_FMT_S16NE;
74 CActiveAEBufferPool::~CActiveAEBufferPool()
76 CSampleBuffer *buffer;
77 while(!m_allSamples.empty())
79 buffer = m_allSamples.front();
80 m_allSamples.pop_front();
85 CSampleBuffer* CActiveAEBufferPool::GetFreeBuffer()
87 CSampleBuffer* buf = NULL;
89 if (!m_freeSamples.empty())
91 buf = m_freeSamples.front();
92 m_freeSamples.pop_front();
98 void CActiveAEBufferPool::ReturnBuffer(CSampleBuffer *buffer)
100 buffer->pkt->nb_samples = 0;
101 m_freeSamples.push_back(buffer);
104 bool CActiveAEBufferPool::Create(unsigned int totaltime)
106 CSampleBuffer *buffer;
108 config.fmt = CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat);
109 config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat);
110 config.channels = m_format.m_channelLayout.Count();
111 config.sample_rate = m_format.m_sampleRate;
112 config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout);
114 unsigned int time = 0;
115 unsigned int buffertime = (m_format.m_frames*1000) / m_format.m_sampleRate;
117 while (time < totaltime || n < 5)
119 buffer = new CSampleBuffer();
121 buffer->pkt = new CSoundPacket(config, m_format.m_frames);
123 m_allSamples.push_back(buffer);
124 m_freeSamples.push_back(buffer);
132 //-----------------------------------------------------------------------------
134 CActiveAEBufferPoolResample::CActiveAEBufferPoolResample(AEAudioFormat inputFormat, AEAudioFormat outputFormat, AEQuality quality)
135 : CActiveAEBufferPool(outputFormat)
137 m_inputFormat = inputFormat;
138 if (AE_IS_RAW(m_inputFormat.m_dataFormat))
139 m_inputFormat.m_dataFormat = AE_FMT_S16NE;
141 m_fillPackets = false;
145 m_resampleRatio = 1.0;
146 m_resampleQuality = quality;
147 m_changeResampler = false;
148 m_stereoUpmix = false;
152 CActiveAEBufferPoolResample::~CActiveAEBufferPoolResample()
157 bool CActiveAEBufferPoolResample::Create(unsigned int totaltime, bool remap, bool upmix, bool normalize)
159 CActiveAEBufferPool::Create(totaltime);
161 m_stereoUpmix = upmix;
163 if ((m_format.m_channelLayout.Count() < m_inputFormat.m_channelLayout.Count() && !normalize))
166 if (m_inputFormat.m_channelLayout != m_format.m_channelLayout ||
167 m_inputFormat.m_sampleRate != m_format.m_sampleRate ||
168 m_inputFormat.m_dataFormat != m_format.m_dataFormat ||
171 m_resampler = new CActiveAEResample();
172 m_resampler->Init(CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout),
173 m_format.m_channelLayout.Count(),
174 m_format.m_sampleRate,
175 CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
176 CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
177 CActiveAEResample::GetAVChannelLayout(m_inputFormat.m_channelLayout),
178 m_inputFormat.m_channelLayout.Count(),
179 m_inputFormat.m_sampleRate,
180 CActiveAEResample::GetAVSampleFormat(m_inputFormat.m_dataFormat),
181 CAEUtil::DataFormatToUsedBits(m_inputFormat.m_dataFormat),
184 remap ? &m_format.m_channelLayout : NULL,
188 m_changeResampler = false;
193 void CActiveAEBufferPoolResample::ChangeResampler()
197 m_resampler = new CActiveAEResample();
198 m_resampler->Init(CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout),
199 m_format.m_channelLayout.Count(),
200 m_format.m_sampleRate,
201 CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
202 CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
203 CActiveAEResample::GetAVChannelLayout(m_inputFormat.m_channelLayout),
204 m_inputFormat.m_channelLayout.Count(),
205 m_inputFormat.m_sampleRate,
206 CActiveAEResample::GetAVSampleFormat(m_inputFormat.m_dataFormat),
207 CAEUtil::DataFormatToUsedBits(m_inputFormat.m_dataFormat),
213 m_changeResampler = false;
216 bool CActiveAEBufferPoolResample::ResampleBuffers(unsigned int timestamp)
223 if (m_changeResampler)
228 while(!m_inputSamples.empty())
230 in = m_inputSamples.front();
231 m_inputSamples.pop_front();
232 in->timestamp = timestamp;
233 m_outputSamples.push_back(in);
237 else if (m_procSample || !m_freeSamples.empty())
239 // GetBufferedSamples is not accurate because of rounding errors
240 int out_samples = m_resampler->GetBufferedSamples();
243 free_samples = m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples;
245 free_samples = m_format.m_frames;
247 bool skipInput = false;
248 // avoid that ffmpeg resample buffer grows too large
249 if (out_samples > free_samples * 2 && !m_empty)
252 bool hasInput = !m_inputSamples.empty();
254 if (hasInput || skipInput || m_drain || m_changeResampler)
258 m_procSample = GetFreeBuffer();
261 if (hasInput && !skipInput && !m_changeResampler)
263 in = m_inputSamples.front();
264 m_inputSamples.pop_front();
269 int start = m_procSample->pkt->nb_samples *
270 m_procSample->pkt->bytes_per_sample *
271 m_procSample->pkt->config.channels /
272 m_procSample->pkt->planes;
274 for(int i=0; i<m_procSample->pkt->planes; i++)
276 m_planes[i] = m_procSample->pkt->data[i] + start;
279 out_samples = m_resampler->Resample(m_planes,
280 m_procSample->pkt->max_nb_samples - m_procSample->pkt->nb_samples,
281 in ? in->pkt->data : NULL,
282 in ? in->pkt->nb_samples : 0,
284 m_procSample->pkt->nb_samples += out_samples;
286 m_empty = (out_samples == 0);
288 if ((m_drain || m_changeResampler) && m_empty)
290 if (m_fillPackets && m_procSample->pkt->nb_samples != 0)
293 start = m_procSample->pkt->nb_samples *
294 m_procSample->pkt->bytes_per_sample *
295 m_procSample->pkt->config.channels /
296 m_procSample->pkt->planes;
297 for(int i=0; i<m_procSample->pkt->planes; i++)
299 memset(m_procSample->pkt->data[i]+start, 0, m_procSample->pkt->linesize-start);
302 m_procSample->timestamp = timestamp;
304 // check if draining is finished
305 if (m_drain && m_procSample->pkt->nb_samples == 0)
307 m_procSample->Return();
311 m_outputSamples.push_back(m_procSample);
314 if (m_changeResampler)
317 // some methods like encode require completely filled packets
318 else if (!m_fillPackets || (m_procSample->pkt->nb_samples == m_procSample->pkt->max_nb_samples))
320 m_procSample->timestamp = timestamp;
321 m_outputSamples.push_back(m_procSample);
332 float CActiveAEBufferPoolResample::GetDelay()
335 std::deque<CSampleBuffer*>::iterator itBuf;
338 delay += m_procSample->pkt->nb_samples / m_procSample->pkt->config.sample_rate;
340 for(itBuf=m_inputSamples.begin(); itBuf!=m_inputSamples.end(); ++itBuf)
342 delay += (float)(*itBuf)->pkt->nb_samples / (*itBuf)->pkt->config.sample_rate;
345 for(itBuf=m_outputSamples.begin(); itBuf!=m_outputSamples.end(); ++itBuf)
347 delay += (float)(*itBuf)->pkt->nb_samples / (*itBuf)->pkt->config.sample_rate;
352 int samples = m_resampler->GetBufferedSamples();
353 delay += (float)samples / m_format.m_sampleRate;
359 void CActiveAEBufferPoolResample::Flush()
363 m_procSample->Return();
366 while (!m_inputSamples.empty())
368 m_inputSamples.front()->Return();
369 m_inputSamples.pop_front();
371 while (!m_outputSamples.empty())
373 m_outputSamples.front()->Return();
374 m_outputSamples.pop_front();