react-native-alpha-video 0.0.0-stage → 1.0.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 (283) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +903 -2
  3. package/THIRD_PARTY_NOTICES.md +30 -0
  4. package/android/av1/build.gradle +67 -0
  5. package/android/av1/consumer-rules.pro +4 -0
  6. package/android/av1/src/main/cpp/Av1Codec_jni.cpp +8 -0
  7. package/android/av1/src/main/cpp/CMakeLists.txt +34 -0
  8. package/android/av1/src/main/java/dev/mediacache/alphavideo/av1/Av1Codec.java +21 -0
  9. package/android/build.gradle +85 -0
  10. package/android/consumer-rules.pro +2 -0
  11. package/android/gradle.properties +1 -0
  12. package/android/publish.gradle +82 -0
  13. package/android/settings.gradle +5 -0
  14. package/android/src/main/AndroidManifest.xml +1 -0
  15. package/android/src/main/cpp/CMakeLists.txt +59 -0
  16. package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoCodecs.java +73 -0
  17. package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoView.java +1966 -0
  18. package/android/src/main/java/dev/mediacache/alphavideo/BufferedDualStreamPlayer.java +978 -0
  19. package/android/src/main/java/dev/mediacache/alphavideo/Fetcher.java +37 -0
  20. package/android/src/main/java/dev/mediacache/alphavideo/HttpFetcher.java +156 -0
  21. package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecColor.java +47 -0
  22. package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecDecoders.java +135 -0
  23. package/android/src/main/java/dev/mediacache/alphavideo/RangeSourceLink.java +54 -0
  24. package/android/src/main/java/dev/mediacache/alphavideo/SourceReader.java +174 -0
  25. package/android/src/main/java/dev/mediacache/alphavideo/SurfaceTextureVideoDecoder.java +802 -0
  26. package/android/src/main/java/dev/mediacache/alphavideo/WebMAlphaPlayerNative.java +95 -0
  27. package/android/src/main/java/dev/mediacache/alphavideo/WebMFrame.java +54 -0
  28. package/android/src/main/java/dev/mediacache/alphavideo/WebMSource.java +160 -0
  29. package/android/src/rangesource/java/dev/mediacache/alphavideo/AppDataSource.java +50 -0
  30. package/android/vpx/build.gradle +67 -0
  31. package/android/vpx/consumer-rules.pro +4 -0
  32. package/android/vpx/src/main/cpp/CMakeLists.txt +34 -0
  33. package/android/vpx/src/main/cpp/VpxCodec_jni.cpp +8 -0
  34. package/android/vpx/src/main/java/dev/mediacache/alphavideo/vpx/VpxCodec.java +21 -0
  35. package/codecs/av1/Dav1dDecoderPlugin.cpp +157 -0
  36. package/codecs/av1/Dav1dDecoderPlugin.h +17 -0
  37. package/codecs/vpx/VpxDecoderPlugin.cpp +103 -0
  38. package/codecs/vpx/VpxDecoderPlugin.h +17 -0
  39. package/cpp/AlphaDemuxer.cpp +984 -0
  40. package/cpp/AlphaDemuxer.h +123 -0
  41. package/cpp/AlphaVideoDecoderPlugin.h +84 -0
  42. package/cpp/Av1SequenceHeader.cpp +175 -0
  43. package/cpp/Av1SequenceHeader.h +25 -0
  44. package/cpp/ByteSource.cpp +116 -0
  45. package/cpp/ByteSource.h +59 -0
  46. package/cpp/RangeSourceClient.h +40 -0
  47. package/cpp/VideoDecoder.cpp +157 -0
  48. package/cpp/VideoDecoder.h +83 -0
  49. package/cpp/WebMAlphaPlayer.cpp +1666 -0
  50. package/cpp/WebMAlphaPlayer.h +389 -0
  51. package/cpp/WebMAlphaPlayer_jni.cpp +1380 -0
  52. package/cpp/YuvToRgb.cpp +39 -0
  53. package/cpp/YuvToRgb.h +40 -0
  54. package/ios/Sources/AlphaVideo/AlphaVideoCodecs.mm +63 -0
  55. package/ios/Sources/AlphaVideo/AlphaVideoInternal.h +70 -0
  56. package/ios/Sources/AlphaVideo/AlphaVideoPlayer.mm +994 -0
  57. package/ios/Sources/AlphaVideo/AlphaVideoSource.mm +476 -0
  58. package/ios/Sources/AlphaVideo/AlphaVideoView.mm +374 -0
  59. package/ios/Sources/AlphaVideo/include/AlphaVideo.h +303 -0
  60. package/ios/Sources/AlphaVideoAV1/AlphaVideoAV1Codec.mm +16 -0
  61. package/ios/Sources/AlphaVideoAV1/include/AlphaVideoAV1.h +18 -0
  62. package/ios/Sources/AlphaVideoVPX/AlphaVideoVPXCodec.mm +16 -0
  63. package/ios/Sources/AlphaVideoVPX/include/AlphaVideoVPX.h +17 -0
  64. package/lib/commonjs/AlphaVideoView.js +187 -0
  65. package/lib/commonjs/AlphaVideoView.js.map +1 -0
  66. package/lib/commonjs/AlphaVideoViewNativeComponent.js +47 -0
  67. package/lib/commonjs/AlphaVideoViewNativeComponent.js.map +1 -0
  68. package/lib/commonjs/AlphaVideoViewNativeComponent.web.js +11 -0
  69. package/lib/commonjs/AlphaVideoViewNativeComponent.web.js.map +1 -0
  70. package/lib/commonjs/NativeAlphaVideoModule.js +10 -0
  71. package/lib/commonjs/NativeAlphaVideoModule.js.map +1 -0
  72. package/lib/commonjs/NativeAlphaVideoModule.web.js +9 -0
  73. package/lib/commonjs/NativeAlphaVideoModule.web.js.map +1 -0
  74. package/lib/commonjs/WebPlayer.js +12 -0
  75. package/lib/commonjs/WebPlayer.js.map +1 -0
  76. package/lib/commonjs/WebPlayer.web.js +92 -0
  77. package/lib/commonjs/WebPlayer.web.js.map +1 -0
  78. package/lib/commonjs/index.js +124 -0
  79. package/lib/commonjs/index.js.map +1 -0
  80. package/lib/module/AlphaVideoView.js +187 -0
  81. package/lib/module/AlphaVideoView.js.map +1 -0
  82. package/lib/module/AlphaVideoViewNativeComponent.js +47 -0
  83. package/lib/module/AlphaVideoViewNativeComponent.js.map +1 -0
  84. package/lib/module/AlphaVideoViewNativeComponent.web.js +11 -0
  85. package/lib/module/AlphaVideoViewNativeComponent.web.js.map +1 -0
  86. package/lib/module/NativeAlphaVideoModule.js +10 -0
  87. package/lib/module/NativeAlphaVideoModule.js.map +1 -0
  88. package/lib/module/NativeAlphaVideoModule.web.js +9 -0
  89. package/lib/module/NativeAlphaVideoModule.web.js.map +1 -0
  90. package/lib/module/WebPlayer.js +12 -0
  91. package/lib/module/WebPlayer.js.map +1 -0
  92. package/lib/module/WebPlayer.web.js +92 -0
  93. package/lib/module/WebPlayer.web.js.map +1 -0
  94. package/lib/module/index.js +124 -0
  95. package/lib/module/index.js.map +1 -0
  96. package/lib/typescript/react-native/src/AlphaVideoView.d.ts +189 -0
  97. package/lib/typescript/react-native/src/AlphaVideoView.d.ts.map +1 -0
  98. package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts +109 -0
  99. package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts.map +1 -0
  100. package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts +5 -0
  101. package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts.map +1 -0
  102. package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts +21 -0
  103. package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts.map +1 -0
  104. package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts +3 -0
  105. package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts.map +1 -0
  106. package/lib/typescript/react-native/src/WebPlayer.d.ts +3 -0
  107. package/lib/typescript/react-native/src/WebPlayer.d.ts.map +1 -0
  108. package/lib/typescript/react-native/src/WebPlayer.web.d.ts +9 -0
  109. package/lib/typescript/react-native/src/WebPlayer.web.d.ts.map +1 -0
  110. package/lib/typescript/react-native/src/index.d.ts +77 -0
  111. package/lib/typescript/react-native/src/index.d.ts.map +1 -0
  112. package/licenses/dav1d-COPYING.txt +23 -0
  113. package/licenses/libvpx-LICENSE.txt +31 -0
  114. package/licenses/libvpx-PATENTS.txt +23 -0
  115. package/licenses/libwebm-LICENSE.txt +30 -0
  116. package/licenses/libwebm-PATENTS.txt +23 -0
  117. package/package.json +150 -4
  118. package/prebuilt/android/arm64-v8a/lib/libdav1d.a +0 -0
  119. package/prebuilt/android/arm64-v8a/lib/libvpx.a +0 -0
  120. package/prebuilt/android/armeabi-v7a/lib/libdav1d.a +0 -0
  121. package/prebuilt/android/armeabi-v7a/lib/libvpx.a +0 -0
  122. package/prebuilt/android/x86_64/lib/libdav1d.a +0 -0
  123. package/prebuilt/android/x86_64/lib/libvpx.a +0 -0
  124. package/prebuilt/include/dav1d/common.h +94 -0
  125. package/prebuilt/include/dav1d/data.h +117 -0
  126. package/prebuilt/include/dav1d/dav1d.h +329 -0
  127. package/prebuilt/include/dav1d/headers.h +440 -0
  128. package/prebuilt/include/dav1d/picture.h +157 -0
  129. package/prebuilt/include/dav1d/version.h +50 -0
  130. package/prebuilt/include/vpx/vp8.h +136 -0
  131. package/prebuilt/include/vpx/vp8dx.h +228 -0
  132. package/prebuilt/include/vpx/vpx_codec.h +475 -0
  133. package/prebuilt/include/vpx/vpx_decoder.h +365 -0
  134. package/prebuilt/include/vpx/vpx_frame_buffer.h +83 -0
  135. package/prebuilt/include/vpx/vpx_image.h +209 -0
  136. package/prebuilt/include/vpx/vpx_integer.h +40 -0
  137. package/prebuilt/ios/lib/libdav1d.a +0 -0
  138. package/prebuilt/ios/lib/libvpx.a +0 -0
  139. package/prebuilt/ios-simulator/include/dav1d/common.h +94 -0
  140. package/prebuilt/ios-simulator/include/dav1d/data.h +117 -0
  141. package/prebuilt/ios-simulator/include/dav1d/dav1d.h +329 -0
  142. package/prebuilt/ios-simulator/include/dav1d/headers.h +440 -0
  143. package/prebuilt/ios-simulator/include/dav1d/picture.h +157 -0
  144. package/prebuilt/ios-simulator/include/dav1d/version.h +50 -0
  145. package/prebuilt/ios-simulator/include/vpx/vp8.h +136 -0
  146. package/prebuilt/ios-simulator/include/vpx/vp8dx.h +228 -0
  147. package/prebuilt/ios-simulator/include/vpx/vpx_codec.h +475 -0
  148. package/prebuilt/ios-simulator/include/vpx/vpx_decoder.h +365 -0
  149. package/prebuilt/ios-simulator/include/vpx/vpx_frame_buffer.h +83 -0
  150. package/prebuilt/ios-simulator/include/vpx/vpx_image.h +209 -0
  151. package/prebuilt/ios-simulator/include/vpx/vpx_integer.h +40 -0
  152. package/prebuilt/ios-simulator/lib/libdav1d.a +0 -0
  153. package/prebuilt/ios-simulator/lib/libvpx.a +0 -0
  154. package/react-native/android/CMakeLists.txt +14 -0
  155. package/react-native/android/build.gradle +110 -0
  156. package/react-native/android/src/main/AndroidManifest.xml +1 -0
  157. package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModule.java +102 -0
  158. package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoPackage.java +50 -0
  159. package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManager.java +317 -0
  160. package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +10 -0
  161. package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +23 -0
  162. package/react-native/android/src/norangesource/java/dev/mediacache/alphavideo/AppDataSource.java +15 -0
  163. package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +30 -0
  164. package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +61 -0
  165. package/react-native/ios/RNAlphaVideoViewComponentView.mm +173 -0
  166. package/react-native/ios/RNAlphaVideoViewManager.mm +147 -0
  167. package/react-native/src/AlphaVideoView.tsx +329 -0
  168. package/react-native/src/AlphaVideoViewNativeComponent.ts +132 -0
  169. package/react-native/src/AlphaVideoViewNativeComponent.web.ts +5 -0
  170. package/react-native/src/NativeAlphaVideoModule.ts +22 -0
  171. package/react-native/src/NativeAlphaVideoModule.web.ts +2 -0
  172. package/react-native/src/WebPlayer.tsx +7 -0
  173. package/react-native/src/WebPlayer.web.tsx +60 -0
  174. package/react-native/src/index.tsx +144 -0
  175. package/react-native-alpha-video.podspec +99 -0
  176. package/react-native.config.js +12 -0
  177. package/scripts/build_codecs_android.sh +246 -0
  178. package/scripts/build_codecs_ios.sh +31 -0
  179. package/scripts/build_codecs_ios_device.sh +210 -0
  180. package/scripts/build_codecs_ios_simulator.sh +256 -0
  181. package/scripts/build_wasm.sh +230 -0
  182. package/scripts/build_xcframework.sh +49 -0
  183. package/scripts/fetch-prebuilt.sh +48 -0
  184. package/scripts/package_release.sh +107 -0
  185. package/scripts/publish-android.sh +85 -0
  186. package/scripts/vendor_range_source.sh +47 -0
  187. package/third_party/libwebm/AUTHORS.TXT +5 -0
  188. package/third_party/libwebm/LICENSE.TXT +30 -0
  189. package/third_party/libwebm/PATENTS.TXT +23 -0
  190. package/third_party/libwebm/README.md +7 -0
  191. package/third_party/libwebm/webm_parser/include/webm/buffer_reader.h +138 -0
  192. package/third_party/libwebm/webm_parser/include/webm/callback.h +363 -0
  193. package/third_party/libwebm/webm_parser/include/webm/dom_types.h +1781 -0
  194. package/third_party/libwebm/webm_parser/include/webm/element.h +208 -0
  195. package/third_party/libwebm/webm_parser/include/webm/file_reader.h +103 -0
  196. package/third_party/libwebm/webm_parser/include/webm/id.h +1085 -0
  197. package/third_party/libwebm/webm_parser/include/webm/istream_reader.h +99 -0
  198. package/third_party/libwebm/webm_parser/include/webm/reader.h +94 -0
  199. package/third_party/libwebm/webm_parser/include/webm/status.h +166 -0
  200. package/third_party/libwebm/webm_parser/include/webm/webm_parser.h +133 -0
  201. package/third_party/libwebm/webm_parser/src/ancestory.cc +334 -0
  202. package/third_party/libwebm/webm_parser/src/ancestory.h +83 -0
  203. package/third_party/libwebm/webm_parser/src/audio_parser.h +84 -0
  204. package/third_party/libwebm/webm_parser/src/bit_utils.cc +26 -0
  205. package/third_party/libwebm/webm_parser/src/bit_utils.h +24 -0
  206. package/third_party/libwebm/webm_parser/src/block_additions_parser.h +30 -0
  207. package/third_party/libwebm/webm_parser/src/block_group_parser.h +71 -0
  208. package/third_party/libwebm/webm_parser/src/block_header_parser.cc +76 -0
  209. package/third_party/libwebm/webm_parser/src/block_header_parser.h +65 -0
  210. package/third_party/libwebm/webm_parser/src/block_more_parser.h +32 -0
  211. package/third_party/libwebm/webm_parser/src/block_parser.cc +285 -0
  212. package/third_party/libwebm/webm_parser/src/block_parser.h +126 -0
  213. package/third_party/libwebm/webm_parser/src/bool_parser.h +95 -0
  214. package/third_party/libwebm/webm_parser/src/buffer_reader.cc +110 -0
  215. package/third_party/libwebm/webm_parser/src/byte_parser.h +144 -0
  216. package/third_party/libwebm/webm_parser/src/callback.cc +155 -0
  217. package/third_party/libwebm/webm_parser/src/chapter_atom_parser.h +42 -0
  218. package/third_party/libwebm/webm_parser/src/chapter_display_parser.h +34 -0
  219. package/third_party/libwebm/webm_parser/src/chapters_parser.h +28 -0
  220. package/third_party/libwebm/webm_parser/src/cluster_parser.h +48 -0
  221. package/third_party/libwebm/webm_parser/src/colour_parser.h +55 -0
  222. package/third_party/libwebm/webm_parser/src/content_enc_aes_settings_parser.h +32 -0
  223. package/third_party/libwebm/webm_parser/src/content_encoding_parser.h +38 -0
  224. package/third_party/libwebm/webm_parser/src/content_encodings_parser.h +30 -0
  225. package/third_party/libwebm/webm_parser/src/content_encryption_parser.h +37 -0
  226. package/third_party/libwebm/webm_parser/src/cue_point_parser.h +38 -0
  227. package/third_party/libwebm/webm_parser/src/cue_track_positions_parser.h +39 -0
  228. package/third_party/libwebm/webm_parser/src/cues_parser.h +27 -0
  229. package/third_party/libwebm/webm_parser/src/date_parser.cc +72 -0
  230. package/third_party/libwebm/webm_parser/src/date_parser.h +64 -0
  231. package/third_party/libwebm/webm_parser/src/ebml_parser.h +48 -0
  232. package/third_party/libwebm/webm_parser/src/edition_entry_parser.h +35 -0
  233. package/third_party/libwebm/webm_parser/src/element_parser.h +102 -0
  234. package/third_party/libwebm/webm_parser/src/file_reader.cc +142 -0
  235. package/third_party/libwebm/webm_parser/src/float_parser.cc +77 -0
  236. package/third_party/libwebm/webm_parser/src/float_parser.h +65 -0
  237. package/third_party/libwebm/webm_parser/src/id_element_parser.cc +49 -0
  238. package/third_party/libwebm/webm_parser/src/id_element_parser.h +56 -0
  239. package/third_party/libwebm/webm_parser/src/id_parser.cc +75 -0
  240. package/third_party/libwebm/webm_parser/src/id_parser.h +45 -0
  241. package/third_party/libwebm/webm_parser/src/info_parser.h +44 -0
  242. package/third_party/libwebm/webm_parser/src/int_parser.h +121 -0
  243. package/third_party/libwebm/webm_parser/src/istream_reader.cc +133 -0
  244. package/third_party/libwebm/webm_parser/src/master_parser.cc +298 -0
  245. package/third_party/libwebm/webm_parser/src/master_parser.h +230 -0
  246. package/third_party/libwebm/webm_parser/src/master_value_parser.h +533 -0
  247. package/third_party/libwebm/webm_parser/src/mastering_metadata_parser.h +57 -0
  248. package/third_party/libwebm/webm_parser/src/parser.h +34 -0
  249. package/third_party/libwebm/webm_parser/src/parser_utils.cc +34 -0
  250. package/third_party/libwebm/webm_parser/src/parser_utils.h +64 -0
  251. package/third_party/libwebm/webm_parser/src/projection_parser.h +40 -0
  252. package/third_party/libwebm/webm_parser/src/recursive_parser.h +93 -0
  253. package/third_party/libwebm/webm_parser/src/seek_head_parser.h +27 -0
  254. package/third_party/libwebm/webm_parser/src/seek_parser.h +37 -0
  255. package/third_party/libwebm/webm_parser/src/segment_parser.cc +86 -0
  256. package/third_party/libwebm/webm_parser/src/segment_parser.h +53 -0
  257. package/third_party/libwebm/webm_parser/src/simple_tag_parser.h +37 -0
  258. package/third_party/libwebm/webm_parser/src/size_parser.cc +56 -0
  259. package/third_party/libwebm/webm_parser/src/size_parser.h +43 -0
  260. package/third_party/libwebm/webm_parser/src/skip_callback.h +63 -0
  261. package/third_party/libwebm/webm_parser/src/skip_parser.cc +59 -0
  262. package/third_party/libwebm/webm_parser/src/skip_parser.h +35 -0
  263. package/third_party/libwebm/webm_parser/src/slices_parser.h +30 -0
  264. package/third_party/libwebm/webm_parser/src/tag_parser.h +37 -0
  265. package/third_party/libwebm/webm_parser/src/tags_parser.h +27 -0
  266. package/third_party/libwebm/webm_parser/src/targets_parser.h +35 -0
  267. package/third_party/libwebm/webm_parser/src/time_slice_parser.h +30 -0
  268. package/third_party/libwebm/webm_parser/src/track_entry_parser.h +65 -0
  269. package/third_party/libwebm/webm_parser/src/tracks_parser.h +27 -0
  270. package/third_party/libwebm/webm_parser/src/unknown_parser.cc +49 -0
  271. package/third_party/libwebm/webm_parser/src/unknown_parser.h +38 -0
  272. package/third_party/libwebm/webm_parser/src/var_int_parser.cc +71 -0
  273. package/third_party/libwebm/webm_parser/src/var_int_parser.h +56 -0
  274. package/third_party/libwebm/webm_parser/src/video_parser.h +122 -0
  275. package/third_party/libwebm/webm_parser/src/virtual_block_parser.cc +72 -0
  276. package/third_party/libwebm/webm_parser/src/virtual_block_parser.h +69 -0
  277. package/third_party/libwebm/webm_parser/src/void_parser.cc +49 -0
  278. package/third_party/libwebm/webm_parser/src/void_parser.h +41 -0
  279. package/third_party/libwebm/webm_parser/src/webm_parser.cc +282 -0
  280. package/third_party/range-source/LICENSE +21 -0
  281. package/third_party/range-source/README.md +8 -0
  282. package/third_party/range-source/include/range_source.h +395 -0
  283. package/third_party/range-source/include/range_source_download.h +309 -0
@@ -0,0 +1,374 @@
1
+ /**
2
+ * AlphaVideoView.mm
3
+ * The player view: source resolving, playback mode, the global decode queue and the Metal view.
4
+ */
5
+
6
+ #import "AlphaVideoInternal.h"
7
+
8
+ #define WEBM_VLOG(...) do { if (self.verbose) NSLog(__VA_ARGS__); } while (0)
9
+
10
+ #pragma mark - Global Decode Queue
11
+
12
+ // Serializes preload decoding across all views, so many views spawned at once don't saturate
13
+ // the CPU.
14
+ static dispatch_queue_t _globalDecodeQueue = nil;
15
+ static NSInteger _globalDecodeQueueRefCount = 0;
16
+ static dispatch_semaphore_t _globalDecodeQueueLock = nil;
17
+
18
+ static dispatch_queue_t getGlobalDecodeQueue(void) {
19
+ static dispatch_once_t onceToken;
20
+ dispatch_once(&onceToken, ^{
21
+ _globalDecodeQueueLock = dispatch_semaphore_create(1);
22
+ });
23
+
24
+ dispatch_semaphore_wait(_globalDecodeQueueLock, DISPATCH_TIME_FOREVER);
25
+ if (!_globalDecodeQueue) {
26
+ _globalDecodeQueue = dispatch_queue_create("dev.mediacache.alphavideo.decode", DISPATCH_QUEUE_SERIAL);
27
+ }
28
+ _globalDecodeQueueRefCount++;
29
+ dispatch_semaphore_signal(_globalDecodeQueueLock);
30
+
31
+ return _globalDecodeQueue;
32
+ }
33
+
34
+ static void releaseGlobalDecodeQueue(void) {
35
+ dispatch_semaphore_wait(_globalDecodeQueueLock, DISPATCH_TIME_FOREVER);
36
+ _globalDecodeQueueRefCount--;
37
+ if (_globalDecodeQueueRefCount <= 0 && _globalDecodeQueue) {
38
+ _globalDecodeQueue = nil;
39
+ _globalDecodeQueueRefCount = 0;
40
+ }
41
+ dispatch_semaphore_signal(_globalDecodeQueueLock);
42
+ }
43
+
44
+ #pragma mark - AlphaVideoView
45
+
46
+ static const int64_t AlphaVideoDefaultMaxStorageBytes = 512LL * 1024 * 1024;
47
+
48
+ static void AlphaVideoWarnWithoutAddOn(void) {
49
+ static dispatch_once_t once;
50
+ dispatch_once(&once, ^{
51
+ NSLog(@"[AlphaVideo] range-source isn't installed (the RangeSource SwiftPM product, the alpha-video pod's "
52
+ @"Source subspec, or for React Native npm i react-native-range-source): URLs are downloaded whole for "
53
+ @"each play, without range requests, storage, maxStorageBytes or cacheKey");
54
+ });
55
+ }
56
+
57
+ @interface AlphaVideoView () <AlphaVideoPlayerDelegate>
58
+ @end
59
+
60
+ @implementation AlphaVideoView {
61
+ // Bumped on every source, so a slow open can't load over a newer source. Main queue only.
62
+ NSUInteger _sourceGeneration;
63
+ // The reader of the current source, for URLs and data sources. Main queue only.
64
+ AlphaVideoSourceReader *_reader;
65
+ // Loads that read over the network, in order and off the main queue
66
+ dispatch_queue_t _loadQueue;
67
+ }
68
+
69
+ - (instancetype)initWithFrame:(CGRect)frame {
70
+ self = [super initWithFrame:frame];
71
+ if (self) {
72
+ [self setup];
73
+ }
74
+ return self;
75
+ }
76
+
77
+ - (instancetype)initWithCoder:(NSCoder *)coder {
78
+ self = [super initWithCoder:coder];
79
+ if (self) {
80
+ [self setup];
81
+ }
82
+ return self;
83
+ }
84
+
85
+ - (void)setup {
86
+ self.backgroundColor = [UIColor clearColor];
87
+
88
+ _autoPlay = YES;
89
+ _loop = YES;
90
+ _paused = NO;
91
+ _playbackSpeed = 1.0;
92
+ _mode = @"stream";
93
+ _streamPrefetchAhead = 8;
94
+ _useDecodeQueue = YES;
95
+ _storage = @"auto";
96
+ _maxStorageBytes = AlphaVideoDefaultMaxStorageBytes;
97
+ _loadQueue = dispatch_queue_create("dev.mediacache.alphavideo.load", DISPATCH_QUEUE_SERIAL);
98
+
99
+ _metalView = [[AlphaVideoMetalView alloc] initWithFrame:self.bounds config:[AlphaVideoConfig defaultConfig]];
100
+ _metalView.playerDelegate = self;
101
+ _metalView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
102
+ _metalView.translatesAutoresizingMaskIntoConstraints = YES;
103
+
104
+ [self addSubview:_metalView];
105
+ }
106
+
107
+ - (void)layoutSubviews {
108
+ [super layoutSubviews];
109
+ self.metalView.frame = self.bounds;
110
+ }
111
+
112
+ #pragma mark - Properties
113
+
114
+ - (NSString *)loadedDecoder {
115
+ return [NSString stringWithFormat:@"software (%@)", self.metalView.player.decoderName];
116
+ }
117
+
118
+ - (void)setSource:(NSString *)source {
119
+ if (source == _source || [source isEqualToString:_source]) return;
120
+ _source = [source copy];
121
+ [self scheduleLoad];
122
+ }
123
+
124
+ // What a source is read with: a change reloads it
125
+ - (void)setHeaders:(NSDictionary<NSString *, NSString *> *)headers {
126
+ if (headers == _headers || [headers isEqualToDictionary:_headers]) return;
127
+ _headers = [headers copy];
128
+ if (_source) [self scheduleLoad];
129
+ }
130
+
131
+ - (void)setDataSource:(NSString *)dataSource {
132
+ if (dataSource == _dataSource || [dataSource isEqualToString:_dataSource]) return;
133
+ _dataSource = [dataSource copy];
134
+ if (_source) [self scheduleLoad];
135
+ }
136
+
137
+ /** Loads on the next turn, once the other properties set in this turn have been applied. */
138
+ - (void)scheduleLoad {
139
+ NSUInteger generation = ++_sourceGeneration;
140
+ __weak AlphaVideoView *weakSelf = self;
141
+ dispatch_async(dispatch_get_main_queue(), ^{
142
+ AlphaVideoView *strongSelf = weakSelf;
143
+ if (strongSelf && generation == strongSelf->_sourceGeneration) [strongSelf loadSource];
144
+ });
145
+ }
146
+
147
+ - (void)setStorage:(NSString *)storage {
148
+ if ([storage isEqualToString:@"disk"] || [storage isEqualToString:@"memory"] || [storage isEqualToString:@"none"]) {
149
+ _storage = [storage copy];
150
+ } else {
151
+ _storage = @"auto";
152
+ }
153
+ }
154
+
155
+ - (void)setMaxStorageBytes:(int64_t)maxStorageBytes {
156
+ _maxStorageBytes = maxStorageBytes > 0 ? maxStorageBytes : AlphaVideoDefaultMaxStorageBytes;
157
+ }
158
+
159
+ - (void)setAutoPlay:(BOOL)autoPlay {
160
+ _autoPlay = autoPlay;
161
+ self.metalView.autoPlay = autoPlay && !_paused;
162
+ }
163
+
164
+ - (void)setLoop:(BOOL)loop {
165
+ _loop = loop;
166
+ self.metalView.loop = loop;
167
+ }
168
+
169
+ - (void)setPaused:(BOOL)paused {
170
+ _paused = paused;
171
+ // A view paused before it loads must not start on load
172
+ self.metalView.autoPlay = _autoPlay && !paused;
173
+ if (paused) {
174
+ [self.metalView pause];
175
+ } else if (self.autoPlay) {
176
+ [self.metalView play];
177
+ }
178
+ }
179
+
180
+ - (void)setPlaybackSpeed:(double)playbackSpeed {
181
+ _playbackSpeed = playbackSpeed;
182
+ self.metalView.playbackSpeed = playbackSpeed;
183
+ }
184
+
185
+ - (void)setVerbose:(BOOL)verbose {
186
+ _verbose = verbose;
187
+ self.metalView.verbose = verbose;
188
+ }
189
+
190
+ - (void)setMode:(NSString *)mode {
191
+ if ([mode isEqualToString:@"preload"] || [mode isEqualToString:@"streamAndPreload"]) {
192
+ _mode = [mode copy];
193
+ } else {
194
+ _mode = @"stream";
195
+ }
196
+ [self updatePlayerConfig];
197
+ }
198
+
199
+ - (void)setStreamPrefetchAhead:(int)streamPrefetchAhead {
200
+ _streamPrefetchAhead = streamPrefetchAhead > 0 ? streamPrefetchAhead : 8;
201
+ [self updatePlayerConfig];
202
+ }
203
+
204
+ - (void)updatePlayerConfig {
205
+ AlphaVideoConfig *config = [self.metalView.player getConfig];
206
+ config.mode = _mode;
207
+ config.stream = [_mode isEqualToString:@"stream"];
208
+ config.streamPrefetchAhead = _streamPrefetchAhead;
209
+ [self.metalView.player setConfig:config];
210
+
211
+ WEBM_VLOG(@"AlphaVideoView mode: %@, prefetchAhead=%d", _mode, _streamPrefetchAhead);
212
+ }
213
+
214
+ #pragma mark - Source Loading
215
+
216
+ - (void)loadSource {
217
+ NSString *sourceUri = self.source;
218
+ if (sourceUri.length == 0) return;
219
+
220
+ [self updatePlayerConfig];
221
+ _reader = nil;
222
+
223
+ WEBM_VLOG(@"AlphaVideoView loading: %@ (mode=%@, useDecodeQueue=%d)", sourceUri, _mode, _useDecodeQueue);
224
+
225
+ BOOL appSource = self.dataSource.length > 0;
226
+ BOOL remote = [sourceUri hasPrefix:@"https://"] || [sourceUri hasPrefix:@"http://"];
227
+ if (!appSource && !remote) {
228
+ NSString *path = AlphaVideoLocalPathForSource(sourceUri);
229
+ if (!path) {
230
+ [self playerDidEncounterError:[NSString stringWithFormat:
231
+ @"Unsupported source '%@'. Use https://, file://, an absolute path or asset://", sourceUri] code:nil];
232
+ } else if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
233
+ [self playerDidEncounterError:[NSString stringWithFormat:@"File not found: %@", sourceUri] code:nil];
234
+ } else {
235
+ [self loadWithQueue:^(AlphaVideoView *view) { [view.metalView loadFromPath:path]; } offMain:NO];
236
+ }
237
+ return;
238
+ }
239
+
240
+ if (!AlphaVideoRangeSourcePlugin()) {
241
+ if (appSource) {
242
+ [self playerDidEncounterError:[NSString stringWithFormat:
243
+ @"The data source \"%@\" needs the range-source add-on (the RangeSource SwiftPM product, the "
244
+ @"alpha-video pod's Source subspec, or for React Native react-native-range-source), which the "
245
+ @"app doesn't include", self.dataSource]
246
+ code:AlphaVideoErrorNoSourceModule];
247
+ return;
248
+ }
249
+ AlphaVideoWarnWithoutAddOn();
250
+ }
251
+
252
+ NSString *dataSource = appSource ? [self.dataSource copy] : nil;
253
+ NSURL *url = [NSURL URLWithString:sourceUri];
254
+ if (!url) {
255
+ [self playerDidEncounterError:[NSString stringWithFormat:@"Invalid URL: %@", sourceUri] code:nil];
256
+ return;
257
+ }
258
+ NSString *storage = [_storage isEqualToString:@"auto"] ? (appSource ? @"none" : @"disk") : _storage;
259
+ NSString *key = self.cacheKey.length > 0 ? self.cacheKey : sourceUri;
260
+ NSDictionary<NSString *, NSString *> *headers = self.headers ?: @{};
261
+ int64_t maxStorageBytes = _maxStorageBytes;
262
+ // The stream modes start on the first bytes. Preload decodes the whole clip before showing
263
+ // anything, and would hold the global decode queue for the whole transfer.
264
+ BOOL fetchFirst = [_mode isEqualToString:@"preload"];
265
+ NSUInteger generation = _sourceGeneration;
266
+ __weak AlphaVideoView *weakSelf = self;
267
+ dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
268
+ NSString *error = nil;
269
+ AlphaVideoSourceReader *reader = [AlphaVideoSourceReader openURL:url
270
+ dataSource:dataSource
271
+ headers:headers
272
+ storage:storage
273
+ key:key
274
+ maxStorageBytes:maxStorageBytes
275
+ error:&error];
276
+ if (reader && fetchFirst && ![reader fetchAll:&error]) reader = nil;
277
+ dispatch_async(dispatch_get_main_queue(), ^{
278
+ AlphaVideoView *strongSelf = weakSelf;
279
+ if (!strongSelf || generation != strongSelf->_sourceGeneration) return;
280
+ if (!reader) {
281
+ [strongSelf playerDidEncounterError:[NSString stringWithFormat:@"Loading %@ failed: %@", sourceUri, error] code:nil];
282
+ return;
283
+ }
284
+ strongSelf->_reader = reader;
285
+ [strongSelf loadWithQueue:^(AlphaVideoView *view) { [view.metalView loadFromReader:reader]; } offMain:YES];
286
+ });
287
+ });
288
+ }
289
+
290
+ /**
291
+ * Preload and streamAndPreload go through the global decode queue when useDecodeQueue is on;
292
+ * stream mode is light enough to load directly, on the main queue for a local file and on this
293
+ * view's load queue (`offMain`) for one that reads its header over the network.
294
+ */
295
+ - (void)loadWithQueue:(void (^)(AlphaVideoView *view))load offMain:(BOOL)offMain {
296
+ BOOL shouldUseQueue = ![_mode isEqualToString:@"stream"] && _useDecodeQueue;
297
+ __weak AlphaVideoView *weakSelf = self;
298
+
299
+ if (shouldUseQueue) {
300
+ WEBM_VLOG(@"Using global decode queue for: %@", self.source);
301
+ dispatch_queue_t queue = getGlobalDecodeQueue();
302
+ dispatch_async(queue, ^{
303
+ AlphaVideoView *strongSelf = weakSelf;
304
+ // Blocks until decodeAllFrames completes
305
+ if (strongSelf) load(strongSelf);
306
+ releaseGlobalDecodeQueue();
307
+ });
308
+ } else if (offMain) {
309
+ dispatch_async(_loadQueue, ^{
310
+ AlphaVideoView *strongSelf = weakSelf;
311
+ if (strongSelf) load(strongSelf);
312
+ });
313
+ } else {
314
+ load(self);
315
+ }
316
+ }
317
+
318
+ #pragma mark - Playback Control
319
+
320
+ - (void)play {
321
+ [self.metalView play];
322
+ }
323
+
324
+ - (void)pause {
325
+ [self.metalView pause];
326
+ }
327
+
328
+ - (void)stop {
329
+ [self.metalView stop];
330
+ }
331
+
332
+ - (void)seekToFrame:(int)frame {
333
+ [self.metalView seekToFrame:frame];
334
+ }
335
+
336
+ - (void)seekToTime:(double)seconds {
337
+ [self.metalView seekToTime:seconds];
338
+ }
339
+
340
+ #pragma mark - AlphaVideoPlayerDelegate
341
+
342
+ - (void)playerDidLoad:(int)totalFrames width:(int)width height:(int)height {
343
+ WEBM_VLOG(@"AlphaVideoView loaded: %d frames, %dx%d", totalFrames, width, height);
344
+ id<AlphaVideoViewDelegate> delegate = self.delegate;
345
+ if ([delegate respondsToSelector:@selector(alphaVideoView:didLoadFrames:width:height:)]) {
346
+ [delegate alphaVideoView:self didLoadFrames:totalFrames width:width height:height];
347
+ }
348
+ }
349
+
350
+ - (void)playerDidReceiveFrame:(AlphaVideoFrame *)frame {
351
+ // The Metal view draws the frame
352
+ }
353
+
354
+ - (void)playerDidEncounterError:(NSString *)error code:(nullable NSString *)code {
355
+ NSLog(@"AlphaVideoView error: %@", error);
356
+ id<AlphaVideoViewDelegate> delegate = self.delegate;
357
+ if ([delegate respondsToSelector:@selector(alphaVideoView:didFailWithError:code:)]) {
358
+ [delegate alphaVideoView:self didFailWithError:error ?: @"Unknown error" code:code];
359
+ }
360
+ }
361
+
362
+ - (void)playerDidEnd {
363
+ WEBM_VLOG(@"AlphaVideoView ended");
364
+ id<AlphaVideoViewDelegate> delegate = self.delegate;
365
+ if ([delegate respondsToSelector:@selector(alphaVideoViewDidEnd:)]) {
366
+ [delegate alphaVideoViewDidEnd:self];
367
+ }
368
+ }
369
+
370
+ - (void)playerPreloadComplete:(int)totalFrames timeMs:(double)timeMs {
371
+ WEBM_VLOG(@"AlphaVideoView preload complete: %d frames in %.1fms", totalFrames, timeMs);
372
+ }
373
+
374
+ @end
@@ -0,0 +1,303 @@
1
+ /**
2
+ * AlphaVideo.h
3
+ * Transparent video for iOS: VP8, VP9 or AV1 WebM with alpha, decoded by the C++ core's codec modules
4
+ * (libvpx, dav1d) and drawn with Metal. AlphaVideoView is the view to use; the rest is the
5
+ * lower-level API.
6
+ */
7
+
8
+ #import <Foundation/Foundation.h>
9
+ #import <Metal/Metal.h>
10
+ #import <MetalKit/MetalKit.h>
11
+ #import <UIKit/UIKit.h>
12
+
13
+ NS_ASSUME_NONNULL_BEGIN
14
+
15
+ /**
16
+ * The error code when no linked codec module decodes the file: the message names the module to
17
+ * add (AlphaVideoVPX for VP8 and VP9, AlphaVideoAV1 for AV1).
18
+ */
19
+ extern NSString *const AlphaVideoErrorNoDecoder;
20
+
21
+ /**
22
+ * The error code for a data source without the range-source add-on, which reads them (the
23
+ * RangeSource SwiftPM product, the alpha-video pod's Source subspec, or for React Native
24
+ * react-native-range-source).
25
+ */
26
+ extern NSString *const AlphaVideoErrorNoSourceModule;
27
+
28
+ /**
29
+ * The software decoders the player plays with. The codec modules register themselves when the
30
+ * app links them, nothing to call: SwiftPM products AlphaVideoVPX (libvpx, VP8, VP9) and AlphaVideoAV1
31
+ * (dav1d, AV1), or pods alpha-video/VPX and alpha-video/AV1.
32
+ */
33
+ @interface AlphaVideoCodecs : NSObject
34
+
35
+ /**
36
+ * Registers another software decoder: `pluginList` is a native AlphaVideoDecoderPluginList
37
+ * (cpp/AlphaVideoDecoderPlugin.h). Registered decoders come after the modules', which a stream
38
+ * tries first. NO, with `error`, for a decoder built for another plugin ABI.
39
+ */
40
+ + (BOOL)registerPluginList:(const void *)pluginList error:(NSError **)error;
41
+
42
+ /** The registered software decoders, e.g. @[@"libvpx v1.15.2", @"dav1d 1.5.1"]; empty with none. */
43
+ @property (class, nonatomic, readonly) NSArray<NSString *> *softwareDecoders;
44
+
45
+ @end
46
+
47
+ /**
48
+ * Frame data structure for Metal rendering
49
+ */
50
+ @interface AlphaVideoFrame : NSObject
51
+
52
+ @property (nonatomic, readonly) NSData *yPlane;
53
+ @property (nonatomic, readonly) NSData *uPlane;
54
+ @property (nonatomic, readonly) NSData *vPlane;
55
+ @property (nonatomic, readonly) NSData *aPlane;
56
+
57
+ @property (nonatomic, readonly) int width;
58
+ @property (nonatomic, readonly) int height;
59
+ @property (nonatomic, readonly) int frameIndex;
60
+ @property (nonatomic, readonly) double timestamp;
61
+
62
+ // Raw pointers for direct Metal texture upload (faster than NSData copy)
63
+ @property (nonatomic, readonly) const uint8_t *yPlanePtr;
64
+ @property (nonatomic, readonly) const uint8_t *uPlanePtr;
65
+ @property (nonatomic, readonly) const uint8_t *vPlanePtr;
66
+ @property (nonatomic, readonly) const uint8_t *aPlanePtr;
67
+
68
+ @property (nonatomic, readonly) int yStride;
69
+ @property (nonatomic, readonly) int uvStride;
70
+ @property (nonatomic, readonly) int aStride;
71
+
72
+ @end
73
+
74
+ /**
75
+ * Player statistics
76
+ */
77
+ @interface AlphaVideoStats : NSObject
78
+
79
+ @property (nonatomic, readonly) int64_t framesDecoded;
80
+ @property (nonatomic, readonly) int64_t cacheHits;
81
+ @property (nonatomic, readonly) int64_t cacheMisses;
82
+ @property (nonatomic, readonly) double avgDecodeTimeMs;
83
+ @property (nonatomic, readonly) double cacheHitRate;
84
+
85
+ @end
86
+
87
+ /**
88
+ * Delegate for player events
89
+ */
90
+ @protocol AlphaVideoPlayerDelegate <NSObject>
91
+
92
+ @optional
93
+ - (void)playerDidLoad:(int)totalFrames width:(int)width height:(int)height;
94
+ - (void)playerDidReceiveFrame:(AlphaVideoFrame *)frame;
95
+ - (void)playerDidStartPlaying;
96
+ - (void)playerDidPause;
97
+ - (void)playerDidStop;
98
+ - (void)playerDidLoop;
99
+ - (void)playerDidEnd;
100
+ // `code`: AlphaVideoErrorNoDecoder, AlphaVideoErrorNoSourceModule, or nil
101
+ - (void)playerDidEncounterError:(NSString *)error code:(nullable NSString *)code;
102
+ - (void)playerPreloadProgress:(int)loaded total:(int)total;
103
+ - (void)playerPreloadComplete:(int)totalFrames timeMs:(double)timeMs;
104
+
105
+ @end
106
+
107
+ /**
108
+ * Configuration for the player
109
+ */
110
+ @interface AlphaVideoConfig : NSObject
111
+
112
+ @property (nonatomic) int decodeThreads; // Default: 4
113
+ @property (nonatomic) int cacheSize; // Default: 250
114
+ @property (nonatomic) BOOL preloadAllFrames; // Default: YES
115
+ @property (nonatomic) BOOL loopPlayback; // Default: YES
116
+ @property (nonatomic) double playbackSpeed; // Default: 1.0
117
+
118
+ // Playback mode: "preload", "stream", or "streamAndPreload"
119
+ // - preload: decode all frames upfront, then play
120
+ // - stream (default): decode on-demand with sliding window cache
121
+ // - streamAndPreload: start playing immediately, cache all frames for smooth looping
122
+ @property (nonatomic, copy) NSString *mode; // Default: "stream"
123
+
124
+ // Legacy stream property (deprecated, use mode instead)
125
+ @property (nonatomic) BOOL stream; // Default: YES
126
+ @property (nonatomic) int streamPrefetchAhead; // Default: 8 (frames decoded ahead; all stream mode keeps)
127
+
128
+ + (instancetype)defaultConfig;
129
+
130
+ @end
131
+
132
+ /**
133
+ * Main Objective-C++ wrapper for WebMAlphaPlayer C++ core
134
+ */
135
+ @interface AlphaVideoPlayer : NSObject
136
+
137
+ @property (nonatomic, weak, nullable) id<AlphaVideoPlayerDelegate> delegate;
138
+ @property (nonatomic, readonly) BOOL isLoaded;
139
+ @property (nonatomic, readonly) BOOL isPlaying;
140
+ @property (nonatomic, readonly) int currentFrame;
141
+ @property (nonatomic, readonly) double currentTime;
142
+ @property (nonatomic, readonly) double duration;
143
+ @property (nonatomic, readonly) int totalFrames;
144
+ @property (nonatomic, readonly) int width;
145
+ @property (nonatomic, readonly) int height;
146
+ @property (nonatomic, readonly) double frameRate;
147
+ // The decoder for the loaded clip: "libvpx", or "dav1d" (AV1)
148
+ @property (nonatomic, readonly) NSString *decoderName;
149
+
150
+ // Initialization
151
+ - (instancetype)init;
152
+ - (instancetype)initWithConfig:(AlphaVideoConfig *)config;
153
+
154
+ // Configuration
155
+ - (void)setConfig:(AlphaVideoConfig *)config;
156
+ - (AlphaVideoConfig *)getConfig;
157
+ // C++ core info logging; errors are always logged
158
+ - (void)setVerbose:(BOOL)verbose;
159
+
160
+ // Loading. AlphaVideoView also plays URLs and data sources, read by range as they play.
161
+ - (BOOL)loadFromFile:(NSString *)path;
162
+ - (BOOL)loadFromData:(NSData *)data;
163
+ - (void)unload;
164
+
165
+ // Playback
166
+ - (void)play;
167
+ - (void)pause;
168
+ - (void)stop;
169
+ - (void)seekToTime:(double)seconds;
170
+ - (void)seekToFrame:(int)frameIndex;
171
+
172
+ /**
173
+ * Changes playback rate live, without moving the playhead.
174
+ *
175
+ * Distinct from setting `playbackSpeed` in the config, which only takes effect at load: this
176
+ * reaches the running playback loop, so a rate swapped on hover applies to the next frame.
177
+ */
178
+ - (void)setPlaybackSpeed:(double)speed;
179
+ - (double)playbackSpeed;
180
+
181
+ // Direct frame access (for manual rendering)
182
+ - (nullable AlphaVideoFrame *)getFrame:(int)index;
183
+ - (nullable AlphaVideoFrame *)getCurrentFrame;
184
+
185
+ // Statistics
186
+ - (AlphaVideoStats *)getStats;
187
+ - (void)resetStats;
188
+
189
+ // The decoder libraries, e.g. "libvpx v1.14.0, dav1d 1.5.1"
190
+ + (NSString *)libraryVersions;
191
+
192
+ @end
193
+
194
+ /**
195
+ * Metal-based view that uses the C++ player
196
+ * High-performance GPU-accelerated YUV→RGB conversion
197
+ */
198
+ @interface AlphaVideoMetalView : MTKView
199
+
200
+ @property (nonatomic, strong, readonly) AlphaVideoPlayer *player;
201
+ @property (nonatomic, weak, nullable) id<AlphaVideoPlayerDelegate> playerDelegate;
202
+
203
+ // Source management
204
+ @property (nonatomic, copy, nullable) NSString *sourcePath;
205
+
206
+ // Playback configuration
207
+ @property (nonatomic) BOOL autoPlay;
208
+ @property (nonatomic) BOOL loop;
209
+ @property (nonatomic) double playbackSpeed;
210
+
211
+ // Log lifecycle and per-frame events; errors and warnings are always logged
212
+ @property (nonatomic) BOOL verbose;
213
+
214
+ // Initialization
215
+ - (instancetype)initWithFrame:(CGRect)frame;
216
+ - (instancetype)initWithFrame:(CGRect)frame config:(AlphaVideoConfig *)config;
217
+
218
+ // Loading
219
+ - (BOOL)loadFromPath:(NSString *)path;
220
+ - (void)unloadVideo;
221
+
222
+ // Playback control
223
+ - (void)play;
224
+ - (void)pause;
225
+ - (void)stop;
226
+ - (void)seekToFrame:(int)frame;
227
+ - (void)seekToTime:(double)seconds;
228
+
229
+ // Rendering
230
+ - (void)renderFrame:(AlphaVideoFrame *)frame;
231
+ - (void)renderCurrentFrame;
232
+
233
+ @end
234
+
235
+ @class AlphaVideoView;
236
+
237
+ /** AlphaVideoView events, delivered on the main queue. */
238
+ @protocol AlphaVideoViewDelegate <NSObject>
239
+ @optional
240
+ - (void)alphaVideoView:(AlphaVideoView *)view didLoadFrames:(int)totalFrames width:(int)width height:(int)height;
241
+ // `code`: AlphaVideoErrorNoDecoder, or nil
242
+ - (void)alphaVideoView:(AlphaVideoView *)view didFailWithError:(NSString *)error code:(nullable NSString *)code;
243
+ - (void)alphaVideoViewDidEnd:(AlphaVideoView *)view;
244
+ @end
245
+
246
+ /**
247
+ * The player view: resolves a source, loads it in the chosen mode and draws it with Metal.
248
+ *
249
+ * `source` takes an https:// or http:// URL (read by range requests as it plays, or without the
250
+ * range-source add-on downloaded whole),
251
+ * asset://path inside the app bundle, a file:// URL or an absolute path, or with `dataSource` any
252
+ * URL that data source reads. A new source loads on the next main-queue turn, so set the other
253
+ * properties in the same turn and they apply to it.
254
+ */
255
+ @interface AlphaVideoView : UIView
256
+
257
+ @property (nonatomic, weak, nullable) id<AlphaVideoViewDelegate> delegate;
258
+
259
+ @property (nonatomic, copy, nullable) NSString *source;
260
+ // Sent with every request for an http(s) source, and given to a data source
261
+ @property (nonatomic, copy, nullable) NSDictionary<NSString *, NSString *> *headers;
262
+ // Reads the source through the data source registered under this name with range-source's
263
+ // RangeDataSources (the range-source add-on)
264
+ @property (nonatomic, copy, nullable) NSString *dataSource;
265
+ // What the store keeps the source under, instead of its URL (for presigned URLs that change)
266
+ @property (nonatomic, copy, nullable) NSString *cacheKey;
267
+ // Where a URL's or data source's bytes are kept between plays: "disk" (Caches/alpha-video),
268
+ // "memory" (for the app's lifetime) or "none". "auto" (default) is disk for URLs and none for a
269
+ // data source. The store is partial: it keeps what has been played, and a clip held whole plays
270
+ // again offline.
271
+ @property (nonatomic, copy) NSString *storage;
272
+ // The store's cap over every clip in it, least recently played out first. Default: 512 MB
273
+ @property (nonatomic) int64_t maxStorageBytes;
274
+
275
+ // "stream" (default) decodes a few frames ahead while playing; "preload" decodes every frame
276
+ // before playing; "streamAndPreload" starts like stream and keeps every frame after the first
277
+ // pass. The stream modes play URLs as they arrive; preload fetches the whole file first.
278
+ @property (nonatomic, copy) NSString *mode;
279
+ @property (nonatomic) int streamPrefetchAhead; // Frames decoded ahead while streaming, all it keeps. Default: 8
280
+ // Preload and streamAndPreload decode one clip at a time across all views. Default: YES
281
+ @property (nonatomic) BOOL useDecodeQueue;
282
+
283
+ @property (nonatomic) BOOL autoPlay; // Default: YES
284
+ @property (nonatomic) BOOL loop; // Default: YES
285
+ @property (nonatomic) BOOL paused;
286
+ @property (nonatomic) double playbackSpeed; // Default: 1.0, changeable while playing
287
+ // Log lifecycle and per-frame events; errors are always logged
288
+ @property (nonatomic) BOOL verbose;
289
+
290
+ @property (nonatomic, strong, readonly) AlphaVideoMetalView *metalView;
291
+ // The engine and decoder playing the loaded clip, as Android's onLoad names it: "software (dav1d)"
292
+ @property (nonatomic, readonly) NSString *loadedDecoder;
293
+
294
+ - (void)play;
295
+ - (void)pause;
296
+ - (void)stop;
297
+ // Both clamp to the clip and keep playing or stay paused; a paused view shows the frame.
298
+ - (void)seekToFrame:(int)frame;
299
+ - (void)seekToTime:(double)seconds;
300
+
301
+ @end
302
+
303
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,16 @@
1
+ /**
2
+ * AlphaVideoAV1Codec.mm
3
+ * The av1 codec module (dav1d: AV1, 8- to 12-bit) on iOS. AlphaVideoCodecs finds this class by
4
+ * name and registers its plugin list.
5
+ */
6
+
7
+ #import "AlphaVideoAV1.h"
8
+ #include "Dav1dDecoderPlugin.h"
9
+
10
+ @implementation AlphaVideoAV1Codec
11
+
12
+ + (const void *)pluginList {
13
+ return reinterpret_cast<const void *>(&alpha_video_av1_plugins);
14
+ }
15
+
16
+ @end