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.
Files changed (237) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +303 -2
  3. package/android/BUILD_VALIDATION.md +62 -0
  4. package/android/CMakeLists.txt +99 -0
  5. package/android/build-validation.json +262 -0
  6. package/android/build.gradle +185 -0
  7. package/android/cpp/EncoderTargets.cpp +226 -0
  8. package/android/cpp/EncoderTargets.h +70 -0
  9. package/android/cpp/JNIHelpers.cpp +15 -0
  10. package/android/cpp/JNIHelpers.h +20 -0
  11. package/android/cpp/NativeEventDispatcher.cpp +59 -0
  12. package/android/cpp/NativeEventDispatcher.h +31 -0
  13. package/android/cpp/NativeHardwareBuffer.cpp +397 -0
  14. package/android/cpp/NativeHardwareBuffer.h +34 -0
  15. package/android/cpp/NativeRgbaBuffer.cpp +45 -0
  16. package/android/cpp/NativeRgbaBuffer.h +9 -0
  17. package/android/cpp/ReturnedVideoFrames.h +37 -0
  18. package/android/cpp/RgbaFrameLease.h +53 -0
  19. package/android/cpp/VideoCapabilities.cpp +87 -0
  20. package/android/cpp/VideoCapabilities.h +44 -0
  21. package/android/cpp/VideoComposition.cpp +170 -0
  22. package/android/cpp/VideoComposition.h +36 -0
  23. package/android/cpp/VideoCompositionFramesExtractor.cpp +82 -0
  24. package/android/cpp/VideoCompositionFramesExtractor.h +48 -0
  25. package/android/cpp/VideoCompositionFramesExtractorHostObject.cpp +230 -0
  26. package/android/cpp/VideoCompositionFramesExtractorHostObject.h +42 -0
  27. package/android/cpp/VideoCompositionFramesExtractorSyncHostObject.cpp +133 -0
  28. package/android/cpp/VideoCompositionFramesExtractorSyncHostObject.h +46 -0
  29. package/android/cpp/VideoEncoderHostObject.cpp +318 -0
  30. package/android/cpp/VideoEncoderHostObject.h +76 -0
  31. package/android/cpp/VideoFrame.cpp +293 -0
  32. package/android/cpp/VideoFrame.h +27 -0
  33. package/android/cpp/VideoPlayer.cpp +96 -0
  34. package/android/cpp/VideoPlayer.h +52 -0
  35. package/android/cpp/VideoPlayerHostObject.cpp +225 -0
  36. package/android/cpp/VideoPlayerHostObject.h +43 -0
  37. package/android/cpp/cpp-adapter.cpp +316 -0
  38. package/android/gradle.properties +5 -0
  39. package/android/instrumentation-inventory.json +178 -0
  40. package/android/proguard-rules.pro +4 -0
  41. package/android/src/main/AndroidManifest.xml +2 -0
  42. package/android/src/main/java/com/azzapp/rnskv/AudioCompositionExporter.java +537 -0
  43. package/android/src/main/java/com/azzapp/rnskv/AudioCompositionPlayer.java +321 -0
  44. package/android/src/main/java/com/azzapp/rnskv/BufferLifetime.java +55 -0
  45. package/android/src/main/java/com/azzapp/rnskv/DecodeRequests.java +100 -0
  46. package/android/src/main/java/com/azzapp/rnskv/DecoderWindow.java +55 -0
  47. package/android/src/main/java/com/azzapp/rnskv/DisplayVsyncPeriod.java +72 -0
  48. package/android/src/main/java/com/azzapp/rnskv/EGLResourcesHolder.java +132 -0
  49. package/android/src/main/java/com/azzapp/rnskv/EGLUtils.java +225 -0
  50. package/android/src/main/java/com/azzapp/rnskv/FrameSize.java +50 -0
  51. package/android/src/main/java/com/azzapp/rnskv/GLFrameExtractor.java +510 -0
  52. package/android/src/main/java/com/azzapp/rnskv/JNIHelpers.java +12 -0
  53. package/android/src/main/java/com/azzapp/rnskv/NativeEventDispatcher.java +25 -0
  54. package/android/src/main/java/com/azzapp/rnskv/NativeHardwareBuffer.java +62 -0
  55. package/android/src/main/java/com/azzapp/rnskv/NativeRgbaBuffer.java +43 -0
  56. package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoModule.java +45 -0
  57. package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoPackage.java +43 -0
  58. package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoSpec.java +9 -0
  59. package/android/src/main/java/com/azzapp/rnskv/RgbaBufferAllocator.java +114 -0
  60. package/android/src/main/java/com/azzapp/rnskv/RgbaLayout.java +33 -0
  61. package/android/src/main/java/com/azzapp/rnskv/SurfaceOutputPolicy.java +13 -0
  62. package/android/src/main/java/com/azzapp/rnskv/TextureRenderer.java +150 -0
  63. package/android/src/main/java/com/azzapp/rnskv/TimeHelpers.java +11 -0
  64. package/android/src/main/java/com/azzapp/rnskv/VideoCapabilities.java +354 -0
  65. package/android/src/main/java/com/azzapp/rnskv/VideoComposition.java +147 -0
  66. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionDecoder.java +779 -0
  67. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractor.java +463 -0
  68. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractorSync.java +241 -0
  69. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionItemDecoder.java +492 -0
  70. package/android/src/main/java/com/azzapp/rnskv/VideoEncoder.java +639 -0
  71. package/android/src/main/java/com/azzapp/rnskv/VideoFrame.java +74 -0
  72. package/android/src/main/java/com/azzapp/rnskv/VideoPlayer.java +361 -0
  73. package/cpp/RNSVCheckedSizes.h +54 -0
  74. package/cpp/RNSVEventEmitter.cpp +199 -0
  75. package/cpp/RNSVEventEmitter.h +31 -0
  76. package/cpp/RNSVHostObject.cpp +79 -0
  77. package/cpp/RNSVHostObject.h +67 -0
  78. package/cpp/RNSVMemoryBudget.cpp +68 -0
  79. package/cpp/RNSVMemoryBudget.h +100 -0
  80. package/cpp/RNSVRuntimeLifecycleMonitor.cpp +88 -0
  81. package/cpp/RNSVRuntimeLifecycleMonitor.h +33 -0
  82. package/docs/ANDROID_DEVICE_306.md +95 -0
  83. package/docs/ANDROID_EXPORT_CACHE_306.md +48 -0
  84. package/docs/ANDROID_MEMORY_RETENTION_306.md +67 -0
  85. package/docs/BENCHMARKS.md +368 -0
  86. package/docs/IOS_DEVICE_TESTS.md +115 -0
  87. package/docs/IOS_SIMULATOR_TESTS.md +74 -0
  88. package/docs/MIGRATION.md +82 -0
  89. package/docs/NATIVE_MEMORY_INVESTIGATION_306.md +88 -0
  90. package/docs/PERFORMANCE_AB_IPHONE_303.md +196 -0
  91. package/docs/PERFORMANCE_AB_SIMULATOR.md +135 -0
  92. package/docs/PERFORMANCE_AB_SOAK_SIMULATOR.md +84 -0
  93. package/docs/PERFORMANCE_IPHONE_306_OPTIMIZATION.md +76 -0
  94. package/docs/PERFORMANCE_SIMULATOR.md +89 -0
  95. package/docs/PERFORMANCE_SIMULATOR_INITIAL.md +96 -0
  96. package/docs/PERFORMANCE_SOAK_IPHONE_303.md +41 -0
  97. package/docs/UPSTREAM_NOTES.md +188 -0
  98. package/docs/assets/banner.svg +26 -0
  99. package/examples/webgpu-overlay.ts +147 -0
  100. package/ios/AVAssetTrackUtils.h +24 -0
  101. package/ios/AudioCompositionUtils.h +27 -0
  102. package/ios/AudioCompositionUtils.mm +113 -0
  103. package/ios/DecoderWindow.h +52 -0
  104. package/ios/NativeResourceStats.h +32 -0
  105. package/ios/RNSVColorSpace.h +50 -0
  106. package/ios/RNSVJSIUtils.h +46 -0
  107. package/ios/RNSVScopedPixelBuffer.h +17 -0
  108. package/ios/RNSVVideoPlayer.h +46 -0
  109. package/ios/RNSVVideoPlayer.mm +410 -0
  110. package/ios/ReactNativeSkiaVideo.h +8 -0
  111. package/ios/ReactNativeSkiaVideo.mm +310 -0
  112. package/ios/SeekPolicy.h +27 -0
  113. package/ios/VideoComposition.h +148 -0
  114. package/ios/VideoCompositionFramesExtractorHostObject.h +105 -0
  115. package/ios/VideoCompositionFramesExtractorHostObject.mm +686 -0
  116. package/ios/VideoCompositionFramesExtractorSyncHostObject.h +37 -0
  117. package/ios/VideoCompositionFramesExtractorSyncHostObject.mm +168 -0
  118. package/ios/VideoCompositionItemDecoder.h +60 -0
  119. package/ios/VideoCompositionItemDecoder.mm +480 -0
  120. package/ios/VideoEncoderHostObject.h +83 -0
  121. package/ios/VideoEncoderHostObject.mm +706 -0
  122. package/ios/VideoFrame.h +66 -0
  123. package/ios/VideoFrame.mm +108 -0
  124. package/ios/VideoPlayerHostObject.h +52 -0
  125. package/ios/VideoPlayerHostObject.mm +332 -0
  126. package/lib/module/NativeReactNativeSkiaVideo.js +5 -0
  127. package/lib/module/NativeReactNativeSkiaVideo.js.map +1 -0
  128. package/lib/module/RNSkiaVideoModule.js +20 -0
  129. package/lib/module/RNSkiaVideoModule.js.map +1 -0
  130. package/lib/module/canvas.js +18 -0
  131. package/lib/module/canvas.js.map +1 -0
  132. package/lib/module/exportCache.js +22 -0
  133. package/lib/module/exportCache.js.map +1 -0
  134. package/lib/module/exportFrames.js +338 -0
  135. package/lib/module/exportFrames.js.map +1 -0
  136. package/lib/module/exportQueue.js +52 -0
  137. package/lib/module/exportQueue.js.map +1 -0
  138. package/lib/module/exportTarget.js +137 -0
  139. package/lib/module/exportTarget.js.map +1 -0
  140. package/lib/module/exportVideoComposition.js +492 -0
  141. package/lib/module/exportVideoComposition.js.map +1 -0
  142. package/lib/module/frameInterop.js +532 -0
  143. package/lib/module/frameInterop.js.map +1 -0
  144. package/lib/module/gpu.js +222 -0
  145. package/lib/module/gpu.js.map +1 -0
  146. package/lib/module/gpuDevice.js +54 -0
  147. package/lib/module/gpuDevice.js.map +1 -0
  148. package/lib/module/index.js +36 -0
  149. package/lib/module/index.js.map +1 -0
  150. package/lib/module/memory.js +38 -0
  151. package/lib/module/memory.js.map +1 -0
  152. package/lib/module/package.json +1 -0
  153. package/lib/module/previewLifecycle.js +52 -0
  154. package/lib/module/previewLifecycle.js.map +1 -0
  155. package/lib/module/runtimeYield.js +10 -0
  156. package/lib/module/runtimeYield.js.map +1 -0
  157. package/lib/module/types.js +4 -0
  158. package/lib/module/types.js.map +1 -0
  159. package/lib/module/utils/useEventListener.js +18 -0
  160. package/lib/module/utils/useEventListener.js.map +1 -0
  161. package/lib/module/videoCompositionPlayer.js +368 -0
  162. package/lib/module/videoCompositionPlayer.js.map +1 -0
  163. package/lib/module/videoFrameImage.js +185 -0
  164. package/lib/module/videoFrameImage.js.map +1 -0
  165. package/lib/module/videoPlayer.js +172 -0
  166. package/lib/module/videoPlayer.js.map +1 -0
  167. package/lib/module/yuvBlit.js +299 -0
  168. package/lib/module/yuvBlit.js.map +1 -0
  169. package/lib/typescript/package.json +1 -0
  170. package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts +7 -0
  171. package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts.map +1 -0
  172. package/lib/typescript/src/RNSkiaVideoModule.d.ts +4 -0
  173. package/lib/typescript/src/RNSkiaVideoModule.d.ts.map +1 -0
  174. package/lib/typescript/src/canvas.d.ts +4 -0
  175. package/lib/typescript/src/canvas.d.ts.map +1 -0
  176. package/lib/typescript/src/exportCache.d.ts +6 -0
  177. package/lib/typescript/src/exportCache.d.ts.map +1 -0
  178. package/lib/typescript/src/exportFrames.d.ts +57 -0
  179. package/lib/typescript/src/exportFrames.d.ts.map +1 -0
  180. package/lib/typescript/src/exportQueue.d.ts +5 -0
  181. package/lib/typescript/src/exportQueue.d.ts.map +1 -0
  182. package/lib/typescript/src/exportTarget.d.ts +28 -0
  183. package/lib/typescript/src/exportTarget.d.ts.map +1 -0
  184. package/lib/typescript/src/exportVideoComposition.d.ts +68 -0
  185. package/lib/typescript/src/exportVideoComposition.d.ts.map +1 -0
  186. package/lib/typescript/src/frameInterop.d.ts +17 -0
  187. package/lib/typescript/src/frameInterop.d.ts.map +1 -0
  188. package/lib/typescript/src/gpu.d.ts +39 -0
  189. package/lib/typescript/src/gpu.d.ts.map +1 -0
  190. package/lib/typescript/src/gpuDevice.d.ts +11 -0
  191. package/lib/typescript/src/gpuDevice.d.ts.map +1 -0
  192. package/lib/typescript/src/index.d.ts +21 -0
  193. package/lib/typescript/src/index.d.ts.map +1 -0
  194. package/lib/typescript/src/memory.d.ts +25 -0
  195. package/lib/typescript/src/memory.d.ts.map +1 -0
  196. package/lib/typescript/src/previewLifecycle.d.ts +22 -0
  197. package/lib/typescript/src/previewLifecycle.d.ts.map +1 -0
  198. package/lib/typescript/src/runtimeYield.d.ts +4 -0
  199. package/lib/typescript/src/runtimeYield.d.ts.map +1 -0
  200. package/lib/typescript/src/types.d.ts +631 -0
  201. package/lib/typescript/src/types.d.ts.map +1 -0
  202. package/lib/typescript/src/utils/useEventListener.d.ts +5 -0
  203. package/lib/typescript/src/utils/useEventListener.d.ts.map +1 -0
  204. package/lib/typescript/src/videoCompositionPlayer.d.ts +105 -0
  205. package/lib/typescript/src/videoCompositionPlayer.d.ts.map +1 -0
  206. package/lib/typescript/src/videoFrameImage.d.ts +60 -0
  207. package/lib/typescript/src/videoFrameImage.d.ts.map +1 -0
  208. package/lib/typescript/src/videoPlayer.d.ts +99 -0
  209. package/lib/typescript/src/videoPlayer.d.ts.map +1 -0
  210. package/lib/typescript/src/yuvBlit.d.ts +50 -0
  211. package/lib/typescript/src/yuvBlit.d.ts.map +1 -0
  212. package/package.json +155 -4
  213. package/patches/react-native-skia+3.7.0.patch +502 -0
  214. package/react-native-skia-webgpu-video.podspec +35 -0
  215. package/scripts/apply-skia-canvas-patch.mjs +48 -0
  216. package/scripts/skia-canvas-patch.json +291 -0
  217. package/src/NativeReactNativeSkiaVideo.ts +8 -0
  218. package/src/RNSkiaVideoModule.ts +27 -0
  219. package/src/canvas.ts +22 -0
  220. package/src/exportCache.ts +27 -0
  221. package/src/exportFrames.ts +421 -0
  222. package/src/exportQueue.ts +65 -0
  223. package/src/exportTarget.ts +179 -0
  224. package/src/exportVideoComposition.ts +718 -0
  225. package/src/frameInterop.ts +684 -0
  226. package/src/gpu.ts +290 -0
  227. package/src/gpuDevice.ts +80 -0
  228. package/src/index.tsx +45 -0
  229. package/src/memory.ts +48 -0
  230. package/src/previewLifecycle.ts +60 -0
  231. package/src/runtimeYield.ts +6 -0
  232. package/src/types.ts +661 -0
  233. package/src/utils/useEventListener.ts +22 -0
  234. package/src/videoCompositionPlayer.ts +568 -0
  235. package/src/videoFrameImage.ts +205 -0
  236. package/src/videoPlayer.ts +318 -0
  237. 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,9 @@
1
+ package com.azzapp.rnskv;
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext;
4
+
5
+ abstract class ReactNativeSkiaVideoSpec extends NativeReactNativeSkiaVideoSpec {
6
+ ReactNativeSkiaVideoSpec(ReactApplicationContext context) {
7
+ super(context);
8
+ }
9
+ }
@@ -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
+ }
@@ -0,0 +1,11 @@
1
+ package com.azzapp.rnskv;
2
+
3
+ public class TimeHelpers {
4
+ public static long secToUs(double sec) {
5
+ return Math.round(sec * 1000000);
6
+ }
7
+
8
+ public static long nsecToUs(long nsec) {
9
+ return Math.round(nsec / 1000);
10
+ }
11
+ }