react-native-skia-webgpu-video 0.0.0-stage → 0.1.0-beta.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 +22 -0
- package/README.md +303 -2
- package/android/BUILD_VALIDATION.md +62 -0
- package/android/CMakeLists.txt +99 -0
- package/android/build-validation.json +262 -0
- package/android/build.gradle +185 -0
- package/android/cpp/EncoderTargets.cpp +226 -0
- package/android/cpp/EncoderTargets.h +70 -0
- package/android/cpp/JNIHelpers.cpp +15 -0
- package/android/cpp/JNIHelpers.h +20 -0
- package/android/cpp/NativeEventDispatcher.cpp +59 -0
- package/android/cpp/NativeEventDispatcher.h +31 -0
- package/android/cpp/NativeHardwareBuffer.cpp +397 -0
- package/android/cpp/NativeHardwareBuffer.h +34 -0
- package/android/cpp/NativeRgbaBuffer.cpp +45 -0
- package/android/cpp/NativeRgbaBuffer.h +9 -0
- package/android/cpp/ReturnedVideoFrames.h +37 -0
- package/android/cpp/RgbaFrameLease.h +53 -0
- package/android/cpp/VideoCapabilities.cpp +87 -0
- package/android/cpp/VideoCapabilities.h +44 -0
- package/android/cpp/VideoComposition.cpp +170 -0
- package/android/cpp/VideoComposition.h +36 -0
- package/android/cpp/VideoCompositionFramesExtractor.cpp +82 -0
- package/android/cpp/VideoCompositionFramesExtractor.h +48 -0
- package/android/cpp/VideoCompositionFramesExtractorHostObject.cpp +230 -0
- package/android/cpp/VideoCompositionFramesExtractorHostObject.h +42 -0
- package/android/cpp/VideoCompositionFramesExtractorSyncHostObject.cpp +133 -0
- package/android/cpp/VideoCompositionFramesExtractorSyncHostObject.h +46 -0
- package/android/cpp/VideoEncoderHostObject.cpp +318 -0
- package/android/cpp/VideoEncoderHostObject.h +76 -0
- package/android/cpp/VideoFrame.cpp +293 -0
- package/android/cpp/VideoFrame.h +27 -0
- package/android/cpp/VideoPlayer.cpp +96 -0
- package/android/cpp/VideoPlayer.h +52 -0
- package/android/cpp/VideoPlayerHostObject.cpp +225 -0
- package/android/cpp/VideoPlayerHostObject.h +43 -0
- package/android/cpp/cpp-adapter.cpp +316 -0
- package/android/gradle.properties +5 -0
- package/android/instrumentation-inventory.json +178 -0
- package/android/proguard-rules.pro +4 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/azzapp/rnskv/AudioCompositionExporter.java +537 -0
- package/android/src/main/java/com/azzapp/rnskv/AudioCompositionPlayer.java +321 -0
- package/android/src/main/java/com/azzapp/rnskv/BufferLifetime.java +55 -0
- package/android/src/main/java/com/azzapp/rnskv/DecodeRequests.java +100 -0
- package/android/src/main/java/com/azzapp/rnskv/DecoderWindow.java +55 -0
- package/android/src/main/java/com/azzapp/rnskv/DisplayVsyncPeriod.java +72 -0
- package/android/src/main/java/com/azzapp/rnskv/EGLResourcesHolder.java +132 -0
- package/android/src/main/java/com/azzapp/rnskv/EGLUtils.java +225 -0
- package/android/src/main/java/com/azzapp/rnskv/FrameSize.java +50 -0
- package/android/src/main/java/com/azzapp/rnskv/GLFrameExtractor.java +510 -0
- package/android/src/main/java/com/azzapp/rnskv/JNIHelpers.java +12 -0
- package/android/src/main/java/com/azzapp/rnskv/NativeEventDispatcher.java +25 -0
- package/android/src/main/java/com/azzapp/rnskv/NativeHardwareBuffer.java +62 -0
- package/android/src/main/java/com/azzapp/rnskv/NativeRgbaBuffer.java +43 -0
- package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoModule.java +45 -0
- package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoPackage.java +43 -0
- package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoSpec.java +9 -0
- package/android/src/main/java/com/azzapp/rnskv/RgbaBufferAllocator.java +114 -0
- package/android/src/main/java/com/azzapp/rnskv/RgbaLayout.java +33 -0
- package/android/src/main/java/com/azzapp/rnskv/SurfaceOutputPolicy.java +13 -0
- package/android/src/main/java/com/azzapp/rnskv/TextureRenderer.java +150 -0
- package/android/src/main/java/com/azzapp/rnskv/TimeHelpers.java +11 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCapabilities.java +354 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoComposition.java +147 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionDecoder.java +779 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractor.java +463 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractorSync.java +241 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoCompositionItemDecoder.java +492 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoEncoder.java +639 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoFrame.java +74 -0
- package/android/src/main/java/com/azzapp/rnskv/VideoPlayer.java +361 -0
- package/cpp/RNSVCheckedSizes.h +54 -0
- package/cpp/RNSVEventEmitter.cpp +199 -0
- package/cpp/RNSVEventEmitter.h +31 -0
- package/cpp/RNSVHostObject.cpp +79 -0
- package/cpp/RNSVHostObject.h +67 -0
- package/cpp/RNSVMemoryBudget.cpp +68 -0
- package/cpp/RNSVMemoryBudget.h +100 -0
- package/cpp/RNSVRuntimeLifecycleMonitor.cpp +88 -0
- package/cpp/RNSVRuntimeLifecycleMonitor.h +33 -0
- package/docs/ANDROID_DEVICE_306.md +95 -0
- package/docs/ANDROID_EXPORT_CACHE_306.md +48 -0
- package/docs/ANDROID_MEMORY_RETENTION_306.md +67 -0
- package/docs/BENCHMARKS.md +368 -0
- package/docs/IOS_DEVICE_TESTS.md +115 -0
- package/docs/IOS_SIMULATOR_TESTS.md +74 -0
- package/docs/MIGRATION.md +82 -0
- package/docs/NATIVE_MEMORY_INVESTIGATION_306.md +88 -0
- package/docs/PERFORMANCE_AB_IPHONE_303.md +196 -0
- package/docs/PERFORMANCE_AB_SIMULATOR.md +135 -0
- package/docs/PERFORMANCE_AB_SOAK_SIMULATOR.md +84 -0
- package/docs/PERFORMANCE_IPHONE_306_OPTIMIZATION.md +76 -0
- package/docs/PERFORMANCE_SIMULATOR.md +89 -0
- package/docs/PERFORMANCE_SIMULATOR_INITIAL.md +96 -0
- package/docs/PERFORMANCE_SOAK_IPHONE_303.md +41 -0
- package/docs/UPSTREAM_NOTES.md +188 -0
- package/docs/assets/banner.svg +26 -0
- package/examples/webgpu-overlay.ts +147 -0
- package/ios/AVAssetTrackUtils.h +24 -0
- package/ios/AudioCompositionUtils.h +27 -0
- package/ios/AudioCompositionUtils.mm +113 -0
- package/ios/DecoderWindow.h +52 -0
- package/ios/NativeResourceStats.h +32 -0
- package/ios/RNSVColorSpace.h +50 -0
- package/ios/RNSVJSIUtils.h +46 -0
- package/ios/RNSVScopedPixelBuffer.h +17 -0
- package/ios/RNSVVideoPlayer.h +46 -0
- package/ios/RNSVVideoPlayer.mm +410 -0
- package/ios/ReactNativeSkiaVideo.h +8 -0
- package/ios/ReactNativeSkiaVideo.mm +310 -0
- package/ios/SeekPolicy.h +27 -0
- package/ios/VideoComposition.h +148 -0
- package/ios/VideoCompositionFramesExtractorHostObject.h +105 -0
- package/ios/VideoCompositionFramesExtractorHostObject.mm +686 -0
- package/ios/VideoCompositionFramesExtractorSyncHostObject.h +37 -0
- package/ios/VideoCompositionFramesExtractorSyncHostObject.mm +168 -0
- package/ios/VideoCompositionItemDecoder.h +60 -0
- package/ios/VideoCompositionItemDecoder.mm +480 -0
- package/ios/VideoEncoderHostObject.h +83 -0
- package/ios/VideoEncoderHostObject.mm +706 -0
- package/ios/VideoFrame.h +66 -0
- package/ios/VideoFrame.mm +108 -0
- package/ios/VideoPlayerHostObject.h +52 -0
- package/ios/VideoPlayerHostObject.mm +332 -0
- package/lib/module/NativeReactNativeSkiaVideo.js +5 -0
- package/lib/module/NativeReactNativeSkiaVideo.js.map +1 -0
- package/lib/module/RNSkiaVideoModule.js +20 -0
- package/lib/module/RNSkiaVideoModule.js.map +1 -0
- package/lib/module/canvas.js +18 -0
- package/lib/module/canvas.js.map +1 -0
- package/lib/module/exportCache.js +22 -0
- package/lib/module/exportCache.js.map +1 -0
- package/lib/module/exportFrames.js +338 -0
- package/lib/module/exportFrames.js.map +1 -0
- package/lib/module/exportQueue.js +52 -0
- package/lib/module/exportQueue.js.map +1 -0
- package/lib/module/exportTarget.js +137 -0
- package/lib/module/exportTarget.js.map +1 -0
- package/lib/module/exportVideoComposition.js +492 -0
- package/lib/module/exportVideoComposition.js.map +1 -0
- package/lib/module/frameInterop.js +532 -0
- package/lib/module/frameInterop.js.map +1 -0
- package/lib/module/gpu.js +222 -0
- package/lib/module/gpu.js.map +1 -0
- package/lib/module/gpuDevice.js +54 -0
- package/lib/module/gpuDevice.js.map +1 -0
- package/lib/module/index.js +36 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/memory.js +38 -0
- package/lib/module/memory.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/previewLifecycle.js +52 -0
- package/lib/module/previewLifecycle.js.map +1 -0
- package/lib/module/runtimeYield.js +10 -0
- package/lib/module/runtimeYield.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/useEventListener.js +18 -0
- package/lib/module/utils/useEventListener.js.map +1 -0
- package/lib/module/videoCompositionPlayer.js +368 -0
- package/lib/module/videoCompositionPlayer.js.map +1 -0
- package/lib/module/videoFrameImage.js +185 -0
- package/lib/module/videoFrameImage.js.map +1 -0
- package/lib/module/videoPlayer.js +172 -0
- package/lib/module/videoPlayer.js.map +1 -0
- package/lib/module/yuvBlit.js +299 -0
- package/lib/module/yuvBlit.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts +7 -0
- package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts.map +1 -0
- package/lib/typescript/src/RNSkiaVideoModule.d.ts +4 -0
- package/lib/typescript/src/RNSkiaVideoModule.d.ts.map +1 -0
- package/lib/typescript/src/canvas.d.ts +4 -0
- package/lib/typescript/src/canvas.d.ts.map +1 -0
- package/lib/typescript/src/exportCache.d.ts +6 -0
- package/lib/typescript/src/exportCache.d.ts.map +1 -0
- package/lib/typescript/src/exportFrames.d.ts +57 -0
- package/lib/typescript/src/exportFrames.d.ts.map +1 -0
- package/lib/typescript/src/exportQueue.d.ts +5 -0
- package/lib/typescript/src/exportQueue.d.ts.map +1 -0
- package/lib/typescript/src/exportTarget.d.ts +28 -0
- package/lib/typescript/src/exportTarget.d.ts.map +1 -0
- package/lib/typescript/src/exportVideoComposition.d.ts +68 -0
- package/lib/typescript/src/exportVideoComposition.d.ts.map +1 -0
- package/lib/typescript/src/frameInterop.d.ts +17 -0
- package/lib/typescript/src/frameInterop.d.ts.map +1 -0
- package/lib/typescript/src/gpu.d.ts +39 -0
- package/lib/typescript/src/gpu.d.ts.map +1 -0
- package/lib/typescript/src/gpuDevice.d.ts +11 -0
- package/lib/typescript/src/gpuDevice.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +21 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/memory.d.ts +25 -0
- package/lib/typescript/src/memory.d.ts.map +1 -0
- package/lib/typescript/src/previewLifecycle.d.ts +22 -0
- package/lib/typescript/src/previewLifecycle.d.ts.map +1 -0
- package/lib/typescript/src/runtimeYield.d.ts +4 -0
- package/lib/typescript/src/runtimeYield.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +631 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/useEventListener.d.ts +5 -0
- package/lib/typescript/src/utils/useEventListener.d.ts.map +1 -0
- package/lib/typescript/src/videoCompositionPlayer.d.ts +105 -0
- package/lib/typescript/src/videoCompositionPlayer.d.ts.map +1 -0
- package/lib/typescript/src/videoFrameImage.d.ts +60 -0
- package/lib/typescript/src/videoFrameImage.d.ts.map +1 -0
- package/lib/typescript/src/videoPlayer.d.ts +99 -0
- package/lib/typescript/src/videoPlayer.d.ts.map +1 -0
- package/lib/typescript/src/yuvBlit.d.ts +50 -0
- package/lib/typescript/src/yuvBlit.d.ts.map +1 -0
- package/package.json +155 -4
- package/patches/react-native-skia+3.7.0.patch +502 -0
- package/react-native-skia-webgpu-video.podspec +35 -0
- package/scripts/apply-skia-canvas-patch.mjs +48 -0
- package/scripts/skia-canvas-patch.json +291 -0
- package/src/NativeReactNativeSkiaVideo.ts +8 -0
- package/src/RNSkiaVideoModule.ts +27 -0
- package/src/canvas.ts +22 -0
- package/src/exportCache.ts +27 -0
- package/src/exportFrames.ts +421 -0
- package/src/exportQueue.ts +65 -0
- package/src/exportTarget.ts +179 -0
- package/src/exportVideoComposition.ts +718 -0
- package/src/frameInterop.ts +684 -0
- package/src/gpu.ts +290 -0
- package/src/gpuDevice.ts +80 -0
- package/src/index.tsx +45 -0
- package/src/memory.ts +48 -0
- package/src/previewLifecycle.ts +60 -0
- package/src/runtimeYield.ts +6 -0
- package/src/types.ts +661 -0
- package/src/utils/useEventListener.ts +22 -0
- package/src/videoCompositionPlayer.ts +568 -0
- package/src/videoFrameImage.ts +205 -0
- package/src/videoPlayer.ts +318 -0
- package/src/yuvBlit.ts +331 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package com.azzapp.rnskv;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Nullable;
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.NativeModule;
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfo;
|
|
8
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
9
|
+
import com.facebook.react.BaseReactPackage;
|
|
10
|
+
|
|
11
|
+
import java.util.HashMap;
|
|
12
|
+
import java.util.Map;
|
|
13
|
+
|
|
14
|
+
public class ReactNativeSkiaVideoPackage extends BaseReactPackage {
|
|
15
|
+
|
|
16
|
+
@Nullable
|
|
17
|
+
@Override
|
|
18
|
+
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
19
|
+
if (name.equals(ReactNativeSkiaVideoModule.NAME)) {
|
|
20
|
+
return new ReactNativeSkiaVideoModule(reactContext);
|
|
21
|
+
} else {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Override
|
|
27
|
+
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
28
|
+
return () -> {
|
|
29
|
+
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
|
|
30
|
+
moduleInfos.put(
|
|
31
|
+
ReactNativeSkiaVideoModule.NAME,
|
|
32
|
+
new ReactModuleInfo(
|
|
33
|
+
ReactNativeSkiaVideoModule.NAME,
|
|
34
|
+
ReactNativeSkiaVideoModule.NAME,
|
|
35
|
+
false, // canOverrideExistingModule
|
|
36
|
+
false, // needsEagerInit
|
|
37
|
+
false, // isCxxModule
|
|
38
|
+
true // isTurboModule
|
|
39
|
+
));
|
|
40
|
+
return moduleInfos;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
package com.azzapp.rnskv;
|
|
2
|
+
import java.nio.ByteBuffer;
|
|
3
|
+
import java.util.function.Function;
|
|
4
|
+
import java.util.function.IntFunction;
|
|
5
|
+
import java.util.function.IntConsumer;
|
|
6
|
+
import java.util.function.IntToLongFunction;
|
|
7
|
+
import java.util.function.LongConsumer;
|
|
8
|
+
|
|
9
|
+
/** Allocation transaction registers its budget owner before allocating any pixel storage. */
|
|
10
|
+
final class RgbaBufferAllocator {
|
|
11
|
+
private final BufferLifetime lifetimes;
|
|
12
|
+
private final IntToLongFunction reserve;
|
|
13
|
+
private final LongConsumer release;
|
|
14
|
+
private final IntFunction<ByteBuffer> allocateBacking;
|
|
15
|
+
private final Function<ByteBuffer, ByteBuffer> alias;
|
|
16
|
+
private final IntConsumer checkHeap;
|
|
17
|
+
private final Runnable reclaim;
|
|
18
|
+
/** Collections asked for when the native budget refuses a reservation. */
|
|
19
|
+
static final int RECLAIM_ATTEMPTS = 3;
|
|
20
|
+
RgbaBufferAllocator(BufferLifetime lifetimes, IntToLongFunction reserve, LongConsumer release,
|
|
21
|
+
IntFunction<ByteBuffer> allocateBacking, Function<ByteBuffer, ByteBuffer> alias) {
|
|
22
|
+
this(lifetimes, reserve, release, allocateBacking, alias, size -> {});
|
|
23
|
+
}
|
|
24
|
+
RgbaBufferAllocator(BufferLifetime lifetimes, IntToLongFunction reserve, LongConsumer release,
|
|
25
|
+
IntFunction<ByteBuffer> allocateBacking, Function<ByteBuffer, ByteBuffer> alias, IntConsumer checkHeap) {
|
|
26
|
+
this(lifetimes, reserve, release, allocateBacking, alias, checkHeap, () -> {});
|
|
27
|
+
}
|
|
28
|
+
RgbaBufferAllocator(BufferLifetime lifetimes, IntToLongFunction reserve, LongConsumer release,
|
|
29
|
+
IntFunction<ByteBuffer> allocateBacking, Function<ByteBuffer, ByteBuffer> alias, IntConsumer checkHeap,
|
|
30
|
+
Runnable reclaim) {
|
|
31
|
+
this.lifetimes = lifetimes; this.reserve = reserve; this.release = release;
|
|
32
|
+
this.allocateBacking = allocateBacking; this.alias = alias; this.checkHeap = checkHeap;
|
|
33
|
+
this.reclaim = reclaim;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Refuse a single backing too large for ART's heap and cleanup headroom.
|
|
37
|
+
* Do not subtract currently occupied heap: allocateDirect must be allowed to
|
|
38
|
+
* trigger ART's natural GC and reclaim unreachable backing owners. A free-heap
|
|
39
|
+
* precheck would stop streaming before that GC, leaving reclaimable buffers live.
|
|
40
|
+
* The native quota and narrow allocation-OOM catch remain the actual limits. */
|
|
41
|
+
static void checkAllocationCapacity(int size, long maxHeap) {
|
|
42
|
+
if (size <= 0) throw new IllegalArgumentException("Invalid RGBA allocation size");
|
|
43
|
+
if (maxHeap <= 0) throw new IllegalStateException("Android heap capacity is unavailable");
|
|
44
|
+
long headroom = Math.min(16L * 1024 * 1024, maxHeap / 16);
|
|
45
|
+
long available = Math.max(0, maxHeap - headroom);
|
|
46
|
+
if ((long) size + 7 > available) {
|
|
47
|
+
throw new IllegalStateException("Android RGBA memory budget exceeds single-allocation Java heap capacity; "
|
|
48
|
+
+ "reduce maxLongSide or use lazyDecoders (requested=" + ((long) size + 7)
|
|
49
|
+
+ ", available=" + available + ", headroom=" + headroom + ")");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
ByteBuffer allocate(int size) {
|
|
54
|
+
lifetimes.drain();
|
|
55
|
+
checkHeap.accept(size);
|
|
56
|
+
long token = reserveReclaiming(size);
|
|
57
|
+
Allocation owner;
|
|
58
|
+
try {
|
|
59
|
+
owner = new Allocation();
|
|
60
|
+
// Pre-register before the large allocation. Alias/registration failures
|
|
61
|
+
// remain accounted until this owner and its backing have been collected.
|
|
62
|
+
lifetimes.track(owner, null, token);
|
|
63
|
+
} catch (Throwable error) {
|
|
64
|
+
// No pixel backing has been allocated at this point.
|
|
65
|
+
release.accept(token);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
// Re-check any injected capacity policy after the reservation; concurrent heap
|
|
69
|
+
// use itself is handled by ART allocation/GC and the narrow OOM catch below.
|
|
70
|
+
checkHeap.accept(size);
|
|
71
|
+
try {
|
|
72
|
+
owner.backing = allocateBacking.apply(size);
|
|
73
|
+
} catch (OutOfMemoryError firstError) {
|
|
74
|
+
// ART may have queued dead JNI roots during its allocation GC. Drain them
|
|
75
|
+
// before one retry, so their backing owners can be reclaimed by that next
|
|
76
|
+
// natural allocation GC. Live aliases are not queued and remain untouched.
|
|
77
|
+
lifetimes.drain();
|
|
78
|
+
try {
|
|
79
|
+
owner.backing = allocateBacking.apply(size);
|
|
80
|
+
} catch (OutOfMemoryError finalError) {
|
|
81
|
+
// Retry only the backing allocation, once, with the same reserved owner.
|
|
82
|
+
// No alias escaped. Never return its token early while storage might live.
|
|
83
|
+
throw new IllegalStateException("Android RGBA memory budget exhausted during allocation; "
|
|
84
|
+
+ "reduce maxLongSide or use lazyDecoders (requested=" + size + ", attempts=2)", finalError);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
ByteBuffer exposed = alias.apply(owner.backing);
|
|
88
|
+
lifetimes.track(exposed, owner, 0);
|
|
89
|
+
return exposed;
|
|
90
|
+
}
|
|
91
|
+
/** A buffer holds its reservation until the GC finds it unreachable. A fast
|
|
92
|
+
* decode drops a frame per vsync, 8 MB each in 1080p, and those dead buffers
|
|
93
|
+
* filled the native budget before the Java heap asked for a collection: the
|
|
94
|
+
* budget refused frames nobody held. Refused while buffers are tracked, the
|
|
95
|
+
* reservation is retried after a collection has returned theirs. */
|
|
96
|
+
private long reserveReclaiming(int size) {
|
|
97
|
+
try {
|
|
98
|
+
return reserve.applyAsLong(size);
|
|
99
|
+
} catch (RuntimeException refused) {
|
|
100
|
+
RuntimeException last = refused;
|
|
101
|
+
for (int attempt = 0; attempt < RECLAIM_ATTEMPTS && lifetimes.trackedCount() > 0; attempt++) {
|
|
102
|
+
reclaim.run();
|
|
103
|
+
lifetimes.drain();
|
|
104
|
+
try {
|
|
105
|
+
return reserve.applyAsLong(size);
|
|
106
|
+
} catch (RuntimeException again) {
|
|
107
|
+
last = again;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
throw last;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
private static final class Allocation { ByteBuffer backing; }
|
|
114
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.azzapp.rnskv;
|
|
2
|
+
|
|
3
|
+
/** Checked byte arithmetic shared by readback and encoder upload. */
|
|
4
|
+
final class RgbaLayout {
|
|
5
|
+
private RgbaLayout() {}
|
|
6
|
+
|
|
7
|
+
static int bytesPerRow(int width) {
|
|
8
|
+
if (width <= 0 || width > Integer.MAX_VALUE / 4) {
|
|
9
|
+
throw new IllegalArgumentException("Invalid RGBA width: " + width);
|
|
10
|
+
}
|
|
11
|
+
return width * 4;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static int byteSize(int width, int height) {
|
|
15
|
+
int stride = bytesPerRow(width);
|
|
16
|
+
if (height <= 0 || height > Integer.MAX_VALUE / stride) {
|
|
17
|
+
throw new IllegalArgumentException("Invalid RGBA height: " + height);
|
|
18
|
+
}
|
|
19
|
+
return stride * height;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static int requiredBytes(int width, int height, int stride) {
|
|
23
|
+
int packedStride = bytesPerRow(width);
|
|
24
|
+
if (stride < packedStride || height <= 0) {
|
|
25
|
+
throw new IllegalArgumentException("Invalid RGBA stride or height");
|
|
26
|
+
}
|
|
27
|
+
long bytes = (long) stride * (height - 1) + packedStride;
|
|
28
|
+
if (bytes > Integer.MAX_VALUE) {
|
|
29
|
+
throw new IllegalArgumentException("RGBA upload exceeds Android ByteBuffer limits");
|
|
30
|
+
}
|
|
31
|
+
return (int) bytes;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package com.azzapp.rnskv;
|
|
2
|
+
|
|
3
|
+
import android.media.MediaCodec;
|
|
4
|
+
|
|
5
|
+
/** Surface frames can have no byte payload; an empty EOS is only a stream marker. */
|
|
6
|
+
final class SurfaceOutputPolicy {
|
|
7
|
+
private SurfaceOutputPolicy() { }
|
|
8
|
+
|
|
9
|
+
static boolean hasFrame(int size, int flags) {
|
|
10
|
+
return (flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0
|
|
11
|
+
&& (size > 0 || (flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
package com.azzapp.rnskv;
|
|
2
|
+
|
|
3
|
+
import android.opengl.GLES11Ext;
|
|
4
|
+
import android.opengl.GLES20;
|
|
5
|
+
|
|
6
|
+
import java.nio.FloatBuffer;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A class that renders a texture.
|
|
10
|
+
*/
|
|
11
|
+
public class TextureRenderer {
|
|
12
|
+
|
|
13
|
+
private static final String VERTEX_SHADER =
|
|
14
|
+
"""
|
|
15
|
+
attribute vec4 aFramePosition;
|
|
16
|
+
attribute vec4 aTexCoords;
|
|
17
|
+
uniform mat4 uTexTransform;
|
|
18
|
+
varying vec2 vTexCoords;
|
|
19
|
+
void main() {
|
|
20
|
+
gl_Position = aFramePosition;
|
|
21
|
+
vTexCoords = (uTexTransform * aTexCoords).xy;
|
|
22
|
+
}
|
|
23
|
+
""";
|
|
24
|
+
|
|
25
|
+
private static final String FRAGMENT_SHADER =
|
|
26
|
+
"""
|
|
27
|
+
precision highp float;
|
|
28
|
+
uniform sampler2D uTexSampler;
|
|
29
|
+
varying vec2 vTexCoords;
|
|
30
|
+
void main() {
|
|
31
|
+
gl_FragColor = texture2D(uTexSampler, vTexCoords);
|
|
32
|
+
}
|
|
33
|
+
""";
|
|
34
|
+
|
|
35
|
+
private static final String FRAGMENT_SHADER_EXTERNAL =
|
|
36
|
+
"""
|
|
37
|
+
#extension GL_OES_EGL_image_external : require
|
|
38
|
+
precision highp float;
|
|
39
|
+
uniform samplerExternalOES uTexSampler;
|
|
40
|
+
varying vec2 vTexCoords;
|
|
41
|
+
void main() {
|
|
42
|
+
gl_FragColor = texture2D(uTexSampler, vTexCoords);
|
|
43
|
+
}
|
|
44
|
+
""";
|
|
45
|
+
|
|
46
|
+
private static final FloatBuffer POS_VERTICES = EGLUtils.createFloatBuffer(
|
|
47
|
+
-1f, -1f, 0f, 1f,
|
|
48
|
+
1f, -1f, 0f, 1f,
|
|
49
|
+
-1f, 1f, 0f, 1f,
|
|
50
|
+
1f, 1f, 0f, 1f
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
private static final FloatBuffer TEX_VERTICES = EGLUtils.createFloatBuffer(
|
|
54
|
+
0f, 1f, 0f, 1f,
|
|
55
|
+
1f, 1f, 0f, 1f,
|
|
56
|
+
0f, 0f, 0f, 1f,
|
|
57
|
+
1f, 0f, 0f, 1f
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
private final int program;
|
|
61
|
+
|
|
62
|
+
private final int aFramePositionLoc;
|
|
63
|
+
|
|
64
|
+
private final int aTexCoordsLoc;
|
|
65
|
+
|
|
66
|
+
private final int uTexTransformLoc;
|
|
67
|
+
|
|
68
|
+
private final int uTexSamplerLoc;
|
|
69
|
+
|
|
70
|
+
boolean external = false;
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
public TextureRenderer() {
|
|
74
|
+
this(false);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Create a new TextureRenderer.
|
|
79
|
+
*/
|
|
80
|
+
public TextureRenderer(boolean external) {
|
|
81
|
+
this.external = external;
|
|
82
|
+
program = EGLUtils.createProgram(
|
|
83
|
+
VERTEX_SHADER,
|
|
84
|
+
external ? FRAGMENT_SHADER_EXTERNAL : FRAGMENT_SHADER
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
aFramePositionLoc = GLES20.glGetAttribLocation(
|
|
88
|
+
program,
|
|
89
|
+
"aFramePosition"
|
|
90
|
+
);
|
|
91
|
+
aTexCoordsLoc = GLES20.glGetAttribLocation(
|
|
92
|
+
program,
|
|
93
|
+
"aTexCoords"
|
|
94
|
+
);
|
|
95
|
+
uTexTransformLoc = GLES20.glGetUniformLocation(
|
|
96
|
+
program,
|
|
97
|
+
"uTexTransform"
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
uTexSamplerLoc = GLES20.glGetUniformLocation(
|
|
101
|
+
program,
|
|
102
|
+
"uTexSampler"
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Draw the texture.
|
|
108
|
+
*
|
|
109
|
+
* @param textureId the texture to draw
|
|
110
|
+
* @param transformMatrix the texture transform matrix to apply
|
|
111
|
+
* (usually the texture matrix from a SurfaceTexture)
|
|
112
|
+
*/
|
|
113
|
+
public void draw(
|
|
114
|
+
int textureId,
|
|
115
|
+
float[] transformMatrix
|
|
116
|
+
) {
|
|
117
|
+
GLES20.glUseProgram(program);
|
|
118
|
+
|
|
119
|
+
GLES20.glEnableVertexAttribArray(aFramePositionLoc);
|
|
120
|
+
GLES20.glVertexAttribPointer(
|
|
121
|
+
aFramePositionLoc, 4, GLES20.GL_FLOAT, false, 0,
|
|
122
|
+
POS_VERTICES
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
GLES20.glEnableVertexAttribArray(aTexCoordsLoc);
|
|
126
|
+
GLES20.glVertexAttribPointer(
|
|
127
|
+
aTexCoordsLoc, 4, GLES20.GL_FLOAT, false, 0,
|
|
128
|
+
TEX_VERTICES
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
GLES20.glUniformMatrix4fv(uTexTransformLoc, 1, false, transformMatrix, 0);
|
|
132
|
+
|
|
133
|
+
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
|
134
|
+
GLES20.glBindTexture(
|
|
135
|
+
external ? GLES11Ext.GL_TEXTURE_EXTERNAL_OES : GLES20.GL_TEXTURE_2D, textureId);
|
|
136
|
+
GLES20.glUniform1i(uTexSamplerLoc, 0);
|
|
137
|
+
|
|
138
|
+
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
|
139
|
+
|
|
140
|
+
GLES20.glDisableVertexAttribArray(aFramePositionLoc);
|
|
141
|
+
GLES20.glDisableVertexAttribArray(aTexCoordsLoc);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Release the resources. (delete the program)
|
|
146
|
+
*/
|
|
147
|
+
public void release() {
|
|
148
|
+
GLES20.glDeleteProgram(program);
|
|
149
|
+
}
|
|
150
|
+
}
|