captions-mssapi-stream.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include <windows.h>
  2. #include <sapi.h>
  3. #include <condition_variable>
  4. #include <mutex>
  5. #include <vector>
  6. #include <obs.h>
  7. #include <media-io/audio-resampler.h>
  8. #include <util/circlebuf.h>
  9. #include <util/windows/WinHandle.hpp>
  10. #include <fstream>
  11. class CircleBuf {
  12. circlebuf buf = {};
  13. public:
  14. inline ~CircleBuf() {circlebuf_free(&buf);}
  15. inline operator circlebuf*() {return &buf;}
  16. inline circlebuf *operator->() {return &buf;}
  17. };
  18. class Resampler {
  19. audio_resampler_t *resampler = nullptr;
  20. public:
  21. inline void Reset(const WAVEFORMATEX *wfex)
  22. {
  23. const struct audio_output_info *aoi =
  24. audio_output_get_info(obs_get_audio());
  25. struct resample_info src;
  26. src.samples_per_sec = aoi->samples_per_sec;
  27. src.format = aoi->format;
  28. src.speakers = aoi->speakers;
  29. struct resample_info dst;
  30. dst.samples_per_sec = uint32_t(wfex->nSamplesPerSec);
  31. dst.format = AUDIO_FORMAT_16BIT;
  32. dst.speakers = (enum speaker_layout)wfex->nChannels;
  33. if (resampler)
  34. audio_resampler_destroy(resampler);
  35. resampler = audio_resampler_create(&dst, &src);
  36. }
  37. inline ~Resampler() {audio_resampler_destroy(resampler);}
  38. inline operator audio_resampler_t*() {return resampler;}
  39. };
  40. class CaptionStream : public ISpAudio {
  41. volatile long refs = 1;
  42. SPAUDIOBUFFERINFO buf_info = {};
  43. ULONG notify_size = 0;
  44. SPAUDIOSTATE state;
  45. WinHandle event;
  46. ULONG vol = 0;
  47. std::condition_variable cv;
  48. std::mutex m;
  49. std::vector<int16_t> temp_buf;
  50. WAVEFORMATEX format = {};
  51. Resampler resampler;
  52. CircleBuf buf;
  53. ULONG wait_size = 0;
  54. DWORD samplerate = 0;
  55. ULARGE_INTEGER pos = {};
  56. ULONGLONG write_pos = 0;
  57. public:
  58. CaptionStream(DWORD samplerate);
  59. void Stop();
  60. void PushAudio(const struct audio_data *audio_data, bool muted);
  61. // IUnknown methods
  62. STDMETHODIMP QueryInterface(REFIID riid, void **ppv) override;
  63. STDMETHODIMP_(ULONG) AddRef() override;
  64. STDMETHODIMP_(ULONG) Release() override;
  65. // ISequentialStream methods
  66. STDMETHODIMP Read(void *data, ULONG bytes, ULONG *read_bytes) override;
  67. STDMETHODIMP Write(const void *data, ULONG bytes, ULONG *written_bytes)
  68. override;
  69. // IStream methods
  70. STDMETHODIMP Seek(LARGE_INTEGER move, DWORD origin,
  71. ULARGE_INTEGER *new_pos) override;
  72. STDMETHODIMP SetSize(ULARGE_INTEGER new_size) override;
  73. STDMETHODIMP CopyTo(IStream *stream, ULARGE_INTEGER bytes,
  74. ULARGE_INTEGER *read_bytes,
  75. ULARGE_INTEGER *written_bytes) override;
  76. STDMETHODIMP Commit(DWORD commit_flags) override;
  77. STDMETHODIMP Revert(void) override;
  78. STDMETHODIMP LockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
  79. DWORD type) override;
  80. STDMETHODIMP UnlockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
  81. DWORD type) override;
  82. STDMETHODIMP Stat(STATSTG *stg, DWORD flags) override;
  83. STDMETHODIMP Clone(IStream **stream) override;
  84. // ISpStreamFormat methods
  85. STDMETHODIMP GetFormat(GUID *guid, WAVEFORMATEX **co_mem_wfex_out)
  86. override;
  87. // ISpAudio methods
  88. STDMETHODIMP SetState(SPAUDIOSTATE state, ULONGLONG reserved) override;
  89. STDMETHODIMP SetFormat(REFGUID guid_ref, const WAVEFORMATEX *wfex)
  90. override;
  91. STDMETHODIMP GetStatus(SPAUDIOSTATUS *status) override;
  92. STDMETHODIMP SetBufferInfo(const SPAUDIOBUFFERINFO *buf_info) override;
  93. STDMETHODIMP GetBufferInfo(SPAUDIOBUFFERINFO *buf_info) override;
  94. STDMETHODIMP GetDefaultFormat(GUID *format,
  95. WAVEFORMATEX **co_mem_wfex_out) override;
  96. STDMETHODIMP_(HANDLE) EventHandle(void) override;
  97. STDMETHODIMP GetVolumeLevel(ULONG *level) override;
  98. STDMETHODIMP SetVolumeLevel(ULONG level) override;
  99. STDMETHODIMP GetBufferNotifySize(ULONG *size) override;
  100. STDMETHODIMP SetBufferNotifySize(ULONG size) override;
  101. };