encoder.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256
  1. #include <util/darray.h>
  2. #include <util/dstr.hpp>
  3. #include <obs-module.h>
  4. #include <algorithm>
  5. #include <cstdlib>
  6. #include <initializer_list>
  7. #include <memory>
  8. #include <mutex>
  9. #include <vector>
  10. #ifndef _WIN32
  11. #include <AudioToolbox/AudioToolbox.h>
  12. #endif
  13. #define CA_LOG(level, format, ...) \
  14. blog(level, "[CoreAudio encoder]: " format, ##__VA_ARGS__)
  15. #define CA_LOG_ENCODER(format_name, encoder, level, format, ...) \
  16. blog(level, "[CoreAudio %s: '%s']: " format, \
  17. format_name, obs_encoder_get_name(encoder), \
  18. ##__VA_ARGS__)
  19. #define CA_BLOG(level, format, ...) \
  20. CA_LOG_ENCODER(ca->format_name, ca->encoder, level, format, \
  21. ##__VA_ARGS__)
  22. #define CA_CO_LOG(level, format, ...) \
  23. do { \
  24. if (ca) \
  25. CA_BLOG(level, format, ##__VA_ARGS__); \
  26. else \
  27. CA_LOG(level, format, ##__VA_ARGS__); \
  28. } while (false)
  29. #ifdef _WIN32
  30. #include "windows-imports.h"
  31. #endif
  32. using namespace std;
  33. namespace {
  34. struct asbd_builder {
  35. AudioStreamBasicDescription asbd;
  36. asbd_builder &sample_rate(Float64 rate)
  37. {
  38. asbd.mSampleRate = rate;
  39. return *this;
  40. }
  41. asbd_builder &format_id(UInt32 format)
  42. {
  43. asbd.mFormatID = format;
  44. return *this;
  45. }
  46. asbd_builder &format_flags(UInt32 flags)
  47. {
  48. asbd.mFormatFlags = flags;
  49. return *this;
  50. }
  51. asbd_builder &bytes_per_packet(UInt32 bytes)
  52. {
  53. asbd.mBytesPerPacket = bytes;
  54. return *this;
  55. }
  56. asbd_builder &frames_per_packet(UInt32 frames)
  57. {
  58. asbd.mFramesPerPacket = frames;
  59. return *this;
  60. }
  61. asbd_builder &bytes_per_frame(UInt32 bytes)
  62. {
  63. asbd.mBytesPerFrame = bytes;
  64. return *this;
  65. }
  66. asbd_builder &channels_per_frame(UInt32 channels)
  67. {
  68. asbd.mChannelsPerFrame = channels;
  69. return *this;
  70. }
  71. asbd_builder &bits_per_channel(UInt32 bits)
  72. {
  73. asbd.mBitsPerChannel = bits;
  74. return *this;
  75. }
  76. };
  77. struct ca_encoder {
  78. obs_encoder_t *encoder;
  79. const char *format_name;
  80. UInt32 format_id;
  81. const initializer_list<UInt32> *allowed_formats;
  82. AudioConverterRef converter;
  83. size_t output_buffer_size;
  84. vector<uint8_t> output_buffer;
  85. size_t out_frames_per_packet;
  86. size_t in_packets;
  87. size_t in_frame_size;
  88. size_t in_bytes_required;
  89. DARRAY(uint8_t) input_buffer;
  90. size_t bytes_read;
  91. uint64_t total_samples;
  92. uint64_t samples_per_second;
  93. vector<uint8_t> extra_data;
  94. size_t channels;
  95. ~ca_encoder()
  96. {
  97. if (converter)
  98. AudioConverterDispose(converter);
  99. da_free(input_buffer);
  100. }
  101. };
  102. typedef struct ca_encoder ca_encoder;
  103. }
  104. namespace std {
  105. #ifndef _WIN32
  106. template <>
  107. struct default_delete<remove_pointer<CFErrorRef>::type> {
  108. void operator()(remove_pointer<CFErrorRef>::type *err)
  109. {
  110. CFRelease(err);
  111. }
  112. };
  113. template <>
  114. struct default_delete<remove_pointer<CFStringRef>::type> {
  115. void operator()(remove_pointer<CFStringRef>::type *str)
  116. {
  117. CFRelease(str);
  118. }
  119. };
  120. #endif
  121. template <>
  122. struct default_delete<remove_pointer<AudioConverterRef>::type> {
  123. void operator()(AudioConverterRef converter)
  124. {
  125. AudioConverterDispose(converter);
  126. }
  127. };
  128. }
  129. template <typename T>
  130. using cf_ptr = unique_ptr<typename remove_pointer<T>::type>;
  131. #ifndef _MSC_VER
  132. __attribute__((__format__(__printf__, 3, 4)))
  133. #endif
  134. static void log_to_dstr(DStr &str, ca_encoder *ca, const char *fmt, ...)
  135. {
  136. dstr prev_str = *static_cast<dstr*>(str);
  137. va_list args;
  138. va_start(args, fmt);
  139. dstr_vcatf(str, fmt, args);
  140. va_end(args);
  141. if (str->array)
  142. return;
  143. char array[4096];
  144. va_start(args, fmt);
  145. vsnprintf(array, 4096, fmt, args);
  146. va_end(args);
  147. array[4095] = 0;
  148. if (!prev_str.array && !prev_str.len)
  149. CA_CO_LOG(LOG_ERROR, "Could not allocate buffer for logging:"
  150. "\n'%s'", array);
  151. else
  152. CA_CO_LOG(LOG_ERROR, "Could not allocate buffer for logging:"
  153. "\n'%s'\nPrevious log entries:\n%s",
  154. array, prev_str.array);
  155. bfree(prev_str.array);
  156. }
  157. static const char *flush_log(DStr &log)
  158. {
  159. if (!log->array || !log->len)
  160. return "";
  161. if (log->array[log->len - 1] == '\n') {
  162. log->array[log->len - 1] = 0; //Get rid of last newline
  163. log->len -= 1;
  164. }
  165. return log->array;
  166. }
  167. #define CA_CO_DLOG_(level, format) \
  168. CA_CO_LOG(level, format "%s%s", \
  169. log->array ? ":\n" : "", flush_log(log))
  170. #define CA_CO_DLOG(level, format, ...) \
  171. CA_CO_LOG(level, format "%s%s", ##__VA_ARGS__, \
  172. log->array ? ":\n" : "", flush_log(log))
  173. static const char *aac_get_name(void)
  174. {
  175. return obs_module_text("CoreAudioAAC");
  176. }
  177. static const char *code_to_str(OSStatus code)
  178. {
  179. switch (code) {
  180. #define HANDLE_CODE(c) case c: return #c
  181. HANDLE_CODE(kAudio_UnimplementedError);
  182. HANDLE_CODE(kAudio_FileNotFoundError);
  183. HANDLE_CODE(kAudio_FilePermissionError);
  184. HANDLE_CODE(kAudio_TooManyFilesOpenError);
  185. HANDLE_CODE(kAudio_BadFilePathError);
  186. HANDLE_CODE(kAudio_ParamError);
  187. HANDLE_CODE(kAudio_MemFullError);
  188. HANDLE_CODE(kAudioConverterErr_FormatNotSupported);
  189. HANDLE_CODE(kAudioConverterErr_OperationNotSupported);
  190. HANDLE_CODE(kAudioConverterErr_PropertyNotSupported);
  191. HANDLE_CODE(kAudioConverterErr_InvalidInputSize);
  192. HANDLE_CODE(kAudioConverterErr_InvalidOutputSize);
  193. HANDLE_CODE(kAudioConverterErr_UnspecifiedError);
  194. HANDLE_CODE(kAudioConverterErr_BadPropertySizeError);
  195. HANDLE_CODE(kAudioConverterErr_RequiresPacketDescriptionsError);
  196. HANDLE_CODE(kAudioConverterErr_InputSampleRateOutOfRange);
  197. HANDLE_CODE(kAudioConverterErr_OutputSampleRateOutOfRange);
  198. #undef HANDLE_CODE
  199. default: break;
  200. }
  201. return NULL;
  202. }
  203. static DStr osstatus_to_dstr(OSStatus code)
  204. {
  205. DStr result;
  206. #ifndef _WIN32
  207. cf_ptr<CFErrorRef> err{CFErrorCreate(kCFAllocatorDefault,
  208. kCFErrorDomainOSStatus, code, NULL)};
  209. cf_ptr<CFStringRef> str{CFErrorCopyDescription(err.get())};
  210. CFIndex length = CFStringGetLength(str.get());
  211. CFIndex max_size = CFStringGetMaximumSizeForEncoding(length,
  212. kCFStringEncodingUTF8);
  213. dstr_ensure_capacity(result, max_size);
  214. if (result->array && CFStringGetCString(str.get(), result->array,
  215. max_size, kCFStringEncodingUTF8)) {
  216. dstr_resize(result, strlen(result->array));
  217. return result;
  218. }
  219. #endif
  220. const char *code_str = code_to_str(code);
  221. dstr_printf(result, "%s%s%d%s",
  222. code_str ? code_str : "",
  223. code_str ? " (" : "",
  224. static_cast<int>(code),
  225. code_str ? ")" : "");
  226. return result;
  227. }
  228. static void log_osstatus(int log_level, ca_encoder *ca, const char *context,
  229. OSStatus code)
  230. {
  231. DStr str = osstatus_to_dstr(code);
  232. if (ca)
  233. CA_BLOG(log_level, "Error in %s: %s", context, str->array);
  234. else
  235. CA_LOG(log_level, "Error in %s: %s", context, str->array);
  236. }
  237. static const char *format_id_to_str(UInt32 format_id)
  238. {
  239. #define FORMAT_TO_STR(x) case x: return #x
  240. switch (format_id) {
  241. FORMAT_TO_STR(kAudioFormatLinearPCM);
  242. FORMAT_TO_STR(kAudioFormatAC3);
  243. FORMAT_TO_STR(kAudioFormat60958AC3);
  244. FORMAT_TO_STR(kAudioFormatAppleIMA4);
  245. FORMAT_TO_STR(kAudioFormatMPEG4AAC);
  246. FORMAT_TO_STR(kAudioFormatMPEG4CELP);
  247. FORMAT_TO_STR(kAudioFormatMPEG4HVXC);
  248. FORMAT_TO_STR(kAudioFormatMPEG4TwinVQ);
  249. FORMAT_TO_STR(kAudioFormatMACE3);
  250. FORMAT_TO_STR(kAudioFormatMACE6);
  251. FORMAT_TO_STR(kAudioFormatULaw);
  252. FORMAT_TO_STR(kAudioFormatALaw);
  253. FORMAT_TO_STR(kAudioFormatQDesign);
  254. FORMAT_TO_STR(kAudioFormatQDesign2);
  255. FORMAT_TO_STR(kAudioFormatQUALCOMM);
  256. FORMAT_TO_STR(kAudioFormatMPEGLayer1);
  257. FORMAT_TO_STR(kAudioFormatMPEGLayer2);
  258. FORMAT_TO_STR(kAudioFormatMPEGLayer3);
  259. FORMAT_TO_STR(kAudioFormatTimeCode);
  260. FORMAT_TO_STR(kAudioFormatMIDIStream);
  261. FORMAT_TO_STR(kAudioFormatParameterValueStream);
  262. FORMAT_TO_STR(kAudioFormatAppleLossless);
  263. FORMAT_TO_STR(kAudioFormatMPEG4AAC_HE);
  264. FORMAT_TO_STR(kAudioFormatMPEG4AAC_LD);
  265. FORMAT_TO_STR(kAudioFormatMPEG4AAC_ELD);
  266. FORMAT_TO_STR(kAudioFormatMPEG4AAC_ELD_SBR);
  267. FORMAT_TO_STR(kAudioFormatMPEG4AAC_HE_V2);
  268. FORMAT_TO_STR(kAudioFormatMPEG4AAC_Spatial);
  269. FORMAT_TO_STR(kAudioFormatAMR);
  270. FORMAT_TO_STR(kAudioFormatAudible);
  271. FORMAT_TO_STR(kAudioFormatiLBC);
  272. FORMAT_TO_STR(kAudioFormatDVIIntelIMA);
  273. FORMAT_TO_STR(kAudioFormatMicrosoftGSM);
  274. FORMAT_TO_STR(kAudioFormatAES3);
  275. }
  276. #undef FORMAT_TO_STR
  277. return "Unknown format";
  278. }
  279. static void aac_destroy(void *data)
  280. {
  281. ca_encoder *ca = static_cast<ca_encoder*>(data);
  282. delete ca;
  283. }
  284. template <typename Func>
  285. static bool query_converter_property_raw(DStr &log, ca_encoder *ca,
  286. AudioFormatPropertyID property,
  287. const char *get_property_info, const char *get_property,
  288. AudioConverterRef converter, Func &&func)
  289. {
  290. UInt32 size = 0;
  291. OSStatus code = AudioConverterGetPropertyInfo(converter, property,
  292. &size, nullptr);
  293. if (code) {
  294. log_to_dstr(log, ca, "%s: %s\n", get_property_info,
  295. osstatus_to_dstr(code)->array);
  296. return false;
  297. }
  298. if (!size) {
  299. log_to_dstr(log, ca, "%s returned 0 size\n", get_property_info);
  300. return false;
  301. }
  302. vector<uint8_t> buffer;
  303. try {
  304. buffer.resize(size);
  305. } catch (...) {
  306. log_to_dstr(log, ca, "Failed to allocate %u bytes for %s\n",
  307. static_cast<uint32_t>(size), get_property);
  308. return false;
  309. }
  310. code = AudioConverterGetProperty(converter, property, &size,
  311. buffer.data());
  312. if (code) {
  313. log_to_dstr(log, ca, "%s: %s\n", get_property,
  314. osstatus_to_dstr(code)->array);
  315. return false;
  316. }
  317. func(size, static_cast<void*>(buffer.data()));
  318. return true;
  319. }
  320. #define EXPAND_CONVERTER_NAMES(x) x, \
  321. "AudioConverterGetPropertyInfo(" #x ")", \
  322. "AudioConverterGetProperty(" #x ")"
  323. template <typename Func>
  324. static bool enumerate_bitrates(DStr &log, ca_encoder *ca,
  325. AudioConverterRef converter, Func &&func)
  326. {
  327. auto helper = [&](UInt32 size, void *data)
  328. {
  329. auto range = static_cast<AudioValueRange*>(data);
  330. size_t num_ranges = size / sizeof(AudioValueRange);
  331. for (size_t i = 0; i < num_ranges; i++)
  332. func(static_cast<UInt32>(range[i].mMinimum),
  333. static_cast<UInt32>(range[i].mMaximum));
  334. };
  335. return query_converter_property_raw(log, ca, EXPAND_CONVERTER_NAMES(
  336. kAudioConverterApplicableEncodeBitRates),
  337. converter, helper);
  338. }
  339. typedef void (*bitrate_enumeration_func)(void *data, UInt32 min, UInt32 max);
  340. static bool enumerate_bitrates(ca_encoder *ca, AudioConverterRef converter,
  341. bitrate_enumeration_func enum_func, void *data)
  342. {
  343. if (!converter && ca)
  344. converter = ca->converter;
  345. UInt32 size;
  346. OSStatus code = AudioConverterGetPropertyInfo(converter,
  347. kAudioConverterApplicableEncodeBitRates,
  348. &size, NULL);
  349. if (code) {
  350. log_osstatus(LOG_WARNING, ca,
  351. "AudioConverterGetPropertyInfo(bitrates)",
  352. code);
  353. return false;
  354. }
  355. if (!size) {
  356. if (ca)
  357. CA_BLOG(LOG_WARNING, "Query for applicable bitrates "
  358. "returned 0 size");
  359. else
  360. CA_LOG(LOG_WARNING, "Query for applicable bitrates "
  361. "returned 0 size");
  362. return false;
  363. }
  364. size_t num_bitrates = (size + sizeof(AudioValueRange) - 1) /
  365. sizeof(AudioValueRange);
  366. vector<AudioValueRange> bitrates;
  367. try {
  368. bitrates.resize(num_bitrates);
  369. } catch (...) {
  370. if (ca)
  371. CA_BLOG(LOG_WARNING, "Could not allocate buffer while "
  372. "enumerating bitrates");
  373. else
  374. CA_LOG(LOG_WARNING, "Could not allocate buffer while "
  375. "enumerating bitrates");
  376. return false;
  377. }
  378. code = AudioConverterGetProperty(converter,
  379. kAudioConverterApplicableEncodeBitRates,
  380. &size, bitrates.data());
  381. if (code) {
  382. log_osstatus(LOG_WARNING, ca,
  383. "AudioConverterGetProperty(bitrates)", code);
  384. return false;
  385. }
  386. for (size_t i = 0; i < num_bitrates; i++)
  387. enum_func(data, (UInt32)bitrates[i].mMinimum,
  388. (UInt32)bitrates[i].mMaximum);
  389. return num_bitrates > 0;
  390. }
  391. static bool bitrate_valid(DStr &log, ca_encoder *ca,
  392. AudioConverterRef converter, UInt32 bitrate)
  393. {
  394. bool valid = false;
  395. auto helper = [&](UInt32 min_, UInt32 max_)
  396. {
  397. if (min_ == bitrate || max_ == bitrate)
  398. valid = true;
  399. };
  400. enumerate_bitrates(log, ca, converter, helper);
  401. return valid;
  402. }
  403. static bool create_encoder(DStr &log, ca_encoder *ca,
  404. AudioStreamBasicDescription *in,
  405. AudioStreamBasicDescription *out,
  406. UInt32 format_id, UInt32 bitrate, UInt32 rate_control)
  407. {
  408. #define STATUS_CHECK(c) \
  409. code = c; \
  410. if (code) { \
  411. log_to_dstr(log, ca, #c " returned %s", \
  412. osstatus_to_dstr(code)->array); \
  413. return false; \
  414. }
  415. auto out_ = asbd_builder()
  416. .sample_rate((Float64)ca->samples_per_second)
  417. .channels_per_frame((UInt32)ca->channels)
  418. .format_id(format_id)
  419. .asbd;
  420. UInt32 size = sizeof(*out);
  421. OSStatus code;
  422. STATUS_CHECK(AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
  423. 0, NULL, &size, &out_));
  424. *out = out_;
  425. STATUS_CHECK(AudioConverterNew(in, out, &ca->converter))
  426. STATUS_CHECK(AudioConverterSetProperty(ca->converter,
  427. kAudioCodecPropertyBitRateControlMode,
  428. sizeof(rate_control), &rate_control));
  429. if (!bitrate_valid(log, ca, ca->converter, bitrate)) {
  430. log_to_dstr(log, ca, "Encoder does not support bitrate %u "
  431. "for format %s (0x%x)\n",
  432. (uint32_t)bitrate, format_id_to_str(format_id),
  433. (uint32_t)format_id);
  434. return false;
  435. }
  436. ca->format_id = format_id;
  437. return true;
  438. #undef STATUS_CHECK
  439. }
  440. static const initializer_list<UInt32> aac_formats = {
  441. kAudioFormatMPEG4AAC_HE_V2,
  442. kAudioFormatMPEG4AAC_HE,
  443. kAudioFormatMPEG4AAC,
  444. };
  445. static const initializer_list<UInt32> aac_lc_formats = {
  446. kAudioFormatMPEG4AAC,
  447. };
  448. static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
  449. {
  450. #define STATUS_CHECK(c) \
  451. code = c; \
  452. if (code) { \
  453. log_osstatus(LOG_ERROR, ca.get(), #c, code); \
  454. return nullptr; \
  455. }
  456. UInt32 bitrate = (UInt32)obs_data_get_int(settings, "bitrate") * 1000;
  457. if (!bitrate) {
  458. CA_LOG_ENCODER("AAC", encoder, LOG_ERROR,
  459. "Invalid bitrate specified");
  460. return NULL;
  461. }
  462. const enum audio_format format = AUDIO_FORMAT_FLOAT;
  463. if (is_audio_planar(format)) {
  464. CA_LOG_ENCODER("AAC", encoder, LOG_ERROR,
  465. "Got non-interleaved audio format %d", format);
  466. return NULL;
  467. }
  468. unique_ptr<ca_encoder> ca;
  469. try {
  470. ca.reset(new ca_encoder());
  471. } catch (...) {
  472. CA_LOG_ENCODER("AAC", encoder, LOG_ERROR,
  473. "Could not allocate encoder");
  474. return nullptr;
  475. }
  476. ca->encoder = encoder;
  477. ca->format_name = "AAC";
  478. audio_t *audio = obs_encoder_audio(encoder);
  479. const struct audio_output_info *aoi = audio_output_get_info(audio);
  480. ca->channels = audio_output_get_channels(audio);
  481. ca->samples_per_second = audio_output_get_sample_rate(audio);
  482. size_t bytes_per_frame = get_audio_size(format, aoi->speakers, 1);
  483. size_t bits_per_channel = get_audio_bytes_per_channel(format) * 8;
  484. auto in = asbd_builder()
  485. .sample_rate((Float64)ca->samples_per_second)
  486. .channels_per_frame((UInt32)ca->channels)
  487. .bytes_per_frame((UInt32)bytes_per_frame)
  488. .frames_per_packet(1)
  489. .bytes_per_packet((UInt32)(1 * bytes_per_frame))
  490. .bits_per_channel((UInt32)bits_per_channel)
  491. .format_id(kAudioFormatLinearPCM)
  492. .format_flags(kAudioFormatFlagsNativeEndian |
  493. kAudioFormatFlagIsPacked |
  494. kAudioFormatFlagIsFloat |
  495. 0)
  496. .asbd;
  497. AudioStreamBasicDescription out;
  498. UInt32 rate_control = kAudioCodecBitRateControlMode_Constant;
  499. if (obs_data_get_bool(settings, "allow he-aac")) {
  500. ca->allowed_formats = &aac_formats;
  501. } else {
  502. ca->allowed_formats = &aac_lc_formats;
  503. }
  504. DStr log;
  505. bool encoder_created = false;
  506. for (UInt32 format_id : *ca->allowed_formats) {
  507. log_to_dstr(log, ca.get(), "Trying format %s (0x%x)\n",
  508. format_id_to_str(format_id),
  509. (uint32_t)format_id);
  510. if (!create_encoder(log, ca.get(), &in, &out, format_id,
  511. bitrate, rate_control))
  512. continue;
  513. encoder_created = true;
  514. break;
  515. }
  516. if (!encoder_created) {
  517. CA_CO_DLOG(LOG_ERROR, "Could not create encoder for "
  518. "selected format%s",
  519. ca->allowed_formats->size() == 1 ? "" : "s");
  520. return nullptr;
  521. }
  522. if (log->len)
  523. CA_CO_DLOG_(LOG_DEBUG, "Encoder created");
  524. OSStatus code;
  525. UInt32 converter_quality = kAudioConverterQuality_Max;
  526. STATUS_CHECK(AudioConverterSetProperty(ca->converter,
  527. kAudioConverterCodecQuality,
  528. sizeof(converter_quality), &converter_quality));
  529. STATUS_CHECK(AudioConverterSetProperty(ca->converter,
  530. kAudioConverterEncodeBitRate,
  531. sizeof(bitrate), &bitrate));
  532. UInt32 size = sizeof(in);
  533. STATUS_CHECK(AudioConverterGetProperty(ca->converter,
  534. kAudioConverterCurrentInputStreamDescription,
  535. &size, &in));
  536. size = sizeof(out);
  537. STATUS_CHECK(AudioConverterGetProperty(ca->converter,
  538. kAudioConverterCurrentOutputStreamDescription,
  539. &size, &out));
  540. ca->in_frame_size = in.mBytesPerFrame;
  541. ca->in_packets = out.mFramesPerPacket / in.mFramesPerPacket;
  542. ca->in_bytes_required = ca->in_packets * ca->in_frame_size;
  543. ca->out_frames_per_packet = out.mFramesPerPacket;
  544. da_init(ca->input_buffer);
  545. ca->output_buffer_size = out.mBytesPerPacket;
  546. if (out.mBytesPerPacket == 0) {
  547. UInt32 max_packet_size = 0;
  548. size = sizeof(max_packet_size);
  549. code = AudioConverterGetProperty(ca->converter,
  550. kAudioConverterPropertyMaximumOutputPacketSize,
  551. &size, &max_packet_size);
  552. if (code) {
  553. log_osstatus(LOG_WARNING, ca.get(),
  554. "AudioConverterGetProperty(PacketSz)",
  555. code);
  556. ca->output_buffer_size = 32768;
  557. } else {
  558. ca->output_buffer_size = max_packet_size;
  559. }
  560. }
  561. try {
  562. ca->output_buffer.resize(ca->output_buffer_size);
  563. } catch (...) {
  564. CA_BLOG(LOG_ERROR, "Failed to allocate output buffer");
  565. return nullptr;
  566. }
  567. const char *format_name =
  568. out.mFormatID == kAudioFormatMPEG4AAC_HE_V2 ? "HE-AAC v2" :
  569. out.mFormatID == kAudioFormatMPEG4AAC_HE ? "HE-AAC" : "AAC";
  570. CA_BLOG(LOG_INFO, "settings:\n"
  571. "\tmode: %s\n"
  572. "\tbitrate: %u\n"
  573. "\tsample rate: %llu\n"
  574. "\tcbr: %s\n"
  575. "\toutput buffer: %lu",
  576. format_name, (unsigned int)bitrate / 1000,
  577. ca->samples_per_second,
  578. rate_control == kAudioCodecBitRateControlMode_Constant ?
  579. "on" : "off",
  580. (unsigned long)ca->output_buffer_size);
  581. return ca.release();
  582. }
  583. static OSStatus complex_input_data_proc(AudioConverterRef inAudioConverter,
  584. UInt32 *ioNumberDataPackets, AudioBufferList *ioData,
  585. AudioStreamPacketDescription **outDataPacketDescription,
  586. void *inUserData)
  587. {
  588. UNUSED_PARAMETER(inAudioConverter);
  589. UNUSED_PARAMETER(outDataPacketDescription);
  590. ca_encoder *ca = static_cast<ca_encoder*>(inUserData);
  591. if (ca->bytes_read) {
  592. da_erase_range(ca->input_buffer, 0, ca->bytes_read);
  593. ca->bytes_read = 0;
  594. }
  595. if (ca->input_buffer.num < ca->in_bytes_required) {
  596. *ioNumberDataPackets = 0;
  597. ioData->mBuffers[0].mData = NULL;
  598. return 1;
  599. }
  600. *ioNumberDataPackets =
  601. (UInt32)(ca->in_bytes_required / ca->in_frame_size);
  602. ioData->mNumberBuffers = 1;
  603. ioData->mBuffers[0].mData = ca->input_buffer.array;
  604. ioData->mBuffers[0].mNumberChannels = (UInt32)ca->channels;
  605. ioData->mBuffers[0].mDataByteSize = (UInt32)ca->in_bytes_required;
  606. ca->bytes_read += ca->in_packets * ca->in_frame_size;
  607. return 0;
  608. }
  609. #ifdef _MSC_VER
  610. // disable warning that recommends if ((foo = bar > 0) == false) over
  611. // if (!(foo = bar > 0))
  612. #pragma warning(push)
  613. #pragma warning(disable: 4706)
  614. #endif
  615. static bool aac_encode(void *data, struct encoder_frame *frame,
  616. struct encoder_packet *packet, bool *received_packet)
  617. {
  618. ca_encoder *ca = static_cast<ca_encoder*>(data);
  619. da_push_back_array(ca->input_buffer, frame->data[0],
  620. frame->linesize[0]);
  621. if ((ca->input_buffer.num - ca->bytes_read) < ca->in_bytes_required)
  622. return true;
  623. UInt32 packets = 1;
  624. AudioBufferList buffer_list = { 0 };
  625. buffer_list.mNumberBuffers = 1;
  626. buffer_list.mBuffers[0].mNumberChannels = (UInt32)ca->channels;
  627. buffer_list.mBuffers[0].mDataByteSize = (UInt32)ca->output_buffer_size;
  628. buffer_list.mBuffers[0].mData = ca->output_buffer.data();
  629. AudioStreamPacketDescription out_desc = { 0 };
  630. OSStatus code = AudioConverterFillComplexBuffer(ca->converter,
  631. complex_input_data_proc, ca, &packets,
  632. &buffer_list, &out_desc);
  633. if (code && code != 1) {
  634. log_osstatus(LOG_ERROR, ca, "AudioConverterFillComplexBuffer",
  635. code);
  636. return false;
  637. }
  638. if (!(*received_packet = packets > 0))
  639. return true;
  640. packet->pts = ca->total_samples;
  641. packet->dts = ca->total_samples;
  642. packet->timebase_num = 1;
  643. packet->timebase_den = (uint32_t)ca->samples_per_second;
  644. packet->type = OBS_ENCODER_AUDIO;
  645. packet->size = out_desc.mDataByteSize;
  646. packet->data =
  647. (uint8_t*)buffer_list.mBuffers[0].mData + out_desc.mStartOffset;
  648. ca->total_samples += ca->bytes_read / ca->in_frame_size;
  649. return true;
  650. }
  651. #ifdef _MSC_VER
  652. #pragma warning(pop)
  653. #endif
  654. static void aac_audio_info(void *data, struct audio_convert_info *info)
  655. {
  656. UNUSED_PARAMETER(data);
  657. info->format = AUDIO_FORMAT_FLOAT;
  658. }
  659. static size_t aac_frame_size(void *data)
  660. {
  661. ca_encoder *ca = static_cast<ca_encoder*>(data);
  662. return ca->out_frames_per_packet;
  663. }
  664. /* The following code was extracted from encca_aac.c in HandBrake's libhb */
  665. #define MP4ESDescrTag 0x03
  666. #define MP4DecConfigDescrTag 0x04
  667. #define MP4DecSpecificDescrTag 0x05
  668. // based off of mov_mp4_read_descr_len from mov.c in ffmpeg's libavformat
  669. static int read_descr_len(uint8_t **buffer)
  670. {
  671. int len = 0;
  672. int count = 4;
  673. while (count--)
  674. {
  675. int c = *(*buffer)++;
  676. len = (len << 7) | (c & 0x7f);
  677. if (!(c & 0x80))
  678. break;
  679. }
  680. return len;
  681. }
  682. // based off of mov_mp4_read_descr from mov.c in ffmpeg's libavformat
  683. static int read_descr(uint8_t **buffer, int *tag)
  684. {
  685. *tag = *(*buffer)++;
  686. return read_descr_len(buffer);
  687. }
  688. // based off of mov_read_esds from mov.c in ffmpeg's libavformat
  689. static void read_esds_desc_ext(uint8_t* desc_ext, vector<uint8_t> &buffer,
  690. bool version_flags)
  691. {
  692. uint8_t *esds = desc_ext;
  693. int tag, len;
  694. if (version_flags)
  695. esds += 4; // version + flags
  696. read_descr(&esds, &tag);
  697. esds += 2; // ID
  698. if (tag == MP4ESDescrTag)
  699. esds++; // priority
  700. read_descr(&esds, &tag);
  701. if (tag == MP4DecConfigDescrTag) {
  702. esds++; // object type id
  703. esds++; // stream type
  704. esds += 3; // buffer size db
  705. esds += 4; // max bitrate
  706. esds += 4; // average bitrate
  707. len = read_descr(&esds, &tag);
  708. if (tag == MP4DecSpecificDescrTag)
  709. try {
  710. buffer.assign(esds, esds + len);
  711. } catch (...) {
  712. //leave buffer empty
  713. }
  714. }
  715. }
  716. /* extracted code ends here */
  717. static void query_extra_data(ca_encoder *ca)
  718. {
  719. UInt32 size = 0;
  720. OSStatus code;
  721. code = AudioConverterGetPropertyInfo(ca->converter,
  722. kAudioConverterCompressionMagicCookie,
  723. &size, NULL);
  724. if (code) {
  725. log_osstatus(LOG_ERROR, ca,
  726. "AudioConverterGetPropertyInfo(magic_cookie)",
  727. code);
  728. return;
  729. }
  730. if (!size) {
  731. CA_BLOG(LOG_WARNING, "Got 0 data size info for magic_cookie");
  732. return;
  733. }
  734. vector<uint8_t> extra_data;
  735. try {
  736. extra_data.resize(size);
  737. } catch (...) {
  738. CA_BLOG(LOG_WARNING, "Could not allocate extra data buffer");
  739. return;
  740. }
  741. code = AudioConverterGetProperty(ca->converter,
  742. kAudioConverterCompressionMagicCookie,
  743. &size, extra_data.data());
  744. if (code) {
  745. log_osstatus(LOG_ERROR, ca,
  746. "AudioConverterGetProperty(magic_cookie)",
  747. code);
  748. return;
  749. }
  750. if (!size) {
  751. CA_BLOG(LOG_WARNING, "Got 0 data size for magic_cookie");
  752. return;
  753. }
  754. read_esds_desc_ext(extra_data.data(), ca->extra_data, false);
  755. }
  756. static bool aac_extra_data(void *data, uint8_t **extra_data, size_t *size)
  757. {
  758. ca_encoder *ca = static_cast<ca_encoder*>(data);
  759. if (!ca->extra_data.size())
  760. query_extra_data(ca);
  761. if (!ca->extra_data.size())
  762. return false;
  763. *extra_data = ca->extra_data.data();
  764. *size = ca->extra_data.size();
  765. return true;
  766. }
  767. static asbd_builder fill_common_asbd_fields(asbd_builder builder,
  768. bool in=false)
  769. {
  770. UInt32 bytes_per_frame = 8;
  771. UInt32 channels = 2;
  772. UInt32 bits_per_channel = bytes_per_frame / channels * 8;
  773. builder.channels_per_frame(channels);
  774. if (in) {
  775. builder
  776. .bytes_per_frame(bytes_per_frame)
  777. .frames_per_packet(1)
  778. .bytes_per_packet(1 * bytes_per_frame)
  779. .bits_per_channel(bits_per_channel);
  780. }
  781. return builder;
  782. }
  783. static AudioStreamBasicDescription get_default_in_asbd()
  784. {
  785. return fill_common_asbd_fields(asbd_builder(), true)
  786. .sample_rate(44100)
  787. .format_id(kAudioFormatLinearPCM)
  788. .format_flags(kAudioFormatFlagsNativeEndian |
  789. kAudioFormatFlagIsPacked |
  790. kAudioFormatFlagIsFloat |
  791. 0)
  792. .asbd;
  793. }
  794. static asbd_builder get_default_out_asbd_builder()
  795. {
  796. return fill_common_asbd_fields(asbd_builder())
  797. .sample_rate(44100);
  798. }
  799. static cf_ptr<AudioConverterRef> get_converter(DStr &log, ca_encoder *ca,
  800. AudioStreamBasicDescription out,
  801. AudioStreamBasicDescription in = get_default_in_asbd())
  802. {
  803. UInt32 size = sizeof(out);
  804. OSStatus code;
  805. #define STATUS_CHECK(x) \
  806. code = x; \
  807. if (code) { \
  808. log_to_dstr(log, ca, "%s: %s\n", #x, \
  809. osstatus_to_dstr(code)->array); \
  810. return nullptr; \
  811. }
  812. STATUS_CHECK(AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
  813. 0, NULL, &size, &out));
  814. AudioConverterRef converter;
  815. STATUS_CHECK(AudioConverterNew(&in, &out, &converter));
  816. return cf_ptr<AudioConverterRef>{converter};
  817. #undef STATUS_CHECK
  818. }
  819. static AudioConverterRef get_default_converter(UInt32 format_id)
  820. {
  821. auto out = get_default_out_asbd_builder()
  822. .format_id(format_id)
  823. .asbd;
  824. DStr log;
  825. auto converter = get_converter(log, nullptr, out);
  826. if (!converter) {
  827. CA_LOG(LOG_ERROR, "Couldn't get default converter for format "
  828. "%s (0x%x):\n%s",
  829. format_id_to_str(format_id),
  830. static_cast<uint32_t>(format_id),
  831. flush_log(log));
  832. return nullptr;
  833. }
  834. return converter.release();
  835. }
  836. static AudioConverterRef aac_default_converter(void)
  837. {
  838. return get_default_converter(kAudioFormatMPEG4AAC);
  839. }
  840. static AudioConverterRef he_aac_default_converter(void)
  841. {
  842. return get_default_converter(kAudioFormatMPEG4AAC_HE);
  843. }
  844. static bool find_best_match(DStr &log, ca_encoder *ca, UInt32 bitrate,
  845. UInt32 &best_match)
  846. {
  847. UInt32 actual_bitrate = bitrate * 1000;
  848. bool found_match = false;
  849. auto handle_bitrate = [&](UInt32 candidate)
  850. {
  851. if (abs(static_cast<intmax_t>(actual_bitrate - candidate)) <
  852. abs(static_cast<intmax_t>(actual_bitrate - best_match))) {
  853. log_to_dstr(log, ca, "Found new best match %u\n",
  854. static_cast<uint32_t>(candidate));
  855. found_match = true;
  856. best_match = candidate;
  857. }
  858. };
  859. auto helper = [&](UInt32 min_, UInt32 max_)
  860. {
  861. handle_bitrate(min_);
  862. if (min_ == max_)
  863. return;
  864. log_to_dstr(log, ca, "Got actual bit rate range: %u<->%u\n",
  865. static_cast<uint32_t>(min_),
  866. static_cast<uint32_t>(max_));
  867. handle_bitrate(max_);
  868. };
  869. for (UInt32 format_id : aac_formats) {
  870. log_to_dstr(log, ca, "Trying %s (0x%x)\n",
  871. format_id_to_str(format_id), format_id);
  872. auto out = get_default_out_asbd_builder()
  873. .format_id(format_id)
  874. .asbd;
  875. auto converter = get_converter(log, ca, out);
  876. if (converter)
  877. enumerate_bitrates(log, ca, converter.get(),
  878. helper);
  879. else
  880. log_to_dstr(log, ca, "Could not get converter\n");
  881. }
  882. best_match /= 1000;
  883. return found_match;
  884. }
  885. static UInt32 find_matching_bitrate(UInt32 bitrate)
  886. {
  887. static UInt32 match = bitrate;
  888. static once_flag once;
  889. call_once(once, [&]()
  890. {
  891. DStr log;
  892. ca_encoder *ca = nullptr;
  893. if (!find_best_match(log, ca, bitrate, match)) {
  894. CA_CO_DLOG(LOG_ERROR, "No matching bitrates found for "
  895. "target bitrate %u",
  896. static_cast<uint32_t>(bitrate));
  897. match = bitrate;
  898. return;
  899. }
  900. if (match != bitrate) {
  901. CA_CO_DLOG(LOG_INFO, "Default bitrate (%u) isn't "
  902. "supported, returning %u as closest match",
  903. static_cast<uint32_t>(bitrate),
  904. static_cast<uint32_t>(match));
  905. return;
  906. }
  907. if (log->len)
  908. CA_CO_DLOG(LOG_DEBUG, "Default bitrate matching log "
  909. "for bitrate %u",
  910. static_cast<uint32_t>(bitrate));
  911. });
  912. return match;
  913. }
  914. static void aac_defaults(obs_data_t *settings)
  915. {
  916. obs_data_set_default_int(settings, "bitrate",
  917. find_matching_bitrate(128));
  918. obs_data_set_default_bool(settings, "allow he-aac", true);
  919. }
  920. static vector<UInt32> get_bitrates(DStr &log, ca_encoder *ca)
  921. {
  922. vector<UInt32> bitrates;
  923. auto handle_bitrate = [&](UInt32 bitrate)
  924. {
  925. if (find(begin(bitrates), end(bitrates), bitrate) ==
  926. end(bitrates)) {
  927. log_to_dstr(log, ca, "Adding bitrate %u\n",
  928. static_cast<uint32_t>(bitrate));
  929. bitrates.push_back(bitrate);
  930. } else {
  931. log_to_dstr(log, ca, "Bitrate %u already added\n",
  932. static_cast<uint32_t>(bitrate));
  933. }
  934. };
  935. auto helper = [&](UInt32 min_, UInt32 max_)
  936. {
  937. handle_bitrate(min_);
  938. if (min_ == max_)
  939. return;
  940. log_to_dstr(log, ca, "Got actual bitrate range: %u<->%u\n",
  941. static_cast<uint32_t>(min_),
  942. static_cast<uint32_t>(max_));
  943. handle_bitrate(max_);
  944. };
  945. for (UInt32 format_id : (ca ? *ca->allowed_formats : aac_formats)) {
  946. log_to_dstr(log, ca, "Trying %s (0x%x)\n",
  947. format_id_to_str(format_id),
  948. static_cast<uint32_t>(format_id));
  949. auto out = get_default_out_asbd_builder()
  950. .format_id(format_id)
  951. .asbd;
  952. auto converter = get_converter(log, ca, out);
  953. if (converter)
  954. enumerate_bitrates(log, ca, converter.get(), helper);
  955. }
  956. return bitrates;
  957. }
  958. static void add_bitrates(obs_property_t *prop, ca_encoder *ca)
  959. {
  960. DStr log;
  961. auto bitrates = get_bitrates(log, ca);
  962. if (!bitrates.size()) {
  963. CA_CO_DLOG_(LOG_ERROR, "Couldn't find available bitrates");
  964. return;
  965. }
  966. if (log->len)
  967. CA_CO_DLOG_(LOG_DEBUG, "Bitrate enumeration log");
  968. sort(begin(bitrates), end(bitrates));
  969. DStr buffer;
  970. for (UInt32 bitrate : bitrates) {
  971. dstr_printf(buffer, "%u", (uint32_t)bitrate / 1000);
  972. obs_property_list_add_int(prop, buffer->array, bitrate / 1000);
  973. }
  974. }
  975. static obs_properties_t *aac_properties(void *data)
  976. {
  977. ca_encoder *ca = static_cast<ca_encoder*>(data);
  978. obs_properties_t *props = obs_properties_create();
  979. obs_property_t *p = obs_properties_add_list(props, "bitrate",
  980. obs_module_text("Bitrate"),
  981. OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
  982. add_bitrates(p, ca);
  983. obs_properties_add_bool(props, "allow he-aac",
  984. obs_module_text("AllowHEAAC"));
  985. return props;
  986. }
  987. OBS_DECLARE_MODULE()
  988. OBS_MODULE_USE_DEFAULT_LOCALE("coreaudio-encoder", "en-US")
  989. bool obs_module_load(void)
  990. {
  991. #ifdef _WIN32
  992. if (!load_core_audio()) {
  993. CA_LOG(LOG_WARNING, "Couldn't load CoreAudio AAC encoder");
  994. return true;
  995. }
  996. CA_LOG(LOG_INFO, "Adding CoreAudio AAC encoder");
  997. #endif
  998. struct obs_encoder_info aac_info;
  999. aac_info.id = "CoreAudio_AAC";
  1000. aac_info.type = OBS_ENCODER_AUDIO;
  1001. aac_info.codec = "AAC";
  1002. aac_info.get_name = aac_get_name;
  1003. aac_info.destroy = aac_destroy;
  1004. aac_info.create = aac_create;
  1005. aac_info.encode = aac_encode;
  1006. aac_info.get_frame_size = aac_frame_size;
  1007. aac_info.get_audio_info = aac_audio_info;
  1008. aac_info.get_extra_data = aac_extra_data;
  1009. aac_info.get_defaults = aac_defaults;
  1010. aac_info.get_properties = aac_properties;
  1011. obs_register_encoder(&aac_info);
  1012. return true;
  1013. }
  1014. #ifdef _WIN32
  1015. void obs_module_unload(void)
  1016. {
  1017. unload_core_audio();
  1018. }
  1019. #endif