encoder.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. #include <util/darray.h>
  2. #include <util/dstr.h>
  3. #include <obs-module.h>
  4. #ifndef _WIN32
  5. #include <AudioToolbox/AudioToolbox.h>
  6. #endif
  7. #define CA_LOG(level, format, ...) \
  8. blog(level, "[CoreAudio encoder]: " format, ##__VA_ARGS__)
  9. #define CA_LOG_ENCODER(format_name, encoder, level, format, ...) \
  10. blog(level, "[CoreAudio %s: '%s']: " format, \
  11. format_name, obs_encoder_get_name(encoder), \
  12. ##__VA_ARGS__)
  13. #define CA_BLOG(level, format, ...) \
  14. CA_LOG_ENCODER(ca->format_name, ca->encoder, level, format, \
  15. ##__VA_ARGS__)
  16. #ifdef _WIN32
  17. #include "windows-imports.h"
  18. #endif
  19. struct ca_encoder {
  20. obs_encoder_t *encoder;
  21. const char *format_name;
  22. UInt32 format_id;
  23. const UInt32 *allowed_formats;
  24. size_t num_allowed_formats;
  25. AudioConverterRef converter;
  26. size_t output_buffer_size;
  27. uint8_t *output_buffer;
  28. size_t out_frames_per_packet;
  29. size_t in_packets;
  30. size_t in_frame_size;
  31. size_t in_bytes_required;
  32. DARRAY(uint8_t) input_buffer;
  33. size_t bytes_read;
  34. uint64_t total_samples;
  35. uint64_t samples_per_second;
  36. uint8_t *extra_data;
  37. uint32_t extra_data_size;
  38. size_t channels;
  39. };
  40. typedef struct ca_encoder ca_encoder;
  41. static const char *aac_get_name(void)
  42. {
  43. return obs_module_text("CoreAudioAAC");
  44. }
  45. static const char *code_to_str(OSStatus code)
  46. {
  47. switch (code) {
  48. #define HANDLE_CODE(c) case c: return #c
  49. HANDLE_CODE(kAudio_UnimplementedError);
  50. HANDLE_CODE(kAudio_FileNotFoundError);
  51. HANDLE_CODE(kAudio_FilePermissionError);
  52. HANDLE_CODE(kAudio_TooManyFilesOpenError);
  53. HANDLE_CODE(kAudio_BadFilePathError);
  54. HANDLE_CODE(kAudio_ParamError);
  55. HANDLE_CODE(kAudio_MemFullError);
  56. HANDLE_CODE(kAudioConverterErr_FormatNotSupported);
  57. HANDLE_CODE(kAudioConverterErr_OperationNotSupported);
  58. HANDLE_CODE(kAudioConverterErr_PropertyNotSupported);
  59. HANDLE_CODE(kAudioConverterErr_InvalidInputSize);
  60. HANDLE_CODE(kAudioConverterErr_InvalidOutputSize);
  61. HANDLE_CODE(kAudioConverterErr_UnspecifiedError);
  62. HANDLE_CODE(kAudioConverterErr_BadPropertySizeError);
  63. HANDLE_CODE(kAudioConverterErr_RequiresPacketDescriptionsError);
  64. HANDLE_CODE(kAudioConverterErr_InputSampleRateOutOfRange);
  65. HANDLE_CODE(kAudioConverterErr_OutputSampleRateOutOfRange);
  66. #undef HANDLE_CODE
  67. default: break;
  68. }
  69. return NULL;
  70. }
  71. static void log_osstatus(ca_encoder *ca, const char *context, OSStatus code)
  72. {
  73. #ifndef _WIN32
  74. CFErrorRef err = CFErrorCreate(kCFAllocatorDefault,
  75. kCFErrorDomainOSStatus, code, NULL);
  76. CFStringRef str = CFErrorCopyDescription(err);
  77. CFIndex length = CFStringGetLength(str);
  78. CFIndex max_size = CFStringGetMaximumSizeForEncoding(length,
  79. kCFStringEncodingUTF8);
  80. char *c_str = malloc(max_size);
  81. if (CFStringGetCString(str, c_str, max_size, kCFStringEncodingUTF8)) {
  82. if (ca)
  83. CA_BLOG(LOG_ERROR, "Error in %s: %s", context, c_str);
  84. else
  85. CA_LOG(LOG_ERROR, "Error in %s: %s", context, c_str);
  86. } else {
  87. #endif
  88. const char *code_str = code_to_str(code);
  89. if (ca)
  90. CA_BLOG(LOG_ERROR, "Error in %s: %s%s%d%s", context,
  91. code_str ? code_str : "",
  92. code_str ? " (" : "",
  93. (int)code,
  94. code_str ? ")" : "");
  95. else
  96. CA_LOG(LOG_ERROR, "Error in %s: %s%s%d%s", context,
  97. code_str ? code_str : "",
  98. code_str ? " (" : "",
  99. (int)code,
  100. code_str ? ")" : "");
  101. #ifndef _WIN32
  102. }
  103. free(c_str);
  104. CFRelease(str);
  105. CFRelease(err);
  106. #endif
  107. }
  108. static const char *format_id_to_str(UInt32 format_id)
  109. {
  110. #define FORMAT_TO_STR(x) case x: return #x
  111. switch (format_id) {
  112. FORMAT_TO_STR(kAudioFormatLinearPCM);
  113. FORMAT_TO_STR(kAudioFormatAC3);
  114. FORMAT_TO_STR(kAudioFormat60958AC3);
  115. FORMAT_TO_STR(kAudioFormatAppleIMA4);
  116. FORMAT_TO_STR(kAudioFormatMPEG4AAC);
  117. FORMAT_TO_STR(kAudioFormatMPEG4CELP);
  118. FORMAT_TO_STR(kAudioFormatMPEG4HVXC);
  119. FORMAT_TO_STR(kAudioFormatMPEG4TwinVQ);
  120. FORMAT_TO_STR(kAudioFormatMACE3);
  121. FORMAT_TO_STR(kAudioFormatMACE6);
  122. FORMAT_TO_STR(kAudioFormatULaw);
  123. FORMAT_TO_STR(kAudioFormatALaw);
  124. FORMAT_TO_STR(kAudioFormatQDesign);
  125. FORMAT_TO_STR(kAudioFormatQDesign2);
  126. FORMAT_TO_STR(kAudioFormatQUALCOMM);
  127. FORMAT_TO_STR(kAudioFormatMPEGLayer1);
  128. FORMAT_TO_STR(kAudioFormatMPEGLayer2);
  129. FORMAT_TO_STR(kAudioFormatMPEGLayer3);
  130. FORMAT_TO_STR(kAudioFormatTimeCode);
  131. FORMAT_TO_STR(kAudioFormatMIDIStream);
  132. FORMAT_TO_STR(kAudioFormatParameterValueStream);
  133. FORMAT_TO_STR(kAudioFormatAppleLossless);
  134. FORMAT_TO_STR(kAudioFormatMPEG4AAC_HE);
  135. FORMAT_TO_STR(kAudioFormatMPEG4AAC_LD);
  136. FORMAT_TO_STR(kAudioFormatMPEG4AAC_ELD);
  137. FORMAT_TO_STR(kAudioFormatMPEG4AAC_ELD_SBR);
  138. FORMAT_TO_STR(kAudioFormatMPEG4AAC_HE_V2);
  139. FORMAT_TO_STR(kAudioFormatMPEG4AAC_Spatial);
  140. FORMAT_TO_STR(kAudioFormatAMR);
  141. FORMAT_TO_STR(kAudioFormatAudible);
  142. FORMAT_TO_STR(kAudioFormatiLBC);
  143. FORMAT_TO_STR(kAudioFormatDVIIntelIMA);
  144. FORMAT_TO_STR(kAudioFormatMicrosoftGSM);
  145. FORMAT_TO_STR(kAudioFormatAES3);
  146. }
  147. #undef FORMAT_TO_STR
  148. return "Unknown format";
  149. }
  150. static void aac_destroy(void *data)
  151. {
  152. ca_encoder *ca = data;
  153. if (ca->converter)
  154. AudioConverterDispose(ca->converter);
  155. da_free(ca->input_buffer);
  156. bfree(ca->extra_data);
  157. bfree(ca->output_buffer);
  158. bfree(ca);
  159. }
  160. typedef void (*bitrate_enumeration_func)(void *data, UInt32 min, UInt32 max);
  161. static bool enumerate_bitrates(ca_encoder *ca, AudioConverterRef converter,
  162. bitrate_enumeration_func enum_func, void *data)
  163. {
  164. if (!converter && ca)
  165. converter = ca->converter;
  166. UInt32 size;
  167. OSStatus code = AudioConverterGetPropertyInfo(converter,
  168. kAudioConverterApplicableEncodeBitRates,
  169. &size, NULL);
  170. if (code) {
  171. log_osstatus(ca, "AudioConverterGetPropertyInfo(bitrates)",
  172. code);
  173. return false;
  174. }
  175. if (!size) {
  176. if (ca)
  177. CA_BLOG(LOG_ERROR, "Query for applicable bitrates "
  178. "returned 0 size");
  179. else
  180. CA_LOG(LOG_ERROR, "Query for applicable bitrates "
  181. "returned 0 size");
  182. return false;
  183. }
  184. AudioValueRange *bitrates = malloc(size);
  185. code = AudioConverterGetProperty(converter,
  186. kAudioConverterApplicableEncodeBitRates,
  187. &size, bitrates);
  188. if (code) {
  189. log_osstatus(ca, "AudioConverterGetProperty(bitrates)", code);
  190. return false;
  191. }
  192. size_t num_bitrates = size / sizeof(AudioValueRange);
  193. for (size_t i = 0; i < num_bitrates; i++)
  194. enum_func(data, (UInt32)bitrates[i].mMinimum,
  195. (UInt32)bitrates[i].mMaximum);
  196. free(bitrates);
  197. return num_bitrates > 0;
  198. }
  199. struct validate_bitrate_helper {
  200. UInt32 bitrate;
  201. bool valid;
  202. };
  203. typedef struct validate_bitrate_helper validate_bitrate_helper;
  204. static void validate_bitrate_func(void *data, UInt32 min, UInt32 max)
  205. {
  206. validate_bitrate_helper *valid = data;
  207. if (valid->bitrate >= min && valid->bitrate <= max)
  208. valid->valid = true;
  209. }
  210. static bool bitrate_valid(ca_encoder *ca, AudioConverterRef converter,
  211. UInt32 bitrate)
  212. {
  213. validate_bitrate_helper helper = {
  214. .bitrate = bitrate,
  215. .valid = false,
  216. };
  217. enumerate_bitrates(ca, converter, validate_bitrate_func, &helper);
  218. return helper.valid;
  219. }
  220. static bool create_encoder(ca_encoder *ca, AudioStreamBasicDescription *in,
  221. AudioStreamBasicDescription *out,
  222. UInt32 format_id, UInt32 bitrate, UInt32 rate_control)
  223. {
  224. #define STATUS_CHECK(c) \
  225. code = c; \
  226. if (code) { \
  227. log_osstatus(ca, #c, code); \
  228. return false; \
  229. }
  230. AudioStreamBasicDescription out_ = {
  231. .mSampleRate = (Float64)ca->samples_per_second,
  232. .mChannelsPerFrame = (UInt32)ca->channels,
  233. .mBytesPerFrame = 0,
  234. .mFramesPerPacket = 0,
  235. .mBitsPerChannel = 0,
  236. .mFormatID = format_id,
  237. .mFormatFlags = 0
  238. };
  239. UInt32 size = sizeof(*out);
  240. OSStatus code;
  241. STATUS_CHECK(AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
  242. 0, NULL, &size, &out_));
  243. *out = out_;
  244. STATUS_CHECK(AudioConverterNew(in, out, &ca->converter))
  245. STATUS_CHECK(AudioConverterSetProperty(ca->converter,
  246. kAudioCodecPropertyBitRateControlMode,
  247. sizeof(rate_control), &rate_control));
  248. if (!bitrate_valid(ca, NULL, bitrate)) {
  249. CA_BLOG(LOG_ERROR, "Encoder does not support bitrate %u for "
  250. "format %s (0x%x)",
  251. (uint32_t)bitrate, format_id_to_str(format_id),
  252. (uint32_t)format_id);
  253. return false;
  254. }
  255. ca->format_id = format_id;
  256. return true;
  257. #undef STATUS_CHECK
  258. }
  259. static const UInt32 aac_formats[] = {
  260. kAudioFormatMPEG4AAC_HE_V2,
  261. kAudioFormatMPEG4AAC_HE,
  262. kAudioFormatMPEG4AAC,
  263. };
  264. static const UInt32 aac_lc_formats[] = {
  265. kAudioFormatMPEG4AAC,
  266. };
  267. static void *aac_create(obs_data_t *settings, obs_encoder_t *encoder)
  268. {
  269. #define STATUS_CHECK(c) \
  270. code = c; \
  271. if (code) { \
  272. log_osstatus(ca, #c, code); \
  273. goto free; \
  274. }
  275. UInt32 bitrate = (UInt32)obs_data_get_int(settings, "bitrate") * 1000;
  276. if (!bitrate) {
  277. CA_LOG_ENCODER("AAC", encoder, LOG_ERROR,
  278. "Invalid bitrate specified");
  279. return NULL;
  280. }
  281. const enum audio_format format = AUDIO_FORMAT_FLOAT;
  282. if (is_audio_planar(format)) {
  283. CA_LOG_ENCODER("AAC", encoder, LOG_ERROR,
  284. "Got non-interleaved audio format %d", format);
  285. return NULL;
  286. }
  287. ca_encoder *ca = bzalloc(sizeof(ca_encoder));
  288. ca->encoder = encoder;
  289. ca->format_name = "AAC";
  290. audio_t *audio = obs_encoder_audio(encoder);
  291. const struct audio_output_info *aoi = audio_output_get_info(audio);
  292. ca->channels = audio_output_get_channels(audio);
  293. ca->samples_per_second = audio_output_get_sample_rate(audio);
  294. size_t bytes_per_frame = get_audio_size(format, aoi->speakers, 1);
  295. size_t bits_per_channel = get_audio_bytes_per_channel(format) * 8;
  296. AudioStreamBasicDescription in = {
  297. .mSampleRate = (Float64)ca->samples_per_second,
  298. .mChannelsPerFrame = (UInt32)ca->channels,
  299. .mBytesPerFrame = (UInt32)bytes_per_frame,
  300. .mFramesPerPacket = 1,
  301. .mBytesPerPacket = (UInt32)(1 * bytes_per_frame),
  302. .mBitsPerChannel = (UInt32)bits_per_channel,
  303. .mFormatID = kAudioFormatLinearPCM,
  304. .mFormatFlags = kAudioFormatFlagsNativeEndian |
  305. kAudioFormatFlagIsPacked |
  306. kAudioFormatFlagIsFloat |
  307. 0
  308. };
  309. AudioStreamBasicDescription out;
  310. UInt32 rate_control = kAudioCodecBitRateControlMode_Constant;
  311. #define USE_FORMATS(x) { \
  312. ca->allowed_formats = x; \
  313. ca->num_allowed_formats = sizeof(x)/sizeof(x[0]); \
  314. }
  315. if (obs_data_get_bool(settings, "allow he-aac")) {
  316. USE_FORMATS(aac_formats);
  317. } else {
  318. USE_FORMATS(aac_lc_formats);
  319. }
  320. #undef USE_FORMATS
  321. bool encoder_created = false;
  322. for (size_t i = 0; i < ca->num_allowed_formats; i++) {
  323. UInt32 format_id = ca->allowed_formats[i];
  324. CA_BLOG(LOG_INFO, "Trying format %s (0x%x)",
  325. format_id_to_str(format_id),
  326. (uint32_t)format_id);
  327. if (!create_encoder(ca, &in, &out, format_id, bitrate,
  328. rate_control))
  329. continue;
  330. encoder_created = true;
  331. break;
  332. }
  333. if (!encoder_created) {
  334. CA_BLOG(LOG_ERROR, "Could not create encoder for "
  335. "selected format%s",
  336. ca->num_allowed_formats == 1 ? "" : "s");
  337. goto free;
  338. }
  339. OSStatus code;
  340. UInt32 converter_quality = kAudioConverterQuality_Max;
  341. STATUS_CHECK(AudioConverterSetProperty(ca->converter,
  342. kAudioConverterCodecQuality,
  343. sizeof(converter_quality), &converter_quality));
  344. STATUS_CHECK(AudioConverterSetProperty(ca->converter,
  345. kAudioConverterEncodeBitRate,
  346. sizeof(bitrate), &bitrate));
  347. UInt32 size = sizeof(in);
  348. STATUS_CHECK(AudioConverterGetProperty(ca->converter,
  349. kAudioConverterCurrentInputStreamDescription,
  350. &size, &in));
  351. size = sizeof(out);
  352. STATUS_CHECK(AudioConverterGetProperty(ca->converter,
  353. kAudioConverterCurrentOutputStreamDescription,
  354. &size, &out));
  355. ca->in_frame_size = in.mBytesPerFrame;
  356. ca->in_packets = out.mFramesPerPacket / in.mFramesPerPacket;
  357. ca->in_bytes_required = ca->in_packets * ca->in_frame_size;
  358. ca->out_frames_per_packet = out.mFramesPerPacket;
  359. da_init(ca->input_buffer);
  360. ca->output_buffer_size = out.mBytesPerPacket;
  361. if (out.mBytesPerPacket == 0) {
  362. UInt32 max_packet_size = 0;
  363. size = sizeof(max_packet_size);
  364. code = AudioConverterGetProperty(ca->converter,
  365. kAudioConverterPropertyMaximumOutputPacketSize,
  366. &size, &max_packet_size);
  367. if (code) {
  368. log_osstatus(ca, "AudioConverterGetProperty(PacketSz)",
  369. code);
  370. ca->output_buffer_size = 32768;
  371. } else {
  372. ca->output_buffer_size = max_packet_size;
  373. }
  374. }
  375. ca->output_buffer = bmalloc(ca->output_buffer_size);
  376. const char *format_name =
  377. out.mFormatID == kAudioFormatMPEG4AAC_HE_V2 ? "HE-AAC v2" :
  378. out.mFormatID == kAudioFormatMPEG4AAC_HE ? "HE-AAC" : "AAC";
  379. CA_BLOG(LOG_INFO, "settings:\n"
  380. "\tmode: %s\n"
  381. "\tbitrate: %u\n"
  382. "\tsample rate: %llu\n"
  383. "\tcbr: %s\n"
  384. "\toutput buffer: %lu",
  385. format_name, bitrate / 1000, ca->samples_per_second,
  386. rate_control == kAudioCodecBitRateControlMode_Constant ?
  387. "on" : "off",
  388. (unsigned long)ca->output_buffer_size);
  389. return ca;
  390. free:
  391. aac_destroy(ca);
  392. return NULL;
  393. }
  394. static OSStatus complex_input_data_proc(AudioConverterRef inAudioConverter,
  395. UInt32 *ioNumberDataPackets, AudioBufferList *ioData,
  396. AudioStreamPacketDescription **outDataPacketDescription,
  397. void *inUserData)
  398. {
  399. UNUSED_PARAMETER(inAudioConverter);
  400. UNUSED_PARAMETER(outDataPacketDescription);
  401. ca_encoder *ca = inUserData;
  402. if (ca->bytes_read) {
  403. da_erase_range(ca->input_buffer, 0, ca->bytes_read);
  404. ca->bytes_read = 0;
  405. }
  406. if (ca->input_buffer.num < ca->in_bytes_required) {
  407. *ioNumberDataPackets = 0;
  408. ioData->mBuffers[0].mData = NULL;
  409. return 1;
  410. }
  411. *ioNumberDataPackets =
  412. (UInt32)(ca->in_bytes_required / ca->in_frame_size);
  413. ioData->mNumberBuffers = 1;
  414. ioData->mBuffers[0].mData = ca->input_buffer.array;
  415. ioData->mBuffers[0].mNumberChannels = (UInt32)ca->channels;
  416. ioData->mBuffers[0].mDataByteSize = (UInt32)ca->in_bytes_required;
  417. ca->bytes_read += ca->in_packets * ca->in_frame_size;
  418. return 0;
  419. }
  420. static bool aac_encode(void *data, struct encoder_frame *frame,
  421. struct encoder_packet *packet, bool *received_packet)
  422. {
  423. ca_encoder *ca = data;
  424. da_push_back_array(ca->input_buffer, frame->data[0],
  425. frame->linesize[0]);
  426. if ((ca->input_buffer.num - ca->bytes_read) < ca->in_bytes_required)
  427. return true;
  428. UInt32 packets = 1;
  429. AudioBufferList buffer_list = {
  430. .mNumberBuffers = 1,
  431. .mBuffers = { {
  432. .mNumberChannels = (UInt32)ca->channels,
  433. .mDataByteSize = (UInt32)ca->output_buffer_size,
  434. .mData = ca->output_buffer,
  435. } },
  436. };
  437. AudioStreamPacketDescription out_desc = { 0 };
  438. OSStatus code = AudioConverterFillComplexBuffer(ca->converter,
  439. complex_input_data_proc, ca, &packets,
  440. &buffer_list, &out_desc);
  441. if (code && code != 1) {
  442. log_osstatus(ca, "AudioConverterFillComplexBuffer", code);
  443. return false;
  444. }
  445. if (!(*received_packet = packets > 0))
  446. return true;
  447. packet->pts = ca->total_samples;
  448. packet->dts = ca->total_samples;
  449. packet->timebase_num = 1;
  450. packet->timebase_den = (uint32_t)ca->samples_per_second;
  451. packet->type = OBS_ENCODER_AUDIO;
  452. packet->size = out_desc.mDataByteSize;
  453. packet->data =
  454. (uint8_t*)buffer_list.mBuffers[0].mData + out_desc.mStartOffset;
  455. ca->total_samples += ca->bytes_read / ca->in_frame_size;
  456. return true;
  457. }
  458. static void aac_audio_info(void *data, struct audio_convert_info *info)
  459. {
  460. UNUSED_PARAMETER(data);
  461. info->format = AUDIO_FORMAT_FLOAT;
  462. }
  463. static size_t aac_frame_size(void *data)
  464. {
  465. ca_encoder *ca = data;
  466. return ca->out_frames_per_packet;
  467. }
  468. /* The following code was extracted from encca_aac.c in HandBrake's libhb */
  469. #define MP4ESDescrTag 0x03
  470. #define MP4DecConfigDescrTag 0x04
  471. #define MP4DecSpecificDescrTag 0x05
  472. // based off of mov_mp4_read_descr_len from mov.c in ffmpeg's libavformat
  473. static int read_descr_len(uint8_t **buffer)
  474. {
  475. int len = 0;
  476. int count = 4;
  477. while (count--)
  478. {
  479. int c = *(*buffer)++;
  480. len = (len << 7) | (c & 0x7f);
  481. if (!(c & 0x80))
  482. break;
  483. }
  484. return len;
  485. }
  486. // based off of mov_mp4_read_descr from mov.c in ffmpeg's libavformat
  487. static int read_descr(uint8_t **buffer, int *tag)
  488. {
  489. *tag = *(*buffer)++;
  490. return read_descr_len(buffer);
  491. }
  492. // based off of mov_read_esds from mov.c in ffmpeg's libavformat
  493. static void read_esds_desc_ext(uint8_t* desc_ext, uint8_t **buffer,
  494. uint32_t *size, bool version_flags)
  495. {
  496. uint8_t *esds = desc_ext;
  497. int tag, len;
  498. *size = 0;
  499. if (version_flags)
  500. esds += 4; // version + flags
  501. read_descr(&esds, &tag);
  502. esds += 2; // ID
  503. if (tag == MP4ESDescrTag)
  504. esds++; // priority
  505. read_descr(&esds, &tag);
  506. if (tag == MP4DecConfigDescrTag) {
  507. esds++; // object type id
  508. esds++; // stream type
  509. esds += 3; // buffer size db
  510. esds += 4; // max bitrate
  511. esds += 4; // average bitrate
  512. len = read_descr(&esds, &tag);
  513. if (tag == MP4DecSpecificDescrTag) {
  514. *buffer = bzalloc(len + 8);
  515. if (*buffer) {
  516. memcpy(*buffer, esds, len);
  517. *size = len;
  518. }
  519. }
  520. }
  521. }
  522. /* extracted code ends here */
  523. static void query_extra_data(ca_encoder *ca)
  524. {
  525. UInt32 size = 0;
  526. OSStatus code;
  527. code = AudioConverterGetPropertyInfo(ca->converter,
  528. kAudioConverterCompressionMagicCookie,
  529. &size, NULL);
  530. if (code) {
  531. log_osstatus(ca, "AudioConverterGetPropertyInfo(magic_cookie)",
  532. code);
  533. return;
  534. }
  535. if (!size) {
  536. CA_BLOG(LOG_WARNING, "Got 0 data size info for magic_cookie");
  537. return;
  538. }
  539. uint8_t *extra_data = malloc(size);
  540. code = AudioConverterGetProperty(ca->converter,
  541. kAudioConverterCompressionMagicCookie,
  542. &size, extra_data);
  543. if (code) {
  544. log_osstatus(ca, "AudioConverterGetProperty(magic_cookie)",
  545. code);
  546. goto free;
  547. }
  548. if (!size) {
  549. CA_BLOG(LOG_WARNING, "Got 0 data size for magic_cookie");
  550. goto free;
  551. }
  552. read_esds_desc_ext(extra_data, &ca->extra_data, &ca->extra_data_size,
  553. false);
  554. free:
  555. free(extra_data);
  556. }
  557. static bool aac_extra_data(void *data, uint8_t **extra_data, size_t *size)
  558. {
  559. ca_encoder *ca = data;
  560. if (!ca->extra_data)
  561. query_extra_data(ca);
  562. if (!ca->extra_data_size)
  563. return false;
  564. *extra_data = ca->extra_data;
  565. *size = ca->extra_data_size;
  566. return true;
  567. }
  568. static AudioConverterRef get_default_converter(UInt32 format_id)
  569. {
  570. UInt32 bytes_per_frame = 8;
  571. UInt32 channels = 2;
  572. UInt32 bits_per_channel = bytes_per_frame / channels * 8;
  573. AudioStreamBasicDescription in = {
  574. .mSampleRate = 44100,
  575. .mChannelsPerFrame = channels,
  576. .mBytesPerFrame = bytes_per_frame,
  577. .mFramesPerPacket = 1,
  578. .mBytesPerPacket = 1 * bytes_per_frame,
  579. .mBitsPerChannel = bits_per_channel,
  580. .mFormatID = kAudioFormatLinearPCM,
  581. .mFormatFlags = kAudioFormatFlagsNativeEndian |
  582. kAudioFormatFlagIsPacked |
  583. kAudioFormatFlagIsFloat |
  584. 0
  585. };
  586. AudioStreamBasicDescription out = {
  587. .mSampleRate = 44100,
  588. .mChannelsPerFrame = channels,
  589. .mBytesPerFrame = 0,
  590. .mFramesPerPacket = 0,
  591. .mBitsPerChannel = 0,
  592. .mFormatID = format_id,
  593. .mFormatFlags = 0
  594. };
  595. UInt32 size = sizeof(out);
  596. OSStatus code = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
  597. 0, NULL, &size, &out);
  598. if (code) {
  599. log_osstatus(NULL, "AudioFormatGetProperty(format_info)", code);
  600. return NULL;
  601. }
  602. AudioConverterRef converter;
  603. code = AudioConverterNew(&in, &out, &converter);
  604. if (code) {
  605. log_osstatus(NULL, "AudioConverterNew", code);
  606. return NULL;
  607. }
  608. return converter;
  609. }
  610. static AudioConverterRef aac_default_converter(void)
  611. {
  612. return get_default_converter(kAudioFormatMPEG4AAC);
  613. }
  614. static AudioConverterRef he_aac_default_converter(void)
  615. {
  616. return get_default_converter(kAudioFormatMPEG4AAC_HE);
  617. }
  618. struct find_matching_bitrate_helper {
  619. UInt32 bitrate;
  620. UInt32 best_match;
  621. int diff;
  622. };
  623. typedef struct find_matching_bitrate_helper find_matching_bitrate_helper;
  624. static void find_matching_bitrate_func(void *data, UInt32 min, UInt32 max)
  625. {
  626. find_matching_bitrate_helper *helper = data;
  627. int min_diff = abs((int)helper->bitrate - (int)min);
  628. int max_diff = abs((int)helper->bitrate - (int)max);
  629. if (min_diff < helper->diff) {
  630. helper->best_match = min;
  631. helper->diff = min_diff;
  632. }
  633. if (max_diff < helper->diff) {
  634. helper->best_match = max;
  635. helper->diff = max_diff;
  636. }
  637. }
  638. static UInt32 find_matching_bitrate(UInt32 bitrate)
  639. {
  640. find_matching_bitrate_helper helper = {
  641. .bitrate = bitrate * 1000,
  642. .best_match = 0,
  643. .diff = INT_MAX,
  644. };
  645. AudioConverterRef converter = aac_default_converter();
  646. if (!converter) {
  647. CA_LOG(LOG_ERROR, "Could not get converter to match "
  648. "default bitrate");
  649. return bitrate;
  650. }
  651. bool has_bitrates = enumerate_bitrates(NULL, converter,
  652. find_matching_bitrate_func, &helper);
  653. AudioConverterDispose(converter);
  654. if (!has_bitrates) {
  655. CA_LOG(LOG_ERROR, "No bitrates found while matching "
  656. "default bitrate");
  657. AudioConverterDispose(converter);
  658. return bitrate;
  659. }
  660. if (helper.best_match != helper.bitrate)
  661. CA_LOG(LOG_INFO, "Returning closest matching bitrate %u "
  662. "instead of requested bitrate %u",
  663. (uint32_t)helper.best_match / 1000,
  664. (uint32_t)bitrate);
  665. return helper.best_match / 1000;
  666. }
  667. static void aac_defaults(obs_data_t *settings)
  668. {
  669. obs_data_set_default_int(settings, "bitrate",
  670. find_matching_bitrate(128));
  671. obs_data_set_default_bool(settings, "allow he-aac", true);
  672. }
  673. struct add_bitrates_helper {
  674. DARRAY(UInt32) bitrates;
  675. };
  676. typedef struct add_bitrates_helper add_bitrates_helper;
  677. static void add_bitrates_func(void *data, UInt32 min, UInt32 max)
  678. {
  679. add_bitrates_helper *helper = data;
  680. if (da_find(helper->bitrates, &min, 0) == DARRAY_INVALID)
  681. da_push_back(helper->bitrates, &min);
  682. if (da_find(helper->bitrates, &max, 0) == DARRAY_INVALID)
  683. da_push_back(helper->bitrates, &max);
  684. }
  685. static int bitrate_compare(const void *data1, const void *data2)
  686. {
  687. const UInt32 *bitrate1 = data1;
  688. const UInt32 *bitrate2 = data2;
  689. return (int)*bitrate1 - (int)*bitrate2;
  690. }
  691. static void add_bitrates(obs_property_t *prop, ca_encoder *ca)
  692. {
  693. add_bitrates_helper helper = { 0 };
  694. const size_t num_formats = ca ?
  695. ca->num_allowed_formats :
  696. sizeof(aac_formats)/sizeof(aac_formats[0]);
  697. const UInt32 *allowed_formats = ca ? ca->allowed_formats : aac_formats;
  698. for (size_t i = 0; i < num_formats; i++)
  699. enumerate_bitrates(ca,
  700. get_default_converter(allowed_formats[i]),
  701. add_bitrates_func, &helper);
  702. if (!helper.bitrates.num)
  703. return;
  704. qsort(helper.bitrates.array, helper.bitrates.num, sizeof(UInt32),
  705. bitrate_compare);
  706. struct dstr str = { 0 };
  707. for (size_t i = 0; i < helper.bitrates.num; i++) {
  708. dstr_printf(&str, "%u",
  709. (uint32_t)helper.bitrates.array[i]/1000);
  710. obs_property_list_add_int(prop, str.array,
  711. helper.bitrates.array[i]/1000);
  712. }
  713. dstr_free(&str);
  714. }
  715. static obs_properties_t *aac_properties(void *data)
  716. {
  717. ca_encoder *ca = data;
  718. obs_properties_t *props = obs_properties_create();
  719. obs_property_t *p = obs_properties_add_list(props, "bitrate",
  720. obs_module_text("Bitrate"),
  721. OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
  722. add_bitrates(p, ca);
  723. obs_properties_add_bool(props, "allow he-aac",
  724. obs_module_text("AllowHEAAC"));
  725. return props;
  726. }
  727. static struct obs_encoder_info aac_info = {
  728. .id = "CoreAudio_AAC",
  729. .type = OBS_ENCODER_AUDIO,
  730. .codec = "AAC",
  731. .get_name = aac_get_name,
  732. .destroy = aac_destroy,
  733. .create = aac_create,
  734. .encode = aac_encode,
  735. .get_frame_size = aac_frame_size,
  736. .get_audio_info = aac_audio_info,
  737. .get_extra_data = aac_extra_data,
  738. .get_defaults = aac_defaults,
  739. };
  740. OBS_DECLARE_MODULE()
  741. OBS_MODULE_USE_DEFAULT_LOCALE("coreaudio-encoder", "en-US")
  742. bool obs_module_load(void)
  743. {
  744. #ifdef _WIN32
  745. if (!load_core_audio()) {
  746. CA_LOG(LOG_WARNING, "Couldn't load CoreAudio AAC encoder");
  747. return true;
  748. }
  749. CA_LOG(LOG_INFO, "Adding CoreAudio AAC encoder");
  750. #endif
  751. obs_register_encoder(&aac_info);
  752. return true;
  753. }
  754. #ifdef _WIN32
  755. void obs_module_unload(void)
  756. {
  757. unload_core_audio();
  758. }
  759. #endif