You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.7KB

  1. /*
  2. * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
  5. *
  6. * Use of this source code is governed by MIT license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include "Util/logger.h"
  11. #include "AudioSRC.h"
  12. #include "SDLAudioDevice.h"
  13. using namespace std;
  14. using namespace toolkit;
  15. INSTANCE_IMP(SDLAudioDevice);
  16. SDLAudioDevice::~SDLAudioDevice() {
  17. SDL_CloseAudio();
  18. }
  19. SDLAudioDevice::SDLAudioDevice() {
  20. SDL_AudioSpec wanted_spec;
  21. wanted_spec.freq = DEFAULT_SAMPLERATE;
  22. wanted_spec.format = DEFAULT_FORMAT;
  23. wanted_spec.channels = DEFAULT_CHANNEL;
  24. wanted_spec.silence = 0;
  25. wanted_spec.samples = DEFAULT_SAMPLES;
  26. wanted_spec.userdata = this;
  27. wanted_spec.callback = [](void *userdata, Uint8 *stream, int len) {
  28. SDLAudioDevice *_this = (SDLAudioDevice *) userdata;
  29. _this->onReqPCM((char *) stream, len);
  30. };
  31. if (SDL_OpenAudio(&wanted_spec, &_audio_config) < 0) {
  32. throw std::runtime_error("SDL_OpenAudio failed");
  33. }
  34. InfoL << "actual audioSpec, " << "freq:" << _audio_config.freq
  35. << ", format:" << hex << _audio_config.format << dec
  36. << ", channels:" << (int) _audio_config.channels
  37. << ", samples:" << _audio_config.samples
  38. << ", pcm size:" << _audio_config.size;
  39. _play_buf.reset(new char[_audio_config.size], [](char *ptr) {
  40. delete[] ptr;
  41. });
  42. }
  43. void SDLAudioDevice::addChannel(AudioSRC *chn) {
  44. lock_guard<recursive_mutex> lck(_channel_mtx);
  45. if (_channels.empty()) {
  46. SDL_PauseAudio(0);
  47. }
  48. chn->setOutputAudioConfig(_audio_config);
  49. _channels.emplace(chn);
  50. }
  51. void SDLAudioDevice::delChannel(AudioSRC *chn) {
  52. lock_guard<recursive_mutex> lck(_channel_mtx);
  53. _channels.erase(chn);
  54. if (_channels.empty()) {
  55. SDL_PauseAudio(true);
  56. }
  57. }
  58. void SDLAudioDevice::onReqPCM(char *stream, int len) {
  59. lock_guard<recursive_mutex> lck(_channel_mtx);
  60. int size;
  61. int channel = 0;
  62. for (auto &chn : _channels) {
  63. if (channel == 0) {
  64. size = chn->getPCMData(_play_buf.get(), len);
  65. if (size) {
  66. memcpy(stream, _play_buf.get(), size);
  67. }
  68. } else {
  69. size = chn->getPCMData(_play_buf.get(), len);
  70. if (size) {
  71. SDL_MixAudio((Uint8 *) stream, (Uint8 *) _play_buf.get(), size, SDL_MIX_MAXVOLUME);
  72. }
  73. }
  74. if (size) {
  75. channel++;
  76. }
  77. }
  78. if (!channel) {
  79. memset(stream, 0, len);
  80. }
  81. }