AudioLayer.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "Main.h"
  2. #include "AudioLayer.h"
  3. #include "VideoLayer.h"
  4. #include <Mmreg.h>
  5. #include <cassert>
  6. #include "util.h"
  7. #include "config.h"
  8. #include "AudioThread.h"
  9. #include "api.h"
  10. #pragma warning(disable:4355) // warning C4355: 'this' : used in base member initializer list
  11. AudioLayer::AudioLayer(IWMReader *_reader)
  12. : reader(_reader), audioOutputNum( -1),
  13. reader2(0), offset(0), new_offset(0),
  14. startPosition(0), videoCatchup(0),
  15. opened(false), killSwitch(0),
  16. audioThread(this), latency(0)
  17. {
  18. reader->AddRef();
  19. if (FAILED(reader->QueryInterface(&reader2)))
  20. reader2 = 0;
  21. killSwitch = CreateEvent(NULL, TRUE, FALSE, NULL);
  22. }
  23. void AudioLayer::Opened()
  24. {
  25. ResetEvent(killSwitch);
  26. if (AudioLayer::OpenAudio())
  27. {
  28. ResetEvent(killSwitch);
  29. BOOL dedicatedThread = config_audio_dedicated_thread ? TRUE : FALSE;
  30. reader2->SetOutputSetting(audioOutputNum, g_wszDedicatedDeliveryThread, WMT_TYPE_BOOL, (BYTE *) & dedicatedThread, sizeof(dedicatedThread));
  31. BOOL outOfOrder = config_audio_outoforder ? TRUE : FALSE;
  32. reader2->SetOutputSetting(audioOutputNum, g_wszDeliverOnReceive, WMT_TYPE_BOOL, (BYTE *) & outOfOrder, sizeof(outOfOrder));
  33. BOOL justInTime = config_lowmemory ? TRUE : FALSE;
  34. reader2->SetOutputSetting(audioOutputNum, g_wszJustInTimeDecode, WMT_TYPE_BOOL, (BYTE *) & justInTime, sizeof(justInTime));
  35. opened = true;
  36. offset = ((QWORD)latency) * 10000;
  37. new_offset = config_audio_early ? (latency + config_audio_early_pad) : 0;
  38. reader2->SetOutputSetting(audioOutputNum, g_wszEarlyDataDelivery, WMT_TYPE_DWORD, (BYTE *) & new_offset , sizeof(new_offset));
  39. winamp.OpenViz(latency, SampleRate());
  40. }
  41. WMHandler::Opened();
  42. }
  43. void AudioLayer::Started()
  44. {
  45. ResetEvent(killSwitch);
  46. if (opened)
  47. {
  48. audioThread.Start(&First());
  49. }
  50. WMHandler::Started();
  51. }
  52. void AudioLayer::Stopped()
  53. {
  54. if (opened)
  55. audioThread.Stop();
  56. WMHandler::Stopped();
  57. }
  58. WM_MEDIA_TYPE *NewMediaType(IWMOutputMediaProps *props)
  59. {
  60. DWORD mediaTypeSize;
  61. props->GetMediaType(0, &mediaTypeSize);
  62. WM_MEDIA_TYPE *mediaType = (WM_MEDIA_TYPE *)new unsigned char[mediaTypeSize];
  63. props->GetMediaType(mediaType, &mediaTypeSize);
  64. return mediaType;
  65. }
  66. bool AudioLayer::OpenAudio()
  67. {
  68. audioOutputNum = -1;
  69. DWORD numOutputs, output, format, numFormats;
  70. IWMOutputMediaProps *formatProperties;
  71. GUID mediaType;
  72. if (FAILED((reader->GetOutputCount(&numOutputs))))
  73. return false;
  74. for (output = 0;output < numOutputs;output++)
  75. {
  76. HRESULT hr;
  77. DWORD speakerConfig = config_audio_num_channels;
  78. if (AGAVE_API_CONFIG && AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"mono", false)) // force mono?
  79. speakerConfig = DSSPEAKER_MONO;
  80. else if (AGAVE_API_CONFIG && !AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"surround", true)) // is surround disallowed?
  81. speakerConfig = DSSPEAKER_STEREO;
  82. hr = reader2->SetOutputSetting(output, g_wszSpeakerConfig, WMT_TYPE_DWORD, (BYTE *) & speakerConfig, sizeof(speakerConfig));
  83. assert(hr == S_OK);
  84. BOOL discreteChannels = TRUE;
  85. hr = reader2->SetOutputSetting(output, g_wszEnableDiscreteOutput, WMT_TYPE_BOOL, (BYTE *) & discreteChannels , sizeof(discreteChannels ));
  86. assert(hr == S_OK);
  87. if (FAILED(reader->GetOutputFormatCount(output, &numFormats)))
  88. continue;
  89. for (format = 0;format < numFormats;format++)
  90. {
  91. reader->GetOutputFormat(output, format, &formatProperties);
  92. formatProperties->GetType(&mediaType);
  93. if (mediaType == WMMEDIATYPE_Audio)
  94. {
  95. WM_MEDIA_TYPE *mediaType = NewMediaType(formatProperties);
  96. if (mediaType->subtype == WMMEDIASUBTYPE_PCM)
  97. {
  98. if (AGAVE_API_CONFIG)
  99. {
  100. unsigned int bits = AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"bits", 16);
  101. WAVEFORMATEXTENSIBLE *waveFormat = (WAVEFORMATEXTENSIBLE *) mediaType->pbFormat;
  102. if (waveFormat->Format.cbSize >= 22)
  103. waveFormat->Samples.wValidBitsPerSample=bits;
  104. waveFormat->Format.wBitsPerSample=bits;
  105. waveFormat->Format.nBlockAlign = (waveFormat->Format.wBitsPerSample / 8) * waveFormat->Format.nChannels;
  106. waveFormat->Format.nAvgBytesPerSec=waveFormat->Format.nSamplesPerSec * waveFormat->Format.nBlockAlign;
  107. if (FAILED(formatProperties->SetMediaType(mediaType)))
  108. {
  109. // blah, just use the default settings then
  110. delete[] mediaType;
  111. mediaType = NewMediaType(formatProperties);
  112. }
  113. }
  114. AudioFormat::Open(mediaType);
  115. delete mediaType;
  116. bool video = false;
  117. First().HasVideo(video);
  118. // this is needed to prevent an audio glitch on first playback
  119. if (out)
  120. {
  121. extern WMDRM mod;
  122. out->SetVolume(mod.GetVolume());
  123. out->SetPan(mod.GetPan());
  124. }
  125. latency = out->Open(SampleRate(), Channels(), ValidBits(), (video ? -666 : -1), -1);
  126. if (latency >= 0)
  127. {
  128. audioOutputNum = output;
  129. reader->SetOutputProps(audioOutputNum, formatProperties);
  130. formatProperties->Release();
  131. return true;
  132. }
  133. else
  134. {
  135. formatProperties->Release();
  136. AudioFormat::Close();
  137. continue;
  138. }
  139. }
  140. delete mediaType;
  141. formatProperties->Release();
  142. }
  143. }
  144. }
  145. return false;
  146. }
  147. void AudioLayer::SampleReceived(QWORD &timeStamp, QWORD &duration, unsigned long &outputNum, unsigned long &flags, INSSBuffer *&sample)
  148. {
  149. if (outputNum == audioOutputNum)
  150. {
  151. if (WaitForSingleObject(killSwitch, 0) == WAIT_OBJECT_0)
  152. return ;
  153. if (videoCatchup)
  154. {
  155. videoCatchup = videoCatchup / 20000;
  156. videoCatchup = min(videoCatchup, offset / 40000);
  157. unsigned int num = (unsigned int) (videoCatchup / VIDEO_ACCEPTABLE_JITTER_MS);
  158. while (num--)
  159. {
  160. if (WaitForSingleObject(killSwitch, VIDEO_ACCEPTABLE_JITTER_MS) == WAIT_OBJECT_0)
  161. return ;
  162. }
  163. videoCatchup = 0;
  164. }
  165. while (!audioThread.AddBuffer(sample, timeStamp, flags, false))
  166. {
  167. if (WaitForSingleObject(killSwitch, VIDEO_ACCEPTABLE_JITTER_MS) == WAIT_OBJECT_0)
  168. break;
  169. }
  170. }
  171. else
  172. WMHandler::SampleReceived(timeStamp, duration, outputNum, flags, sample);
  173. }
  174. void AudioLayer::VideoCatchup(QWORD time)
  175. {
  176. videoCatchup = time;
  177. WMHandler::VideoCatchup(time);
  178. }
  179. void AudioLayer::Closed()
  180. {
  181. if (opened)
  182. {
  183. out->Close();
  184. winamp.CloseViz();
  185. }
  186. opened = false;
  187. //AudioFormat::Close();
  188. WMHandler::Closed();
  189. }
  190. AudioLayer::~AudioLayer()
  191. {
  192. audioThread.Kill();
  193. if (reader2)
  194. reader2->Release();
  195. if (reader)
  196. reader->Release();
  197. CloseHandle(killSwitch);
  198. }
  199. void AudioLayer::Kill()
  200. {
  201. SetEvent(killSwitch);
  202. if (opened)
  203. audioThread.SignalStop();
  204. WMHandler::Kill();
  205. if (opened)
  206. audioThread.WaitForStop();
  207. }
  208. void AudioLayer::EndOfFile()
  209. {
  210. if (!opened || audioThread.EndOfFile())
  211. WMHandler::EndOfFile();
  212. }