Merge pull request #4361 from afedchin/dxva_h264_intel_g
[vuplus_xbmc] / xbmc / cores / AudioEngine / Engines / ActiveAE / ActiveAESink.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 <sstream>
22
23 #include "ActiveAESink.h"
24 #include "cores/AudioEngine/Utils/AEUtil.h"
25 #include "utils/EndianSwap.h"
26 #include "ActiveAE.h"
27
28 #include "settings/Settings.h"
29
30 using namespace ActiveAE;
31
32 CActiveAESink::CActiveAESink(CEvent *inMsgEvent) :
33   CThread("AESink"),
34   m_controlPort("SinkControlPort", inMsgEvent, &m_outMsgEvent),
35   m_dataPort("SinkDataPort", inMsgEvent, &m_outMsgEvent)
36 {
37   m_inMsgEvent = inMsgEvent;
38   m_sink = NULL;
39   m_stats = NULL;
40   m_convertBuffer = NULL;
41   m_volume = 0.0;
42 }
43
44 void CActiveAESink::Start()
45 {
46   if (!IsRunning())
47   {
48     Create();
49     SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
50   }
51 }
52
53 void CActiveAESink::Dispose()
54 {
55   m_bStop = true;
56   m_outMsgEvent.Set();
57   StopThread();
58   m_controlPort.Purge();
59   m_dataPort.Purge();
60
61   if (m_sink)
62   {
63     m_sink->Drain();
64     m_sink->Deinitialize();
65     delete m_sink;
66     m_sink = NULL;
67   }
68
69   delete m_sampleOfSilence.pkt;
70   m_sampleOfSilence.pkt = NULL;
71
72   if (m_convertBuffer)
73   {
74     _aligned_free(m_convertBuffer);
75     m_convertBuffer = NULL;
76   }
77 }
78
79 AEDeviceType CActiveAESink::GetDeviceType(const std::string &device)
80 {
81   std::string dev = device;
82   std::string dri;
83   CAESinkFactory::ParseDevice(dev, dri);
84   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
85   {
86     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
87     {
88       CAEDeviceInfo& info = *itt2;
89       if (info.m_deviceName == dev)
90         return info.m_deviceType;
91     }
92   }
93   return AE_DEVTYPE_PCM;
94 }
95
96 bool CActiveAESink::HasPassthroughDevice()
97 {
98   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
99   {
100     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
101     {
102       CAEDeviceInfo& info = *itt2;
103       if (info.m_deviceType != AE_DEVTYPE_PCM)
104         return true;
105     }
106   }
107   return false;
108 }
109
110 bool CActiveAESink::SupportsFormat(const std::string &device, AEDataFormat format, int samplerate)
111 {
112   std::string dev = device;
113   std::string dri;
114   CAESinkFactory::ParseDevice(dev, dri);
115   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
116   {
117     if (dri == itt->m_sinkName)
118     {
119       for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
120       {
121         CAEDeviceInfo& info = *itt2;
122         if (info.m_deviceName == dev)
123         {
124           AEDataFormatList::iterator itt3;
125           itt3 = find(info.m_dataFormats.begin(), info.m_dataFormats.end(), format);
126           if (itt3 != info.m_dataFormats.end())
127           {
128             AESampleRateList::iterator itt4;
129             itt4 = find(info.m_sampleRates.begin(), info.m_sampleRates.end(), samplerate);
130             if (itt4 != info.m_sampleRates.end())
131               return true;
132             else
133               return false;
134           }
135           else
136             return false;
137         }
138       }
139     }
140   }
141   return false;
142 }
143
144 enum SINK_STATES
145 {
146   S_TOP = 0,                      // 0
147   S_TOP_UNCONFIGURED,             // 1
148   S_TOP_CONFIGURED,               // 2
149   S_TOP_CONFIGURED_SUSPEND,       // 3
150   S_TOP_CONFIGURED_IDLE,          // 4
151   S_TOP_CONFIGURED_PLAY,          // 5
152   S_TOP_CONFIGURED_SILENCE,       // 6
153 };
154
155 int SINK_parentStates[] = {
156     -1,
157     0, //TOP_UNCONFIGURED
158     0, //TOP_CONFIGURED
159     2, //TOP_CONFIGURED_SUSPEND
160     2, //TOP_CONFIGURED_IDLE
161     2, //TOP_CONFIGURED_PLAY
162     2, //TOP_CONFIGURED_SILENCE
163 };
164
165 void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
166 {
167   for (int state = m_state; ; state = SINK_parentStates[state])
168   {
169     switch (state)
170     {
171     case S_TOP: // TOP
172       if (port == &m_controlPort)
173       {
174         switch (signal)
175         {
176         case CSinkControlProtocol::CONFIGURE:
177           SinkConfig *data;
178           data = (SinkConfig*)msg->data;
179           if (data)
180           {
181             m_requestedFormat = data->format;
182             m_stats = data->stats;
183             m_device = *(data->device);
184           }
185           m_extError = false;
186           m_extSilenceTimer = 0;
187           m_extStreaming = false;
188           ReturnBuffers();
189           OpenSink();
190
191           if (!m_extError)
192           {
193             SinkReply reply;
194             reply.format = m_sinkFormat;
195             reply.cacheTotal = m_sink->GetCacheTotal();
196             reply.latency = m_sink->GetLatency();
197             reply.hasVolume = m_sink->HasVolume();
198             m_state = S_TOP_CONFIGURED_IDLE;
199             m_extTimeout = 10000;
200             msg->Reply(CSinkControlProtocol::ACC, &reply, sizeof(SinkReply));
201           }
202           else
203           {
204             m_state = S_TOP_UNCONFIGURED;
205             msg->Reply(CSinkControlProtocol::ERR);
206           }
207           return;
208
209         case CSinkControlProtocol::UNCONFIGURE:
210           ReturnBuffers();
211           if (m_sink)
212           {
213             m_sink->Drain();
214             m_sink->Deinitialize();
215             delete m_sink;
216             m_sink = NULL;
217           }
218           m_state = S_TOP_UNCONFIGURED;
219           msg->Reply(CSinkControlProtocol::ACC);
220           return;
221
222         case CSinkControlProtocol::FLUSH:
223           ReturnBuffers();
224           msg->Reply(CSinkControlProtocol::ACC);
225           return;
226
227         case CSinkControlProtocol::APPFOCUSED:
228           m_extAppFocused = *(bool*)msg->data;
229           SetSilenceTimer();
230           m_extTimeout = 0;
231           return;
232
233         default:
234           break;
235         }
236       }
237       else if (port == &m_dataPort)
238       {
239         switch (signal)
240         {
241         case CSinkDataProtocol::DRAIN:
242           msg->Reply(CSinkDataProtocol::ACC);
243           m_state = S_TOP_UNCONFIGURED;
244           m_extTimeout = 0;
245           return;
246         default:
247           break;
248         }
249       }
250       {
251         std::string portName = port == NULL ? "timer" : port->portName;
252         CLog::Log(LOGWARNING, "CActiveAESink::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
253       }
254       return;
255
256     case S_TOP_UNCONFIGURED:
257       if (port == NULL) // timeout
258       {
259         switch (signal)
260         {
261         case CSinkControlProtocol::TIMEOUT:
262           m_extTimeout = 1000;
263           return;
264         default:
265           break;
266         }
267       }
268       else if (port == &m_dataPort)
269       {
270         switch (signal)
271         {
272         case CSinkDataProtocol::SAMPLE:
273           CSampleBuffer *samples;
274           int timeout;
275           samples = *((CSampleBuffer**)msg->data);
276           timeout = 1000*samples->pkt->nb_samples/samples->pkt->config.sample_rate;
277           Sleep(timeout);
278           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
279           m_extTimeout = 0;
280           return;
281         default:
282           break;
283         }
284       }
285       break;
286
287     case S_TOP_CONFIGURED:
288       if (port == &m_controlPort)
289       {
290         switch (signal)
291         {
292         case CSinkControlProtocol::STREAMING:
293           m_extStreaming = *(bool*)msg->data;
294           SetSilenceTimer();
295           if (!m_extSilenceTimer.IsTimePast())
296           {
297             m_state = S_TOP_CONFIGURED_SILENCE;
298           }
299           m_extTimeout = 0;
300           return;
301         case CSinkControlProtocol::VOLUME:
302           m_volume = *(float*)msg->data;
303           m_sink->SetVolume(m_volume);
304           return;
305         default:
306           break;
307         }
308       }
309       else if (port == &m_dataPort)
310       {
311         switch (signal)
312         {
313         case CSinkDataProtocol::DRAIN:
314           m_sink->Drain();
315           msg->Reply(CSinkDataProtocol::ACC);
316           m_state = S_TOP_CONFIGURED_IDLE;
317           m_extTimeout = 10000;
318           return;
319         case CSinkDataProtocol::SAMPLE:
320           CSampleBuffer *samples;
321           unsigned int delay;
322           samples = *((CSampleBuffer**)msg->data);
323           delay = OutputSamples(samples);
324           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
325           if (m_extError)
326           {
327             m_sink->Deinitialize();
328             delete m_sink;
329             m_sink = NULL;
330             m_state = S_TOP_CONFIGURED_SUSPEND;
331             m_extTimeout = 0;
332           }
333           else
334           {
335             m_state = S_TOP_CONFIGURED_PLAY;
336             m_extTimeout = delay / 2;
337             m_extSilenceTimer.Set(m_extSilenceTimeout);
338           }
339           return;
340         default:
341           break;
342         }
343       }
344       break;
345
346     case S_TOP_CONFIGURED_SUSPEND:
347       if (port == &m_controlPort)
348       {
349         switch (signal)
350         {
351         case CSinkControlProtocol::STREAMING:
352           m_extStreaming = *(bool*)msg->data;
353           SetSilenceTimer();
354           m_extTimeout = 0;
355           return;
356         case CSinkControlProtocol::VOLUME:
357           m_volume = *(float*)msg->data;
358           return;
359         default:
360           break;
361         }
362       }
363       else if (port == &m_dataPort)
364       {
365         switch (signal)
366         {
367         case CSinkDataProtocol::SAMPLE:
368           m_extError = false;
369           OpenSink();
370           OutputSamples(&m_sampleOfSilence);
371           m_state = S_TOP_CONFIGURED_PLAY;
372           m_extTimeout = 0;
373           m_bStateMachineSelfTrigger = true;
374           return;
375         case CSinkDataProtocol::DRAIN:
376           msg->Reply(CSinkDataProtocol::ACC);
377           return;
378         default:
379           break;
380         }
381       }
382       else if (port == NULL) // timeout
383       {
384         switch (signal)
385         {
386         case CSinkControlProtocol::TIMEOUT:
387           m_extTimeout = 10000;
388           return;
389         default:
390           break;
391         }
392       }
393       break;
394
395     case S_TOP_CONFIGURED_IDLE:
396       if (port == &m_dataPort)
397       {
398         switch (signal)
399         {
400         case CSinkDataProtocol::SAMPLE:
401           OutputSamples(&m_sampleOfSilence);
402           m_state = S_TOP_CONFIGURED_PLAY;
403           m_extTimeout = 0;
404           m_bStateMachineSelfTrigger = true;
405           return;
406         default:
407           break;
408         }
409       }
410       else if (port == NULL) // timeout
411       {
412         switch (signal)
413         {
414         case CSinkControlProtocol::TIMEOUT:
415           m_sink->Deinitialize();
416           delete m_sink;
417           m_sink = NULL;
418           m_state = S_TOP_CONFIGURED_SUSPEND;
419           m_extTimeout = 10000;
420           return;
421         default:
422           break;
423         }
424       }
425       break;
426
427     case S_TOP_CONFIGURED_PLAY:
428       if (port == NULL) // timeout
429       {
430         switch (signal)
431         {
432         case CSinkControlProtocol::TIMEOUT:
433           if (!m_extSilenceTimer.IsTimePast())
434           {
435             m_state = S_TOP_CONFIGURED_SILENCE;
436             m_extTimeout = 0;
437           }
438           else
439           {
440             m_sink->Drain();
441             m_state = S_TOP_CONFIGURED_IDLE;
442             if (m_extAppFocused)
443               m_extTimeout = 10000;
444             else
445               m_extTimeout = 0;
446           }
447           return;
448         default:
449           break;
450         }
451       }
452       break;
453
454     case S_TOP_CONFIGURED_SILENCE:
455       if (port == NULL) // timeout
456       {
457         switch (signal)
458         {
459         case CSinkControlProtocol::TIMEOUT:
460           OutputSamples(&m_sampleOfSilence);
461           if (m_extError)
462           {
463             m_sink->Deinitialize();
464             delete m_sink;
465             m_sink = NULL;
466             m_state = S_TOP_CONFIGURED_SUSPEND;
467           }
468           else
469             m_state = S_TOP_CONFIGURED_PLAY;
470           m_extTimeout = 0;
471           return;
472         default:
473           break;
474         }
475       }
476       break;
477
478     default: // we are in no state, should not happen
479       CLog::Log(LOGERROR, "CActiveAESink::%s - no valid state: %d", __FUNCTION__, m_state);
480       return;
481     }
482   } // for
483 }
484
485 void CActiveAESink::Process()
486 {
487   Message *msg = NULL;
488   Protocol *port = NULL;
489   bool gotMsg;
490   XbmcThreads::EndTime timer;
491
492   m_state = S_TOP_UNCONFIGURED;
493   m_extTimeout = 1000;
494   m_bStateMachineSelfTrigger = false;
495   m_extAppFocused = true;
496
497   while (!m_bStop)
498   {
499     gotMsg = false;
500     timer.Set(m_extTimeout);
501
502     if (m_bStateMachineSelfTrigger)
503     {
504       m_bStateMachineSelfTrigger = false;
505       // self trigger state machine
506       StateMachine(msg->signal, port, msg);
507       if (!m_bStateMachineSelfTrigger)
508       {
509         msg->Release();
510         msg = NULL;
511       }
512       continue;
513     }
514     // check control port
515     else if (m_controlPort.ReceiveOutMessage(&msg))
516     {
517       gotMsg = true;
518       port = &m_controlPort;
519     }
520     // check data port
521     else if (m_dataPort.ReceiveOutMessage(&msg))
522     {
523       gotMsg = true;
524       port = &m_dataPort;
525     }
526
527     if (gotMsg)
528     {
529       StateMachine(msg->signal, port, msg);
530       if (!m_bStateMachineSelfTrigger)
531       {
532         msg->Release();
533         msg = NULL;
534       }
535       continue;
536     }
537
538     // wait for message
539     else if (m_outMsgEvent.WaitMSec(m_extTimeout))
540     {
541       m_extTimeout = timer.MillisLeft();
542       continue;
543     }
544     // time out
545     else
546     {
547       msg = m_controlPort.GetMessage();
548       msg->signal = CSinkControlProtocol::TIMEOUT;
549       port = 0;
550       // signal timeout to state machine
551       StateMachine(msg->signal, port, msg);
552       if (!m_bStateMachineSelfTrigger)
553       {
554         msg->Release();
555         msg = NULL;
556       }
557     }
558   }
559 }
560
561 void CActiveAESink::EnumerateSinkList(bool force)
562 {
563   if (!m_sinkInfoList.empty() && !force)
564     return;
565
566   unsigned int c_retry = 4;
567   m_sinkInfoList.clear();
568   CAESinkFactory::EnumerateEx(m_sinkInfoList);
569   while(m_sinkInfoList.size() == 0 && c_retry > 0)
570   {
571     CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
572     Sleep(1500);
573     c_retry--;
574     // retry the enumeration
575     CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
576   }
577   CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
578   PrintSinks();
579 }
580
581 void CActiveAESink::PrintSinks()
582 {
583   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
584   {
585     CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
586     int count = 0;
587     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
588     {
589       CLog::Log(LOGNOTICE, "    Device %d", ++count);
590       CAEDeviceInfo& info = *itt2;
591       std::stringstream ss((std::string)info);
592       std::string line;
593       while(std::getline(ss, line, '\n'))
594         CLog::Log(LOGNOTICE, "        %s", line.c_str());
595     }
596   }
597 }
598
599 void CActiveAESink::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
600 {
601   EnumerateSinkList(false);
602
603   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
604   {
605     AESinkInfo sinkInfo = *itt;
606     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
607     {
608       CAEDeviceInfo devInfo = *itt2;
609       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
610         continue;
611
612       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
613
614       std::stringstream ss;
615
616       /* add the sink name if we have more then one sink type */
617       if (m_sinkInfoList.size() > 1)
618         ss << sinkInfo.m_sinkName << ": ";
619
620       ss << devInfo.m_displayName;
621       if (!devInfo.m_displayNameExtra.empty())
622         ss << ", " << devInfo.m_displayNameExtra;
623
624       devices.push_back(AEDevice(ss.str(), device));
625     }
626   }
627 }
628
629 std::string CActiveAESink::GetDefaultDevice(bool passthrough)
630 {
631   EnumerateSinkList(false);
632
633   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
634   {
635     AESinkInfo sinkInfo = *itt;
636     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
637     {
638       CAEDeviceInfo devInfo = *itt2;
639       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
640         continue;
641
642       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
643       return device;
644     }
645   }
646   return "default";
647 }
648
649 void CActiveAESink::GetDeviceFriendlyName(std::string &device)
650 {
651   m_deviceFriendlyName = "Device not found";
652   /* Match the device and find its friendly name */
653   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
654   {
655     AESinkInfo sinkInfo = *itt;
656     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
657     {
658       CAEDeviceInfo& devInfo = *itt2;
659       if (devInfo.m_deviceName == device)
660       {
661         m_deviceFriendlyName = devInfo.m_displayName;
662         break;
663       }
664     }
665   }
666   return;
667 }
668
669 void CActiveAESink::OpenSink()
670 {
671   // we need a copy of m_device here because ParseDevice and CreateDevice write back
672   // into this variable
673   std::string device = m_device;
674   std::string driver;
675   bool passthrough = AE_IS_RAW(m_requestedFormat.m_dataFormat);
676
677   CAESinkFactory::ParseDevice(device, driver);
678   if (driver.empty() && m_sink)
679     driver = m_sink->GetName();
680
681   CLog::Log(LOGINFO, "CActiveAESink::OpenSink - initialize sink");
682
683   if (m_sink)
684   {
685     m_sink->Drain();
686     m_sink->Deinitialize();
687     delete m_sink;
688     m_sink = NULL;
689   }
690
691   // get the display name of the device
692   GetDeviceFriendlyName(device);
693
694   // if we already have a driver, prepend it to the device string
695   if (!driver.empty())
696     device = driver + ":" + device;
697
698   // WARNING: this changes format and does not use passthrough
699   m_sinkFormat = m_requestedFormat;
700   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
701   m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
702
703   // try first device in out list
704   if (!m_sink && !m_sinkInfoList.empty())
705   {
706     driver = m_sinkInfoList.front().m_sinkName;
707     device = m_sinkInfoList.front().m_deviceInfoList.front().m_deviceName;
708     GetDeviceFriendlyName(device);
709     if (!driver.empty())
710       device = driver + ":" + device;
711     m_sinkFormat = m_requestedFormat;
712     CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
713     m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
714   }
715
716   // open NULL sink
717   // TODO: should not be required by ActiveAE
718   if (!m_sink)
719   {
720     device = "NULL:NULL";
721     m_sinkFormat = m_requestedFormat;
722     CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - open NULL sink");
723     m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
724   }
725
726   if (!m_sink)
727   {
728     CLog::Log(LOGERROR, "CActiveAESink::OpenSink - no sink was returned");
729     m_extError = true;
730     return;
731   }
732
733   m_sink->SetVolume(m_volume);
734
735 #ifdef WORDS_BIGENDIAN
736   if (m_sinkFormat.m_dataFormat == AE_FMT_S16BE)
737     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
738   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32BE)
739     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
740 #else
741   if (m_sinkFormat.m_dataFormat == AE_FMT_S16LE)
742     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
743   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32LE)
744     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
745 #endif
746
747   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - %s Initialized:", m_sink->GetName());
748   CLog::Log(LOGDEBUG, "  Output Device : %s", m_deviceFriendlyName.c_str());
749   CLog::Log(LOGDEBUG, "  Sample Rate   : %d", m_sinkFormat.m_sampleRate);
750   CLog::Log(LOGDEBUG, "  Sample Format : %s", CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat));
751   CLog::Log(LOGDEBUG, "  Channel Count : %d", m_sinkFormat.m_channelLayout.Count());
752   CLog::Log(LOGDEBUG, "  Channel Layout: %s", ((std::string)m_sinkFormat.m_channelLayout).c_str());
753   CLog::Log(LOGDEBUG, "  Frames        : %d", m_sinkFormat.m_frames);
754   CLog::Log(LOGDEBUG, "  Frame Samples : %d", m_sinkFormat.m_frameSamples);
755   CLog::Log(LOGDEBUG, "  Frame Size    : %d", m_sinkFormat.m_frameSize);
756
757   // init sample of silence
758   SampleConfig config;
759   config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
760   config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
761   config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
762   config.channels = m_sinkFormat.m_channelLayout.Count();
763   config.sample_rate = m_sinkFormat.m_sampleRate;
764
765   // init sample of silence/noise
766   delete m_sampleOfSilence.pkt;
767   m_sampleOfSilence.pkt = new CSoundPacket(config, m_sinkFormat.m_frames);
768   m_sampleOfSilence.pkt->nb_samples = m_sampleOfSilence.pkt->max_nb_samples;
769   if (!passthrough)
770     GenerateNoise();
771
772   if (m_convertBuffer)
773   {
774     _aligned_free(m_convertBuffer);
775     m_convertBuffer = NULL;
776   }
777   m_convertFn = NULL;
778   m_convertState = CHECK_CONVERT;
779 }
780
781 void CActiveAESink::ReturnBuffers()
782 {
783   Message *msg = NULL;
784   CSampleBuffer *samples;
785   while (m_dataPort.ReceiveOutMessage(&msg))
786   {
787     if (msg->signal == CSinkDataProtocol::SAMPLE)
788     {
789       samples = *((CSampleBuffer**)msg->data);
790       msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
791     }
792   }
793 }
794
795 unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
796 {
797   uint8_t *buffer = samples->pkt->data[0];
798   unsigned int frames = samples->pkt->nb_samples;
799   unsigned int maxFrames;
800   int retry = 0;
801   unsigned int written = 0;
802   double sinkDelay = 0.0;
803
804   switch(m_convertState)
805   {
806   case SKIP_CONVERT:
807     break;
808   case NEED_CONVERT:
809     EnsureConvertBuffer(samples);
810     buffer = Convert(samples);
811     break;
812   case NEED_BYTESWAP:
813     Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
814     break;
815   case CHECK_CONVERT:
816     ConvertInit(samples);
817     if (m_convertState == NEED_CONVERT)
818       buffer = Convert(samples);
819     else if (m_convertState == NEED_BYTESWAP)
820       Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
821     break;
822   default:
823     break;
824   }
825
826   while(frames > 0)
827   {
828     maxFrames = std::min(frames, m_sinkFormat.m_frames);
829     written = m_sink->AddPackets(buffer, maxFrames, true, true);
830     if (written == 0)
831     {
832       Sleep(500*m_sinkFormat.m_frames/m_sinkFormat.m_sampleRate);
833       retry++;
834       if (retry > 4)
835       {
836         m_extError = true;
837         CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed");
838         m_stats->UpdateSinkDelay(0, frames);
839         return 0;
840       }
841       else
842         continue;
843     }
844     else if (written > maxFrames)
845     {
846       m_extError = true;
847       CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error");
848       m_stats->UpdateSinkDelay(0, samples->pool ? maxFrames : 0);
849       return 0;
850     }
851     frames -= written;
852     buffer += written*m_sinkFormat.m_frameSize;
853     sinkDelay = m_sink->GetDelay();
854     m_stats->UpdateSinkDelay(sinkDelay, samples->pool ? written : 0);
855   }
856   return sinkDelay*1000;
857 }
858
859 void CActiveAESink::ConvertInit(CSampleBuffer* samples)
860 {
861   if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat)
862   {
863     m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat);
864     if (m_convertBuffer)
865       _aligned_free(m_convertBuffer);
866     m_convertBufferSampleSize = samples->pkt->max_nb_samples;
867     m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
868     memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
869     m_convertState = NEED_CONVERT;
870   }
871   else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
872   {
873     m_convertState = NEED_BYTESWAP;
874   }
875   else
876     m_convertState = SKIP_CONVERT;
877 }
878
879 void CActiveAESink::EnsureConvertBuffer(CSampleBuffer* samples)
880 {
881   if (!m_convertBuffer)
882     return;
883
884   if (samples->pkt->max_nb_samples <= m_convertBufferSampleSize)
885     return;
886
887   _aligned_free(m_convertBuffer);
888   m_convertBufferSampleSize = samples->pkt->max_nb_samples;
889   m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
890   memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
891 }
892
893 uint8_t* CActiveAESink::Convert(CSampleBuffer* samples)
894 {
895   m_convertFn((float*)samples->pkt->data[0], samples->pkt->nb_samples * samples->pkt->config.channels, m_convertBuffer);
896   return m_convertBuffer;
897 }
898
899 #define PI 3.1415926536f
900
901 void CActiveAESink::GenerateNoise()
902 {
903   int nb_floats = m_sinkFormat.m_frames*m_sinkFormat.m_channelLayout.Count();
904   float *noise = (float*)_aligned_malloc(nb_floats*sizeof(float), 16);
905
906   float R1, R2;
907   for(int i=0; i<nb_floats;i++)
908   {
909     do
910     {
911       R1 = (float) rand() / (float) RAND_MAX;
912       R2 = (float) rand() / (float) RAND_MAX;
913     }
914     while(R1 == 0.0f);
915     
916     noise[i] = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ) * 0.00001f;
917   }
918
919   AEDataFormat fmt = CActiveAEResample::GetAESampleFormat(m_sampleOfSilence.pkt->config.fmt, m_sampleOfSilence.pkt->config.bits_per_sample);
920   CAEConvert::AEConvertFrFn convertFn = CAEConvert::FrFloat(fmt);
921   convertFn(noise, nb_floats, m_sampleOfSilence.pkt->data[0]);
922   _aligned_free(noise);
923 }
924
925 void CActiveAESink::SetSilenceTimer()
926 {
927   if (m_extStreaming)
928     m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
929   else if (m_extAppFocused)
930     m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
931   else
932     m_extSilenceTimeout = 0;
933   m_extSilenceTimer.Set(m_extSilenceTimeout);
934 }