99989b385cc52579c42fb8e99e675d04a9510c66
[vuplus_xbmc] / xbmc / cores / AudioEngine / Engines / ActiveAE / ActiveAEStream.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program 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
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "system.h"
22 #include "threads/SingleLock.h"
23 #include "utils/log.h"
24 #include "utils/MathUtils.h"
25
26 #include "cores/AudioEngine/AEFactory.h"
27 #include "cores/AudioEngine/Utils/AEUtil.h"
28
29 #include "ActiveAE.h"
30 #include "ActiveAEStream.h"
31
32 using namespace ActiveAE;
33
34 /* typecast AE to CActiveAE */
35 #define AE (*((CActiveAE*)CAEFactory::GetEngine()))
36
37
38 CActiveAEStream::CActiveAEStream(AEAudioFormat *format)
39 {
40   m_format = *format;
41   m_bufferedTime = 0;
42   m_currentBuffer = NULL;
43   m_drain = false;
44   m_paused = false;
45   m_rgain = 1.0;
46   m_volume = 1.0;
47   m_amplify = 1.0;
48   m_streamSpace = m_format.m_frameSize * m_format.m_frames;
49   m_streamDraining = false;
50   m_streamDrained = false;
51   m_streamFading = false;
52   m_streamFreeBuffers = 0;
53   m_streamIsBuffering = true;
54   m_streamSlave = NULL;
55   m_convertFn = NULL;
56   m_leftoverBuffer = new uint8_t[m_format.m_frameSize];
57   m_leftoverBytes = 0;
58   m_forceResampler = false;
59   m_remapper = NULL;
60   m_remapBuffer = NULL;
61 }
62
63 CActiveAEStream::~CActiveAEStream()
64 {
65   delete [] m_leftoverBuffer;
66   delete m_remapper;
67   delete m_remapBuffer;
68 }
69
70 void CActiveAEStream::IncFreeBuffers()
71 {
72   CSingleLock lock(m_streamLock);
73   m_streamFreeBuffers++;
74 }
75
76 void CActiveAEStream::DecFreeBuffers()
77 {
78   CSingleLock lock(m_streamLock);
79   m_streamFreeBuffers--;
80 }
81
82 void CActiveAEStream::ResetFreeBuffers()
83 {
84   CSingleLock lock(m_streamLock);
85   m_streamFreeBuffers = 0;
86 }
87
88 void CActiveAEStream::InitRemapper()
89 {
90   // check if input format follows ffmpeg channel mask
91   bool needRemap = false;
92   unsigned int avLast, avCur = 0;
93   for(unsigned int i=0; i<m_format.m_channelLayout.Count(); i++)
94   {
95     avLast = avCur;
96     avCur = CActiveAEResample::GetAVChannel(m_format.m_channelLayout[i]);
97     if(avCur < avLast)
98     {
99       needRemap = true;
100       break;
101     }
102   }
103
104   if(needRemap)
105   {
106     CLog::Log(LOGDEBUG, "CActiveAEStream::%s - initialize remapper", __FUNCTION__);
107
108     m_remapper = new CActiveAEResample();
109     uint64_t avLayout = CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout);
110
111     // build layout according to ffmpeg channel order
112     // we need this for reference
113     CAEChannelInfo ffmpegLayout;
114     ffmpegLayout.Reset();
115     int idx = 0;
116     for(unsigned int i=0; i<m_format.m_channelLayout.Count(); i++)
117     {
118       for(unsigned int j=0; j<m_format.m_channelLayout.Count(); j++)
119       {
120         idx = m_remapper->GetAVChannelIndex(m_format.m_channelLayout[j], avLayout);
121         if (idx == (int)i)
122         {
123           ffmpegLayout += m_format.m_channelLayout[j];
124           break;
125         }
126       }
127     }
128
129     // build remap layout we can pass to resampler as destination layout
130     CAEChannelInfo remapLayout;
131     remapLayout.Reset();
132     for(unsigned int i=0; i<m_format.m_channelLayout.Count(); i++)
133     {
134       for(unsigned int j=0; j<m_format.m_channelLayout.Count(); j++)
135       {
136         idx = m_remapper->GetAVChannelIndex(m_format.m_channelLayout[j], avLayout);
137         if (idx == (int)i)
138         {
139           remapLayout += ffmpegLayout[j];
140           break;
141         }
142       }
143     }
144
145     // initialize resampler for only doing remapping
146     m_remapper->Init(avLayout,
147                      m_format.m_channelLayout.Count(),
148                      m_format.m_sampleRate,
149                      CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
150                      CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
151                      avLayout,
152                      m_format.m_channelLayout.Count(),
153                      m_format.m_sampleRate,
154                      CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
155                      CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
156                      false,
157                      false,
158                      &remapLayout,
159                      AE_QUALITY_LOW); // not used for remapping
160
161     // extra sound packet, we can't resample to the same buffer
162     m_remapBuffer = new CSoundPacket(m_inputBuffers->m_allSamples[0]->pkt->config, m_inputBuffers->m_allSamples[0]->pkt->max_nb_samples);
163   }
164 }
165
166 void CActiveAEStream::RemapBuffer()
167 {
168   if(m_remapper)
169   {
170     int samples = m_remapper->Resample(m_remapBuffer->data, m_remapBuffer->max_nb_samples,
171                                        m_currentBuffer->pkt->data, m_currentBuffer->pkt->nb_samples,
172                                        1.0);
173
174     if (samples != m_currentBuffer->pkt->nb_samples)
175     {
176       CLog::Log(LOGERROR, "CActiveAEStream::%s - error remapping", __FUNCTION__);
177     }
178
179     // swap sound packets
180     CSoundPacket *tmp = m_remapBuffer;
181     tmp = m_currentBuffer->pkt;
182     m_currentBuffer->pkt = m_remapBuffer;
183     m_remapBuffer = tmp;
184   }
185 }
186
187 unsigned int CActiveAEStream::GetSpace()
188 {
189   CSingleLock lock(m_streamLock);
190   return m_streamFreeBuffers * m_streamSpace;
191 }
192
193 unsigned int CActiveAEStream::AddData(void *data, unsigned int size)
194 {
195   Message *msg;
196   unsigned int copied = 0;
197   unsigned int bytesToCopy = size;
198   uint8_t *buf = (uint8_t*)data;
199
200   while(copied < size)
201   {
202     buf = ((uint8_t*)data) + copied;
203     bytesToCopy = size - copied;
204
205     if (m_currentBuffer)
206     {
207       // fill leftover buffer and copy it first
208       if (m_leftoverBytes && bytesToCopy >= (m_format.m_frameSize - m_leftoverBytes))
209       {
210         int fillbytes = m_format.m_frameSize - m_leftoverBytes;
211         memcpy(m_leftoverBuffer+m_leftoverBytes, buf, fillbytes);
212         copied += fillbytes;
213         // leftover buffer will be copied on next cycle
214         buf = m_leftoverBuffer;
215         bytesToCopy = m_format.m_frameSize;
216         m_leftoverBytes = 0;
217       }
218
219       int start = m_currentBuffer->pkt->nb_samples *
220                   m_currentBuffer->pkt->bytes_per_sample *
221                   m_currentBuffer->pkt->config.channels /
222                   m_currentBuffer->pkt->planes;
223
224       int freeSamples = m_currentBuffer->pkt->max_nb_samples - m_currentBuffer->pkt->nb_samples;
225       int availableSamples = bytesToCopy / m_format.m_frameSize;
226
227       // if we don't have a full frame, copy to leftover buffer
228       if (!availableSamples && bytesToCopy)
229       {
230         memcpy(m_leftoverBuffer+m_leftoverBytes, buf, bytesToCopy);
231         m_leftoverBytes = bytesToCopy;
232         copied += bytesToCopy;
233       }
234
235       int samples = std::min(freeSamples, availableSamples);
236       int bytes = samples * m_format.m_frameSize;
237
238       //TODO: handle planar formats
239       if (m_convertFn)
240         m_convertFn(buf, samples*m_currentBuffer->pkt->config.channels, (float*)(m_currentBuffer->pkt->data[0] + start));
241       else
242         memcpy(m_currentBuffer->pkt->data[0] + start, buf, bytes);
243       {
244         CSingleLock lock(*m_statsLock);
245         m_currentBuffer->pkt->nb_samples += samples;
246         m_bufferedTime += (double)samples / m_currentBuffer->pkt->config.sample_rate;
247       }
248       if (buf != m_leftoverBuffer)
249         copied += bytes;
250       if (m_currentBuffer->pkt->nb_samples == m_currentBuffer->pkt->max_nb_samples)
251       {
252         MsgStreamSample msgData;
253         msgData.buffer = m_currentBuffer;
254         msgData.stream = this;
255         RemapBuffer();
256         m_streamPort->SendOutMessage(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
257         m_currentBuffer = NULL;
258       }
259       continue;
260     }
261     else if (m_streamPort->ReceiveInMessage(&msg))
262     {
263       if (msg->signal == CActiveAEDataProtocol::STREAMBUFFER)
264       {
265         m_currentBuffer = *((CSampleBuffer**)msg->data);
266         msg->Release();
267         DecFreeBuffers();
268         continue;
269       }
270       else
271       {
272         CLog::Log(LOGERROR, "CActiveAEStream::AddData - unknown signal");
273         msg->Release();
274         break;
275       }
276     }
277     if (!m_inMsgEvent.WaitMSec(200))
278       break;
279   }
280   return copied;
281 }
282
283 double CActiveAEStream::GetDelay()
284 {
285   return AE.GetDelay(this);
286 }
287
288 bool CActiveAEStream::IsBuffering()
289 {
290   CSingleLock lock(m_streamLock);
291   return m_streamIsBuffering;
292 }
293
294 double CActiveAEStream::GetCacheTime()
295 {
296   return AE.GetCacheTime(this);
297 }
298
299 double CActiveAEStream::GetCacheTotal()
300 {
301   return AE.GetCacheTotal(this);
302 }
303
304 void CActiveAEStream::Pause()
305 {
306   AE.PauseStream(this, true);
307 }
308
309 void CActiveAEStream::Resume()
310 {
311   AE.PauseStream(this, false);
312 }
313
314 void CActiveAEStream::Drain(bool wait)
315 {
316   Message *msg;
317   CActiveAEStream *stream = this;
318
319   m_streamDraining = true;
320   m_streamDrained = false;
321
322   Message *reply;
323   if (m_streamPort->SendOutMessageSync(CActiveAEDataProtocol::DRAINSTREAM,
324                                        &reply,2000,
325                                        &stream, sizeof(CActiveAEStream*)))
326   {
327     bool success = reply->signal == CActiveAEDataProtocol::ACC ? true : false;
328     reply->Release();
329     if (!success)
330     {
331       CLog::Log(LOGERROR, "CActiveAEStream::Drain - no acc");
332     }
333   }
334
335   if (m_currentBuffer)
336   {
337     MsgStreamSample msgData;
338     msgData.buffer = m_currentBuffer;
339     msgData.stream = this;
340     RemapBuffer();
341     m_streamPort->SendOutMessage(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
342     m_currentBuffer = NULL;
343   }
344
345   XbmcThreads::EndTime timer(2000);
346   while (!timer.IsTimePast())
347   {
348     if (m_streamPort->ReceiveInMessage(&msg))
349     {
350       if (msg->signal == CActiveAEDataProtocol::STREAMBUFFER)
351       {
352         MsgStreamSample msgData;
353         msgData.stream = this;
354         msgData.buffer = *((CSampleBuffer**)msg->data);
355         msg->Reply(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
356         DecFreeBuffers();
357         continue;
358       }
359       else if (msg->signal == CActiveAEDataProtocol::STREAMDRAINED)
360       {
361         msg->Release();
362         return;
363       }
364     }
365     else if (!wait)
366       return;
367
368     m_inMsgEvent.WaitMSec(timer.MillisLeft());
369   }
370   CLog::Log(LOGERROR, "CActiveAEStream::Drain - timeout out");
371 }
372
373 bool CActiveAEStream::IsDraining()
374 {
375   CSingleLock lock(m_streamLock);
376   return m_streamDraining;
377 }
378
379 bool CActiveAEStream::IsDrained()
380 {
381   CSingleLock lock(m_streamLock);
382   return m_streamDrained;
383 }
384
385 void CActiveAEStream::Flush()
386 {
387   m_currentBuffer = NULL;
388   m_leftoverBytes = 0;
389   AE.FlushStream(this);
390   ResetFreeBuffers();
391 }
392
393 float CActiveAEStream::GetAmplification()
394 {
395   return m_streamAmplify;
396 }
397
398 void CActiveAEStream::SetAmplification(float amplify)
399 {
400   m_streamAmplify = amplify;
401   AE.SetStreamAmplification(this, m_streamAmplify);
402 }
403
404 float CActiveAEStream::GetReplayGain()
405 {
406   return m_streamRgain;
407 }
408
409 void CActiveAEStream::SetReplayGain(float factor)
410 {
411   m_streamRgain = std::max( 0.0f, factor);
412   AE.SetStreamReplaygain(this, m_streamRgain);
413 }
414
415 float CActiveAEStream::GetVolume()
416 {
417   return m_streamVolume;
418 }
419
420 void CActiveAEStream::SetVolume(float volume)
421 {
422   m_streamVolume = std::max( 0.0f, std::min(1.0f, volume));
423   AE.SetStreamVolume(this, m_streamVolume);
424 }
425
426 double CActiveAEStream::GetResampleRatio()
427 {
428   return m_streamResampleRatio;
429 }
430
431 bool CActiveAEStream::SetResampleRatio(double ratio)
432 {
433   m_streamResampleRatio = ratio;
434   AE.SetStreamResampleRatio(this, m_streamResampleRatio);
435   return true;
436 }
437
438 void CActiveAEStream::FadeVolume(float from, float target, unsigned int time)
439 {
440   if (time == 0 || AE_IS_RAW(m_format.m_dataFormat))
441     return;
442
443   m_streamFading = true;
444   AE.SetStreamFade(this, from, target, time);
445 }
446
447 bool CActiveAEStream::IsFading()
448 {
449   CSingleLock lock(m_streamLock);
450   return m_streamFading;
451 }
452
453 const unsigned int CActiveAEStream::GetFrameSize() const
454 {
455   return m_format.m_frameSize;
456 }
457
458 const unsigned int CActiveAEStream::GetChannelCount() const
459 {
460   return m_format.m_channelLayout.Count();
461 }
462
463 const unsigned int CActiveAEStream::GetSampleRate() const
464 {
465   return m_format.m_sampleRate;
466 }
467
468 const unsigned int CActiveAEStream::GetEncodedSampleRate() const
469 {
470   return m_format.m_encodedRate;
471 }
472
473 const enum AEDataFormat CActiveAEStream::GetDataFormat() const
474 {
475   return m_format.m_dataFormat;
476 }
477
478 void CActiveAEStream::RegisterAudioCallback(IAudioCallback* pCallback)
479 {
480 }
481
482 void CActiveAEStream::UnRegisterAudioCallback()
483 {
484 }
485
486 void CActiveAEStream::RegisterSlave(IAEStream *slave)
487 {
488   CSingleLock lock(m_streamLock);
489   m_streamSlave = slave;
490 }
491