mf-aac-encoder.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. #include <obs-module.h>
  2. #include "mf-aac-encoder.hpp"
  3. #include <mferror.h>
  4. #include <mftransform.h>
  5. #include <wmcodecdsp.h>
  6. #include <comdef.h>
  7. #define MF_LOG_AAC(level, format, ...) \
  8. MF_LOG_ENCODER("AAC", ObsEncoder(), level, format, ##__VA_ARGS__)
  9. #define MF_LOG_COM(msg, hr) MF_LOG_AAC(LOG_ERROR, \
  10. msg " failed, %S (0x%08lx)", \
  11. _com_error(hr).ErrorMessage(), hr)
  12. #define HRC(r) \
  13. if(FAILED(hr = (r))) { \
  14. MF_LOG_COM(#r, hr); \
  15. goto fail; \
  16. }
  17. using namespace MFAAC;
  18. #define CONST_ARRAY(name, ...) static const UINT32 name[] = { __VA_ARGS__ };
  19. CONST_ARRAY(VALID_BITRATES, 96, 128, 160, 192);
  20. CONST_ARRAY(VALID_CHANNELS, 1, 2);
  21. CONST_ARRAY(VALID_BITS_PER_SAMPLE, 16);
  22. CONST_ARRAY(VALID_SAMPLERATES, 44100, 48000 );
  23. #undef CONST_ARRAY
  24. template <int N>
  25. static UINT32 FindBestMatch(const UINT32 (&validValues)[N], UINT32 value)
  26. {
  27. for (UINT32 val : validValues) {
  28. if (val >= value)
  29. return val;
  30. }
  31. // Only downgrade if no values are better
  32. return validValues[N - 1];
  33. }
  34. template <int N>
  35. static bool IsValid(const UINT32 (&validValues)[N], UINT32 value)
  36. {
  37. for (UINT32 val : validValues) {
  38. if (val == value)
  39. return true;
  40. }
  41. return false;
  42. };
  43. UINT32 MFAAC::FindBestBitrateMatch(UINT32 value)
  44. {
  45. return FindBestMatch(VALID_BITRATES, value);
  46. }
  47. UINT32 MFAAC::FindBestChannelsMatch(UINT32 value)
  48. {
  49. return FindBestMatch(VALID_CHANNELS, value);
  50. }
  51. UINT32 MFAAC::FindBestBitsPerSampleMatch(UINT32 value)
  52. {
  53. return FindBestMatch(VALID_BITS_PER_SAMPLE, value);
  54. }
  55. UINT32 MFAAC::FindBestSamplerateMatch(UINT32 value)
  56. {
  57. return FindBestMatch(VALID_SAMPLERATES, value);
  58. }
  59. bool MFAAC::BitrateValid(UINT32 value)
  60. {
  61. return IsValid(VALID_BITRATES, value);
  62. }
  63. bool MFAAC::ChannelsValid(UINT32 value)
  64. {
  65. return IsValid(VALID_CHANNELS, value);
  66. }
  67. bool MFAAC::BitsPerSampleValid(UINT32 value)
  68. {
  69. return IsValid(VALID_BITS_PER_SAMPLE, value);
  70. }
  71. bool MFAAC::SamplerateValid(UINT32 value)
  72. {
  73. return IsValid(VALID_SAMPLERATES, value);
  74. }
  75. HRESULT MFAAC::Encoder::CreateMediaTypes(ComPtr<IMFMediaType> &i,
  76. ComPtr<IMFMediaType> &o)
  77. {
  78. HRESULT hr;
  79. HRC(MFCreateMediaType(&i));
  80. HRC(MFCreateMediaType(&o));
  81. HRC(i->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
  82. HRC(i->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM));
  83. HRC(i->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample));
  84. HRC(i->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, sampleRate));
  85. HRC(i->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, channels));
  86. HRC(o->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
  87. HRC(o->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC));
  88. HRC(o->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample));
  89. HRC(o->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, sampleRate));
  90. HRC(o->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, channels));
  91. HRC(o->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND,
  92. (bitrate * 1000) / 8));
  93. return S_OK;
  94. fail:
  95. return hr;
  96. }
  97. void MFAAC::Encoder::InitializeExtraData()
  98. {
  99. UINT16 *extraData16 = (UINT16 *)extraData;
  100. UINT16 profile = 2; //Low Complexity
  101. #define SWAPU16(x) (x>>8) | (x<<8)
  102. // Profile
  103. // XXXX X... .... ....
  104. *extraData16 = profile << 11;
  105. // Sample Index (3=48, 4=44.1)
  106. // .... .XXX X... ....
  107. *extraData16 |= sampleRate == 48000 ? 3 : 4 << 7;
  108. // Channels
  109. // .... .... .XXX X...
  110. *extraData16 |= channels << 3;
  111. *extraData16 = SWAPU16(*extraData16);
  112. // Extensions
  113. extraData16++;
  114. *extraData16 = 0x2b7 << 5;
  115. // Profile
  116. *extraData16 |= profile;
  117. *extraData16 = SWAPU16(*extraData16);
  118. extraData[4] = 0;
  119. #undef SWAPU16
  120. }
  121. bool MFAAC::Encoder::Initialize()
  122. {
  123. HRESULT hr;
  124. ComPtr<IMFTransform> transform_;
  125. ComPtr<IMFMediaType> inputType, outputType;
  126. if (!BitrateValid(bitrate)) {
  127. MF_LOG_AAC(LOG_WARNING, "invalid bitrate (kbps) '%d'", bitrate);
  128. return false;
  129. }
  130. if (!ChannelsValid(channels)) {
  131. MF_LOG_AAC(LOG_WARNING, "invalid channel count '%d", channels);
  132. return false;
  133. }
  134. if (!SamplerateValid(sampleRate)) {
  135. MF_LOG_AAC(LOG_WARNING, "invalid sample rate (hz) '%d",
  136. sampleRate);
  137. return false;
  138. }
  139. if (!BitsPerSampleValid(bitsPerSample)) {
  140. MF_LOG_AAC(LOG_WARNING, "invalid bits-per-sample (bits) '%d'",
  141. bitsPerSample);
  142. return false;
  143. }
  144. InitializeExtraData();
  145. HRC(CoCreateInstance(CLSID_AACMFTEncoder, NULL, CLSCTX_INPROC_SERVER,
  146. IID_PPV_ARGS(&transform_)));
  147. HRC(CreateMediaTypes(inputType, outputType));
  148. HRC(transform_->SetInputType(0, inputType.Get(), 0));
  149. HRC(transform_->SetOutputType(0, outputType.Get(), 0));
  150. HRC(transform_->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING,
  151. NULL));
  152. HRC(transform_->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM,
  153. NULL));
  154. MF_LOG_AAC(LOG_INFO, "encoder created\n"
  155. "\tbitrate: %d\n"
  156. "\tchannels: %d\n"
  157. "\tsample rate: %d\n"
  158. "\tbits-per-sample: %d\n",
  159. bitrate, channels, sampleRate, bitsPerSample);
  160. transform = transform_;
  161. return true;
  162. fail:
  163. return false;
  164. }
  165. HRESULT MFAAC::Encoder::CreateEmptySample(ComPtr<IMFSample> &sample,
  166. ComPtr<IMFMediaBuffer> &buffer, DWORD length)
  167. {
  168. HRESULT hr;
  169. HRC(MFCreateSample(&sample));
  170. HRC(MFCreateMemoryBuffer(length, &buffer));
  171. HRC(sample->AddBuffer(buffer.Get()));
  172. return S_OK;
  173. fail:
  174. return hr;
  175. }
  176. HRESULT MFAAC::Encoder::EnsureCapacity(ComPtr<IMFSample> &sample, DWORD length)
  177. {
  178. HRESULT hr;
  179. ComPtr<IMFMediaBuffer> buffer;
  180. DWORD currentLength;
  181. if (!sample) {
  182. HRC(CreateEmptySample(sample, buffer, length));
  183. } else {
  184. HRC(sample->GetBufferByIndex(0, &buffer));
  185. }
  186. HRC(buffer->GetMaxLength(&currentLength));
  187. if (currentLength < length) {
  188. HRC(sample->RemoveAllBuffers());
  189. HRC(MFCreateMemoryBuffer(length, &buffer));
  190. HRC(sample->AddBuffer(buffer));
  191. } else {
  192. buffer->SetCurrentLength(0);
  193. }
  194. packetBuffer.reserve(length);
  195. return S_OK;
  196. fail:
  197. return hr;
  198. }
  199. bool MFAAC::Encoder::ProcessInput(UINT8 *data, UINT32 data_length,
  200. UINT64 pts, Status *status)
  201. {
  202. HRESULT hr;
  203. ComPtr<IMFSample> sample;
  204. ComPtr<IMFMediaBuffer> buffer;
  205. BYTE *bufferData;
  206. INT64 samplePts;
  207. UINT32 samples;
  208. UINT64 sampleDur;
  209. HRC(CreateEmptySample(sample, buffer, data_length));
  210. HRC(buffer->Lock(&bufferData, NULL, NULL));
  211. memcpy(bufferData, data, data_length);
  212. HRC(buffer->Unlock());
  213. HRC(buffer->SetCurrentLength(data_length));
  214. samples = data_length / channels / (bitsPerSample / 8);
  215. sampleDur = (UINT64)(((float) sampleRate / channels / samples) * 10000);
  216. samplePts = pts / 100;
  217. HRC(sample->SetSampleTime(samplePts));
  218. HRC(sample->SetSampleDuration(sampleDur));
  219. hr = transform->ProcessInput(0, sample, 0);
  220. if (hr == MF_E_NOTACCEPTING) {
  221. *status = NOT_ACCEPTING;
  222. return true;
  223. } else if (FAILED(hr)) {
  224. MF_LOG_COM("process input", hr);
  225. return false;
  226. }
  227. *status = SUCCESS;
  228. return true;
  229. fail:
  230. *status = FAILURE;
  231. return false;
  232. }
  233. bool MFAAC::Encoder::ProcessOutput(UINT8 **data, UINT32 *dataLength,
  234. UINT64 *pts, Status *status)
  235. {
  236. HRESULT hr;
  237. DWORD outputFlags, outputStatus;
  238. MFT_OUTPUT_STREAM_INFO outputInfo = {0};
  239. MFT_OUTPUT_DATA_BUFFER output = {0};
  240. ComPtr<IMFMediaBuffer> outputBuffer;
  241. BYTE *bufferData;
  242. DWORD bufferLength;
  243. INT64 samplePts;
  244. HRC(transform->GetOutputStatus(&outputFlags));
  245. if (outputFlags != MFT_OUTPUT_STATUS_SAMPLE_READY) {
  246. *status = NEED_MORE_INPUT;
  247. return true;
  248. }
  249. HRC(transform->GetOutputStreamInfo(0, &outputInfo));
  250. EnsureCapacity(outputSample, outputInfo.cbSize);
  251. output.pSample = outputSample.Get();
  252. hr = transform->ProcessOutput(0, 1, &output, &outputStatus);
  253. if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
  254. *status = NEED_MORE_INPUT;
  255. return true;
  256. } else if (FAILED(hr)) {
  257. MF_LOG_COM("process output", hr);
  258. return false;
  259. }
  260. HRC(outputSample->GetBufferByIndex(0, &outputBuffer));
  261. HRC(outputBuffer->Lock(&bufferData, NULL, &bufferLength));
  262. packetBuffer.assign(bufferData, bufferData + bufferLength);
  263. HRC(outputBuffer->Unlock());
  264. HRC(outputSample->GetSampleTime(&samplePts));
  265. *pts = samplePts * 100;
  266. *data = &packetBuffer[0];
  267. *dataLength = bufferLength;
  268. *status = SUCCESS;
  269. return true;
  270. fail:
  271. *status = FAILURE;
  272. return false;
  273. }
  274. bool MFAAC::Encoder::ExtraData(UINT8 **extraData_, UINT32 *extraDataLength)
  275. {
  276. *extraData_ = extraData;
  277. *extraDataLength = sizeof(extraData);
  278. return true;
  279. }