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,95 @@
|
|
|
1
|
+
package dev.mediacache.alphavideo;
|
|
2
|
+
|
|
3
|
+
import java.nio.ByteBuffer;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* JNI bridge to C++ WebMAlphaPlayer core
|
|
7
|
+
* Provides high-performance VP9+Alpha WebM playback
|
|
8
|
+
*/
|
|
9
|
+
public class WebMAlphaPlayerNative {
|
|
10
|
+
|
|
11
|
+
static {
|
|
12
|
+
System.loadLibrary("alphavideo");
|
|
13
|
+
AlphaVideoCodecs.discover();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Listener for player events
|
|
18
|
+
*/
|
|
19
|
+
public interface PlayerListener {
|
|
20
|
+
void onLoad(int totalFrames, int width, int height);
|
|
21
|
+
void onFrame(int frameIndex, ByteBuffer yPlane, ByteBuffer uPlane, ByteBuffer vPlane, ByteBuffer aPlane, int width, int height);
|
|
22
|
+
void onPlay();
|
|
23
|
+
void onPause();
|
|
24
|
+
void onStop();
|
|
25
|
+
void onLoop();
|
|
26
|
+
void onEnd();
|
|
27
|
+
/** @param code {@link AlphaVideoView#ERROR_NO_DECODER}, or null */
|
|
28
|
+
void onError(String error, String code);
|
|
29
|
+
void onPreloadComplete(int totalFrames, double timeMs);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Player lifecycle
|
|
33
|
+
public static native long nativeCreate(
|
|
34
|
+
int decodeThreads,
|
|
35
|
+
int cacheSize,
|
|
36
|
+
boolean preloadAllFrames,
|
|
37
|
+
boolean loopPlayback,
|
|
38
|
+
double playbackSpeed,
|
|
39
|
+
String mode, // Playback mode: "preload", "stream", or "streamAndPreload"
|
|
40
|
+
int streamPrefetchAhead // Frames decoded ahead of the shown one (default: 8)
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
public static native void nativeDestroy(long playerId);
|
|
44
|
+
|
|
45
|
+
// Callbacks
|
|
46
|
+
public static native void nativeSetListener(long playerId, PlayerListener listener);
|
|
47
|
+
|
|
48
|
+
// Loading
|
|
49
|
+
public static native boolean nativeLoadFromFile(long playerId, String path);
|
|
50
|
+
/** Bytes [offset, offset + length) of fd; length -1 means to end of file. fd is duplicated. */
|
|
51
|
+
public static native boolean nativeLoadFromFd(long playerId, int fd, long offset, long length);
|
|
52
|
+
/** A {@link SourceReader} reference; the player takes a reference of its own. */
|
|
53
|
+
static native boolean nativeLoadFromReader(long playerId, long reader);
|
|
54
|
+
public static native boolean nativeLoadFromBytes(long playerId, byte[] data);
|
|
55
|
+
public static native void nativeUnload(long playerId);
|
|
56
|
+
|
|
57
|
+
// Playback control
|
|
58
|
+
public static native void nativePlay(long playerId);
|
|
59
|
+
public static native void nativePause(long playerId);
|
|
60
|
+
public static native void nativeStop(long playerId);
|
|
61
|
+
public static native void nativeSeekToFrame(long playerId, int frameIndex);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Changes playback rate without moving the playhead. Safe mid-playback.
|
|
65
|
+
*/
|
|
66
|
+
public static native void nativeSetPlaybackSpeed(long playerId, double speed);
|
|
67
|
+
public static native void nativeSetVerbose(long playerId, boolean verbose);
|
|
68
|
+
public static native void nativeSeekToTime(long playerId, double seconds);
|
|
69
|
+
|
|
70
|
+
// State queries
|
|
71
|
+
public static native boolean nativeIsLoaded(long playerId);
|
|
72
|
+
public static native boolean nativeIsPlaying(long playerId);
|
|
73
|
+
public static native int nativeGetCurrentFrame(long playerId);
|
|
74
|
+
public static native int nativeGetTotalFrames(long playerId);
|
|
75
|
+
public static native int nativeGetWidth(long playerId);
|
|
76
|
+
public static native int nativeGetHeight(long playerId);
|
|
77
|
+
public static native double nativeGetDuration(long playerId);
|
|
78
|
+
public static native double nativeGetFrameRate(long playerId);
|
|
79
|
+
/** The loaded clip's YUV to RGB for the shader: a column-major mat4, or null if no player. */
|
|
80
|
+
public static native float[] nativeGetYuvToRgb(long playerId);
|
|
81
|
+
/** The decoder for the loaded clip, "libvpx" or "dav1d", or null if no player. */
|
|
82
|
+
public static native String nativeGetDecoderName(long playerId);
|
|
83
|
+
/** The same matrix for a stream's colour range and matrix (YuvToRgb.h), by the core's rules. */
|
|
84
|
+
public static native float[] nativeYuvToRgbFor(int colorRange, int colorSpace, int width, int height);
|
|
85
|
+
|
|
86
|
+
// Direct frame access
|
|
87
|
+
public static native WebMFrame nativeGetFrame(long playerId, int frameIndex);
|
|
88
|
+
|
|
89
|
+
// Statistics
|
|
90
|
+
public static native long[] nativeGetStats(long playerId);
|
|
91
|
+
public static native void nativeResetStats(long playerId);
|
|
92
|
+
|
|
93
|
+
/** The registered software decoders, e.g. "libvpx v1.14.0, dav1d 1.5.1"; empty with none. */
|
|
94
|
+
public static native String nativeGetLibraryVersions();
|
|
95
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
package dev.mediacache.alphavideo;
|
|
2
|
+
|
|
3
|
+
import java.nio.ByteBuffer;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents a decoded YUVA frame from the C++ player
|
|
7
|
+
* Uses direct ByteBuffers for zero-copy access to plane data
|
|
8
|
+
*/
|
|
9
|
+
public class WebMFrame {
|
|
10
|
+
|
|
11
|
+
private final ByteBuffer yPlane;
|
|
12
|
+
private final ByteBuffer uPlane;
|
|
13
|
+
private final ByteBuffer vPlane;
|
|
14
|
+
private final ByteBuffer aPlane;
|
|
15
|
+
private final int width;
|
|
16
|
+
private final int height;
|
|
17
|
+
private final int frameIndex;
|
|
18
|
+
private final double timestamp;
|
|
19
|
+
|
|
20
|
+
public WebMFrame(
|
|
21
|
+
ByteBuffer yPlane,
|
|
22
|
+
ByteBuffer uPlane,
|
|
23
|
+
ByteBuffer vPlane,
|
|
24
|
+
ByteBuffer aPlane,
|
|
25
|
+
int width,
|
|
26
|
+
int height,
|
|
27
|
+
int frameIndex,
|
|
28
|
+
double timestamp
|
|
29
|
+
) {
|
|
30
|
+
this.yPlane = yPlane;
|
|
31
|
+
this.uPlane = uPlane;
|
|
32
|
+
this.vPlane = vPlane;
|
|
33
|
+
this.aPlane = aPlane;
|
|
34
|
+
this.width = width;
|
|
35
|
+
this.height = height;
|
|
36
|
+
this.frameIndex = frameIndex;
|
|
37
|
+
this.timestamp = timestamp;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public ByteBuffer getYPlane() { return yPlane; }
|
|
41
|
+
public ByteBuffer getUPlane() { return uPlane; }
|
|
42
|
+
public ByteBuffer getVPlane() { return vPlane; }
|
|
43
|
+
public ByteBuffer getAPlane() { return aPlane; }
|
|
44
|
+
|
|
45
|
+
public int getWidth() { return width; }
|
|
46
|
+
public int getHeight() { return height; }
|
|
47
|
+
public int getFrameIndex() { return frameIndex; }
|
|
48
|
+
public double getTimestamp() { return timestamp; }
|
|
49
|
+
|
|
50
|
+
// Convenience getters for plane sizes
|
|
51
|
+
public int getYSize() { return width * height; }
|
|
52
|
+
public int getUVSize() { return ((width + 1) / 2) * ((height + 1) / 2); }
|
|
53
|
+
public int getASize() { return width * height; }
|
|
54
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
package dev.mediacache.alphavideo;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.content.res.AssetFileDescriptor;
|
|
5
|
+
import android.content.res.Resources;
|
|
6
|
+
import android.net.Uri;
|
|
7
|
+
import android.os.ParcelFileDescriptor;
|
|
8
|
+
|
|
9
|
+
import java.io.File;
|
|
10
|
+
import java.io.FileNotFoundException;
|
|
11
|
+
import java.io.IOException;
|
|
12
|
+
import java.util.regex.Pattern;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A local video the player can read in place: a file, an APK asset, a raw resource, or a
|
|
16
|
+
* content:// URI.
|
|
17
|
+
*
|
|
18
|
+
* Every local kind opens as an {@link AssetFileDescriptor} (descriptor + byte range), which
|
|
19
|
+
* native code reads directly, so nothing is copied out first. A URL or an app's data source is read
|
|
20
|
+
* through a {@link SourceReader} instead, by range as it plays.
|
|
21
|
+
*/
|
|
22
|
+
final class WebMSource {
|
|
23
|
+
|
|
24
|
+
private enum Kind { FILE, ASSET, RAW, CONTENT, READER }
|
|
25
|
+
|
|
26
|
+
private static final String ASSET_SCHEME = "asset://";
|
|
27
|
+
// What Image.resolveAssetSource(require(...)) gives in a release build: a res/raw name
|
|
28
|
+
private static final Pattern RAW_RESOURCE_NAME = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
|
|
29
|
+
|
|
30
|
+
private final Kind kind;
|
|
31
|
+
private final String location;
|
|
32
|
+
// READER only
|
|
33
|
+
private final SourceReader reader;
|
|
34
|
+
|
|
35
|
+
private WebMSource(Kind kind, String location) {
|
|
36
|
+
this(kind, location, null);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private WebMSource(Kind kind, String location, SourceReader reader) {
|
|
40
|
+
this.kind = kind;
|
|
41
|
+
this.location = location;
|
|
42
|
+
this.reader = reader;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static WebMSource file(String path) {
|
|
46
|
+
return new WebMSource(Kind.FILE, path);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** {@code uri} read through {@code reader}. */
|
|
50
|
+
static WebMSource reader(String uri, SourceReader reader) {
|
|
51
|
+
return new WebMSource(Kind.READER, uri, reader);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Null unless this is read through a reader, not {@link #open}. */
|
|
55
|
+
SourceReader reader() {
|
|
56
|
+
return reader;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Parses {@code file:///abs/path}, {@code /abs/path}, {@code asset://relative/path},
|
|
61
|
+
* {@code content://...}, or a bare res/raw resource name.
|
|
62
|
+
*
|
|
63
|
+
* @throws IllegalArgumentException for anything else
|
|
64
|
+
*/
|
|
65
|
+
static WebMSource parse(String uri) {
|
|
66
|
+
if (uri.startsWith(ASSET_SCHEME)) {
|
|
67
|
+
String path = Uri.decode(uri.substring(ASSET_SCHEME.length()));
|
|
68
|
+
while (path.startsWith("/")) path = path.substring(1);
|
|
69
|
+
if (path.isEmpty()) throw new IllegalArgumentException("Empty asset path: " + uri);
|
|
70
|
+
return new WebMSource(Kind.ASSET, path);
|
|
71
|
+
}
|
|
72
|
+
if (uri.startsWith("content://")) {
|
|
73
|
+
return new WebMSource(Kind.CONTENT, uri);
|
|
74
|
+
}
|
|
75
|
+
if (uri.startsWith("file://")) {
|
|
76
|
+
String path = Uri.parse(uri).getPath();
|
|
77
|
+
if (path == null || path.isEmpty()) throw new IllegalArgumentException("Bad file URI: " + uri);
|
|
78
|
+
return file(path);
|
|
79
|
+
}
|
|
80
|
+
if (uri.startsWith("/")) {
|
|
81
|
+
return file(uri);
|
|
82
|
+
}
|
|
83
|
+
if (RAW_RESOURCE_NAME.matcher(uri).matches()) {
|
|
84
|
+
return new WebMSource(Kind.RAW, uri);
|
|
85
|
+
}
|
|
86
|
+
throw new IllegalArgumentException(
|
|
87
|
+
"Unsupported source '" + uri + "'. Use https://, file://, an absolute path, asset:// or content://");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** The caller closes the descriptor; native code duplicates it if it needs to keep reading. */
|
|
91
|
+
AssetFileDescriptor open(Context context) throws IOException {
|
|
92
|
+
switch (kind) {
|
|
93
|
+
case ASSET:
|
|
94
|
+
return openAsset(context);
|
|
95
|
+
case RAW:
|
|
96
|
+
return openRawResource(context);
|
|
97
|
+
case READER:
|
|
98
|
+
throw new IllegalStateException(location + " is read through its SourceReader");
|
|
99
|
+
case CONTENT: {
|
|
100
|
+
AssetFileDescriptor afd = context.getContentResolver()
|
|
101
|
+
.openAssetFileDescriptor(Uri.parse(location), "r");
|
|
102
|
+
if (afd == null) throw new FileNotFoundException("Cannot open " + location);
|
|
103
|
+
return afd;
|
|
104
|
+
}
|
|
105
|
+
default: {
|
|
106
|
+
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
|
|
107
|
+
new File(location), ParcelFileDescriptor.MODE_READ_ONLY);
|
|
108
|
+
return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private AssetFileDescriptor openAsset(Context context) throws IOException {
|
|
114
|
+
try {
|
|
115
|
+
return context.getAssets().openFd(location);
|
|
116
|
+
} catch (FileNotFoundException e) {
|
|
117
|
+
if (!assetExists(context)) throw new FileNotFoundException("Asset not found: " + location);
|
|
118
|
+
// openFd only works on assets stored uncompressed in the APK.
|
|
119
|
+
throw new IOException("Asset " + location + " is compressed in the APK; add its extension to "
|
|
120
|
+
+ "android.androidResources.noCompress in the app's build.gradle");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private AssetFileDescriptor openRawResource(Context context) throws IOException {
|
|
125
|
+
Resources resources = context.getResources();
|
|
126
|
+
int id = resources.getIdentifier(location, "raw", context.getPackageName());
|
|
127
|
+
if (id == 0) throw new FileNotFoundException("No res/raw resource named " + location);
|
|
128
|
+
try {
|
|
129
|
+
return resources.openRawResourceFd(id);
|
|
130
|
+
} catch (Resources.NotFoundException e) {
|
|
131
|
+
// openRawResourceFd only works on resources stored uncompressed in the APK.
|
|
132
|
+
throw new IOException("Resource res/raw/" + location + " is compressed in the APK; add its "
|
|
133
|
+
+ "extension to android.androidResources.noCompress in the app's build.gradle");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private boolean assetExists(Context context) {
|
|
138
|
+
int slash = location.lastIndexOf('/');
|
|
139
|
+
String dir = slash < 0 ? "" : location.substring(0, slash);
|
|
140
|
+
String name = location.substring(slash + 1);
|
|
141
|
+
try {
|
|
142
|
+
String[] names = context.getAssets().list(dir);
|
|
143
|
+
if (names == null) return false;
|
|
144
|
+
for (String n : names) {
|
|
145
|
+
if (n.equals(name)) return true;
|
|
146
|
+
}
|
|
147
|
+
} catch (IOException ignored) {
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@Override
|
|
153
|
+
public String toString() {
|
|
154
|
+
switch (kind) {
|
|
155
|
+
case ASSET: return ASSET_SCHEME + location;
|
|
156
|
+
case RAW: return "res/raw/" + location;
|
|
157
|
+
default: return location;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
package dev.mediacache.alphavideo;
|
|
2
|
+
|
|
3
|
+
import android.net.Uri;
|
|
4
|
+
|
|
5
|
+
import java.io.IOException;
|
|
6
|
+
import java.util.Map;
|
|
7
|
+
|
|
8
|
+
import dev.mediacache.rangesource.RangeDataSource;
|
|
9
|
+
import dev.mediacache.rangesource.RangeDataSources;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* An app's data source, registered with range-source's {@code RangeDataSources}, as a
|
|
13
|
+
* {@link Fetcher}. The only class that touches the add-on's types: load it only once
|
|
14
|
+
* {@link RangeSourceLink#available()}, as an app may leave the add-on out.
|
|
15
|
+
*/
|
|
16
|
+
final class AppDataSource implements Fetcher {
|
|
17
|
+
|
|
18
|
+
private final RangeDataSource source;
|
|
19
|
+
|
|
20
|
+
private AppDataSource(RangeDataSource source) {
|
|
21
|
+
this.source = source;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A new source from the factory registered under {@code name}, or null if there's none. */
|
|
25
|
+
static Fetcher create(String name) {
|
|
26
|
+
RangeDataSource.Factory factory = RangeDataSources.get(name);
|
|
27
|
+
return factory != null ? new AppDataSource(factory.create()) : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Override
|
|
31
|
+
public Info open(Uri uri, long position, Map<String, String> headers) throws IOException {
|
|
32
|
+
RangeDataSource.Info info = source.open(uri, position, headers);
|
|
33
|
+
return new Info(info.size, info.etag, info.lastModified);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Override
|
|
37
|
+
public int read(byte[] buffer, int offset, int length) throws IOException {
|
|
38
|
+
return source.read(buffer, offset, length);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Override
|
|
42
|
+
public void close() throws IOException {
|
|
43
|
+
source.close();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Override
|
|
47
|
+
public void cancel() {
|
|
48
|
+
source.cancel();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// dev.mediacache:alpha-video-vpx: libvpx, VP8 and VP9 in software for alpha-video's C++ core. alpha-video
|
|
2
|
+
// finds it on the classpath (AlphaVideoCodecs), so adding the dependency is all an app does.
|
|
3
|
+
|
|
4
|
+
apply plugin: 'com.android.library'
|
|
5
|
+
|
|
6
|
+
def safeExtGet(name, fallback) {
|
|
7
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : fallback
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
group = 'dev.mediacache'
|
|
11
|
+
version = rootProject.version
|
|
12
|
+
|
|
13
|
+
android {
|
|
14
|
+
namespace 'dev.mediacache.alphavideo.vpx'
|
|
15
|
+
compileSdk safeExtGet('compileSdkVersion', 36)
|
|
16
|
+
ndkVersion safeExtGet('ndkVersion', '27.1.12297006')
|
|
17
|
+
|
|
18
|
+
defaultConfig {
|
|
19
|
+
minSdk safeExtGet('minSdkVersion', 24)
|
|
20
|
+
consumerProguardFiles 'consumer-rules.pro'
|
|
21
|
+
|
|
22
|
+
externalNativeBuild {
|
|
23
|
+
cmake {
|
|
24
|
+
cppFlags '-std=c++17 -O3'
|
|
25
|
+
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
|
|
26
|
+
// Its own C++ runtime: the core talks to it through C, and a second
|
|
27
|
+
// libc++_shared.so beside the core's would clash in the app
|
|
28
|
+
arguments '-DANDROID_STL=c++_static'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
externalNativeBuild {
|
|
34
|
+
cmake {
|
|
35
|
+
path 'src/main/cpp/CMakeLists.txt'
|
|
36
|
+
version '3.22.1'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
compileOptions {
|
|
41
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
42
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
publishing {
|
|
46
|
+
singleVariant('release') {
|
|
47
|
+
withSourcesJar()
|
|
48
|
+
withJavadocJar()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
repositories {
|
|
54
|
+
google()
|
|
55
|
+
mavenCentral()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
dependencies {
|
|
59
|
+
api rootProject
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
ext.publishArtifactId = 'alpha-video-vpx'
|
|
63
|
+
ext.publishDescription = 'libvpx for alpha-video: VP8 and VP9 transparent video in software, for files and devices MediaCodec can\'t take, preload, and many players at once.'
|
|
64
|
+
ext.publishLicenses = [
|
|
65
|
+
[name: 'BSD-3-Clause (bundled libvpx)', url: 'https://chromium.googlesource.com/webm/libvpx/+/refs/tags/v1.14.0/LICENSE'],
|
|
66
|
+
]
|
|
67
|
+
apply from: rootProject.file('publish.gradle')
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# libalphavideo_vpx.so: libvpx and its decoder plugin. It doesn't link the core: VpxCodec hands the
|
|
2
|
+
# core the plugin list's address (AlphaVideoCodecs.java).
|
|
3
|
+
cmake_minimum_required(VERSION 3.22.1)
|
|
4
|
+
project(alphavideo_vpx)
|
|
5
|
+
|
|
6
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
7
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
8
|
+
|
|
9
|
+
get_filename_component(MODULE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../.." ABSOLUTE)
|
|
10
|
+
# libvpx, prebuilt per ABI (scripts/build_codecs_android.sh)
|
|
11
|
+
set(CODECS_ROOT "${MODULE_ROOT}/prebuilt/android/${ANDROID_ABI}")
|
|
12
|
+
|
|
13
|
+
add_library(alphavideo_vpx SHARED
|
|
14
|
+
${MODULE_ROOT}/codecs/vpx/VpxDecoderPlugin.cpp
|
|
15
|
+
VpxCodec_jni.cpp
|
|
16
|
+
)
|
|
17
|
+
target_include_directories(alphavideo_vpx PRIVATE
|
|
18
|
+
${MODULE_ROOT}/cpp
|
|
19
|
+
${MODULE_ROOT}/codecs/vpx
|
|
20
|
+
${MODULE_ROOT}/prebuilt/include
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Google Play requires 16 KB-aligned segments for Android 15+; NDK r27 and older link 4 KB by default.
|
|
24
|
+
target_link_options(alphavideo_vpx PRIVATE "-Wl,-z,max-page-size=16384")
|
|
25
|
+
# libvpx stays private to this library, so an app that ships its own copy (ffmpeg-kit's
|
|
26
|
+
# libavcodec.so links it) can't interpose on it, or it on the app's.
|
|
27
|
+
target_link_options(alphavideo_vpx PRIVATE "-Wl,--exclude-libs,ALL")
|
|
28
|
+
|
|
29
|
+
target_link_libraries(alphavideo_vpx ${CODECS_ROOT}/lib/libvpx.a m)
|
|
30
|
+
|
|
31
|
+
set_target_properties(alphavideo_vpx PROPERTIES
|
|
32
|
+
CXX_VISIBILITY_PRESET hidden
|
|
33
|
+
C_VISIBILITY_PRESET hidden
|
|
34
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package dev.mediacache.alphavideo.vpx;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The vpx codec module: libvpx's VP8 and VP9 decoders for alpha-video's C++ core. alpha-video finds this
|
|
5
|
+
* class on the classpath and registers it (dev.mediacache.alphavideo.AlphaVideoCodecs); apps don't
|
|
6
|
+
* call it.
|
|
7
|
+
*/
|
|
8
|
+
public final class VpxCodec {
|
|
9
|
+
static {
|
|
10
|
+
System.loadLibrary("alphavideo_vpx");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
private VpxCodec() {}
|
|
14
|
+
|
|
15
|
+
/** The address of the module's native AlphaVideoDecoderPluginList. */
|
|
16
|
+
public static long pluginList() {
|
|
17
|
+
return nativePluginList();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private static native long nativePluginList();
|
|
21
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#include "Dav1dDecoderPlugin.h"
|
|
2
|
+
|
|
3
|
+
#include <dav1d/dav1d.h>
|
|
4
|
+
|
|
5
|
+
#include <algorithm>
|
|
6
|
+
#include <cerrno>
|
|
7
|
+
#include <cstdio>
|
|
8
|
+
#include <cstring>
|
|
9
|
+
#include <new>
|
|
10
|
+
|
|
11
|
+
#if defined(__aarch64__) && defined(__linux__)
|
|
12
|
+
#include <asm/hwcap.h>
|
|
13
|
+
#include <sys/auxv.h>
|
|
14
|
+
|
|
15
|
+
#include <mutex>
|
|
16
|
+
|
|
17
|
+
// Exported by libdav1d (src/cpu.h), but not in its public headers
|
|
18
|
+
extern "C" void dav1d_set_cpu_flags_mask(unsigned mask);
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
namespace {
|
|
22
|
+
|
|
23
|
+
// dav1d takes SVE2 from HWCAP2 alone. Android's emulator on Apple M4 reports SVE2 without SVE and
|
|
24
|
+
// traps SVE instructions, so 10-bit AV1 crashed there; real SVE2 CPUs always have SVE.
|
|
25
|
+
void maskUnusableCpuFlags() {
|
|
26
|
+
#if defined(__aarch64__) && defined(__linux__)
|
|
27
|
+
static std::once_flag once;
|
|
28
|
+
std::call_once(once, [] {
|
|
29
|
+
if ((getauxval(AT_HWCAP2) & HWCAP2_SVE2) && !(getauxval(AT_HWCAP) & HWCAP_SVE)) {
|
|
30
|
+
constexpr unsigned kDav1dArmSve = 1u << 3, kDav1dArmSve2 = 1u << 4; // src/arm/cpu.h
|
|
31
|
+
dav1d_set_cpu_flags_mask(~(kDav1dArmSve | kDav1dArmSve2));
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
#endif
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Driven as FFmpeg's libdav1d wrapper drives it. dav1d_get_picture with no new data since the
|
|
38
|
+
// last call drains frames held by frame threads, so it's only called right after sending data,
|
|
39
|
+
// or when draining.
|
|
40
|
+
struct Dav1dDecoder {
|
|
41
|
+
Dav1dContext* ctx = nullptr;
|
|
42
|
+
Dav1dData data = {};
|
|
43
|
+
Dav1dPicture picture = {};
|
|
44
|
+
bool draining = false;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
int supportsStream(const AlphaVideoStreamInfo* stream) {
|
|
48
|
+
return stream->codec == ALPHA_VIDEO_CODEC_AV1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
void* openDecoder(const AlphaVideoStreamInfo*, int threads, char* error, size_t errorSize) {
|
|
52
|
+
maskUnusableCpuFlags();
|
|
53
|
+
auto* decoder = new (std::nothrow) Dav1dDecoder();
|
|
54
|
+
if (!decoder) {
|
|
55
|
+
std::snprintf(error, errorSize, "dav1d: out of memory");
|
|
56
|
+
return nullptr;
|
|
57
|
+
}
|
|
58
|
+
Dav1dSettings settings;
|
|
59
|
+
dav1d_default_settings(&settings);
|
|
60
|
+
settings.n_threads = std::max(threads, 0);
|
|
61
|
+
settings.max_frame_delay = 0; // dav1d's choice for the thread count
|
|
62
|
+
settings.all_layers = 0; // Only the highest spatial layer
|
|
63
|
+
if (dav1d_open(&decoder->ctx, &settings) < 0) {
|
|
64
|
+
std::snprintf(error, errorSize, "dav1d: failed to open");
|
|
65
|
+
delete decoder;
|
|
66
|
+
return nullptr;
|
|
67
|
+
}
|
|
68
|
+
return decoder;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
int sendPacket(void* opaque, const uint8_t* data, int size, int64_t ptsUs) {
|
|
72
|
+
auto* decoder = static_cast<Dav1dDecoder*>(opaque);
|
|
73
|
+
decoder->draining = false;
|
|
74
|
+
dav1d_data_unref(&decoder->data);
|
|
75
|
+
if (size <= 0) return 1;
|
|
76
|
+
uint8_t* buffer = dav1d_data_create(&decoder->data, static_cast<size_t>(size));
|
|
77
|
+
if (!buffer) return 0;
|
|
78
|
+
std::memcpy(buffer, data, static_cast<size_t>(size));
|
|
79
|
+
decoder->data.m.timestamp = ptsUs;
|
|
80
|
+
return 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
int receivePicture(void* opaque, AlphaVideoPicture* out) {
|
|
84
|
+
auto* decoder = static_cast<Dav1dDecoder*>(opaque);
|
|
85
|
+
dav1d_picture_unref(&decoder->picture);
|
|
86
|
+
// A drain can stop at a frame it drops (an invisible one) with more behind it
|
|
87
|
+
int drainRetries = 1;
|
|
88
|
+
for (;;) {
|
|
89
|
+
if (decoder->data.sz) {
|
|
90
|
+
const int res = dav1d_send_data(decoder->ctx, &decoder->data);
|
|
91
|
+
if (res < 0 && res != DAV1D_ERR(EAGAIN)) {
|
|
92
|
+
dav1d_data_unref(&decoder->data);
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
} else if (!decoder->draining) {
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
const int res = dav1d_get_picture(decoder->ctx, &decoder->picture);
|
|
99
|
+
if (res == 0) break;
|
|
100
|
+
if (res != DAV1D_ERR(EAGAIN)) return 0;
|
|
101
|
+
if (decoder->draining && drainRetries-- == 0) return 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const Dav1dPicture& p = decoder->picture;
|
|
105
|
+
const Dav1dSequenceHeader* seq = p.seq_hdr;
|
|
106
|
+
out->planes[0] = static_cast<const uint8_t*>(p.data[0]);
|
|
107
|
+
out->planes[1] = static_cast<const uint8_t*>(p.data[1]);
|
|
108
|
+
out->planes[2] = static_cast<const uint8_t*>(p.data[2]);
|
|
109
|
+
out->strides[0] = static_cast<int>(p.stride[0]);
|
|
110
|
+
out->strides[1] = out->strides[2] = static_cast<int>(p.stride[1]);
|
|
111
|
+
out->width = p.p.w;
|
|
112
|
+
out->height = p.p.h;
|
|
113
|
+
out->chromaShiftX = p.p.layout == DAV1D_PIXEL_LAYOUT_I420 || p.p.layout == DAV1D_PIXEL_LAYOUT_I422;
|
|
114
|
+
out->chromaShiftY = p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
|
|
115
|
+
out->monochrome = p.p.layout == DAV1D_PIXEL_LAYOUT_I400;
|
|
116
|
+
if (out->monochrome) out->planes[1] = out->planes[2] = nullptr;
|
|
117
|
+
out->bitDepth = p.p.bpc;
|
|
118
|
+
out->colorRange = seq && seq->color_range ? 2 : 1;
|
|
119
|
+
// FFmpeg's test for GBR output
|
|
120
|
+
out->rgb = seq && p.p.layout == DAV1D_PIXEL_LAYOUT_I444 && seq->mtrx == DAV1D_MC_IDENTITY &&
|
|
121
|
+
seq->pri == DAV1D_COLOR_PRI_BT709 && seq->trc == DAV1D_TRC_SRGB;
|
|
122
|
+
out->ptsUs = p.m.timestamp;
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
void drainDecoder(void* opaque) {
|
|
127
|
+
static_cast<Dav1dDecoder*>(opaque)->draining = true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
void flushDecoder(void* opaque) {
|
|
131
|
+
auto* decoder = static_cast<Dav1dDecoder*>(opaque);
|
|
132
|
+
dav1d_data_unref(&decoder->data);
|
|
133
|
+
dav1d_picture_unref(&decoder->picture);
|
|
134
|
+
dav1d_flush(decoder->ctx);
|
|
135
|
+
decoder->draining = false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
void closeDecoder(void* opaque) {
|
|
139
|
+
auto* decoder = static_cast<Dav1dDecoder*>(opaque);
|
|
140
|
+
dav1d_data_unref(&decoder->data);
|
|
141
|
+
dav1d_picture_unref(&decoder->picture);
|
|
142
|
+
if (decoder->ctx) dav1d_close(&decoder->ctx);
|
|
143
|
+
delete decoder;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
} // namespace
|
|
147
|
+
|
|
148
|
+
const AlphaVideoDecoderPlugin* const* alpha_video_av1_plugins(int* count) {
|
|
149
|
+
static const AlphaVideoDecoderPlugin av1 = {
|
|
150
|
+
ALPHA_VIDEO_DECODER_ABI, sizeof(AlphaVideoDecoderPlugin), "dav1d", dav1d_version(),
|
|
151
|
+
ALPHA_VIDEO_CODEC_AV1, supportsStream, openDecoder, sendPacket, receivePicture, drainDecoder,
|
|
152
|
+
flushDecoder, closeDecoder,
|
|
153
|
+
};
|
|
154
|
+
static const AlphaVideoDecoderPlugin* const plugins[] = {&av1};
|
|
155
|
+
*count = 1;
|
|
156
|
+
return plugins;
|
|
157
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#ifndef ALPHA_VIDEO_DAV1D_DECODER_PLUGIN_H
|
|
2
|
+
#define ALPHA_VIDEO_DAV1D_DECODER_PLUGIN_H
|
|
3
|
+
|
|
4
|
+
#include "AlphaVideoDecoderPlugin.h"
|
|
5
|
+
|
|
6
|
+
#ifdef __cplusplus
|
|
7
|
+
extern "C" {
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
/* The av1 codec module's plugins: dav1d (8-, 10- and 12-bit). An AlphaVideoDecoderPluginList. */
|
|
11
|
+
const AlphaVideoDecoderPlugin* const* alpha_video_av1_plugins(int* count);
|
|
12
|
+
|
|
13
|
+
#ifdef __cplusplus
|
|
14
|
+
}
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
#endif
|