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.
- package/LICENSE +21 -0
- package/README.md +903 -2
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/android/av1/build.gradle +67 -0
- package/android/av1/consumer-rules.pro +4 -0
- package/android/av1/src/main/cpp/Av1Codec_jni.cpp +8 -0
- package/android/av1/src/main/cpp/CMakeLists.txt +34 -0
- package/android/av1/src/main/java/dev/mediacache/alphavideo/av1/Av1Codec.java +21 -0
- package/android/build.gradle +85 -0
- package/android/consumer-rules.pro +2 -0
- package/android/gradle.properties +1 -0
- package/android/publish.gradle +82 -0
- package/android/settings.gradle +5 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/cpp/CMakeLists.txt +59 -0
- package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoCodecs.java +73 -0
- package/android/src/main/java/dev/mediacache/alphavideo/AlphaVideoView.java +1966 -0
- package/android/src/main/java/dev/mediacache/alphavideo/BufferedDualStreamPlayer.java +978 -0
- package/android/src/main/java/dev/mediacache/alphavideo/Fetcher.java +37 -0
- package/android/src/main/java/dev/mediacache/alphavideo/HttpFetcher.java +156 -0
- package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecColor.java +47 -0
- package/android/src/main/java/dev/mediacache/alphavideo/MediaCodecDecoders.java +135 -0
- package/android/src/main/java/dev/mediacache/alphavideo/RangeSourceLink.java +54 -0
- package/android/src/main/java/dev/mediacache/alphavideo/SourceReader.java +174 -0
- package/android/src/main/java/dev/mediacache/alphavideo/SurfaceTextureVideoDecoder.java +802 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMAlphaPlayerNative.java +95 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMFrame.java +54 -0
- package/android/src/main/java/dev/mediacache/alphavideo/WebMSource.java +160 -0
- package/android/src/rangesource/java/dev/mediacache/alphavideo/AppDataSource.java +50 -0
- package/android/vpx/build.gradle +67 -0
- package/android/vpx/consumer-rules.pro +4 -0
- package/android/vpx/src/main/cpp/CMakeLists.txt +34 -0
- package/android/vpx/src/main/cpp/VpxCodec_jni.cpp +8 -0
- package/android/vpx/src/main/java/dev/mediacache/alphavideo/vpx/VpxCodec.java +21 -0
- package/codecs/av1/Dav1dDecoderPlugin.cpp +157 -0
- package/codecs/av1/Dav1dDecoderPlugin.h +17 -0
- package/codecs/vpx/VpxDecoderPlugin.cpp +103 -0
- package/codecs/vpx/VpxDecoderPlugin.h +17 -0
- package/cpp/AlphaDemuxer.cpp +984 -0
- package/cpp/AlphaDemuxer.h +123 -0
- package/cpp/AlphaVideoDecoderPlugin.h +84 -0
- package/cpp/Av1SequenceHeader.cpp +175 -0
- package/cpp/Av1SequenceHeader.h +25 -0
- package/cpp/ByteSource.cpp +116 -0
- package/cpp/ByteSource.h +59 -0
- package/cpp/RangeSourceClient.h +40 -0
- package/cpp/VideoDecoder.cpp +157 -0
- package/cpp/VideoDecoder.h +83 -0
- package/cpp/WebMAlphaPlayer.cpp +1666 -0
- package/cpp/WebMAlphaPlayer.h +389 -0
- package/cpp/WebMAlphaPlayer_jni.cpp +1380 -0
- package/cpp/YuvToRgb.cpp +39 -0
- package/cpp/YuvToRgb.h +40 -0
- package/ios/Sources/AlphaVideo/AlphaVideoCodecs.mm +63 -0
- package/ios/Sources/AlphaVideo/AlphaVideoInternal.h +70 -0
- package/ios/Sources/AlphaVideo/AlphaVideoPlayer.mm +994 -0
- package/ios/Sources/AlphaVideo/AlphaVideoSource.mm +476 -0
- package/ios/Sources/AlphaVideo/AlphaVideoView.mm +374 -0
- package/ios/Sources/AlphaVideo/include/AlphaVideo.h +303 -0
- package/ios/Sources/AlphaVideoAV1/AlphaVideoAV1Codec.mm +16 -0
- package/ios/Sources/AlphaVideoAV1/include/AlphaVideoAV1.h +18 -0
- package/ios/Sources/AlphaVideoVPX/AlphaVideoVPXCodec.mm +16 -0
- package/ios/Sources/AlphaVideoVPX/include/AlphaVideoVPX.h +17 -0
- package/lib/commonjs/AlphaVideoView.js +187 -0
- package/lib/commonjs/AlphaVideoView.js.map +1 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.js +47 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.js.map +1 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.web.js +11 -0
- package/lib/commonjs/AlphaVideoViewNativeComponent.web.js.map +1 -0
- package/lib/commonjs/NativeAlphaVideoModule.js +10 -0
- package/lib/commonjs/NativeAlphaVideoModule.js.map +1 -0
- package/lib/commonjs/NativeAlphaVideoModule.web.js +9 -0
- package/lib/commonjs/NativeAlphaVideoModule.web.js.map +1 -0
- package/lib/commonjs/WebPlayer.js +12 -0
- package/lib/commonjs/WebPlayer.js.map +1 -0
- package/lib/commonjs/WebPlayer.web.js +92 -0
- package/lib/commonjs/WebPlayer.web.js.map +1 -0
- package/lib/commonjs/index.js +124 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/AlphaVideoView.js +187 -0
- package/lib/module/AlphaVideoView.js.map +1 -0
- package/lib/module/AlphaVideoViewNativeComponent.js +47 -0
- package/lib/module/AlphaVideoViewNativeComponent.js.map +1 -0
- package/lib/module/AlphaVideoViewNativeComponent.web.js +11 -0
- package/lib/module/AlphaVideoViewNativeComponent.web.js.map +1 -0
- package/lib/module/NativeAlphaVideoModule.js +10 -0
- package/lib/module/NativeAlphaVideoModule.js.map +1 -0
- package/lib/module/NativeAlphaVideoModule.web.js +9 -0
- package/lib/module/NativeAlphaVideoModule.web.js.map +1 -0
- package/lib/module/WebPlayer.js +12 -0
- package/lib/module/WebPlayer.js.map +1 -0
- package/lib/module/WebPlayer.web.js +92 -0
- package/lib/module/WebPlayer.web.js.map +1 -0
- package/lib/module/index.js +124 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoView.d.ts +189 -0
- package/lib/typescript/react-native/src/AlphaVideoView.d.ts.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts +109 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts +5 -0
- package/lib/typescript/react-native/src/AlphaVideoViewNativeComponent.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts +21 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.d.ts.map +1 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts +3 -0
- package/lib/typescript/react-native/src/NativeAlphaVideoModule.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/WebPlayer.d.ts +3 -0
- package/lib/typescript/react-native/src/WebPlayer.d.ts.map +1 -0
- package/lib/typescript/react-native/src/WebPlayer.web.d.ts +9 -0
- package/lib/typescript/react-native/src/WebPlayer.web.d.ts.map +1 -0
- package/lib/typescript/react-native/src/index.d.ts +77 -0
- package/lib/typescript/react-native/src/index.d.ts.map +1 -0
- package/licenses/dav1d-COPYING.txt +23 -0
- package/licenses/libvpx-LICENSE.txt +31 -0
- package/licenses/libvpx-PATENTS.txt +23 -0
- package/licenses/libwebm-LICENSE.txt +30 -0
- package/licenses/libwebm-PATENTS.txt +23 -0
- package/package.json +150 -4
- package/prebuilt/android/arm64-v8a/lib/libdav1d.a +0 -0
- package/prebuilt/android/arm64-v8a/lib/libvpx.a +0 -0
- package/prebuilt/android/armeabi-v7a/lib/libdav1d.a +0 -0
- package/prebuilt/android/armeabi-v7a/lib/libvpx.a +0 -0
- package/prebuilt/android/x86_64/lib/libdav1d.a +0 -0
- package/prebuilt/android/x86_64/lib/libvpx.a +0 -0
- package/prebuilt/include/dav1d/common.h +94 -0
- package/prebuilt/include/dav1d/data.h +117 -0
- package/prebuilt/include/dav1d/dav1d.h +329 -0
- package/prebuilt/include/dav1d/headers.h +440 -0
- package/prebuilt/include/dav1d/picture.h +157 -0
- package/prebuilt/include/dav1d/version.h +50 -0
- package/prebuilt/include/vpx/vp8.h +136 -0
- package/prebuilt/include/vpx/vp8dx.h +228 -0
- package/prebuilt/include/vpx/vpx_codec.h +475 -0
- package/prebuilt/include/vpx/vpx_decoder.h +365 -0
- package/prebuilt/include/vpx/vpx_frame_buffer.h +83 -0
- package/prebuilt/include/vpx/vpx_image.h +209 -0
- package/prebuilt/include/vpx/vpx_integer.h +40 -0
- package/prebuilt/ios/lib/libdav1d.a +0 -0
- package/prebuilt/ios/lib/libvpx.a +0 -0
- package/prebuilt/ios-simulator/include/dav1d/common.h +94 -0
- package/prebuilt/ios-simulator/include/dav1d/data.h +117 -0
- package/prebuilt/ios-simulator/include/dav1d/dav1d.h +329 -0
- package/prebuilt/ios-simulator/include/dav1d/headers.h +440 -0
- package/prebuilt/ios-simulator/include/dav1d/picture.h +157 -0
- package/prebuilt/ios-simulator/include/dav1d/version.h +50 -0
- package/prebuilt/ios-simulator/include/vpx/vp8.h +136 -0
- package/prebuilt/ios-simulator/include/vpx/vp8dx.h +228 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_codec.h +475 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_decoder.h +365 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_frame_buffer.h +83 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_image.h +209 -0
- package/prebuilt/ios-simulator/include/vpx/vpx_integer.h +40 -0
- package/prebuilt/ios-simulator/lib/libdav1d.a +0 -0
- package/prebuilt/ios-simulator/lib/libvpx.a +0 -0
- package/react-native/android/CMakeLists.txt +14 -0
- package/react-native/android/build.gradle +110 -0
- package/react-native/android/src/main/AndroidManifest.xml +1 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModule.java +102 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoPackage.java +50 -0
- package/react-native/android/src/main/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManager.java +317 -0
- package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +10 -0
- package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +23 -0
- package/react-native/android/src/norangesource/java/dev/mediacache/alphavideo/AppDataSource.java +15 -0
- package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoModuleSpec.java +30 -0
- package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/reactnative/AlphaVideoViewManagerSpec.java +61 -0
- package/react-native/ios/RNAlphaVideoViewComponentView.mm +173 -0
- package/react-native/ios/RNAlphaVideoViewManager.mm +147 -0
- package/react-native/src/AlphaVideoView.tsx +329 -0
- package/react-native/src/AlphaVideoViewNativeComponent.ts +132 -0
- package/react-native/src/AlphaVideoViewNativeComponent.web.ts +5 -0
- package/react-native/src/NativeAlphaVideoModule.ts +22 -0
- package/react-native/src/NativeAlphaVideoModule.web.ts +2 -0
- package/react-native/src/WebPlayer.tsx +7 -0
- package/react-native/src/WebPlayer.web.tsx +60 -0
- package/react-native/src/index.tsx +144 -0
- package/react-native-alpha-video.podspec +99 -0
- package/react-native.config.js +12 -0
- package/scripts/build_codecs_android.sh +246 -0
- package/scripts/build_codecs_ios.sh +31 -0
- package/scripts/build_codecs_ios_device.sh +210 -0
- package/scripts/build_codecs_ios_simulator.sh +256 -0
- package/scripts/build_wasm.sh +230 -0
- package/scripts/build_xcframework.sh +49 -0
- package/scripts/fetch-prebuilt.sh +48 -0
- package/scripts/package_release.sh +107 -0
- package/scripts/publish-android.sh +85 -0
- package/scripts/vendor_range_source.sh +47 -0
- package/third_party/libwebm/AUTHORS.TXT +5 -0
- package/third_party/libwebm/LICENSE.TXT +30 -0
- package/third_party/libwebm/PATENTS.TXT +23 -0
- package/third_party/libwebm/README.md +7 -0
- package/third_party/libwebm/webm_parser/include/webm/buffer_reader.h +138 -0
- package/third_party/libwebm/webm_parser/include/webm/callback.h +363 -0
- package/third_party/libwebm/webm_parser/include/webm/dom_types.h +1781 -0
- package/third_party/libwebm/webm_parser/include/webm/element.h +208 -0
- package/third_party/libwebm/webm_parser/include/webm/file_reader.h +103 -0
- package/third_party/libwebm/webm_parser/include/webm/id.h +1085 -0
- package/third_party/libwebm/webm_parser/include/webm/istream_reader.h +99 -0
- package/third_party/libwebm/webm_parser/include/webm/reader.h +94 -0
- package/third_party/libwebm/webm_parser/include/webm/status.h +166 -0
- package/third_party/libwebm/webm_parser/include/webm/webm_parser.h +133 -0
- package/third_party/libwebm/webm_parser/src/ancestory.cc +334 -0
- package/third_party/libwebm/webm_parser/src/ancestory.h +83 -0
- package/third_party/libwebm/webm_parser/src/audio_parser.h +84 -0
- package/third_party/libwebm/webm_parser/src/bit_utils.cc +26 -0
- package/third_party/libwebm/webm_parser/src/bit_utils.h +24 -0
- package/third_party/libwebm/webm_parser/src/block_additions_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/block_group_parser.h +71 -0
- package/third_party/libwebm/webm_parser/src/block_header_parser.cc +76 -0
- package/third_party/libwebm/webm_parser/src/block_header_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/block_more_parser.h +32 -0
- package/third_party/libwebm/webm_parser/src/block_parser.cc +285 -0
- package/third_party/libwebm/webm_parser/src/block_parser.h +126 -0
- package/third_party/libwebm/webm_parser/src/bool_parser.h +95 -0
- package/third_party/libwebm/webm_parser/src/buffer_reader.cc +110 -0
- package/third_party/libwebm/webm_parser/src/byte_parser.h +144 -0
- package/third_party/libwebm/webm_parser/src/callback.cc +155 -0
- package/third_party/libwebm/webm_parser/src/chapter_atom_parser.h +42 -0
- package/third_party/libwebm/webm_parser/src/chapter_display_parser.h +34 -0
- package/third_party/libwebm/webm_parser/src/chapters_parser.h +28 -0
- package/third_party/libwebm/webm_parser/src/cluster_parser.h +48 -0
- package/third_party/libwebm/webm_parser/src/colour_parser.h +55 -0
- package/third_party/libwebm/webm_parser/src/content_enc_aes_settings_parser.h +32 -0
- package/third_party/libwebm/webm_parser/src/content_encoding_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/content_encodings_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/content_encryption_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/cue_point_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/cue_track_positions_parser.h +39 -0
- package/third_party/libwebm/webm_parser/src/cues_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/date_parser.cc +72 -0
- package/third_party/libwebm/webm_parser/src/date_parser.h +64 -0
- package/third_party/libwebm/webm_parser/src/ebml_parser.h +48 -0
- package/third_party/libwebm/webm_parser/src/edition_entry_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/element_parser.h +102 -0
- package/third_party/libwebm/webm_parser/src/file_reader.cc +142 -0
- package/third_party/libwebm/webm_parser/src/float_parser.cc +77 -0
- package/third_party/libwebm/webm_parser/src/float_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/id_element_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/id_element_parser.h +56 -0
- package/third_party/libwebm/webm_parser/src/id_parser.cc +75 -0
- package/third_party/libwebm/webm_parser/src/id_parser.h +45 -0
- package/third_party/libwebm/webm_parser/src/info_parser.h +44 -0
- package/third_party/libwebm/webm_parser/src/int_parser.h +121 -0
- package/third_party/libwebm/webm_parser/src/istream_reader.cc +133 -0
- package/third_party/libwebm/webm_parser/src/master_parser.cc +298 -0
- package/third_party/libwebm/webm_parser/src/master_parser.h +230 -0
- package/third_party/libwebm/webm_parser/src/master_value_parser.h +533 -0
- package/third_party/libwebm/webm_parser/src/mastering_metadata_parser.h +57 -0
- package/third_party/libwebm/webm_parser/src/parser.h +34 -0
- package/third_party/libwebm/webm_parser/src/parser_utils.cc +34 -0
- package/third_party/libwebm/webm_parser/src/parser_utils.h +64 -0
- package/third_party/libwebm/webm_parser/src/projection_parser.h +40 -0
- package/third_party/libwebm/webm_parser/src/recursive_parser.h +93 -0
- package/third_party/libwebm/webm_parser/src/seek_head_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/seek_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/segment_parser.cc +86 -0
- package/third_party/libwebm/webm_parser/src/segment_parser.h +53 -0
- package/third_party/libwebm/webm_parser/src/simple_tag_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/size_parser.cc +56 -0
- package/third_party/libwebm/webm_parser/src/size_parser.h +43 -0
- package/third_party/libwebm/webm_parser/src/skip_callback.h +63 -0
- package/third_party/libwebm/webm_parser/src/skip_parser.cc +59 -0
- package/third_party/libwebm/webm_parser/src/skip_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/slices_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/tag_parser.h +37 -0
- package/third_party/libwebm/webm_parser/src/tags_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/targets_parser.h +35 -0
- package/third_party/libwebm/webm_parser/src/time_slice_parser.h +30 -0
- package/third_party/libwebm/webm_parser/src/track_entry_parser.h +65 -0
- package/third_party/libwebm/webm_parser/src/tracks_parser.h +27 -0
- package/third_party/libwebm/webm_parser/src/unknown_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/unknown_parser.h +38 -0
- package/third_party/libwebm/webm_parser/src/var_int_parser.cc +71 -0
- package/third_party/libwebm/webm_parser/src/var_int_parser.h +56 -0
- package/third_party/libwebm/webm_parser/src/video_parser.h +122 -0
- package/third_party/libwebm/webm_parser/src/virtual_block_parser.cc +72 -0
- package/third_party/libwebm/webm_parser/src/virtual_block_parser.h +69 -0
- package/third_party/libwebm/webm_parser/src/void_parser.cc +49 -0
- package/third_party/libwebm/webm_parser/src/void_parser.h +41 -0
- package/third_party/libwebm/webm_parser/src/webm_parser.cc +282 -0
- package/third_party/range-source/LICENSE +21 -0
- package/third_party/range-source/README.md +8 -0
- package/third_party/range-source/include/range_source.h +395 -0
- 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
|