changed: Improve (fallback) logic for subtitle downloading
[vuplus_xbmc] / xbmc / cores / AudioEngine / Engines / CoreAudio / CoreAudioAEStream.cpp
1 /*
2  *      Copyright (C) 2011-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
23 #include "CoreAudioAE.h"
24 #include "CoreAudioAEStream.h"
25
26 #include "xbmc/cores/AudioEngine/Interfaces/AE.h"
27 #include "xbmc/cores/AudioEngine/AEFactory.h"
28 #include "xbmc/cores/AudioEngine/Utils/AEUtil.h"
29 #include "xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h"
30 #include "settings/Settings.h"
31 #include "threads/SingleLock.h"
32 #include "settings/AdvancedSettings.h"
33 #include "utils/MathUtils.h"
34 #include "utils/log.h"
35
36
37
38 // typecast AE to CCoreAudioAE
39 #define AE (*(CCoreAudioAE*)CAEFactory::GetEngine())
40
41 void CheckOutputBufferSize(void **buffer, int *oldSize, int newSize)
42 {
43   if (newSize > *oldSize)
44   {
45     if (*buffer)
46       _aligned_free(*buffer);
47     *buffer = _aligned_malloc(newSize, 16);
48     *oldSize = newSize;
49   }
50   memset(*buffer, 0x0, *oldSize);
51 }
52
53 using namespace std;
54
55 template <class AudioDataType>
56 static inline void _Upmix(AudioDataType *input,
57   unsigned int channelsInput, AudioDataType *output,
58   unsigned int channelsOutput, unsigned int frames)
59 {
60   unsigned int unused = channelsOutput - channelsInput;
61   AudioDataType *_input  = input;
62   AudioDataType *_output = output;
63
64   for (unsigned int i = 0; i < frames; i++)
65   {
66     // get input channels
67     for(unsigned int j = 0; j < channelsInput; j++)
68       *_output++ = *_input++;
69     // set unused channels
70     for(unsigned int j = 0; j < unused; j++)
71       *_output++ = 0;
72   }
73 }
74
75 void CCoreAudioAEStream::Upmix(void *input,
76   unsigned int channelsInput,  void *output,
77   unsigned int channelsOutput, unsigned int frames, AEDataFormat dataFormat)
78 {
79   // input channels must be less than output channels
80   if (channelsInput >= channelsOutput)
81     return;
82
83   switch (CAEUtil::DataFormatToBits(dataFormat))
84   {
85     case 8:  _Upmix ( (unsigned char *) input, channelsInput, (unsigned char *) output, channelsOutput, frames ); break;
86     case 16: _Upmix ( (short         *) input, channelsInput, (short         *) output, channelsOutput, frames ); break;
87     case 32: _Upmix ( (float         *) input, channelsInput, (float         *) output, channelsOutput, frames ); break;
88     default: _Upmix ( (int           *) input, channelsInput, (int           *) output, channelsOutput, frames ); break;
89   }
90 }
91
92 CCoreAudioAEStream::CCoreAudioAEStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSamplerate, CAEChannelInfo channelLayout, unsigned int options, bool transcode) :
93   m_outputUnit      (NULL ),
94   m_valid           (false),
95   m_delete          (false),
96   m_volume          (1.0f ),
97   m_rgain           (1.0f ),
98   m_slave           (NULL ),
99   m_convertFn       (NULL ),
100   m_Buffer          (NULL ),
101   m_convertBuffer   (NULL ),
102   m_ssrc            (NULL ),
103   m_draining        (false),
104   m_AvgBytesPerSec  (0    ),
105   m_audioCallback   (NULL ),
106   m_fadeRunning     (false),
107   m_frameSize       (0    ),
108   m_doRemap         (true ),
109   m_firstInput      (true ),
110   m_flushRequested  (false),
111   m_encoder         (NULL )
112 {
113   m_ssrcData.data_out             = NULL;
114   m_transcode                     = transcode;
115
116   if (!transcode)
117   {
118     m_rawDataFormat                 = dataFormat;
119     m_StreamFormat.m_dataFormat     = dataFormat;
120     m_StreamFormat.m_sampleRate     = sampleRate;
121     m_StreamFormat.m_encodedRate    = 0;  //we don't support this
122     m_StreamFormat.m_channelLayout  = channelLayout;
123     m_isRaw                         = COREAUDIO_IS_RAW(dataFormat);
124   }
125   else
126   {
127     m_rawDataFormat                 = AE_FMT_AC3;
128     m_StreamFormat.m_dataFormat     = AE_FMT_AC3;
129     m_StreamFormat.m_sampleRate     = 48000;
130     m_StreamFormat.m_encodedRate    = 0;  
131     enum AEChannel ac3Layout[3] = {AE_CH_RAW, AE_CH_RAW, AE_CH_NULL};
132     m_StreamFormat.m_channelLayout  = ac3Layout;
133     m_isRaw                         = true;
134     
135     // setup encoder format
136     m_encoderFormat.m_dataFormat    = dataFormat;
137     m_encoderFormat.m_sampleRate    = sampleRate;
138     m_encoderFormat.m_encodedRate   = 0;
139     m_encoderFormat.m_channelLayout = channelLayout;
140     m_encoderFormat.m_frames        = 0;
141     m_encoderFormat.m_frameSamples  = 0;
142     m_encoderFormat.m_frameSize     = 0;
143   }
144   
145   m_incomingFormat                = dataFormat;
146   m_chLayoutCountStream           = m_StreamFormat.m_channelLayout.Count();
147   m_StreamFormat.m_frameSize      = (CAEUtil::DataFormatToBits(m_rawDataFormat) >> 3) * m_chLayoutCountStream;
148   m_OutputFormat                  = AE.GetAudioFormat();
149   m_chLayoutCountOutput           = m_OutputFormat.m_channelLayout.Count();
150
151   //m_forceResample                 = (options & AESTREAM_FORCE_RESAMPLE) != 0;
152   m_paused                        = (options & AESTREAM_PAUSED) != 0;
153
154   m_vizRemapBufferSize            = m_remapBufferSize = /*m_resampleBufferSize = */ m_upmixBufferSize = m_convertBufferSize = 16*1024;
155   m_convertBuffer                 = (float   *)_aligned_malloc(m_convertBufferSize,16);
156   //m_resampleBuffer                = (float   *)_aligned_malloc(m_resampleBufferSize,16);
157   m_upmixBuffer                   = (uint8_t *)_aligned_malloc(m_upmixBufferSize,16);
158   m_remapBuffer                   = (uint8_t *)_aligned_malloc(m_remapBufferSize,16);
159   m_vizRemapBuffer                = (uint8_t *)_aligned_malloc(m_vizRemapBufferSize,16);
160
161   m_limiter.SetSamplerate(AE.GetSampleRate());
162 }
163
164 CCoreAudioAEStream::~CCoreAudioAEStream()
165 {
166   CloseConverter();
167
168   m_delete = true;
169   m_valid = false;
170
171   InternalFlush();
172
173   _aligned_free(m_convertBuffer); m_convertBuffer = NULL;
174   //_aligned_free(m_resampleBuffer); m_resampleBuffer = NULL;
175   _aligned_free(m_remapBuffer); m_remapBuffer = NULL;
176   _aligned_free(m_vizRemapBuffer); m_vizRemapBuffer = NULL;
177   _aligned_free(m_upmixBuffer); m_upmixBuffer = NULL;
178
179   delete m_Buffer; m_Buffer = NULL;
180
181   delete m_encoder;
182   m_encoder = NULL;
183   ResetEncoder();
184   
185   m_unencodedBuffer.DeAlloc();
186   
187   /*
188   if (m_resample)
189   {
190     _aligned_free(m_ssrcData.data_out);
191     src_delete(m_ssrc);
192     m_ssrc = NULL;
193   }
194   */
195
196   CLog::Log(LOGDEBUG, "CCoreAudioAEStream::~CCoreAudioAEStream - Destructed");
197 }
198
199 void CCoreAudioAEStream::InitializeRemap()
200 {
201   if (!m_isRaw)
202   {
203     if (m_OutputFormat.m_channelLayout != AE.GetChannelLayout())
204     {
205       m_OutputFormat            = AE.GetAudioFormat();
206       m_chLayoutCountOutput     = m_OutputFormat.m_channelLayout.Count();
207       m_OutputBytesPerSample    = (CAEUtil::DataFormatToBits(m_OutputFormat.m_dataFormat) >> 3);
208
209       // re-init the remappers
210       m_remap   .Initialize(m_StreamFormat.m_channelLayout, m_OutputFormat.m_channelLayout, false);
211       m_vizRemap.Initialize(m_StreamFormat.m_channelLayout, CAEChannelInfo(AE_CH_LAYOUT_2_0), false, true);
212
213       InternalFlush();
214     }
215   }
216 }
217
218 void CCoreAudioAEStream::ReinitConverter()
219 {
220   CloseConverter();
221   OpenConverter();
222 }
223
224 // The source logic is in the HAL. The only thing we have to do here
225 // is to allocate the convrter and set the direct input call.
226 void CCoreAudioAEStream::CloseConverter()
227 {
228   // we have a converter, delete it
229   if (m_outputUnit)
230     m_outputUnit = (CAUOutputDevice *) AE.GetHAL()->DestroyUnit(m_outputUnit);
231
232   // it is save to unregister any direct input. the HAL takes care about it.
233   AE.GetHAL()->SetDirectInput(NULL, m_OutputFormat);
234 }
235
236 void CCoreAudioAEStream::OpenConverter()
237 {
238   // we always allocate a converter
239   // the HAL decides if we get converter.
240   // if there is already a converter delete it.
241   if (m_outputUnit)
242     m_outputUnit = (CAUOutputDevice *) AE.GetHAL()->DestroyUnit(m_outputUnit);
243
244   AEAudioFormat format = m_OutputFormat;
245
246   format.m_sampleRate = m_StreamFormat.m_sampleRate;
247   m_outputUnit = (CAUOutputDevice *) AE.GetHAL()->CreateUnit(this, format);
248
249   // it is safe to register any direct input. the HAL takes care about it.
250   AE.GetHAL()->SetDirectInput(this, m_OutputFormat);
251 }
252
253 void CCoreAudioAEStream::Initialize()
254 {
255   if (m_valid)
256     InternalFlush();
257
258   m_OutputFormat = AE.GetAudioFormat();
259   m_chLayoutCountOutput = m_OutputFormat.m_channelLayout.Count();
260
261   if (m_rawDataFormat == AE_FMT_LPCM)
262     m_OutputBytesPerSample = (CAEUtil::DataFormatToBits(AE_FMT_FLOAT) >> 3);
263   else
264     m_OutputBytesPerSample = (CAEUtil::DataFormatToBits(m_OutputFormat.m_dataFormat) >> 3);
265
266   if (m_isRaw || m_transcode)
267   {
268     // we are raw or transcode, which means we need to work in the output format
269     if (m_rawDataFormat != AE_FMT_LPCM)
270     {
271       m_StreamFormat = AE.GetAudioFormat();
272       m_chLayoutCountStream = m_StreamFormat.m_channelLayout.Count();
273     }
274     m_StreamBytesPerSample = (CAEUtil::DataFormatToBits(m_StreamFormat.m_dataFormat) >> 3);
275     m_doRemap = false;
276   }
277   else
278   {
279     if (!m_chLayoutCountStream)
280     {
281       m_valid = false;
282       return;
283     }
284     // Work around a bug in TrueHD and DTSHD deliver
285     if (m_StreamFormat.m_dataFormat == AE_FMT_TRUEHD || m_StreamFormat.m_dataFormat == AE_FMT_DTSHD)
286       m_StreamBytesPerSample = (CAEUtil::DataFormatToBits(AE_FMT_S16NE) >> 3);
287     else
288       m_StreamBytesPerSample = (CAEUtil::DataFormatToBits(m_StreamFormat.m_dataFormat) >> 3);
289     m_StreamFormat.m_frameSize = m_StreamBytesPerSample * m_chLayoutCountStream;
290   }
291
292   if (!m_isRaw)
293   {
294     if (!m_remap.Initialize(m_StreamFormat.m_channelLayout, m_OutputFormat.m_channelLayout, false))
295     {
296       m_valid = false;
297       return;
298     }
299
300     m_doRemap  = m_chLayoutCountStream != 2;
301
302     if (!m_vizRemap.Initialize(m_OutputFormat.m_channelLayout, CAEChannelInfo(AE_CH_LAYOUT_2_0), false, true))
303     {
304       m_valid = false;
305       return;
306     }
307   }
308
309   // only try to convert if we're not in AE_FMT_FLOAT and (we're not raw or we are transcoding)
310   m_convert =
311     (m_StreamFormat.m_dataFormat != AE_FMT_FLOAT && !m_isRaw)
312     ||
313     (m_incomingFormat != AE_FMT_FLOAT && m_transcode);
314   
315   
316   //m_resample = false; //(m_StreamFormat.m_sampleRate != m_OutputFormat.m_sampleRate) && !m_isRaw;
317
318   // if we need to convert, set it up
319   if (m_convert)
320   {
321     // get the conversion function and allocate a buffer for the data
322     CLog::Log(LOGDEBUG, "CCoreAudioAEStream::CCoreAudioAEStream - Converting from %s to AE_FMT_FLOAT", CAEUtil::DataFormatToStr(m_StreamFormat.m_dataFormat));
323     
324     if (!m_transcode)
325       m_convertFn = CAEConvert::ToFloat(m_StreamFormat.m_dataFormat);
326     else
327       m_convertFn = CAEConvert::ToFloat(m_incomingFormat);
328
329     if (!m_convertFn)
330       m_valid = false;
331   }
332   
333   // if we need to transcode, set it up
334   if (m_transcode)
335   {    
336     m_unencodedBuffer.Empty();
337
338     if (!m_encoder || !m_encoder->IsCompatible(m_encoderFormat))
339       SetupEncoder();
340   }
341
342   // if we need to resample, set it up
343   /*
344   if (m_resample)
345   {
346     int err;
347     m_ssrc                   = src_new(SRC_SINC_MEDIUM_QUALITY, m_chLayoutCountStream, &err);
348     m_ssrcData.src_ratio     = (double)m_OutputFormat.m_sampleRate / (double)m_StreamFormat.m_sampleRate;
349     m_ssrcData.data_in       = m_convertBuffer;
350     m_ssrcData.end_of_input  = 0;
351   }
352   */
353
354   // m_AvgBytesPerSec is calculated based on the output format.
355   // we have to keep in mind that we convert our data to the output format
356   m_AvgBytesPerSec = m_OutputFormat.m_frameSize * m_OutputFormat.m_sampleRate;
357
358   delete m_Buffer;
359   m_Buffer = new AERingBuffer(m_AvgBytesPerSec);
360
361   m_fadeRunning = false;
362
363   OpenConverter();
364
365   m_valid = true;
366 }
367
368 void CCoreAudioAEStream::Destroy()
369 {
370   m_valid  = false;
371   m_delete = true;
372   InternalFlush();
373 }
374
375 unsigned int CCoreAudioAEStream::AddData(void *data, unsigned int size)
376 {
377   unsigned int frames   = size / m_StreamFormat.m_frameSize;
378   unsigned int samples  = size / m_StreamBytesPerSample;
379   uint8_t     *adddata  = (uint8_t *)data;
380   unsigned int addsize  = size;
381   unsigned int channelsInBuffer = m_chLayoutCountStream;
382
383   if (m_flushRequested && m_paused)
384     InternalFlush();
385
386   if (!m_valid || size == 0 || data == NULL || !m_Buffer || m_flushRequested)
387     return 0;
388
389   // if the stream is draining
390   if (m_draining)
391   {
392     // if the stream has finished draining, cork it
393     if (m_Buffer && m_Buffer->GetReadSize() == 0)
394       m_draining = false;
395     else
396       return 0;
397   }
398
399   // convert the data if we need to
400   if (m_convert)
401   {
402     CheckOutputBufferSize((void **)&m_convertBuffer, &m_convertBufferSize, frames * channelsInBuffer  * m_OutputBytesPerSample);
403
404     samples = m_convertFn(adddata, size / m_StreamBytesPerSample, m_convertBuffer);
405     frames  = samples / channelsInBuffer;
406     addsize = frames * channelsInBuffer * m_OutputBytesPerSample;
407     adddata = (uint8_t *)m_convertBuffer;
408   }
409   else
410   {
411     samples = size / m_StreamBytesPerSample;
412     adddata = (uint8_t *)data;
413     addsize = size;
414   }
415
416   if (samples == 0)
417     return 0;
418
419   // transcode if we need to
420   if (m_transcode && m_encoder)
421   {
422     // put adddata in the unencodedBuffer
423     if (m_unencodedBuffer.Free() < addsize)
424       m_unencodedBuffer.ReAlloc(m_unencodedBuffer.Used() + addsize);
425     
426     m_unencodedBuffer.Push(adddata, addsize);
427     
428     unsigned int block = m_encoderFormat.m_frames * m_encoderFormat.m_frameSize;
429     
430     // only try to encode if we have enough data
431     if (m_unencodedBuffer.Used() >= block)
432     {
433         frames = m_encoder->Encode((float *)m_unencodedBuffer.Raw(block), m_encoderFormat.m_frames);
434         m_unencodedBuffer.Shift(NULL, frames * m_encoderFormat.m_frameSize);
435         addsize = m_encoder->GetData(&adddata);
436         samples = addsize / m_OutputBytesPerSample;
437     }
438     else
439       // return size here or whoever calling us will block if we return 0
440       // we have essentially been successful, because we add the audio to our buffer to encode
441       return size;
442   }
443
444   if (samples == 0)
445     return 0;
446
447
448   // resample it if we need to
449   /*
450   if (m_resample)
451   {
452     unsigned int resample_frames = samples / m_chLayoutCountStream;
453
454     CheckOutputBufferSize((void **)&m_resampleBuffer, &m_resampleBufferSize,
455                           resample_frames * std::ceil(m_ssrcData.src_ratio) * sizeof(float) * 2);
456
457     m_ssrcData.input_frames   = resample_frames;
458     m_ssrcData.output_frames  = resample_frames * std::ceil(m_ssrcData.src_ratio);
459     m_ssrcData.data_in        = (float *)adddata;
460     m_ssrcData.data_out       = m_resampleBuffer;
461
462     if (src_process(m_ssrc, &m_ssrcData) != 0)
463       return 0;
464
465     frames    = m_ssrcData.output_frames_gen;
466     samples   = frames * m_chLayoutCountStream;
467     adddata   = (uint8_t *)m_ssrcData.data_out;
468   }
469   else
470   {
471     frames    = samples / m_chLayoutCountStream;
472     samples   = frames * m_chLayoutCountStream;
473   }
474   */
475
476   if (m_doRemap)
477   {
478     addsize = frames * m_OutputBytesPerSample * m_chLayoutCountOutput;
479     CheckOutputBufferSize((void **)&m_remapBuffer, &m_remapBufferSize, addsize);
480
481     // downmix/remap the data
482     m_remap.Remap((float *)adddata, (float *)m_remapBuffer, frames);
483     adddata = (uint8_t *)m_remapBuffer;
484     channelsInBuffer = m_OutputFormat.m_channelLayout.Count();
485   }
486
487   // upmix the ouput to output channels
488   if ( (!m_isRaw || m_rawDataFormat == AE_FMT_LPCM) && (m_chLayoutCountOutput > channelsInBuffer) )
489   {
490     CheckOutputBufferSize((void **)&m_upmixBuffer, &m_upmixBufferSize, frames * m_chLayoutCountOutput  * sizeof(float));
491     Upmix(adddata, channelsInBuffer, m_upmixBuffer, m_chLayoutCountOutput, frames, m_OutputFormat.m_dataFormat);
492     adddata = m_upmixBuffer;
493     addsize = frames * m_chLayoutCountOutput *  sizeof(float);
494   }
495
496   unsigned int total_ms_sleep = 0;
497   unsigned int room = m_Buffer->GetWriteSize();
498   while (addsize > room && !m_paused && total_ms_sleep < 100)
499   {
500     // we got deleted
501     if (!m_valid || !m_Buffer || m_draining )
502       return 0;
503
504     unsigned int ms_sleep_time = (1000 * room) / m_AvgBytesPerSec;
505     if (ms_sleep_time == 0)
506       ms_sleep_time++;
507
508     // sleep until we have space (estimated) or 1ms min
509     Sleep(ms_sleep_time);
510     total_ms_sleep += ms_sleep_time;
511
512     room = m_Buffer->GetWriteSize();
513   }
514
515   if (addsize > room)
516     size = 0;
517   else
518     m_Buffer->Write(adddata, addsize);
519
520   // still only return size to indicate success
521   // we likely wrote something !size to m_Buffer, but our called doesn't realy care
522   return size;
523 }
524
525 // this is only called on the context of the coreaudio thread!
526 unsigned int CCoreAudioAEStream::GetFrames(uint8_t *buffer, unsigned int size)
527 {
528   // if we have been deleted
529   if (!m_valid || m_delete || !m_Buffer || m_paused)
530     return 0;
531   
532   if (m_flushRequested)
533   {
534     InternalFlush();
535     return 0;
536   }
537
538   unsigned int readsize = std::min(m_Buffer->GetReadSize(), size);
539   m_Buffer->Read(buffer, readsize);
540
541   if (!m_isRaw)
542   {
543     float *floatBuffer   = (float *)buffer;
544     unsigned int samples = readsize / m_OutputBytesPerSample;
545     unsigned int frames         = samples / m_chLayoutCountOutput;
546
547     // we have a frame, if we have a viz we need to hand the data to it.
548     // Keep in mind that our buffer is already in output format.
549     // So we remap output format to viz format !!!
550     if (m_OutputFormat.m_dataFormat == AE_FMT_FLOAT)
551     {
552       // TODO : Why the hell is vizdata limited ?
553       unsigned int samplesClamped = (samples > 512) ? 512 : samples;
554       if (samplesClamped)
555       {
556         // Viz channel count is 2
557         CheckOutputBufferSize((void **)&m_vizRemapBuffer, &m_vizRemapBufferSize, frames * 2 * sizeof(float));
558
559         m_vizRemap.Remap(floatBuffer, (float*)m_vizRemapBuffer, frames);
560         if (m_audioCallback)
561           m_audioCallback->OnAudioData((float *)m_vizRemapBuffer, samplesClamped);
562       }
563     }
564
565     // if we are fading
566     if (m_fadeRunning)
567     {
568       // TODO: check if we correctly respect the amount of our blockoperation
569       m_volume += (m_fadeStep * ((float)readsize / (float)m_OutputFormat.m_frameSize));
570       m_volume  = std::min(1.0f, std::max(0.0f, m_volume));
571       if (m_fadeDirUp)
572       {
573         if (m_volume >= m_fadeTarget)
574           m_fadeRunning = false;
575       }
576       else
577       {
578         if (m_volume <= m_fadeTarget)
579           m_fadeRunning = false;
580       }
581     }
582     
583     if (m_volume < 1.0f)
584     {
585 #ifdef __SSE__
586       CAEUtil::SSEMulArray(floatBuffer, m_volume, samples);
587 #else
588       for(unsigned int i = 0; i < samples; i++)
589         floatBuffer[i] *= m_volume;
590 #endif
591       CAEUtil::ClampArray(floatBuffer, samples);
592     }
593     // apply volume amplification by using the sogt limiter
594     // TODO - maybe reinvent the coreaudio compressor for this after frodo
595     else if (GetAmplification() != 1.0f)
596     {
597       for(unsigned int i = 0; i < frames; i++)
598       {
599         int frameIdx = i*m_chLayoutCountOutput;
600         float amplification = RunLimiter(&floatBuffer[frameIdx], m_chLayoutCountOutput);
601         float *frameStart = &floatBuffer[frameIdx];
602 #ifdef __SSE___
603         CAEUtil::SSEMulArray(frameStart, amplification, m_chLayoutCountOutput);
604 #else
605         for(unsigned int n = 0; n < m_chLayoutCountOutput; n++)
606           frameStart[n] *= amplification;
607 #endif
608         
609       }
610     }
611   }
612
613   return readsize;
614 }
615
616 const unsigned int CCoreAudioAEStream::GetFrameSize() const
617 {
618   return m_OutputFormat.m_frameSize;
619 }
620
621 unsigned int CCoreAudioAEStream::GetSpace()
622 {
623   if (!m_valid || m_draining)
624     return 0;
625
626   return m_Buffer->GetWriteSize() / m_OutputBytesPerSample  * m_StreamBytesPerSample;
627 }
628
629 double CCoreAudioAEStream::GetDelay()
630 {
631   if (m_delete || !m_Buffer || m_flushRequested)
632     return 0.0f;
633
634   double delayBuffer = (double)(m_Buffer->GetReadSize()) / (double)m_AvgBytesPerSec;
635   double delayTranscoder = 0.0;
636   
637   if (m_transcode)
638     delayTranscoder = (double)(m_unencodedBuffer.Used()) / (double)(m_encoderFormat.m_frameSize * m_encoderFormat.m_sampleRate);
639     
640   return AE.GetDelay() + delayBuffer + delayTranscoder;
641 }
642
643 bool CCoreAudioAEStream::IsBuffering()
644 {
645   return (m_Buffer->GetReadSize() == 0 && m_unencodedBuffer.Used() == 0);
646 }
647
648 double CCoreAudioAEStream::GetCacheTime()
649 {
650   if (m_delete || !m_Buffer || m_flushRequested)
651     return 0.0f;
652   double delayBuffer = (double)(m_Buffer->GetReadSize()) / (double)m_AvgBytesPerSec;
653   double delayTranscoder = 0.0;
654   
655   if (m_transcode)
656     delayTranscoder = (double)(m_unencodedBuffer.Used()) / (double)(m_encoderFormat.m_frameSize * m_encoderFormat.m_sampleRate);
657   
658   return AE.GetDelay() + delayBuffer + delayTranscoder;
659 }
660
661 double CCoreAudioAEStream::GetCacheTotal()
662 {
663   if (m_delete || !m_Buffer)
664     return 0.0f;
665
666   return (double)m_Buffer->GetMaxSize() / (double)m_AvgBytesPerSec;
667 }
668
669
670 bool CCoreAudioAEStream::IsPaused()
671 {
672   return m_paused;
673 }
674
675 bool CCoreAudioAEStream::IsDraining()
676 {
677   return m_draining;
678 }
679
680 bool CCoreAudioAEStream::IsDestroyed()
681 {
682   return m_delete;
683 }
684
685 bool CCoreAudioAEStream::IsValid()
686 {
687   return m_valid;
688 }
689
690 void CCoreAudioAEStream::Pause()
691 {
692   m_paused = true;
693 }
694
695 void CCoreAudioAEStream::Resume()
696 {
697 #if defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV)
698   if (CAEFactory::IsSuspended())
699     CAEFactory::Resume();
700 #endif
701   m_paused = false;
702 }
703
704 void CCoreAudioAEStream::Drain(bool wait)
705 {
706   m_draining = true;
707 }
708
709 bool CCoreAudioAEStream::IsDrained()
710 {
711   return m_Buffer->GetReadSize() == 0;
712 }
713
714 void CCoreAudioAEStream::Flush()
715 {
716   if (m_Buffer)
717     m_flushRequested = true;
718 }
719
720 float CCoreAudioAEStream::GetVolume()
721 {
722   return m_volume;
723 }
724
725 float CCoreAudioAEStream::GetReplayGain()
726 {
727   return m_rgain;
728 }
729
730 void  CCoreAudioAEStream::SetVolume(float volume)
731 {
732   m_volume = std::max( 0.0f, std::min(1.0f, volume));
733 }
734
735 void  CCoreAudioAEStream::SetReplayGain(float factor)
736 {
737   m_rgain  = std::max(-1.0f, std::max(1.0f, factor));
738 }
739
740 void CCoreAudioAEStream::InternalFlush()
741 {
742   // reset the resampler
743   /*
744   if (m_resample) {
745     m_ssrcData.end_of_input = 0;
746     src_reset(m_ssrc);
747   }
748   */
749
750   // Read the buffer empty to avoid Reset
751   // Reset is not lock free.
752   if (m_Buffer)
753   {
754     unsigned int readsize = m_Buffer->GetReadSize();
755     if (readsize)
756     {
757       uint8_t *buffer = (uint8_t *)_aligned_malloc(readsize, 16);
758       m_Buffer->Read(buffer, readsize);
759       _aligned_free(buffer);
760     }
761
762     // if we are draining and are out of packets, tell the slave to resume
763     if (m_draining && m_slave)
764     {
765       m_slave->Resume();
766       m_slave = NULL;
767     }
768   }
769
770   m_flushRequested = false;
771   //if (m_Buffer)
772   //  m_Buffer->Reset();
773 }
774
775 const unsigned int CCoreAudioAEStream::GetChannelCount() const
776 {
777   return m_chLayoutCountStream;
778 }
779
780 const unsigned int CCoreAudioAEStream::GetSampleRate() const
781 {
782   return m_StreamFormat.m_sampleRate;
783 }
784
785 const unsigned int CCoreAudioAEStream::GetEncodedSampleRate() const
786 {
787   return m_StreamFormat.m_encodedRate;
788 }
789
790 const enum AEDataFormat CCoreAudioAEStream::GetDataFormat() const
791 {
792   return m_StreamFormat.m_dataFormat;
793 }
794
795 const bool CCoreAudioAEStream::IsRaw() const
796 {
797   return m_isRaw;
798 }
799
800 double CCoreAudioAEStream::GetResampleRatio()
801 {
802   /*
803   if (!m_resample)
804    return 1.0f;
805
806   double ret = m_ssrcData.src_ratio;
807   return ret;
808   */
809
810   return 1.0f;
811 }
812
813 bool CCoreAudioAEStream::SetResampleRatio(double ratio)
814 {
815   return false;
816   /*
817   if (!m_resample)
818     return;
819
820   src_set_ratio(m_ssrc, ratio);
821   m_ssrcData.src_ratio = ratio;
822   */
823 }
824
825 void CCoreAudioAEStream::RegisterAudioCallback(IAudioCallback* pCallback)
826 {
827   m_audioCallback = pCallback;
828   if (m_audioCallback)
829     m_audioCallback->OnInitialize(2, m_StreamFormat.m_sampleRate, 32);
830 }
831
832 void CCoreAudioAEStream::UnRegisterAudioCallback()
833 {
834   m_audioCallback = NULL;
835 }
836
837 void CCoreAudioAEStream::FadeVolume(float from, float target, unsigned int time)
838 {
839   if (m_isRaw)
840   {
841     m_fadeRunning = false;
842   }
843   else
844   {
845     float delta   = target - from;
846     m_fadeDirUp   = target > from;
847     m_fadeTarget  = target;
848     m_fadeStep    = delta / (((float)m_OutputFormat.m_sampleRate / 1000.0f) * (float)time);
849     m_fadeRunning = true;
850   }
851 }
852
853 bool CCoreAudioAEStream::IsFading()
854 {
855   return m_fadeRunning;
856 }
857
858 void CCoreAudioAEStream::RegisterSlave(IAEStream *stream)
859 {
860   m_slave = stream;
861 }
862
863 OSStatus CCoreAudioAEStream::Render(AudioUnitRenderActionFlags* actionFlags,
864   const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufList)
865 {
866   OSStatus ret = OnRender(actionFlags, pTimeStamp, busNumber, frameCount, pBufList);
867   return ret;
868 }
869
870 OSStatus CCoreAudioAEStream::OnRender(AudioUnitRenderActionFlags *ioActionFlags,
871   const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
872 {
873   // if we have no valid data output silence
874   if (!m_valid || m_delete || !m_Buffer || m_firstInput || m_paused)
875   {
876         for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
877       bzero(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize);
878     if (ioActionFlags)
879       *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
880     m_firstInput = false;
881     return noErr;
882   }
883
884   unsigned int size = inNumberFrames * m_OutputFormat.m_frameSize;
885   //unsigned int size = inNumberFrames * m_StreamFormat.m_frameSize;
886
887   // the index is important if we run encoded
888   unsigned int outputBufferIndex = AE.GetHAL()->GetBufferIndex();
889
890   ioData->mBuffers[outputBufferIndex].mDataByteSize  = GetFrames(
891     (uint8_t*)ioData->mBuffers[outputBufferIndex].mData, size);
892   if (!ioData->mBuffers[outputBufferIndex].mDataByteSize && ioActionFlags)
893     *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
894
895   return noErr;
896 }
897
898 void CCoreAudioAEStream::ResetEncoder()
899 {
900   if (m_encoder)
901     m_encoder->Reset();
902   m_unencodedBuffer.Empty();
903 }
904
905 bool CCoreAudioAEStream::SetupEncoder()
906 {
907   ResetEncoder();
908   delete m_encoder;
909   m_encoder = NULL;
910   
911   if (!m_transcode)
912     return false;
913   
914   m_encoder = new CAEEncoderFFmpeg();
915   if (m_encoder && m_encoder->Initialize(m_encoderFormat))
916     return true;
917   
918   delete m_encoder;
919   m_encoder = NULL;
920   return false;
921 }