react-native-skia-webgpu-video 0.0.0-stage → 0.1.0-beta.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.
Files changed (236) 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/EGLResourcesHolder.java +132 -0
  48. package/android/src/main/java/com/azzapp/rnskv/EGLUtils.java +225 -0
  49. package/android/src/main/java/com/azzapp/rnskv/FrameSize.java +50 -0
  50. package/android/src/main/java/com/azzapp/rnskv/GLFrameExtractor.java +510 -0
  51. package/android/src/main/java/com/azzapp/rnskv/JNIHelpers.java +12 -0
  52. package/android/src/main/java/com/azzapp/rnskv/NativeEventDispatcher.java +25 -0
  53. package/android/src/main/java/com/azzapp/rnskv/NativeHardwareBuffer.java +62 -0
  54. package/android/src/main/java/com/azzapp/rnskv/NativeRgbaBuffer.java +35 -0
  55. package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoModule.java +45 -0
  56. package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoPackage.java +43 -0
  57. package/android/src/main/java/com/azzapp/rnskv/ReactNativeSkiaVideoSpec.java +9 -0
  58. package/android/src/main/java/com/azzapp/rnskv/RgbaBufferAllocator.java +83 -0
  59. package/android/src/main/java/com/azzapp/rnskv/RgbaLayout.java +33 -0
  60. package/android/src/main/java/com/azzapp/rnskv/SurfaceOutputPolicy.java +13 -0
  61. package/android/src/main/java/com/azzapp/rnskv/TextureRenderer.java +150 -0
  62. package/android/src/main/java/com/azzapp/rnskv/TimeHelpers.java +11 -0
  63. package/android/src/main/java/com/azzapp/rnskv/VideoCapabilities.java +354 -0
  64. package/android/src/main/java/com/azzapp/rnskv/VideoComposition.java +147 -0
  65. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionDecoder.java +772 -0
  66. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractor.java +354 -0
  67. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionFramesExtractorSync.java +241 -0
  68. package/android/src/main/java/com/azzapp/rnskv/VideoCompositionItemDecoder.java +492 -0
  69. package/android/src/main/java/com/azzapp/rnskv/VideoEncoder.java +639 -0
  70. package/android/src/main/java/com/azzapp/rnskv/VideoFrame.java +74 -0
  71. package/android/src/main/java/com/azzapp/rnskv/VideoPlayer.java +361 -0
  72. package/cpp/RNSVCheckedSizes.h +54 -0
  73. package/cpp/RNSVEventEmitter.cpp +199 -0
  74. package/cpp/RNSVEventEmitter.h +31 -0
  75. package/cpp/RNSVHostObject.cpp +79 -0
  76. package/cpp/RNSVHostObject.h +67 -0
  77. package/cpp/RNSVMemoryBudget.cpp +68 -0
  78. package/cpp/RNSVMemoryBudget.h +100 -0
  79. package/cpp/RNSVRuntimeLifecycleMonitor.cpp +88 -0
  80. package/cpp/RNSVRuntimeLifecycleMonitor.h +33 -0
  81. package/docs/ANDROID_DEVICE_306.md +95 -0
  82. package/docs/ANDROID_EXPORT_CACHE_306.md +48 -0
  83. package/docs/ANDROID_MEMORY_RETENTION_306.md +67 -0
  84. package/docs/BENCHMARKS.md +368 -0
  85. package/docs/IOS_DEVICE_TESTS.md +115 -0
  86. package/docs/IOS_SIMULATOR_TESTS.md +74 -0
  87. package/docs/MIGRATION.md +82 -0
  88. package/docs/NATIVE_MEMORY_INVESTIGATION_306.md +88 -0
  89. package/docs/PERFORMANCE_AB_IPHONE_303.md +196 -0
  90. package/docs/PERFORMANCE_AB_SIMULATOR.md +135 -0
  91. package/docs/PERFORMANCE_AB_SOAK_SIMULATOR.md +84 -0
  92. package/docs/PERFORMANCE_IPHONE_306_OPTIMIZATION.md +76 -0
  93. package/docs/PERFORMANCE_SIMULATOR.md +89 -0
  94. package/docs/PERFORMANCE_SIMULATOR_INITIAL.md +96 -0
  95. package/docs/PERFORMANCE_SOAK_IPHONE_303.md +41 -0
  96. package/docs/UPSTREAM_NOTES.md +188 -0
  97. package/docs/assets/banner.svg +26 -0
  98. package/examples/webgpu-overlay.ts +147 -0
  99. package/ios/AVAssetTrackUtils.h +24 -0
  100. package/ios/AudioCompositionUtils.h +27 -0
  101. package/ios/AudioCompositionUtils.mm +113 -0
  102. package/ios/DecoderWindow.h +52 -0
  103. package/ios/NativeResourceStats.h +32 -0
  104. package/ios/RNSVColorSpace.h +50 -0
  105. package/ios/RNSVJSIUtils.h +46 -0
  106. package/ios/RNSVScopedPixelBuffer.h +17 -0
  107. package/ios/RNSVVideoPlayer.h +46 -0
  108. package/ios/RNSVVideoPlayer.mm +410 -0
  109. package/ios/ReactNativeSkiaVideo.h +8 -0
  110. package/ios/ReactNativeSkiaVideo.mm +310 -0
  111. package/ios/SeekPolicy.h +27 -0
  112. package/ios/VideoComposition.h +148 -0
  113. package/ios/VideoCompositionFramesExtractorHostObject.h +105 -0
  114. package/ios/VideoCompositionFramesExtractorHostObject.mm +686 -0
  115. package/ios/VideoCompositionFramesExtractorSyncHostObject.h +37 -0
  116. package/ios/VideoCompositionFramesExtractorSyncHostObject.mm +168 -0
  117. package/ios/VideoCompositionItemDecoder.h +60 -0
  118. package/ios/VideoCompositionItemDecoder.mm +480 -0
  119. package/ios/VideoEncoderHostObject.h +83 -0
  120. package/ios/VideoEncoderHostObject.mm +706 -0
  121. package/ios/VideoFrame.h +66 -0
  122. package/ios/VideoFrame.mm +108 -0
  123. package/ios/VideoPlayerHostObject.h +52 -0
  124. package/ios/VideoPlayerHostObject.mm +332 -0
  125. package/lib/module/NativeReactNativeSkiaVideo.js +5 -0
  126. package/lib/module/NativeReactNativeSkiaVideo.js.map +1 -0
  127. package/lib/module/RNSkiaVideoModule.js +20 -0
  128. package/lib/module/RNSkiaVideoModule.js.map +1 -0
  129. package/lib/module/canvas.js +18 -0
  130. package/lib/module/canvas.js.map +1 -0
  131. package/lib/module/exportCache.js +22 -0
  132. package/lib/module/exportCache.js.map +1 -0
  133. package/lib/module/exportFrames.js +338 -0
  134. package/lib/module/exportFrames.js.map +1 -0
  135. package/lib/module/exportQueue.js +52 -0
  136. package/lib/module/exportQueue.js.map +1 -0
  137. package/lib/module/exportTarget.js +137 -0
  138. package/lib/module/exportTarget.js.map +1 -0
  139. package/lib/module/exportVideoComposition.js +492 -0
  140. package/lib/module/exportVideoComposition.js.map +1 -0
  141. package/lib/module/frameInterop.js +532 -0
  142. package/lib/module/frameInterop.js.map +1 -0
  143. package/lib/module/gpu.js +222 -0
  144. package/lib/module/gpu.js.map +1 -0
  145. package/lib/module/gpuDevice.js +54 -0
  146. package/lib/module/gpuDevice.js.map +1 -0
  147. package/lib/module/index.js +36 -0
  148. package/lib/module/index.js.map +1 -0
  149. package/lib/module/memory.js +38 -0
  150. package/lib/module/memory.js.map +1 -0
  151. package/lib/module/package.json +1 -0
  152. package/lib/module/previewLifecycle.js +52 -0
  153. package/lib/module/previewLifecycle.js.map +1 -0
  154. package/lib/module/runtimeYield.js +10 -0
  155. package/lib/module/runtimeYield.js.map +1 -0
  156. package/lib/module/types.js +4 -0
  157. package/lib/module/types.js.map +1 -0
  158. package/lib/module/utils/useEventListener.js +18 -0
  159. package/lib/module/utils/useEventListener.js.map +1 -0
  160. package/lib/module/videoCompositionPlayer.js +348 -0
  161. package/lib/module/videoCompositionPlayer.js.map +1 -0
  162. package/lib/module/videoFrameImage.js +185 -0
  163. package/lib/module/videoFrameImage.js.map +1 -0
  164. package/lib/module/videoPlayer.js +172 -0
  165. package/lib/module/videoPlayer.js.map +1 -0
  166. package/lib/module/yuvBlit.js +299 -0
  167. package/lib/module/yuvBlit.js.map +1 -0
  168. package/lib/typescript/package.json +1 -0
  169. package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts +7 -0
  170. package/lib/typescript/src/NativeReactNativeSkiaVideo.d.ts.map +1 -0
  171. package/lib/typescript/src/RNSkiaVideoModule.d.ts +4 -0
  172. package/lib/typescript/src/RNSkiaVideoModule.d.ts.map +1 -0
  173. package/lib/typescript/src/canvas.d.ts +4 -0
  174. package/lib/typescript/src/canvas.d.ts.map +1 -0
  175. package/lib/typescript/src/exportCache.d.ts +6 -0
  176. package/lib/typescript/src/exportCache.d.ts.map +1 -0
  177. package/lib/typescript/src/exportFrames.d.ts +57 -0
  178. package/lib/typescript/src/exportFrames.d.ts.map +1 -0
  179. package/lib/typescript/src/exportQueue.d.ts +5 -0
  180. package/lib/typescript/src/exportQueue.d.ts.map +1 -0
  181. package/lib/typescript/src/exportTarget.d.ts +28 -0
  182. package/lib/typescript/src/exportTarget.d.ts.map +1 -0
  183. package/lib/typescript/src/exportVideoComposition.d.ts +68 -0
  184. package/lib/typescript/src/exportVideoComposition.d.ts.map +1 -0
  185. package/lib/typescript/src/frameInterop.d.ts +17 -0
  186. package/lib/typescript/src/frameInterop.d.ts.map +1 -0
  187. package/lib/typescript/src/gpu.d.ts +39 -0
  188. package/lib/typescript/src/gpu.d.ts.map +1 -0
  189. package/lib/typescript/src/gpuDevice.d.ts +11 -0
  190. package/lib/typescript/src/gpuDevice.d.ts.map +1 -0
  191. package/lib/typescript/src/index.d.ts +21 -0
  192. package/lib/typescript/src/index.d.ts.map +1 -0
  193. package/lib/typescript/src/memory.d.ts +25 -0
  194. package/lib/typescript/src/memory.d.ts.map +1 -0
  195. package/lib/typescript/src/previewLifecycle.d.ts +22 -0
  196. package/lib/typescript/src/previewLifecycle.d.ts.map +1 -0
  197. package/lib/typescript/src/runtimeYield.d.ts +4 -0
  198. package/lib/typescript/src/runtimeYield.d.ts.map +1 -0
  199. package/lib/typescript/src/types.d.ts +631 -0
  200. package/lib/typescript/src/types.d.ts.map +1 -0
  201. package/lib/typescript/src/utils/useEventListener.d.ts +5 -0
  202. package/lib/typescript/src/utils/useEventListener.d.ts.map +1 -0
  203. package/lib/typescript/src/videoCompositionPlayer.d.ts +85 -0
  204. package/lib/typescript/src/videoCompositionPlayer.d.ts.map +1 -0
  205. package/lib/typescript/src/videoFrameImage.d.ts +60 -0
  206. package/lib/typescript/src/videoFrameImage.d.ts.map +1 -0
  207. package/lib/typescript/src/videoPlayer.d.ts +99 -0
  208. package/lib/typescript/src/videoPlayer.d.ts.map +1 -0
  209. package/lib/typescript/src/yuvBlit.d.ts +50 -0
  210. package/lib/typescript/src/yuvBlit.d.ts.map +1 -0
  211. package/package.json +154 -4
  212. package/patches/react-native-skia+3.7.0.patch +502 -0
  213. package/react-native-skia-webgpu-video.podspec +35 -0
  214. package/scripts/apply-skia-canvas-patch.mjs +48 -0
  215. package/scripts/skia-canvas-patch.json +291 -0
  216. package/src/NativeReactNativeSkiaVideo.ts +8 -0
  217. package/src/RNSkiaVideoModule.ts +27 -0
  218. package/src/canvas.ts +22 -0
  219. package/src/exportCache.ts +27 -0
  220. package/src/exportFrames.ts +421 -0
  221. package/src/exportQueue.ts +65 -0
  222. package/src/exportTarget.ts +179 -0
  223. package/src/exportVideoComposition.ts +718 -0
  224. package/src/frameInterop.ts +684 -0
  225. package/src/gpu.ts +290 -0
  226. package/src/gpuDevice.ts +80 -0
  227. package/src/index.tsx +45 -0
  228. package/src/memory.ts +48 -0
  229. package/src/previewLifecycle.ts +60 -0
  230. package/src/runtimeYield.ts +6 -0
  231. package/src/types.ts +661 -0
  232. package/src/utils/useEventListener.ts +22 -0
  233. package/src/videoCompositionPlayer.ts +520 -0
  234. package/src/videoFrameImage.ts +205 -0
  235. package/src/videoPlayer.ts +318 -0
  236. package/src/yuvBlit.ts +331 -0
@@ -0,0 +1,37 @@
1
+ #pragma once
2
+
3
+ #import "DecoderWindow.h"
4
+ #import "RNSVHostObject.h"
5
+ #import "VideoComposition.h"
6
+ #import "VideoCompositionItemDecoder.h"
7
+ #import "VideoFrame.h"
8
+ #import <AVFoundation/AVFoundation.h>
9
+ #import <jsi/jsi.h>
10
+ #import <map>
11
+
12
+ namespace RNSkiaVideo {
13
+ using namespace facebook;
14
+
15
+ class JSI_EXPORT VideoCompositionFramesExtractorSyncHostObject
16
+ : public RNSVHostObject {
17
+ public:
18
+ VideoCompositionFramesExtractorSyncHostObject(
19
+ std::shared_ptr<VideoComposition> composition);
20
+ ~VideoCompositionFramesExtractorSyncHostObject();
21
+ jsi::Value get(jsi::Runtime&, const jsi::PropNameID& name) override;
22
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& rt) override;
23
+
24
+ private:
25
+ NSObject* lock;
26
+ bool disposed = false;
27
+ bool started = false;
28
+ std::shared_ptr<VideoComposition> composition;
29
+ DecoderWindow window;
30
+ std::map<std::string, std::shared_ptr<VideoCompositionItemDecoder>>
31
+ itemDecoders;
32
+ std::map<std::string, std::shared_ptr<VideoFrame>> currentFrames;
33
+ void release();
34
+ void updateWindow(CMTime time);
35
+ };
36
+
37
+ } // namespace RNSkiaVideo
@@ -0,0 +1,168 @@
1
+ #include "VideoCompositionFramesExtractorSyncHostObject.h"
2
+
3
+ #import "AVAssetTrackUtils.h"
4
+ #import "RNSVJSIUtils.h"
5
+ #include "RNSVCheckedSizes.h"
6
+ #import <AVFoundation/AVFoundation.h>
7
+ #import <Foundation/Foundation.h>
8
+ #import <future>
9
+
10
+ namespace RNSkiaVideo {
11
+
12
+ VideoCompositionFramesExtractorSyncHostObject::
13
+ VideoCompositionFramesExtractorSyncHostObject(
14
+ std::shared_ptr<VideoComposition> composition)
15
+ : composition(composition), window(composition->lazyDecoders, false) {
16
+ lock = [[NSObject alloc] init];
17
+ }
18
+
19
+ VideoCompositionFramesExtractorSyncHostObject::
20
+ ~VideoCompositionFramesExtractorSyncHostObject() {
21
+ this->release();
22
+ }
23
+
24
+ std::vector<jsi::PropNameID>
25
+ VideoCompositionFramesExtractorSyncHostObject::getPropertyNames(
26
+ jsi::Runtime& rt) {
27
+ std::vector<jsi::PropNameID> result;
28
+ result.push_back(jsi::PropNameID::forUtf8(rt, std::string("start")));
29
+ result.push_back(
30
+ jsi::PropNameID::forUtf8(rt, std::string("decodeCompositionFrames")));
31
+ result.push_back(jsi::PropNameID::forUtf8(rt, std::string("dispose")));
32
+ return result;
33
+ }
34
+
35
+ // The methods are created once per runtime (see RNSVHostObject):
36
+ // `decodeCompositionFrames` is read for every exported frame.
37
+ jsi::Value VideoCompositionFramesExtractorSyncHostObject::get(
38
+ jsi::Runtime& runtime, const jsi::PropNameID& propNameId) {
39
+ auto propName = propNameId.utf8(runtime);
40
+ if (propName == "start") {
41
+ return getFunction(
42
+ runtime, propName, 0,
43
+ [this](jsi::Runtime& runtime, const jsi::Value& thisValue,
44
+ const jsi::Value* arguments, size_t count) -> jsi::Value {
45
+ return runPooled([&] {
46
+ @synchronized(lock) {
47
+ if (disposed) throw std::runtime_error("Extractor is disposed");
48
+ if (started) return;
49
+ try {
50
+ for (const auto& item : composition->items) {
51
+ if (!item->isVideo ||
52
+ !window.opens(item->compositionStartTime,
53
+ item->compositionStartTime + item->duration,
54
+ 0, composition->duration, false)) {
55
+ continue;
56
+ }
57
+ itemDecoders[item->id] =
58
+ std::make_shared<VideoCompositionItemDecoder>(item, false);
59
+ }
60
+ started = true;
61
+ } catch (...) {
62
+ itemDecoders.clear();
63
+ throw;
64
+ }
65
+ }
66
+ });
67
+ });
68
+ } else if (propName == "decodeCompositionFrames") {
69
+ return getFunction(
70
+ runtime, propName, 1,
71
+ [this](jsi::Runtime& runtime, const jsi::Value& thisValue,
72
+ const jsi::Value* arguments, size_t count) -> jsi::Value {
73
+ if (count < 1 || !arguments[0].isNumber())
74
+ throw jsi::JSError(runtime, "decodeCompositionFrames expects media seconds");
75
+ auto currentTime = CMTimeMakeWithSeconds(
76
+ checkedMediaSeconds(arguments[0].asNumber()), NSEC_PER_SEC);
77
+ return runPooled([&]() -> jsi::Value {
78
+ @synchronized(lock) {
79
+ if (disposed) throw std::runtime_error("Extractor is disposed");
80
+ auto frames = jsi::Object(runtime);
81
+ updateWindow(currentTime);
82
+ for (const auto& entry : itemDecoders) {
83
+ auto itemId = entry.first;
84
+ auto decoder = entry.second;
85
+
86
+ decoder->advanceDecoder(currentTime);
87
+
88
+ auto previousFrame = currentFrames[itemId];
89
+ auto frame =
90
+ decoder->acquireFrameForTime(currentTime, !previousFrame);
91
+ if (frame) {
92
+ currentFrames[itemId] = frame;
93
+ } else {
94
+ frame = previousFrame;
95
+ }
96
+ if (frame) {
97
+ frames.setProperty(
98
+ runtime, entry.first.c_str(),
99
+ jsi::Object::createFromHostObject(runtime, frame));
100
+ }
101
+ }
102
+ return frames;
103
+ }
104
+ });
105
+ });
106
+ } else if (propName == "dispose") {
107
+ return getFunction(
108
+ runtime, propName, 0,
109
+ [this](jsi::Runtime& runtime, const jsi::Value& thisValue,
110
+ const jsi::Value* arguments, size_t count) -> jsi::Value {
111
+ return runPooled([&] { this->release(); });
112
+ });
113
+ }
114
+ return jsi::Value::undefined();
115
+ }
116
+
117
+ void VideoCompositionFramesExtractorSyncHostObject::release() {
118
+ @synchronized(lock) {
119
+ if (disposed) return;
120
+ disposed = true;
121
+ try {
122
+ for (const auto& entry : itemDecoders) {
123
+ auto decoder = entry.second;
124
+ if (decoder) {
125
+ entry.second->release();
126
+ }
127
+ }
128
+ } catch (...) {
129
+ }
130
+ itemDecoders.clear();
131
+ currentFrames.clear();
132
+ }
133
+ }
134
+
135
+ // Opens the decoders of the items coming up and closes those left behind.
136
+ void VideoCompositionFramesExtractorSyncHostObject::updateWindow(CMTime time) {
137
+ if (!window.isLazy()) {
138
+ return;
139
+ }
140
+ double position = CMTimeGetSeconds(time);
141
+ for (const auto& item : composition->items) {
142
+ if (!item->isVideo) {
143
+ continue;
144
+ }
145
+ double start = item->compositionStartTime;
146
+ double end = start + item->duration;
147
+ auto it = itemDecoders.find(item->id);
148
+ if (it == itemDecoders.end()) {
149
+ if (window.opens(start, end, position, composition->duration, false)) {
150
+ #if defined(RNSV_TRACE_LIFECYCLE) && RNSV_TRACE_LIFECYCLE
151
+ NSLog(@"[rnskv] export open %s at %.3fs", item->id.c_str(), position);
152
+ #endif
153
+ itemDecoders[item->id] = std::make_shared<VideoCompositionItemDecoder>(
154
+ item, false, nil, time);
155
+ }
156
+ } else if (!window.keeps(start, end, position, composition->duration,
157
+ false)) {
158
+ #if defined(RNSV_TRACE_LIFECYCLE) && RNSV_TRACE_LIFECYCLE
159
+ NSLog(@"[rnskv] export close %s at %.3fs", item->id.c_str(), position);
160
+ #endif
161
+ it->second->release();
162
+ itemDecoders.erase(it);
163
+ currentFrames.erase(item->id);
164
+ }
165
+ }
166
+ }
167
+
168
+ } // namespace RNSkiaVideo
@@ -0,0 +1,60 @@
1
+ #pragma once
2
+
3
+ #import "SeekPolicy.h"
4
+ #import "VideoComposition.h"
5
+ #import "VideoFrame.h"
6
+ #import <AVFoundation/AVFoundation.h>
7
+ #import <list>
8
+ #include <atomic>
9
+ #include <mutex>
10
+
11
+ using namespace facebook;
12
+
13
+ namespace RNSkiaVideo {
14
+
15
+ class VideoCompositionItemDecoder {
16
+ public:
17
+ VideoCompositionItemDecoder(std::shared_ptr<VideoCompositionItem> item,
18
+ bool realTime, AVURLAsset* sharedAsset = nil,
19
+ CMTime initialTime = kCMTimeZero);
20
+ ~VideoCompositionItemDecoder();
21
+ void advanceDecoder(CMTime currentTime);
22
+ void seekTo(CMTime currentTime);
23
+ std::shared_ptr<VideoFrame> acquireFrameForTime(CMTime currentTime,
24
+ bool force);
25
+ void release();
26
+
27
+ private:
28
+ NSObject* lock;
29
+ // AVAssetReader cancelReading tears down its internal decode context.
30
+ // It must never race a copyNextSampleBuffer call on that same reader.
31
+ std::mutex readerMutex;
32
+ bool realTime = false;
33
+ bool hasLooped = false;
34
+ // Bumped when the reader is replaced/released; reading a forward seek on
35
+ // keeps its queued samples and outstanding batch in the same generation.
36
+ uint64_t readerGeneration = 0;
37
+ std::shared_ptr<VideoCompositionItem> item;
38
+ double width;
39
+ double height;
40
+ int rotation;
41
+ AVURLAsset* asset;
42
+ AVAssetTrack* videoTrack;
43
+ AVAssetReader* assetReader;
44
+ std::list<std::pair<double, CMSampleBufferRef>> decodedFrames;
45
+ std::list<std::pair<double, CMSampleBufferRef>> nextLoopFrames;
46
+ CMTime lastRequestedTime = kCMTimeInvalid;
47
+ std::shared_ptr<VideoFrame> currentFrame;
48
+ VideoFrameRing frameRing;
49
+ uint64_t producerId = allocateVideoProducerId();
50
+ bool counted = false;
51
+ std::atomic<bool> released{false};
52
+
53
+ void setupReader(CMTime initialTime);
54
+ /** Drops the reader and its decoded frames, keeping the issued ones. */
55
+ void discardReader();
56
+ std::shared_ptr<VideoFrame> makeFrame(CVPixelBufferRef buffer,
57
+ uint64_t memoryToken);
58
+ };
59
+
60
+ } // namespace RNSkiaVideo