react-native-audio-api 0.8.0-nightly-5a12f24-20250901 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/RNAudioAPI.podspec +15 -6
  2. package/android/build.gradle +11 -2
  3. package/android/src/main/cpp/audioapi/CMakeLists.txt +24 -17
  4. package/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp +51 -21
  5. package/android/src/main/jniLibs/arm64-v8a/libavcodec.so +0 -0
  6. package/android/src/main/jniLibs/arm64-v8a/libavformat.so +0 -0
  7. package/android/src/main/jniLibs/arm64-v8a/libavutil.so +0 -0
  8. package/android/src/main/jniLibs/arm64-v8a/libswresample.so +0 -0
  9. package/android/src/main/jniLibs/armeabi-v7a/libavcodec.so +0 -0
  10. package/android/src/main/jniLibs/armeabi-v7a/libavformat.so +0 -0
  11. package/android/src/main/jniLibs/armeabi-v7a/libavutil.so +0 -0
  12. package/android/src/main/jniLibs/armeabi-v7a/libswresample.so +0 -0
  13. package/android/src/main/jniLibs/x86/libavcodec.so +0 -0
  14. package/android/src/main/jniLibs/x86/libavformat.so +0 -0
  15. package/android/src/main/jniLibs/x86/libavutil.so +0 -0
  16. package/android/src/main/jniLibs/x86/libswresample.so +0 -0
  17. package/android/src/main/jniLibs/x86_64/libavcodec.so +0 -0
  18. package/android/src/main/jniLibs/x86_64/libavformat.so +0 -0
  19. package/android/src/main/jniLibs/x86_64/libavutil.so +0 -0
  20. package/android/src/main/jniLibs/x86_64/libswresample.so +0 -0
  21. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +11 -0
  22. package/common/cpp/audioapi/HostObjects/StreamerNodeHostObject.h +30 -0
  23. package/common/cpp/audioapi/core/BaseAudioContext.cpp +9 -0
  24. package/common/cpp/audioapi/core/BaseAudioContext.h +2 -0
  25. package/common/cpp/audioapi/core/sources/StreamerNode.cpp +299 -0
  26. package/common/cpp/audioapi/core/sources/StreamerNode.h +123 -0
  27. package/common/cpp/audioapi/core/utils/AudioDecoder.h +61 -0
  28. package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +14 -2
  29. package/common/cpp/audioapi/core/utils/AudioNodeManager.h +3 -0
  30. package/common/cpp/audioapi/external/arm64-v8a/libcrypto.a +0 -0
  31. package/common/cpp/audioapi/external/arm64-v8a/libssl.a +0 -0
  32. package/common/cpp/audioapi/external/armeabi-v7a/libcrypto.a +0 -0
  33. package/common/cpp/audioapi/external/armeabi-v7a/libssl.a +0 -0
  34. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/ac3_parser.h +36 -0
  35. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/adts_parser.h +37 -0
  36. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/avcodec.h +2947 -0
  37. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/avdct.h +88 -0
  38. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/bsf.h +332 -0
  39. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec.h +367 -0
  40. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_desc.h +134 -0
  41. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_id.h +681 -0
  42. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_par.h +248 -0
  43. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/d3d11va.h +109 -0
  44. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/defs.h +359 -0
  45. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/dirac.h +135 -0
  46. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/dv_profile.h +82 -0
  47. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/dxva2.h +90 -0
  48. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/jni.h +67 -0
  49. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/mediacodec.h +103 -0
  50. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/packet.h +907 -0
  51. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/qsv.h +109 -0
  52. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/vdpau.h +138 -0
  53. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/version.h +45 -0
  54. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/version_major.h +55 -0
  55. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/videotoolbox.h +85 -0
  56. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/vorbis_parser.h +74 -0
  57. package/common/cpp/audioapi/external/ffmpeg_include/libavformat/avformat.h +3004 -0
  58. package/common/cpp/audioapi/external/ffmpeg_include/libavformat/avio.h +831 -0
  59. package/common/cpp/audioapi/external/ffmpeg_include/libavformat/version.h +47 -0
  60. package/common/cpp/audioapi/external/ffmpeg_include/libavformat/version_major.h +50 -0
  61. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/adler32.h +63 -0
  62. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/aes.h +69 -0
  63. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/aes_ctr.h +99 -0
  64. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/ambient_viewing_environment.h +72 -0
  65. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/attributes.h +175 -0
  66. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/audio_fifo.h +187 -0
  67. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/avassert.h +120 -0
  68. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/avconfig.h +6 -0
  69. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/avstring.h +428 -0
  70. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/avutil.h +364 -0
  71. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/base64.h +72 -0
  72. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/blowfish.h +82 -0
  73. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/bprint.h +254 -0
  74. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/bswap.h +105 -0
  75. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/buffer.h +322 -0
  76. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/camellia.h +70 -0
  77. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/cast5.h +80 -0
  78. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/channel_layout.h +762 -0
  79. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/common.h +589 -0
  80. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/container_fifo.h +130 -0
  81. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/cpu.h +150 -0
  82. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/crc.h +102 -0
  83. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/csp.h +192 -0
  84. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/des.h +81 -0
  85. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/detection_bbox.h +108 -0
  86. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/dict.h +242 -0
  87. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/display.h +109 -0
  88. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/dovi_meta.h +396 -0
  89. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/downmix_info.h +115 -0
  90. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/encryption_info.h +205 -0
  91. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/error.h +129 -0
  92. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/eval.h +140 -0
  93. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/executor.h +67 -0
  94. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/ffversion.h +5 -0
  95. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/fifo.h +242 -0
  96. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/file.h +62 -0
  97. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/film_grain_params.h +282 -0
  98. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/frame.h +1163 -0
  99. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hash.h +264 -0
  100. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hdr_dynamic_metadata.h +376 -0
  101. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hdr_dynamic_vivid_metadata.h +292 -0
  102. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hmac.h +99 -0
  103. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext.h +601 -0
  104. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_amf.h +46 -0
  105. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_cuda.h +74 -0
  106. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_d3d11va.h +178 -0
  107. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_d3d12va.h +142 -0
  108. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_drm.h +169 -0
  109. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_dxva2.h +75 -0
  110. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_mediacodec.h +61 -0
  111. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_oh.h +34 -0
  112. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_opencl.h +100 -0
  113. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_qsv.h +87 -0
  114. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_vaapi.h +117 -0
  115. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_vdpau.h +44 -0
  116. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_videotoolbox.h +106 -0
  117. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_vulkan.h +377 -0
  118. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/iamf.h +694 -0
  119. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/imgutils.h +377 -0
  120. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/intfloat.h +77 -0
  121. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/intreadwrite.h +677 -0
  122. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/lfg.h +81 -0
  123. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/log.h +427 -0
  124. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/lzo.h +66 -0
  125. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/macros.h +80 -0
  126. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/mastering_display_metadata.h +137 -0
  127. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/mathematics.h +300 -0
  128. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/md5.h +89 -0
  129. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/mem.h +607 -0
  130. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/motion_vector.h +57 -0
  131. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/murmur3.h +115 -0
  132. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/opt.h +1194 -0
  133. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/parseutils.h +197 -0
  134. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/pixdesc.h +440 -0
  135. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/pixelutils.h +51 -0
  136. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/pixfmt.h +797 -0
  137. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/random_seed.h +57 -0
  138. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/rational.h +225 -0
  139. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/rc4.h +69 -0
  140. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/refstruct.h +297 -0
  141. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/replaygain.h +50 -0
  142. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/ripemd.h +83 -0
  143. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/samplefmt.h +269 -0
  144. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/sha.h +90 -0
  145. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/sha512.h +92 -0
  146. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/spherical.h +243 -0
  147. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/stereo3d.h +325 -0
  148. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/tdrdi.h +164 -0
  149. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/tea.h +71 -0
  150. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/threadmessage.h +115 -0
  151. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/timecode.h +199 -0
  152. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/timestamp.h +85 -0
  153. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/tree.h +137 -0
  154. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/twofish.h +70 -0
  155. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/tx.h +210 -0
  156. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/uuid.h +146 -0
  157. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/version.h +119 -0
  158. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/video_enc_params.h +171 -0
  159. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/video_hint.h +107 -0
  160. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/xtea.h +94 -0
  161. package/common/cpp/audioapi/external/ffmpeg_include/libswresample/swresample.h +587 -0
  162. package/common/cpp/audioapi/external/ffmpeg_include/libswresample/version.h +46 -0
  163. package/common/cpp/audioapi/external/ffmpeg_include/libswresample/version_major.h +31 -0
  164. package/common/cpp/audioapi/external/libavcodec.xcframework/Info.plist +44 -0
  165. package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64/libavcodec.framework/Info.plist +1 -0
  166. package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64/libavcodec.framework/libavcodec +0 -0
  167. package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64_x86_64-simulator/libavcodec.framework/Info.plist +1 -0
  168. package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64_x86_64-simulator/libavcodec.framework/libavcodec +0 -0
  169. package/common/cpp/audioapi/external/libavformat.xcframework/Info.plist +44 -0
  170. package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64/libavformat.framework/Info.plist +1 -0
  171. package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64/libavformat.framework/libavformat +0 -0
  172. package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64_x86_64-simulator/libavformat.framework/Info.plist +1 -0
  173. package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64_x86_64-simulator/libavformat.framework/libavformat +0 -0
  174. package/common/cpp/audioapi/external/libavutil.xcframework/Info.plist +44 -0
  175. package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64/libavutil.framework/Info.plist +1 -0
  176. package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64/libavutil.framework/libavutil +0 -0
  177. package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64_x86_64-simulator/libavutil.framework/Info.plist +1 -0
  178. package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64_x86_64-simulator/libavutil.framework/libavutil +0 -0
  179. package/common/cpp/audioapi/external/libswresample.xcframework/Info.plist +44 -0
  180. package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64/libswresample.framework/Info.plist +1 -0
  181. package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64/libswresample.framework/libswresample +0 -0
  182. package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64_x86_64-simulator/libswresample.framework/Info.plist +1 -0
  183. package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64_x86_64-simulator/libswresample.framework/libswresample +0 -0
  184. package/common/cpp/audioapi/external/x86/libcrypto.a +0 -0
  185. package/common/cpp/audioapi/external/x86/libssl.a +0 -0
  186. package/common/cpp/audioapi/external/x86_64/libcrypto.a +0 -0
  187. package/common/cpp/audioapi/external/x86_64/libssl.a +0 -0
  188. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +402 -0
  189. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +27 -0
  190. package/common/cpp/audioapi/libs/ffmpeg/INSTRUCTIONS.md +26 -0
  191. package/common/cpp/audioapi/libs/ffmpeg/create_xcframework.sh +111 -0
  192. package/common/cpp/audioapi/libs/ffmpeg/ffmpeg_setup.sh +361 -0
  193. package/common/cpp/audioapi/utils/SpscChannel.hpp +47 -38
  194. package/common/cpp/test/CMakeLists.txt +7 -1
  195. package/ios/audioapi/ios/core/AudioDecoder.mm +22 -2
  196. package/lib/commonjs/api.js +7 -0
  197. package/lib/commonjs/api.js.map +1 -1
  198. package/lib/commonjs/core/AudioContext.js.map +1 -1
  199. package/lib/commonjs/core/BaseAudioContext.js +4 -0
  200. package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
  201. package/lib/commonjs/core/StreamerNode.js +15 -0
  202. package/lib/commonjs/core/StreamerNode.js.map +1 -0
  203. package/lib/module/api.js +1 -0
  204. package/lib/module/api.js.map +1 -1
  205. package/lib/module/core/AudioContext.js.map +1 -1
  206. package/lib/module/core/BaseAudioContext.js +4 -0
  207. package/lib/module/core/BaseAudioContext.js.map +1 -1
  208. package/lib/module/core/StreamerNode.js +9 -0
  209. package/lib/module/core/StreamerNode.js.map +1 -0
  210. package/lib/typescript/api.d.ts +1 -0
  211. package/lib/typescript/api.d.ts.map +1 -1
  212. package/lib/typescript/core/AudioContext.d.ts +1 -1
  213. package/lib/typescript/core/AudioContext.d.ts.map +1 -1
  214. package/lib/typescript/core/BaseAudioContext.d.ts +2 -0
  215. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  216. package/lib/typescript/core/StreamerNode.d.ts +5 -0
  217. package/lib/typescript/core/StreamerNode.d.ts.map +1 -0
  218. package/lib/typescript/interfaces.d.ts +5 -1
  219. package/lib/typescript/interfaces.d.ts.map +1 -1
  220. package/package.json +1 -1
  221. package/src/api.ts +1 -0
  222. package/src/core/AudioContext.ts +1 -1
  223. package/src/core/BaseAudioContext.ts +5 -0
  224. package/src/core/StreamerNode.ts +8 -0
  225. package/src/interfaces.ts +6 -1
@@ -0,0 +1,299 @@
1
+ /*
2
+ * This file links to the FFmpeg library, which is licensed under the
3
+ * GNU Lesser General Public License (LGPL) version 2.1 or later.
4
+ *
5
+ * Our own code in this file is licensed under the MIT License, but note
6
+ * that linking with FFmpeg means you must comply with the terms of the
7
+ * LGPL for FFmpeg itself.
8
+ */
9
+
10
+ #include <audioapi/core/BaseAudioContext.h>
11
+ #include <audioapi/core/sources/StreamerNode.h>
12
+ #include <audioapi/core/utils/Locker.h>
13
+ #include <audioapi/dsp/VectorMath.h>
14
+ #include <audioapi/utils/AudioArray.h>
15
+ #include <audioapi/utils/AudioBus.h>
16
+ #include <chrono>
17
+
18
+ namespace audioapi {
19
+ StreamerNode::StreamerNode(BaseAudioContext *context)
20
+ : AudioScheduledSourceNode(context),
21
+ fmtCtx_(nullptr),
22
+ codecCtx_(nullptr),
23
+ decoder_(nullptr),
24
+ codecpar_(nullptr),
25
+ pkt_(nullptr),
26
+ frame_(nullptr),
27
+ pendingFrame_(nullptr),
28
+ bufferedBus_(nullptr),
29
+ bufferedBusIndex_(0),
30
+ maxBufferSize_(0),
31
+ audio_stream_index_(-1),
32
+ swrCtx_(nullptr),
33
+ resampledData_(nullptr),
34
+ maxResampledSamples_(0) {}
35
+
36
+ StreamerNode::~StreamerNode() {
37
+ cleanup();
38
+ }
39
+
40
+ bool StreamerNode::initialize(const std::string &input_url) {
41
+ if (isInitialized_) {
42
+ cleanup();
43
+ }
44
+
45
+ if (!openInput(input_url)) {
46
+ return false;
47
+ }
48
+
49
+ if (!findAudioStream() || !setupDecoder() || !setupResampler()) {
50
+ cleanup();
51
+ return false;
52
+ }
53
+
54
+ pkt_ = av_packet_alloc();
55
+ frame_ = av_frame_alloc();
56
+
57
+ if (pkt_ == nullptr || frame_ == nullptr) {
58
+ cleanup();
59
+ return false;
60
+ }
61
+
62
+ maxBufferSize_ = BUFFER_LENGTH_SECONDS * codecCtx_->sample_rate;
63
+ // If decoding is faster than playing, we buffer few seconds of audio
64
+ bufferedBus_ = std::make_shared<AudioBus>(
65
+ maxBufferSize_, codecpar_->ch_layout.nb_channels, codecCtx_->sample_rate);
66
+
67
+ channelCount_ = codecpar_->ch_layout.nb_channels;
68
+ audioBus_ = std::make_shared<AudioBus>(
69
+ RENDER_QUANTUM_SIZE, channelCount_, context_->getSampleRate());
70
+
71
+ streamingThread_ = std::thread(&StreamerNode::streamAudio, this);
72
+ streamFlag.store(true);
73
+ isInitialized_ = true;
74
+ return true;
75
+ }
76
+
77
+ void StreamerNode::stop(double when) {
78
+ AudioScheduledSourceNode::stop(when);
79
+ streamFlag.store(false);
80
+ }
81
+
82
+ bool StreamerNode::setupResampler() {
83
+ // Allocate resampler context
84
+ swrCtx_ = swr_alloc();
85
+ if (swrCtx_ == nullptr) {
86
+ return false;
87
+ }
88
+
89
+ // Set input parameters (from codec)
90
+ av_opt_set_chlayout(swrCtx_, "in_chlayout", &codecCtx_->ch_layout, 0);
91
+ av_opt_set_int(swrCtx_, "in_sample_rate", codecCtx_->sample_rate, 0);
92
+ av_opt_set_sample_fmt(swrCtx_, "in_sample_fmt", codecCtx_->sample_fmt, 0);
93
+
94
+ // Set output parameters (float)
95
+ av_opt_set_chlayout(swrCtx_, "out_chlayout", &codecCtx_->ch_layout, 0);
96
+ av_opt_set_int(swrCtx_, "out_sample_rate", context_->getSampleRate(), 0);
97
+ av_opt_set_sample_fmt(swrCtx_, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
98
+
99
+ // Initialize the resampler
100
+ if (swr_init(swrCtx_) < 0) {
101
+ return false;
102
+ }
103
+
104
+ // Allocate output buffer for resampled data
105
+ maxResampledSamples_ = INITIAL_MAX_RESAMPLED_SAMPLES;
106
+ int ret = av_samples_alloc_array_and_samples(
107
+ &resampledData_,
108
+ nullptr,
109
+ codecCtx_->ch_layout.nb_channels,
110
+ maxResampledSamples_,
111
+ AV_SAMPLE_FMT_FLTP,
112
+ 0);
113
+
114
+ return ret >= 0;
115
+ }
116
+
117
+ void StreamerNode::streamAudio() {
118
+ while (streamFlag.load()) {
119
+ if (pendingFrame_ != nullptr) {
120
+ if (!processFrameWithResampler(pendingFrame_)) {
121
+ cleanup();
122
+ return;
123
+ }
124
+ } else {
125
+ if (av_read_frame(fmtCtx_, pkt_) < 0) {
126
+ cleanup();
127
+ return;
128
+ }
129
+ if (pkt_->stream_index == audio_stream_index_) {
130
+ if (avcodec_send_packet(codecCtx_, pkt_) != 0) {
131
+ cleanup();
132
+ return;
133
+ }
134
+ if (avcodec_receive_frame(codecCtx_, frame_) != 0) {
135
+ cleanup();
136
+ return;
137
+ }
138
+ if (!processFrameWithResampler(frame_)) {
139
+ cleanup();
140
+ return;
141
+ }
142
+ av_packet_unref(pkt_);
143
+ }
144
+ }
145
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
146
+ }
147
+ }
148
+
149
+ void StreamerNode::processNode(
150
+ const std::shared_ptr<AudioBus> &processingBus,
151
+ int framesToProcess) {
152
+ size_t startOffset = 0;
153
+ size_t offsetLength = 0;
154
+ updatePlaybackInfo(processingBus, framesToProcess, startOffset, offsetLength);
155
+ // If we have enough buffered data, copy to output bus
156
+ if (bufferedBusIndex_ >= framesToProcess) {
157
+ Locker locker(mutex_);
158
+ for (int ch = 0; ch < processingBus->getNumberOfChannels(); ch++) {
159
+ memcpy(
160
+ processingBus->getChannel(ch)->getData(),
161
+ bufferedBus_->getChannel(ch)->getData(),
162
+ offsetLength * sizeof(float));
163
+
164
+ memmove(
165
+ bufferedBus_->getChannel(ch)->getData(),
166
+ bufferedBus_->getChannel(ch)->getData() + offsetLength,
167
+ (maxBufferSize_ - offsetLength) * sizeof(float));
168
+ }
169
+ bufferedBusIndex_ -= offsetLength;
170
+ }
171
+ }
172
+
173
+ bool StreamerNode::processFrameWithResampler(AVFrame *frame) {
174
+ // Check if we need to reallocate the resampled buffer
175
+ int out_samples = swr_get_out_samples(swrCtx_, frame->nb_samples);
176
+ if (out_samples > maxResampledSamples_) {
177
+ av_freep(&resampledData_[0]);
178
+ av_freep(&resampledData_);
179
+
180
+ maxResampledSamples_ = out_samples;
181
+ int ret = av_samples_alloc_array_and_samples(
182
+ &resampledData_,
183
+ nullptr,
184
+ codecCtx_->ch_layout.nb_channels,
185
+ maxResampledSamples_,
186
+ AV_SAMPLE_FMT_FLTP,
187
+ 0);
188
+
189
+ if (ret < 0) {
190
+ return false;
191
+ }
192
+ }
193
+
194
+ // Convert the frame
195
+ int converted_samples = swr_convert(
196
+ swrCtx_,
197
+ resampledData_,
198
+ maxResampledSamples_,
199
+ (const uint8_t **)frame->data,
200
+ frame->nb_samples);
201
+
202
+ if (converted_samples < 0) {
203
+ return false;
204
+ }
205
+
206
+ // Check if converted data fits in buffer
207
+ if (bufferedBusIndex_ + converted_samples > maxBufferSize_) {
208
+ pendingFrame_ = frame;
209
+ return true;
210
+ } else {
211
+ pendingFrame_ = nullptr;
212
+ }
213
+
214
+ // Copy converted data to our buffer
215
+ Locker locker(mutex_);
216
+ for (int ch = 0; ch < codecCtx_->ch_layout.nb_channels; ch++) {
217
+ auto *src = reinterpret_cast<float *>(resampledData_[ch]);
218
+ float *dst = bufferedBus_->getChannel(ch)->getData() + bufferedBusIndex_;
219
+ memcpy(dst, src, converted_samples * sizeof(float));
220
+ }
221
+ bufferedBusIndex_ += converted_samples;
222
+ return true;
223
+ }
224
+
225
+ bool StreamerNode::openInput(const std::string &input_url) {
226
+ if (avformat_open_input(&fmtCtx_, input_url.c_str(), nullptr, nullptr) < 0) {
227
+ return false;
228
+ }
229
+ return avformat_find_stream_info(fmtCtx_, nullptr) >= 0;
230
+ }
231
+
232
+ bool StreamerNode::findAudioStream() {
233
+ audio_stream_index_ = -1;
234
+ codecpar_ = nullptr;
235
+
236
+ for (int i = 0; i < fmtCtx_->nb_streams; ++i) {
237
+ if (fmtCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
238
+ audio_stream_index_ = i;
239
+ codecpar_ = fmtCtx_->streams[i]->codecpar;
240
+ break;
241
+ }
242
+ }
243
+
244
+ return audio_stream_index_ >= 0 && codecpar_ != nullptr;
245
+ }
246
+
247
+ bool StreamerNode::setupDecoder() {
248
+ decoder_ = avcodec_find_decoder(codecpar_->codec_id);
249
+ if (decoder_ == nullptr) {
250
+ return false;
251
+ }
252
+
253
+ codecCtx_ = avcodec_alloc_context3(decoder_);
254
+ if (codecCtx_ == nullptr) {
255
+ return false;
256
+ }
257
+
258
+ if (avcodec_parameters_to_context(codecCtx_, codecpar_) < 0) {
259
+ return false;
260
+ }
261
+
262
+ return avcodec_open2(codecCtx_, decoder_, nullptr) >= 0;
263
+ }
264
+
265
+ void StreamerNode::cleanup() {
266
+ streamFlag.store(false);
267
+ streamingThread_.join();
268
+ if (swrCtx_ != nullptr) {
269
+ swr_free(&swrCtx_);
270
+ }
271
+
272
+ if (resampledData_ != nullptr) {
273
+ av_freep(&resampledData_[0]);
274
+ av_freep(&resampledData_);
275
+ }
276
+
277
+ if (frame_ != nullptr) {
278
+ av_frame_free(&frame_);
279
+ }
280
+
281
+ if (pkt_ != nullptr) {
282
+ av_packet_free(&pkt_);
283
+ }
284
+
285
+ if (codecCtx_ != nullptr) {
286
+ avcodec_free_context(&codecCtx_);
287
+ }
288
+
289
+ if (fmtCtx_ != nullptr) {
290
+ avformat_close_input(&fmtCtx_);
291
+ }
292
+
293
+ audio_stream_index_ = -1;
294
+ isInitialized_ = false;
295
+ decoder_ = nullptr;
296
+ codecpar_ = nullptr;
297
+ maxResampledSamples_ = 0;
298
+ }
299
+ } // namespace audioapi
@@ -0,0 +1,123 @@
1
+ /*
2
+ * This file links to the FFmpeg library, which is licensed under the
3
+ * GNU Lesser General Public License (LGPL) version 2.1 or later.
4
+ *
5
+ * Our own code in this file is licensed under the MIT License, but note
6
+ * that linking with FFmpeg means you must comply with the terms of the
7
+ * LGPL for FFmpeg itself.
8
+ */
9
+
10
+ #pragma once
11
+
12
+ #include <audioapi/core/sources/AudioScheduledSourceNode.h>
13
+
14
+ #ifndef AUDIO_API_TEST_SUITE
15
+ extern "C" {
16
+ #include <libavformat/avformat.h>
17
+ #include <libavcodec/avcodec.h>
18
+ #include <libavutil/samplefmt.h>
19
+ #include <libavutil/channel_layout.h>
20
+ #include <libavutil/opt.h>
21
+ #include <libswresample/swresample.h>
22
+ }
23
+ #endif
24
+
25
+ #include <cmath>
26
+ #include <memory>
27
+ #include <string>
28
+ #include <atomic>
29
+
30
+ namespace audioapi {
31
+
32
+ class AudioBus;
33
+
34
+ class StreamerNode : public AudioScheduledSourceNode {
35
+ public:
36
+ explicit StreamerNode(BaseAudioContext *context);
37
+ ~StreamerNode() override;
38
+
39
+ /**
40
+ * @brief Initialize all necessary ffmpeg components for streaming audio
41
+ */
42
+ bool initialize(const std::string& inputUrl);
43
+ void stop(double when) override;
44
+
45
+ private:
46
+ static constexpr int SIZE = 4'000'000; // 4MB
47
+
48
+ public:
49
+ static constexpr int getEstimatedSize() {
50
+ return StreamerNode::SIZE;
51
+ } // in bytes
52
+
53
+ protected:
54
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
55
+
56
+ private:
57
+ #ifndef AUDIO_API_TEST_SUITE
58
+ AVFormatContext* fmtCtx_;
59
+ AVCodecContext* codecCtx_;
60
+ const AVCodec* decoder_;
61
+ AVCodecParameters* codecpar_;
62
+ AVPacket* pkt_;
63
+ AVFrame* frame_; // Frame that is currently being processed
64
+ AVFrame* pendingFrame_; // Frame that is saved if bufferedBus is full
65
+ std::shared_ptr<AudioBus> bufferedBus_; // audio bus for buffering hls frames
66
+ size_t bufferedBusIndex_; // index in the buffered bus where we write the next frame
67
+ size_t maxBufferSize_; // maximum size of the buffered bus
68
+ int audio_stream_index_; // index of the audio stream channel in the input
69
+ SwrContext* swrCtx_;
70
+ uint8_t** resampledData_; // weird ffmpeg way of using raw byte pointers for resampled data
71
+ int maxResampledSamples_;
72
+ std::mutex mutex_;
73
+ std::thread streamingThread_;
74
+ std::atomic<bool> streamFlag; // Flag to control the streaming thread
75
+ static constexpr float BUFFER_LENGTH_SECONDS = 5.0f; // Length of the buffer in seconds
76
+ static constexpr int INITIAL_MAX_RESAMPLED_SAMPLES = 8192; // Initial size for resampled data
77
+
78
+ /**
79
+ * @brief Setting up the resampler
80
+ * @return true if successful, false otherwise
81
+ */
82
+ bool setupResampler();
83
+
84
+ /**
85
+ * @brief Resample the audio frame, change its sample format and channel layout
86
+ * @param frame The AVFrame to resample
87
+ * @return true if successful, false otherwise
88
+ */
89
+ bool processFrameWithResampler(AVFrame* frame);
90
+
91
+ /**
92
+ * @brief Thread function to continuously read and process audio frames
93
+ * @details This function runs in a separate thread to avoid blocking the main audio processing thread
94
+ * @note It will read frames from the input stream, resample them, and store them in the buffered bus
95
+ * @note The thread will stop when streamFlag is set to false
96
+ */
97
+ void streamAudio();
98
+
99
+ /** @brief Clean up resources */
100
+ void cleanup();
101
+
102
+ /**
103
+ * @brief Open the input stream
104
+ * @param input_url The URL of the input stream
105
+ * @return true if successful, false otherwise
106
+ * @note This function initializes the FFmpeg libraries and opens the input stream
107
+ */
108
+ bool openInput(const std::string& inputUrl);
109
+
110
+ /**
111
+ * @brief Find the audio stream channel in the input
112
+ * @return true if audio stream was found, false otherwise
113
+ */
114
+ bool findAudioStream();
115
+
116
+ /**
117
+ * @brief Set up the decoder for the audio stream
118
+ * @return true if successful, false otherwise
119
+ */
120
+ bool setupDecoder();
121
+ #endif // AUDIO_API_TEST_SUITE
122
+ };
123
+ } // namespace audioapi
@@ -5,9 +5,23 @@
5
5
  #include <memory>
6
6
  #include <string>
7
7
  #include <vector>
8
+ #include <cstring>
9
+ #include <algorithm>
8
10
 
9
11
  namespace audioapi {
10
12
 
13
+ enum class AudioFormat {
14
+ UNKNOWN,
15
+ WAV,
16
+ OGG,
17
+ FLAC,
18
+ AAC,
19
+ MP3,
20
+ M4A,
21
+ MP4,
22
+ MOV
23
+ };
24
+
11
25
  class AudioBus;
12
26
 
13
27
  static constexpr int CHUNK_SIZE = 4096;
@@ -73,6 +87,53 @@ class AudioDecoder {
73
87
  stretch_deinit(stretcher);
74
88
  }
75
89
 
90
+ static AudioFormat detectAudioFormat(const void* data, size_t size) {
91
+ if (size < 12) return AudioFormat::UNKNOWN;
92
+ const auto* bytes = static_cast<const unsigned char*>(data);
93
+
94
+ // WAV/RIFF
95
+ if (std::memcmp(bytes, "RIFF", 4) == 0 && std::memcmp(bytes + 8, "WAVE", 4) == 0)
96
+ return AudioFormat::WAV;
97
+
98
+ // OGG
99
+ if (std::memcmp(bytes, "OggS", 4) == 0)
100
+ return AudioFormat::OGG;
101
+
102
+ // FLAC
103
+ if (std::memcmp(bytes, "fLaC", 4) == 0)
104
+ return AudioFormat::FLAC;
105
+
106
+ // AAC starts with 0xFF 0xF1 or 0xFF 0xF9
107
+ if (bytes[0] == 0xFF && (bytes[1] & 0xF6) == 0xF0)
108
+ return AudioFormat::AAC;
109
+
110
+ // MP3: "ID3" or 11-bit frame sync (0xFF 0xE0)
111
+ if (std::memcmp(bytes, "ID3", 3) == 0)
112
+ return AudioFormat::MP3;
113
+ if (bytes[0] == 0xFF && (bytes[1] & 0xE0) == 0xE0)
114
+ return AudioFormat::MP3;
115
+
116
+ if (std::memcmp(bytes + 4, "ftyp", 4) == 0) {
117
+ if (std::memcmp(bytes + 8, "M4A ", 4) == 0)
118
+ return AudioFormat::M4A;
119
+ else if (std::memcmp(bytes + 8, "qt ", 4) == 0)
120
+ return AudioFormat::MOV;
121
+ return AudioFormat::MP4;
122
+ }
123
+ return AudioFormat::UNKNOWN;
124
+ }
125
+
126
+ static inline bool pathHasExtension(const std::string &path, const std::vector<std::string> &extensions) {
127
+ std::string pathLower = path;
128
+ std::transform(pathLower.begin(), pathLower.end(), pathLower.begin(), ::tolower);
129
+ for (const auto& ext : extensions) {
130
+ if (pathLower.ends_with(ext))
131
+ return true;
132
+ }
133
+ return false;
134
+ }
135
+
136
+
76
137
  [[nodiscard]] static inline int16_t floatToInt16(float sample) {
77
138
  return static_cast<int16_t>(sample * 32768.0f);
78
139
  }
@@ -213,6 +213,18 @@ void AudioNodeManager::handleAddToDeconstructionEvent(
213
213
  }
214
214
  }
215
215
 
216
+ template <typename U>
217
+ inline bool AudioNodeManager::nodeCanBeDestructed(
218
+ std::shared_ptr<U> const &node) {
219
+ // If the node is an AudioScheduledSourceNode, we need to check if it is
220
+ // playing
221
+ if constexpr (std::is_base_of_v<AudioScheduledSourceNode, U>) {
222
+ return node.use_count() == 1 &&
223
+ (node->isUnscheduled() || node->isFinished());
224
+ }
225
+ return node.use_count() == 1;
226
+ }
227
+
216
228
  template <typename U>
217
229
  void AudioNodeManager::prepareNodesForDestruction(
218
230
  std::vector<std::shared_ptr<U>> &vec) {
@@ -238,10 +250,10 @@ void AudioNodeManager::prepareNodesForDestruction(
238
250
  // nodes in range [begin, vec.size()) should be deleted
239
251
  // so new size of the vector will be `begin`
240
252
  while (begin <= end) {
241
- while (begin < end && vec[end].use_count() == 1) {
253
+ while (begin < end && AudioNodeManager::nodeCanBeDestructed(vec[end])) {
242
254
  end--;
243
255
  }
244
- if (vec[begin].use_count() == 1) {
256
+ if (AudioNodeManager::nodeCanBeDestructed(vec[begin])) {
245
257
  std::swap(vec[begin], vec[end]);
246
258
  end--;
247
259
  }
@@ -126,6 +126,9 @@ class AudioNodeManager {
126
126
 
127
127
  template <typename U>
128
128
  void prepareNodesForDestruction(std::vector<std::shared_ptr<U>> &vec);
129
+
130
+ template <typename U>
131
+ inline static bool nodeCanBeDestructed(std::shared_ptr<U> const& node);
129
132
  };
130
133
 
131
134
  #undef AUDIO_NODE_MANAGER_SPSC_OPTIONS
@@ -0,0 +1,36 @@
1
+ /*
2
+ * AC-3 parser prototypes
3
+ * Copyright (c) 2003 Fabrice Bellard
4
+ * Copyright (c) 2003 Michael Niedermayer
5
+ *
6
+ * This file is part of FFmpeg.
7
+ *
8
+ * FFmpeg is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; either
11
+ * version 2.1 of the License, or (at your option) any later version.
12
+ *
13
+ * FFmpeg is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ * Lesser General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Lesser General Public
19
+ * License along with FFmpeg; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+ */
22
+
23
+ #ifndef AVCODEC_AC3_PARSER_H
24
+ #define AVCODEC_AC3_PARSER_H
25
+
26
+ #include <stddef.h>
27
+ #include <stdint.h>
28
+
29
+ /**
30
+ * Extract the bitstream ID and the frame size from AC-3 data.
31
+ */
32
+ int av_ac3_parse_header(const uint8_t *buf, size_t size,
33
+ uint8_t *bitstream_id, uint16_t *frame_size);
34
+
35
+
36
+ #endif /* AVCODEC_AC3_PARSER_H */
@@ -0,0 +1,37 @@
1
+ /*
2
+ * This file is part of FFmpeg.
3
+ *
4
+ * FFmpeg is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * FFmpeg is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with FFmpeg; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+ */
18
+
19
+ #ifndef AVCODEC_ADTS_PARSER_H
20
+ #define AVCODEC_ADTS_PARSER_H
21
+
22
+ #include <stddef.h>
23
+ #include <stdint.h>
24
+
25
+ #define AV_AAC_ADTS_HEADER_SIZE 7
26
+
27
+ /**
28
+ * Extract the number of samples and frames from AAC data.
29
+ * @param[in] buf pointer to AAC data buffer
30
+ * @param[out] samples Pointer to where number of samples is written
31
+ * @param[out] frames Pointer to where number of frames is written
32
+ * @return Returns 0 on success, error code on failure.
33
+ */
34
+ int av_adts_header_parse(const uint8_t *buf, uint32_t *samples,
35
+ uint8_t *frames);
36
+
37
+ #endif /* AVCODEC_ADTS_PARSER_H */