react-native-alpha-video 0.0.0-stage → 1.0.1
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 +908 -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 +90 -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 +1982 -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 +115 -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 +115 -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 +152 -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 +113 -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 +87 -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,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AlphaVideoSource.mm
|
|
3
|
+
* Reading URLs and data sources: the built-in URLSession fetcher, and the reader it feeds, the
|
|
4
|
+
* range-source add-on's through its C table, or without the add-on the basic input's download.
|
|
5
|
+
* A data source is read by the add-on, which the player finds at runtime.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#import "AlphaVideoInternal.h"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
#include <condition_variable>
|
|
12
|
+
#include <functional>
|
|
13
|
+
#include <mutex>
|
|
14
|
+
#include <string>
|
|
15
|
+
|
|
16
|
+
namespace {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Bytes handed from callbacks on any thread to the reader's fetch thread: a response, then data,
|
|
20
|
+
* then the end or an error. With flow control, the producer is paused while more than kHighBytes
|
|
21
|
+
* wait and resumed under kLowBytes.
|
|
22
|
+
*/
|
|
23
|
+
class Pipe {
|
|
24
|
+
public:
|
|
25
|
+
static constexpr size_t kHighBytes = 1024 * 1024;
|
|
26
|
+
static constexpr size_t kLowBytes = 256 * 1024;
|
|
27
|
+
|
|
28
|
+
/** Called under the pipe's lock with true to pause the producer, false to resume it. */
|
|
29
|
+
void setFlowControl(std::function<void(bool)> pause) {
|
|
30
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
31
|
+
pause_ = std::move(pause);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** `skip`: bytes of the data to drop first, for a server that answered from 0. */
|
|
35
|
+
void respond(const webm::SourceInfo& info, int64_t skip = 0) {
|
|
36
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
37
|
+
if (responded_ || done_) return;
|
|
38
|
+
responded_ = true;
|
|
39
|
+
info_ = info;
|
|
40
|
+
skip_ = skip;
|
|
41
|
+
changed_.notify_all();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void push(const uint8_t* data, size_t size) {
|
|
45
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
46
|
+
if (done_ || !responded_) return;
|
|
47
|
+
if (skip_ > 0) {
|
|
48
|
+
size_t dropped = static_cast<size_t>(std::min<int64_t>(skip_, static_cast<int64_t>(size)));
|
|
49
|
+
skip_ -= static_cast<int64_t>(dropped);
|
|
50
|
+
data += dropped;
|
|
51
|
+
size -= dropped;
|
|
52
|
+
}
|
|
53
|
+
if (size == 0) return;
|
|
54
|
+
buffer_.append(reinterpret_cast<const char*>(data), size);
|
|
55
|
+
if (pause_ && !paused_ && bufferedLocked() > kHighBytes) {
|
|
56
|
+
paused_ = true;
|
|
57
|
+
pause_(true);
|
|
58
|
+
}
|
|
59
|
+
changed_.notify_all();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** An empty error is the end of the data. Only the first call counts. */
|
|
63
|
+
void finish(const std::string& error) {
|
|
64
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
65
|
+
if (done_) return;
|
|
66
|
+
done_ = true;
|
|
67
|
+
error_ = error;
|
|
68
|
+
changed_.notify_all();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void cancel() { finish("Cancelled"); }
|
|
72
|
+
|
|
73
|
+
bool waitResponse(webm::SourceInfo& info, std::string& error) {
|
|
74
|
+
std::unique_lock<std::mutex> lock(mutex_);
|
|
75
|
+
changed_.wait(lock, [&] { return responded_ || done_; });
|
|
76
|
+
if (!responded_) {
|
|
77
|
+
error = error_.empty() ? "The source ended without a response" : error_;
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
info = info_;
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Bytes read, 0 at the end, or -1 with `error` set; the data before an error comes first. */
|
|
85
|
+
int64_t read(uint8_t* out, int64_t size, std::string& error) {
|
|
86
|
+
std::unique_lock<std::mutex> lock(mutex_);
|
|
87
|
+
changed_.wait(lock, [&] { return bufferedLocked() > 0 || done_; });
|
|
88
|
+
size_t available = bufferedLocked();
|
|
89
|
+
if (available > 0) {
|
|
90
|
+
size_t n = std::min(available, static_cast<size_t>(size));
|
|
91
|
+
memcpy(out, buffer_.data() + offset_, n);
|
|
92
|
+
offset_ += n;
|
|
93
|
+
if (offset_ == buffer_.size()) {
|
|
94
|
+
buffer_.clear();
|
|
95
|
+
offset_ = 0;
|
|
96
|
+
} else if (offset_ > kHighBytes) {
|
|
97
|
+
buffer_.erase(0, offset_);
|
|
98
|
+
offset_ = 0;
|
|
99
|
+
}
|
|
100
|
+
if (paused_ && bufferedLocked() < kLowBytes) {
|
|
101
|
+
paused_ = false;
|
|
102
|
+
pause_(false);
|
|
103
|
+
}
|
|
104
|
+
return static_cast<int64_t>(n);
|
|
105
|
+
}
|
|
106
|
+
if (!error_.empty()) {
|
|
107
|
+
error = error_;
|
|
108
|
+
return -1;
|
|
109
|
+
}
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private:
|
|
114
|
+
size_t bufferedLocked() const { return buffer_.size() - offset_; }
|
|
115
|
+
|
|
116
|
+
std::mutex mutex_;
|
|
117
|
+
std::condition_variable changed_;
|
|
118
|
+
std::function<void(bool)> pause_;
|
|
119
|
+
bool paused_ = false;
|
|
120
|
+
bool responded_ = false;
|
|
121
|
+
bool done_ = false;
|
|
122
|
+
webm::SourceInfo info_;
|
|
123
|
+
int64_t skip_ = 0;
|
|
124
|
+
std::string buffer_;
|
|
125
|
+
size_t offset_ = 0;
|
|
126
|
+
std::string error_;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
std::string stdString(NSString* text) {
|
|
130
|
+
return text ? std::string(text.UTF8String) : std::string();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
NSString* nsString(const std::string& text) {
|
|
134
|
+
return [NSString stringWithUTF8String:text.c_str()] ?: @"";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
std::string describe(NSError* error) {
|
|
138
|
+
return stdString(error.localizedDescription ?: @"The read failed");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
} // namespace
|
|
142
|
+
|
|
143
|
+
#pragma mark - The built-in URLSession fetcher
|
|
144
|
+
|
|
145
|
+
/** One task's pipe, and where its read starts. */
|
|
146
|
+
@interface AlphaVideoTaskState : NSObject {
|
|
147
|
+
@public
|
|
148
|
+
std::shared_ptr<Pipe> pipe;
|
|
149
|
+
int64_t position;
|
|
150
|
+
}
|
|
151
|
+
@end
|
|
152
|
+
|
|
153
|
+
@implementation AlphaVideoTaskState
|
|
154
|
+
@end
|
|
155
|
+
|
|
156
|
+
/** Routes a session's task callbacks to each task's pipe. Callbacks run on the session's queue. */
|
|
157
|
+
@interface AlphaVideoSessionDelegate : NSObject <NSURLSessionDataDelegate>
|
|
158
|
+
- (void)track:(NSURLSessionTask *)task state:(AlphaVideoTaskState *)state;
|
|
159
|
+
@end
|
|
160
|
+
|
|
161
|
+
@implementation AlphaVideoSessionDelegate {
|
|
162
|
+
// @synchronized (self)
|
|
163
|
+
NSMutableDictionary<NSNumber *, AlphaVideoTaskState *> *_tasks;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
- (instancetype)init {
|
|
167
|
+
if ((self = [super init])) _tasks = [NSMutableDictionary dictionary];
|
|
168
|
+
return self;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
- (void)track:(NSURLSessionTask *)task state:(AlphaVideoTaskState *)state {
|
|
172
|
+
@synchronized (self) {
|
|
173
|
+
_tasks[@(task.taskIdentifier)] = state;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
- (nullable AlphaVideoTaskState *)stateOf:(NSURLSessionTask *)task remove:(BOOL)remove {
|
|
178
|
+
@synchronized (self) {
|
|
179
|
+
AlphaVideoTaskState *state = _tasks[@(task.taskIdentifier)];
|
|
180
|
+
if (remove) [_tasks removeObjectForKey:@(task.taskIdentifier)];
|
|
181
|
+
return state;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
static int64_t AlphaVideoTotalFromContentRange(NSString *contentRange, int64_t *start) {
|
|
186
|
+
// "bytes 100-199/1000", "bytes 100-199/*" or, answering 416, "bytes */1000"
|
|
187
|
+
NSScanner *scanner = [NSScanner scannerWithString:contentRange ?: @""];
|
|
188
|
+
long long first = -1, total = -1;
|
|
189
|
+
if (![scanner scanString:@"bytes" intoString:nil]) return -1;
|
|
190
|
+
if (![scanner scanString:@"*" intoString:nil]) {
|
|
191
|
+
if (![scanner scanLongLong:&first]) return -1;
|
|
192
|
+
[scanner scanUpToString:@"/" intoString:nil];
|
|
193
|
+
}
|
|
194
|
+
if (start) *start = first;
|
|
195
|
+
if (![scanner scanString:@"/" intoString:nil] || ![scanner scanLongLong:&total]) return -1;
|
|
196
|
+
return total;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
- (void)URLSession:(NSURLSession *)session
|
|
200
|
+
dataTask:(NSURLSessionDataTask *)dataTask
|
|
201
|
+
didReceiveResponse:(NSURLResponse *)response
|
|
202
|
+
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
|
|
203
|
+
AlphaVideoTaskState *state = [self stateOf:dataTask remove:NO];
|
|
204
|
+
if (!state) {
|
|
205
|
+
completionHandler(NSURLSessionResponseCancel);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
NSHTTPURLResponse *http = [response isKindOfClass:[NSHTTPURLResponse class]] ? (NSHTTPURLResponse *)response : nil;
|
|
209
|
+
webm::SourceInfo info;
|
|
210
|
+
info.etag = stdString([http valueForHTTPHeaderField:@"ETag"]);
|
|
211
|
+
info.lastModified = stdString([http valueForHTTPHeaderField:@"Last-Modified"]);
|
|
212
|
+
NSString *encoding = [http valueForHTTPHeaderField:@"Content-Encoding"];
|
|
213
|
+
if (encoding.length > 0 && [encoding caseInsensitiveCompare:@"identity"] != NSOrderedSame) {
|
|
214
|
+
// URLSession decodes it, and the offsets would be into the decoded bytes
|
|
215
|
+
state->pipe->finish(stdString([NSString stringWithFormat:@"%@ came compressed (%@)", response.URL, encoding]));
|
|
216
|
+
completionHandler(NSURLSessionResponseCancel);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
NSInteger status = http ? http.statusCode : 200;
|
|
220
|
+
NSString *contentRange = [http valueForHTTPHeaderField:@"Content-Range"];
|
|
221
|
+
if (status == 206) {
|
|
222
|
+
int64_t start = -1;
|
|
223
|
+
info.size = AlphaVideoTotalFromContentRange(contentRange, &start);
|
|
224
|
+
if (start != state->position) {
|
|
225
|
+
state->pipe->finish(stdString([NSString stringWithFormat:@"Asked %@ for bytes from %lld and got %@",
|
|
226
|
+
response.URL, (long long)state->position, contentRange]));
|
|
227
|
+
completionHandler(NSURLSessionResponseCancel);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
state->pipe->respond(info);
|
|
231
|
+
} else if (status == 200) {
|
|
232
|
+
// No ranges: the whole file, read past the bytes before the position
|
|
233
|
+
info.size = response.expectedContentLength >= 0 ? response.expectedContentLength : -1;
|
|
234
|
+
state->pipe->respond(info, state->position);
|
|
235
|
+
} else if (status == 416) {
|
|
236
|
+
// At or past the end: a read that ends at once
|
|
237
|
+
info.size = AlphaVideoTotalFromContentRange(contentRange, nullptr);
|
|
238
|
+
state->pipe->respond(info);
|
|
239
|
+
state->pipe->finish("");
|
|
240
|
+
completionHandler(NSURLSessionResponseCancel);
|
|
241
|
+
return;
|
|
242
|
+
} else {
|
|
243
|
+
state->pipe->finish(stdString([NSString stringWithFormat:@"HTTP %ld for %@", (long)status, response.URL]));
|
|
244
|
+
completionHandler(NSURLSessionResponseCancel);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
completionHandler(NSURLSessionResponseAllow);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
|
|
251
|
+
AlphaVideoTaskState *state = [self stateOf:dataTask remove:NO];
|
|
252
|
+
if (!state) return;
|
|
253
|
+
[data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange range, BOOL *stop) {
|
|
254
|
+
state->pipe->push(static_cast<const uint8_t *>(bytes), range.length);
|
|
255
|
+
}];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
|
|
259
|
+
AlphaVideoTaskState *state = [self stateOf:task remove:YES];
|
|
260
|
+
if (!state) return;
|
|
261
|
+
state->pipe->finish(error ? describe(error) : "");
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@end
|
|
265
|
+
|
|
266
|
+
namespace {
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Reads a URL with URLSession: a `Range: bytes=N-` request per open, kept open as the reader
|
|
270
|
+
* reads on, and suspended while the reader has a megabyte waiting.
|
|
271
|
+
*/
|
|
272
|
+
class URLSessionUpstream : public webm::Upstream {
|
|
273
|
+
public:
|
|
274
|
+
URLSessionUpstream(NSURL* url, NSDictionary<NSString*, NSString*>* headers)
|
|
275
|
+
: url_(url), headers_([headers copy]), delegate_([AlphaVideoSessionDelegate new]) {
|
|
276
|
+
NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
277
|
+
// The reader's store is the cache
|
|
278
|
+
configuration.URLCache = nil;
|
|
279
|
+
configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
|
|
280
|
+
configuration.timeoutIntervalForRequest = 30;
|
|
281
|
+
session_ = [NSURLSession sessionWithConfiguration:configuration delegate:delegate_ delegateQueue:nil];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
~URLSessionUpstream() override {
|
|
285
|
+
close();
|
|
286
|
+
// The session holds its delegate until invalidated
|
|
287
|
+
[session_ invalidateAndCancel];
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
bool open(int64_t position, webm::SourceInfo& info, std::string& error) override {
|
|
291
|
+
close();
|
|
292
|
+
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url_];
|
|
293
|
+
[headers_ enumerateKeysAndObjectsUsingBlock:^(NSString* name, NSString* value, BOOL* stop) {
|
|
294
|
+
[request setValue:value forHTTPHeaderField:name];
|
|
295
|
+
}];
|
|
296
|
+
// Offsets are into the file as stored, so no transparent gzip
|
|
297
|
+
[request setValue:@"identity" forHTTPHeaderField:@"Accept-Encoding"];
|
|
298
|
+
[request setValue:[NSString stringWithFormat:@"bytes=%lld-", (long long)position] forHTTPHeaderField:@"Range"];
|
|
299
|
+
NSURLSessionDataTask* task = [session_ dataTaskWithRequest:request];
|
|
300
|
+
|
|
301
|
+
auto pipe = std::make_shared<Pipe>();
|
|
302
|
+
pipe->setFlowControl([task](bool pause) {
|
|
303
|
+
if (pause) [task suspend];
|
|
304
|
+
else [task resume];
|
|
305
|
+
});
|
|
306
|
+
{
|
|
307
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
308
|
+
if (cancelled_) {
|
|
309
|
+
error = "Cancelled";
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
task_ = task;
|
|
313
|
+
pipe_ = pipe;
|
|
314
|
+
}
|
|
315
|
+
AlphaVideoTaskState* state = [AlphaVideoTaskState new];
|
|
316
|
+
state->pipe = pipe;
|
|
317
|
+
state->position = position;
|
|
318
|
+
[delegate_ track:task state:state];
|
|
319
|
+
[task resume];
|
|
320
|
+
return pipe->waitResponse(info, error);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
int64_t read(uint8_t* out, int64_t size, std::string& error) override {
|
|
324
|
+
std::shared_ptr<Pipe> pipe = currentPipe();
|
|
325
|
+
if (!pipe) {
|
|
326
|
+
error = "Not open";
|
|
327
|
+
return -1;
|
|
328
|
+
}
|
|
329
|
+
return pipe->read(out, size, error);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
void close() override {
|
|
333
|
+
NSURLSessionDataTask* task;
|
|
334
|
+
std::shared_ptr<Pipe> pipe;
|
|
335
|
+
{
|
|
336
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
337
|
+
task = task_;
|
|
338
|
+
pipe = std::move(pipe_);
|
|
339
|
+
task_ = nil;
|
|
340
|
+
}
|
|
341
|
+
if (pipe) pipe->cancel();
|
|
342
|
+
[task cancel];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
void cancel() override {
|
|
346
|
+
{
|
|
347
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
348
|
+
cancelled_ = true;
|
|
349
|
+
}
|
|
350
|
+
close();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private:
|
|
354
|
+
std::shared_ptr<Pipe> currentPipe() {
|
|
355
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
356
|
+
return pipe_;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
NSURL* const url_;
|
|
360
|
+
NSDictionary<NSString*, NSString*>* const headers_;
|
|
361
|
+
AlphaVideoSessionDelegate* const delegate_;
|
|
362
|
+
NSURLSession* session_;
|
|
363
|
+
std::mutex mutex_;
|
|
364
|
+
NSURLSessionDataTask* task_ = nil;
|
|
365
|
+
std::shared_ptr<Pipe> pipe_;
|
|
366
|
+
bool cancelled_ = false;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
} // namespace
|
|
370
|
+
|
|
371
|
+
#pragma mark - AlphaVideoSourceReader
|
|
372
|
+
|
|
373
|
+
NSString *const AlphaVideoErrorNoSourceModule = @"NO_SOURCE_MODULE";
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* The add-on's class, as the player uses it (range-source's RangeSource.h). The player doesn't
|
|
377
|
+
* link the add-on, so it finds the class by name.
|
|
378
|
+
*/
|
|
379
|
+
@protocol AlphaVideoRangeSourceAddOn
|
|
380
|
+
@property (class, nonatomic, readonly) const void *plugin;
|
|
381
|
+
+ (BOOL)getUpstream:(void *)upstream
|
|
382
|
+
forDataSourceNamed:(NSString *)name
|
|
383
|
+
URL:(NSURL *)url
|
|
384
|
+
headers:(NSDictionary<NSString *, NSString *> *)headers;
|
|
385
|
+
@end
|
|
386
|
+
|
|
387
|
+
static Class<AlphaVideoRangeSourceAddOn> AlphaVideoRangeSourceClass(void) {
|
|
388
|
+
Class addOn = NSClassFromString(@"RangeSource");
|
|
389
|
+
return [addOn respondsToSelector:@selector(plugin)]
|
|
390
|
+
&& [addOn respondsToSelector:@selector(getUpstream:forDataSourceNamed:URL:headers:)]
|
|
391
|
+
? addOn : Nil;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const RangeSourcePlugin *AlphaVideoRangeSourcePlugin(void) {
|
|
395
|
+
static const RangeSourcePlugin *plugin = [] {
|
|
396
|
+
Class<AlphaVideoRangeSourceAddOn> addOn = AlphaVideoRangeSourceClass();
|
|
397
|
+
if (!addOn) return static_cast<const RangeSourcePlugin *>(nullptr);
|
|
398
|
+
std::string why;
|
|
399
|
+
const RangeSourcePlugin *usable = webm::usablePlugin(static_cast<const RangeSourcePlugin *>([addOn plugin]), why);
|
|
400
|
+
if (!usable) NSLog(@"[AlphaVideo] Not using range-source: %s", why.c_str());
|
|
401
|
+
return usable;
|
|
402
|
+
}();
|
|
403
|
+
return plugin;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Caches/alpha-video on disk, or the memory store's name
|
|
407
|
+
static NSString *const AlphaVideoStoreName = @"alpha-video";
|
|
408
|
+
|
|
409
|
+
static std::shared_ptr<webm_rs::Store> AlphaVideoStore(const RangeSourcePlugin *plugin, NSString *storage,
|
|
410
|
+
int64_t maxStorageBytes) {
|
|
411
|
+
if ([storage isEqualToString:@"disk"]) {
|
|
412
|
+
NSString *caches = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
|
|
413
|
+
return webm_rs::Store::disk(plugin, stdString([caches stringByAppendingPathComponent:AlphaVideoStoreName]),
|
|
414
|
+
maxStorageBytes);
|
|
415
|
+
}
|
|
416
|
+
if ([storage isEqualToString:@"memory"]) return webm_rs::Store::memory(plugin, stdString(AlphaVideoStoreName), maxStorageBytes);
|
|
417
|
+
return nullptr;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
@implementation AlphaVideoSourceReader {
|
|
421
|
+
std::shared_ptr<webm::SourceReader> _reader;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
+ (instancetype)openURL:(NSURL *)url
|
|
425
|
+
dataSource:(NSString *)dataSource
|
|
426
|
+
headers:(NSDictionary<NSString *, NSString *> *)headers
|
|
427
|
+
storage:(NSString *)storage
|
|
428
|
+
key:(NSString *)key
|
|
429
|
+
maxStorageBytes:(int64_t)maxStorageBytes
|
|
430
|
+
error:(NSString **)error {
|
|
431
|
+
const RangeSourcePlugin *plugin = AlphaVideoRangeSourcePlugin();
|
|
432
|
+
std::string openError;
|
|
433
|
+
std::shared_ptr<webm::SourceReader> reader;
|
|
434
|
+
if (dataSource) {
|
|
435
|
+
RangeSourceUpstream upstream{};
|
|
436
|
+
if (!plugin || ![AlphaVideoRangeSourceClass() getUpstream:&upstream forDataSourceNamed:dataSource URL:url
|
|
437
|
+
headers:headers]) {
|
|
438
|
+
if (error) *error = [NSString stringWithFormat:@"No data source is registered as \"%@\" (RangeDataSources)", dataSource];
|
|
439
|
+
return nil;
|
|
440
|
+
}
|
|
441
|
+
reader = webm_rs::RangeReader::open(plugin, upstream, AlphaVideoStore(plugin, storage, maxStorageBytes),
|
|
442
|
+
stdString(key), webm_rs::ReaderOptions(), openError);
|
|
443
|
+
} else if ([url.scheme isEqualToString:@"https"] || [url.scheme isEqualToString:@"http"]) {
|
|
444
|
+
auto upstream = std::make_unique<URLSessionUpstream>(url, headers);
|
|
445
|
+
reader = plugin
|
|
446
|
+
? std::shared_ptr<webm::SourceReader>(webm_rs::RangeReader::open(
|
|
447
|
+
plugin, std::move(upstream), AlphaVideoStore(plugin, storage, maxStorageBytes), stdString(key),
|
|
448
|
+
webm_rs::ReaderOptions(), openError))
|
|
449
|
+
: webm_rs::DownloadReader::open(std::move(upstream), stdString(NSTemporaryDirectory()), openError);
|
|
450
|
+
} else {
|
|
451
|
+
if (error) *error = [NSString stringWithFormat:@"Not an http(s) URL: %@", url];
|
|
452
|
+
return nil;
|
|
453
|
+
}
|
|
454
|
+
if (!reader) {
|
|
455
|
+
if (error) *error = nsString(openError);
|
|
456
|
+
return nil;
|
|
457
|
+
}
|
|
458
|
+
AlphaVideoSourceReader *result = [AlphaVideoSourceReader new];
|
|
459
|
+
result->_reader = std::move(reader);
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
- (BOOL)fetchAll:(NSString **)error {
|
|
464
|
+
if (_reader->fetchAll()) return YES;
|
|
465
|
+
if (error) {
|
|
466
|
+
std::string message = _reader->lastError();
|
|
467
|
+
*error = message.empty() ? @"Reading the video failed" : nsString(message);
|
|
468
|
+
}
|
|
469
|
+
return NO;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
- (std::shared_ptr<webm::SourceReader>)rangeReader {
|
|
473
|
+
return _reader;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
@end
|