Merge pull request #3164 from koying/fixdroiddvdiso
[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 "AEFactory.h"
27 #include "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 }
60
61 CActiveAEStream::~CActiveAEStream()
62 {
63   delete [] m_leftoverBuffer;
64 }
65
66 void CActiveAEStream::IncFreeBuffers()
67 {
68   CSingleLock lock(m_streamLock);
69   m_streamFreeBuffers++;
70 }
71
72 void CActiveAEStream::DecFreeBuffers()
73 {
74   CSingleLock lock(m_streamLock);
75   m_streamFreeBuffers--;
76 }
77
78 void CActiveAEStream::ResetFreeBuffers()
79 {
80   CSingleLock lock(m_streamLock);
81   m_streamFreeBuffers = 0;
82 }
83
84 unsigned int CActiveAEStream::GetSpace()
85 {
86   CSingleLock lock(m_streamLock);
87   return m_streamFreeBuffers * m_streamSpace;
88 }
89
90 unsigned int CActiveAEStream::AddData(void *data, unsigned int size)
91 {
92   Message *msg;
93   unsigned int copied = 0;
94   unsigned int bytesToCopy = size;
95   uint8_t *buf = (uint8_t*)data;
96
97   while(copied < size)
98   {
99     buf = (uint8_t*)data;
100     bytesToCopy = size - copied;
101
102     if (m_currentBuffer)
103     {
104       // fill leftover buffer and copy it first
105       if (m_leftoverBytes && bytesToCopy >= (m_format.m_frameSize - m_leftoverBytes))
106       {
107         int fillbytes = m_format.m_frameSize - m_leftoverBytes;
108         memcpy(m_leftoverBuffer+m_leftoverBytes, (uint8_t*)data, fillbytes);
109         data = (uint8_t*)data + fillbytes;
110         size -= fillbytes;
111         // leftover buffer will be copied on next cycle
112         buf = m_leftoverBuffer;
113         bytesToCopy = m_format.m_frameSize;
114         m_leftoverBytes = 0;
115       }
116
117       int start = m_currentBuffer->pkt->nb_samples *
118                   m_currentBuffer->pkt->bytes_per_sample *
119                   m_currentBuffer->pkt->config.channels /
120                   m_currentBuffer->pkt->planes;
121
122       int freeSamples = m_currentBuffer->pkt->max_nb_samples - m_currentBuffer->pkt->nb_samples;
123       int availableSamples = bytesToCopy / m_format.m_frameSize;
124
125       // if we don't have a full frame, copy to leftover buffer
126       if (!availableSamples && bytesToCopy)
127       {
128         memcpy(m_leftoverBuffer+m_leftoverBytes, buf+copied, bytesToCopy);
129         m_leftoverBytes = bytesToCopy;
130         copied += bytesToCopy;
131       }
132
133       int samples = std::min(freeSamples, availableSamples);
134       int bytes = samples * m_format.m_frameSize;
135
136       //TODO: handle planar formats
137       if (m_convertFn)
138         m_convertFn(buf+copied, samples*m_currentBuffer->pkt->config.channels, (float*)(m_currentBuffer->pkt->data[0] + start));
139       else
140         memcpy(m_currentBuffer->pkt->data[0] + start, buf+copied, bytes);
141       {
142         CSingleLock lock(*m_statsLock);
143         m_currentBuffer->pkt->nb_samples += samples;
144         m_bufferedTime += (double)samples / m_currentBuffer->pkt->config.sample_rate;
145       }
146       if (buf != m_leftoverBuffer)
147         copied += bytes;
148       if (m_currentBuffer->pkt->nb_samples == m_currentBuffer->pkt->max_nb_samples)
149       {
150         MsgStreamSample msgData;
151         msgData.buffer = m_currentBuffer;
152         msgData.stream = this;
153         m_streamPort->SendOutMessage(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
154         m_currentBuffer = NULL;
155       }
156       continue;
157     }
158     else if (m_streamPort->ReceiveInMessage(&msg))
159     {
160       if (msg->signal == CActiveAEDataProtocol::STREAMBUFFER)
161       {
162         m_currentBuffer = *((CSampleBuffer**)msg->data);
163         msg->Release();
164         DecFreeBuffers();
165         continue;
166       }
167       else
168       {
169         CLog::Log(LOGERROR, "CActiveAEStream::AddData - unknown signal");
170         msg->Release();
171         break;
172       }
173     }
174     if (!m_inMsgEvent.WaitMSec(200))
175       break;
176   }
177   return copied;
178 }
179
180 double CActiveAEStream::GetDelay()
181 {
182   return AE.GetDelay(this);
183 }
184
185 bool CActiveAEStream::IsBuffering()
186 {
187   CSingleLock lock(m_streamLock);
188   return m_streamIsBuffering;
189 }
190
191 double CActiveAEStream::GetCacheTime()
192 {
193   return AE.GetCacheTime(this);
194 }
195
196 double CActiveAEStream::GetCacheTotal()
197 {
198   return AE.GetCacheTotal(this);
199 }
200
201 void CActiveAEStream::Pause()
202 {
203   AE.PauseStream(this, true);
204 }
205
206 void CActiveAEStream::Resume()
207 {
208   AE.PauseStream(this, false);
209 }
210
211 void CActiveAEStream::Drain(bool wait)
212 {
213   Message *msg;
214   CActiveAEStream *stream = this;
215
216   m_streamDraining = true;
217   m_streamDrained = false;
218
219   Message *reply;
220   if (m_streamPort->SendOutMessageSync(CActiveAEDataProtocol::DRAINSTREAM,
221                                        &reply,2000,
222                                        &stream, sizeof(CActiveAEStream*)))
223   {
224     bool success = reply->signal == CActiveAEDataProtocol::ACC ? true : false;
225     reply->Release();
226     if (!success)
227     {
228       CLog::Log(LOGERROR, "CActiveAEStream::Drain - no acc");
229     }
230   }
231
232   if (m_currentBuffer)
233   {
234     MsgStreamSample msgData;
235     msgData.buffer = m_currentBuffer;
236     msgData.stream = this;
237     m_streamPort->SendOutMessage(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
238     m_currentBuffer = NULL;
239   }
240
241   XbmcThreads::EndTime timer(2000);
242   while (!timer.IsTimePast())
243   {
244     if (m_streamPort->ReceiveInMessage(&msg))
245     {
246       if (msg->signal == CActiveAEDataProtocol::STREAMBUFFER)
247       {
248         MsgStreamSample msgData;
249         msgData.stream = this;
250         msgData.buffer = *((CSampleBuffer**)msg->data);
251         msg->Reply(CActiveAEDataProtocol::STREAMSAMPLE, &msgData, sizeof(MsgStreamSample));
252         DecFreeBuffers();
253         continue;
254       }
255       else if (msg->signal == CActiveAEDataProtocol::STREAMDRAINED)
256       {
257         msg->Release();
258         return;
259       }
260     }
261     else if (!wait)
262       return;
263
264     m_inMsgEvent.WaitMSec(timer.MillisLeft());
265   }
266   CLog::Log(LOGERROR, "CActiveAEStream::Drain - timeout out");
267 }
268
269 bool CActiveAEStream::IsDraining()
270 {
271   CSingleLock lock(m_streamLock);
272   return m_streamDraining;
273 }
274
275 bool CActiveAEStream::IsDrained()
276 {
277   CSingleLock lock(m_streamLock);
278   return m_streamDrained;
279 }
280
281 void CActiveAEStream::Flush()
282 {
283   m_currentBuffer = NULL;
284   m_leftoverBytes = 0;
285   AE.FlushStream(this);
286   ResetFreeBuffers();
287 }
288
289 float CActiveAEStream::GetAmplification()
290 {
291   return m_streamAmplify;
292 }
293
294 void CActiveAEStream::SetAmplification(float amplify)
295 {
296   m_streamAmplify = amplify;
297   AE.SetStreamAmplification(this, m_streamAmplify);
298 }
299
300 float CActiveAEStream::GetReplayGain()
301 {
302   return m_streamRgain;
303 }
304
305 void CActiveAEStream::SetReplayGain(float factor)
306 {
307   m_streamRgain = std::max( 0.0f, factor);
308   AE.SetStreamReplaygain(this, m_streamRgain);
309 }
310
311 float CActiveAEStream::GetVolume()
312 {
313   return m_streamVolume;
314 }
315
316 void CActiveAEStream::SetVolume(float volume)
317 {
318   m_streamVolume = std::max( 0.0f, std::min(1.0f, volume));
319   AE.SetStreamVolume(this, m_streamVolume);
320 }
321
322 double CActiveAEStream::GetResampleRatio()
323 {
324   return m_streamResampleRatio;
325 }
326
327 bool CActiveAEStream::SetResampleRatio(double ratio)
328 {
329   m_streamResampleRatio = ratio;
330   AE.SetStreamResampleRatio(this, m_streamResampleRatio);
331   return true;
332 }
333
334 void CActiveAEStream::FadeVolume(float from, float target, unsigned int time)
335 {
336   if (time == 0 || AE_IS_RAW(m_format.m_dataFormat))
337     return;
338
339   m_streamFading = true;
340   AE.SetStreamFade(this, from, target, time);
341 }
342
343 bool CActiveAEStream::IsFading()
344 {
345   CSingleLock lock(m_streamLock);
346   return m_streamFading;
347 }
348
349 const unsigned int CActiveAEStream::GetFrameSize() const
350 {
351   return m_format.m_frameSize;
352 }
353
354 const unsigned int CActiveAEStream::GetChannelCount() const
355 {
356   return m_format.m_channelLayout.Count();
357 }
358
359 const unsigned int CActiveAEStream::GetSampleRate() const
360 {
361   return m_format.m_sampleRate;
362 }
363
364 const unsigned int CActiveAEStream::GetEncodedSampleRate() const
365 {
366   return m_format.m_encodedRate;
367 }
368
369 const enum AEDataFormat CActiveAEStream::GetDataFormat() const
370 {
371   return m_format.m_dataFormat;
372 }
373
374 void CActiveAEStream::RegisterAudioCallback(IAudioCallback* pCallback)
375 {
376 }
377
378 void CActiveAEStream::UnRegisterAudioCallback()
379 {
380 }
381
382 void CActiveAEStream::RegisterSlave(IAEStream *slave)
383 {
384   CSingleLock lock(m_streamLock);
385   m_streamSlave = slave;
386 }
387