react-native-webgpu 0.11.0 → 0.11.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/android/cpp/AndroidPlatformContext.h +42 -8
- package/android/cpp/AndroidVideoPlayer.h +307 -0
- package/android/src/main/java/com/webgpu/WebGPUModule.java +10 -0
- package/android/src/main/java/com/webgpu/WebGPUVideoPlayer.java +420 -0
- package/apple/AppleVideoPlayer.mm +157 -47
- package/cpp/rnwgpu/PlatformContext.h +25 -5
- package/cpp/rnwgpu/api/GPUDevice.cpp +2 -1
- package/cpp/rnwgpu/api/GPUDevice.h +6 -0
- package/cpp/rnwgpu/api/GPUQueue.cpp +80 -10
- package/cpp/rnwgpu/api/GPUQueue.h +15 -4
- package/cpp/rnwgpu/api/VideoFrameBlit.h +355 -0
- package/cpp/rnwgpu/api/VideoPlayer.h +50 -3
- package/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h +30 -3
- package/lib/commonjs/importDevice.js +2 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/main/index.js +12 -0
- package/lib/commonjs/main/index.js.map +1 -1
- package/lib/commonjs/main/index.web.js +11 -0
- package/lib/commonjs/main/index.web.js.map +1 -1
- package/lib/commonjs/video.js +58 -0
- package/lib/commonjs/video.js.map +1 -0
- package/lib/module/importDevice.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/main/index.js +1 -0
- package/lib/module/main/index.js.map +1 -1
- package/lib/module/main/index.web.js +1 -0
- package/lib/module/main/index.web.js.map +1 -1
- package/lib/module/video.js +49 -0
- package/lib/module/video.js.map +1 -0
- package/lib/typescript/lib/commonjs/video.d.ts +30 -0
- package/lib/typescript/lib/commonjs/video.d.ts.map +1 -0
- package/lib/typescript/lib/module/main/index.d.ts +1 -0
- package/lib/typescript/lib/module/main/index.web.d.ts +1 -0
- package/lib/typescript/lib/module/video.d.ts +4 -0
- package/lib/typescript/lib/module/video.d.ts.map +1 -0
- package/lib/typescript/src/importDevice.d.ts +2 -2
- package/lib/typescript/src/index.d.ts +5 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/main/index.d.ts +1 -0
- package/lib/typescript/src/main/index.d.ts.map +1 -1
- package/lib/typescript/src/main/index.web.d.ts +1 -0
- package/lib/typescript/src/main/index.web.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +19 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/video.d.ts +41 -0
- package/lib/typescript/src/video.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/importDevice.ts +2 -2
- package/src/index.tsx +28 -3
- package/src/main/index.tsx +1 -0
- package/src/main/index.web.tsx +1 -0
- package/src/types.ts +60 -7
- package/src/video.ts +69 -0
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
#include "webgpu/webgpu_cpp.h"
|
|
15
15
|
|
|
16
|
+
#include "AndroidVideoPlayer.h"
|
|
16
17
|
#include "PlatformContext.h"
|
|
17
18
|
#include "RNWebGPUManager.h"
|
|
18
19
|
|
|
@@ -112,8 +113,8 @@ public:
|
|
|
112
113
|
}
|
|
113
114
|
// Ownership passes to Java; Java_com_webgpu_WebGPUModule_onViewSnapshot
|
|
114
115
|
// (cpp-adapter.cpp) reclaims it.
|
|
115
|
-
auto *callbacks =
|
|
116
|
-
|
|
116
|
+
auto *callbacks =
|
|
117
|
+
new ViewSnapshotCallbacks{std::move(onSuccess), std::move(onError)};
|
|
117
118
|
env->CallVoidMethod(_module, method, static_cast<jint>(request.viewTag),
|
|
118
119
|
static_cast<jdouble>(request.sourceX),
|
|
119
120
|
static_cast<jdouble>(request.sourceY),
|
|
@@ -236,8 +237,9 @@ public:
|
|
|
236
237
|
result.height = static_cast<int>(bitmapInfo.height);
|
|
237
238
|
result.data.resize(bitmapInfo.height * bitmapInfo.stride);
|
|
238
239
|
memcpy(result.data.data(), bitmapPixels, result.data.size());
|
|
239
|
-
// BitmapFactory hands back premultiplied ARGB_8888 pixels;
|
|
240
|
-
// converts to the representation requested by
|
|
240
|
+
// BitmapFactory hands back premultiplied ARGB_8888 pixels;
|
|
241
|
+
// createImageBitmap converts to the representation requested by
|
|
242
|
+
// premultiplyAlpha.
|
|
241
243
|
result.premultiplied = true;
|
|
242
244
|
|
|
243
245
|
AndroidBitmap_unlockPixels(env, bitmap);
|
|
@@ -339,12 +341,44 @@ public:
|
|
|
339
341
|
return handle;
|
|
340
342
|
}
|
|
341
343
|
|
|
344
|
+
// The decoder writes its native YUV layout whatever format is requested:
|
|
345
|
+
// the frames are sampled through importExternalTexture (see
|
|
346
|
+
// WebGPUVideoPlayer.java).
|
|
342
347
|
std::unique_ptr<IVideoPlayer>
|
|
343
|
-
createVideoPlayer(const std::string &
|
|
348
|
+
createVideoPlayer(const std::string &path,
|
|
344
349
|
VideoPixelFormat /*format*/) override {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
350
|
+
if (!_module) {
|
|
351
|
+
throw std::runtime_error("createVideoPlayer: the WebGPU module is gone");
|
|
352
|
+
}
|
|
353
|
+
jni::Environment::ensureCurrentThreadIsAttached();
|
|
354
|
+
JNIEnv *env = facebook::jni::Environment::current();
|
|
355
|
+
if (!env) {
|
|
356
|
+
throw std::runtime_error(
|
|
357
|
+
"createVideoPlayer: couldn't get the JNI environment");
|
|
358
|
+
}
|
|
359
|
+
jclass moduleClass = env->GetObjectClass(_module);
|
|
360
|
+
jmethodID method =
|
|
361
|
+
env->GetMethodID(moduleClass, "createVideoPlayer",
|
|
362
|
+
"(Ljava/lang/String;)Lcom/webgpu/WebGPUVideoPlayer;");
|
|
363
|
+
env->DeleteLocalRef(moduleClass);
|
|
364
|
+
if (!method) {
|
|
365
|
+
env->ExceptionClear();
|
|
366
|
+
throw std::runtime_error(
|
|
367
|
+
"createVideoPlayer: WebGPUModule.createVideoPlayer not found");
|
|
368
|
+
}
|
|
369
|
+
jstring jPath = env->NewStringUTF(path.c_str());
|
|
370
|
+
jobject player = env->CallObjectMethod(_module, method, jPath);
|
|
371
|
+
env->DeleteLocalRef(jPath);
|
|
372
|
+
if (env->ExceptionCheck()) {
|
|
373
|
+
throw std::runtime_error("createVideoPlayer: " +
|
|
374
|
+
describeAndClearJavaException(env));
|
|
375
|
+
}
|
|
376
|
+
if (player == nullptr) {
|
|
377
|
+
throw std::runtime_error("createVideoPlayer: no player was created");
|
|
378
|
+
}
|
|
379
|
+
auto result = std::make_unique<AndroidVideoPlayer>(env, player);
|
|
380
|
+
env->DeleteLocalRef(player);
|
|
381
|
+
return result;
|
|
348
382
|
}
|
|
349
383
|
|
|
350
384
|
std::string writeTestVideoFile() override {
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <android/hardware_buffer.h>
|
|
4
|
+
#include <android/hardware_buffer_jni.h>
|
|
5
|
+
#include <fbjni/fbjni.h>
|
|
6
|
+
#include <jni.h>
|
|
7
|
+
|
|
8
|
+
#include <memory>
|
|
9
|
+
#include <stdexcept>
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <utility>
|
|
12
|
+
|
|
13
|
+
#include "PlatformContext.h"
|
|
14
|
+
|
|
15
|
+
namespace rnwgpu {
|
|
16
|
+
|
|
17
|
+
// The message of the pending Java exception, which is cleared.
|
|
18
|
+
inline std::string describeAndClearJavaException(JNIEnv *env) {
|
|
19
|
+
jthrowable throwable = env->ExceptionOccurred();
|
|
20
|
+
if (throwable == nullptr) {
|
|
21
|
+
return "unknown error";
|
|
22
|
+
}
|
|
23
|
+
env->ExceptionClear();
|
|
24
|
+
std::string message = "Java exception";
|
|
25
|
+
jclass throwableClass = env->GetObjectClass(throwable);
|
|
26
|
+
jmethodID getMessage =
|
|
27
|
+
env->GetMethodID(throwableClass, "getMessage", "()Ljava/lang/String;");
|
|
28
|
+
if (getMessage != nullptr) {
|
|
29
|
+
auto text =
|
|
30
|
+
static_cast<jstring>(env->CallObjectMethod(throwable, getMessage));
|
|
31
|
+
if (env->ExceptionCheck()) {
|
|
32
|
+
env->ExceptionClear();
|
|
33
|
+
} else if (text != nullptr) {
|
|
34
|
+
const char *chars = env->GetStringUTFChars(text, nullptr);
|
|
35
|
+
if (chars != nullptr) {
|
|
36
|
+
message = chars;
|
|
37
|
+
env->ReleaseStringUTFChars(text, chars);
|
|
38
|
+
}
|
|
39
|
+
env->DeleteLocalRef(text);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
env->DeleteLocalRef(throwableClass);
|
|
43
|
+
env->DeleteLocalRef(throwable);
|
|
44
|
+
return message;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// A global reference to the Java player, shared between AndroidVideoPlayer
|
|
48
|
+
// and the deleters of the frames it handed out (they close each frame's
|
|
49
|
+
// Image through the player). The reference goes away with the last of them.
|
|
50
|
+
class JavaVideoPlayerRef {
|
|
51
|
+
public:
|
|
52
|
+
JavaVideoPlayerRef(JNIEnv *env, jobject local)
|
|
53
|
+
: _object(env->NewGlobalRef(local)) {}
|
|
54
|
+
~JavaVideoPlayerRef() {
|
|
55
|
+
facebook::jni::Environment::ensureCurrentThreadIsAttached();
|
|
56
|
+
JNIEnv *env = facebook::jni::Environment::current();
|
|
57
|
+
if (env != nullptr && _object != nullptr) {
|
|
58
|
+
env->DeleteGlobalRef(_object);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
JavaVideoPlayerRef(const JavaVideoPlayerRef &) = delete;
|
|
62
|
+
JavaVideoPlayerRef &operator=(const JavaVideoPlayerRef &) = delete;
|
|
63
|
+
|
|
64
|
+
jobject get() const { return _object; }
|
|
65
|
+
|
|
66
|
+
private:
|
|
67
|
+
jobject _object;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// IVideoPlayer backed by com.webgpu.WebGPUVideoPlayer: MediaPlayer decodes
|
|
71
|
+
// into an ImageReader whose buffers the GPU samples. The frames keep the
|
|
72
|
+
// decoder's native YUV layout (reported as NV12), for importExternalTexture.
|
|
73
|
+
class AndroidVideoPlayer : public IVideoPlayer {
|
|
74
|
+
public:
|
|
75
|
+
AndroidVideoPlayer(JNIEnv *env, jobject player)
|
|
76
|
+
: _player(std::make_shared<JavaVideoPlayerRef>(env, player)) {
|
|
77
|
+
jclass playerClass = env->GetObjectClass(player);
|
|
78
|
+
_copyLatestFrame =
|
|
79
|
+
method(env, playerClass, "copyLatestFrame", "()Landroid/media/Image;");
|
|
80
|
+
_closeImage =
|
|
81
|
+
method(env, playerClass, "closeImage", "(Landroid/media/Image;)V");
|
|
82
|
+
_play = method(env, playerClass, "play", "()V");
|
|
83
|
+
_pause = method(env, playerClass, "pause", "()V");
|
|
84
|
+
_getPaused = method(env, playerClass, "getPaused", "()Z");
|
|
85
|
+
_getCurrentTime = method(env, playerClass, "getCurrentTime", "()D");
|
|
86
|
+
_seek = method(env, playerClass, "seek", "(D)V");
|
|
87
|
+
_getDuration = method(env, playerClass, "getDuration", "()D");
|
|
88
|
+
_getVolume = method(env, playerClass, "getVolume", "()D");
|
|
89
|
+
_setVolume = method(env, playerClass, "setVolume", "(D)V");
|
|
90
|
+
_getLoop = method(env, playerClass, "getLoop", "()Z");
|
|
91
|
+
_setLoop = method(env, playerClass, "setLoop", "(Z)V");
|
|
92
|
+
_getVideoWidth = method(env, playerClass, "getVideoWidth", "()I");
|
|
93
|
+
_getVideoHeight = method(env, playerClass, "getVideoHeight", "()I");
|
|
94
|
+
_getRotation = method(env, playerClass, "getRotation", "()I");
|
|
95
|
+
_getFrameRate = method(env, playerClass, "getFrameRate", "()D");
|
|
96
|
+
_release = method(env, playerClass, "release", "()V");
|
|
97
|
+
env->DeleteLocalRef(playerClass);
|
|
98
|
+
|
|
99
|
+
jclass imageClass = env->FindClass("android/media/Image");
|
|
100
|
+
_getHardwareBuffer = method(env, imageClass, "getHardwareBuffer",
|
|
101
|
+
"()Landroid/hardware/HardwareBuffer;");
|
|
102
|
+
env->DeleteLocalRef(imageClass);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
~AndroidVideoPlayer() override {
|
|
106
|
+
JNIEnv *env = attach();
|
|
107
|
+
env->CallVoidMethod(_player->get(), _release);
|
|
108
|
+
if (env->ExceptionCheck()) {
|
|
109
|
+
env->ExceptionClear();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
VideoFrameHandle copyLatestFrame() override {
|
|
114
|
+
JNIEnv *env = attach();
|
|
115
|
+
jobject image = env->CallObjectMethod(_player->get(), _copyLatestFrame);
|
|
116
|
+
if (env->ExceptionCheck()) {
|
|
117
|
+
throw std::runtime_error("copyLatestFrame: " +
|
|
118
|
+
describeAndClearJavaException(env));
|
|
119
|
+
}
|
|
120
|
+
if (image == nullptr) {
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
jobject hardwareBuffer = env->CallObjectMethod(image, _getHardwareBuffer);
|
|
125
|
+
if (env->ExceptionCheck() || hardwareBuffer == nullptr) {
|
|
126
|
+
env->ExceptionClear();
|
|
127
|
+
closeImage(env, image);
|
|
128
|
+
env->DeleteLocalRef(image);
|
|
129
|
+
throw std::runtime_error(
|
|
130
|
+
"copyLatestFrame: the decoded frame has no HardwareBuffer");
|
|
131
|
+
}
|
|
132
|
+
AHardwareBuffer *buffer =
|
|
133
|
+
AHardwareBuffer_fromHardwareBuffer(env, hardwareBuffer);
|
|
134
|
+
env->DeleteLocalRef(hardwareBuffer);
|
|
135
|
+
|
|
136
|
+
AHardwareBuffer_Desc desc = {};
|
|
137
|
+
AHardwareBuffer_describe(buffer, &desc);
|
|
138
|
+
if ((desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) == 0) {
|
|
139
|
+
closeImage(env, image);
|
|
140
|
+
env->DeleteLocalRef(image);
|
|
141
|
+
throw std::runtime_error(
|
|
142
|
+
"copyLatestFrame: the decoder allocated frames without "
|
|
143
|
+
"AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE, so the GPU cannot sample "
|
|
144
|
+
"them");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// The frame owns a reference to the buffer and keeps the Image acquired
|
|
148
|
+
// until it is released; closing the Image hands the buffer back to the
|
|
149
|
+
// decoder.
|
|
150
|
+
AHardwareBuffer_acquire(buffer);
|
|
151
|
+
jobject imageRef = env->NewGlobalRef(image);
|
|
152
|
+
env->DeleteLocalRef(image);
|
|
153
|
+
|
|
154
|
+
VideoFrameHandle handle;
|
|
155
|
+
handle.handle = static_cast<void *>(buffer);
|
|
156
|
+
handle.width = desc.width;
|
|
157
|
+
handle.height = desc.height;
|
|
158
|
+
handle.pixelFormat = isRgbFormat(desc.format) ? VideoPixelFormat::BGRA8
|
|
159
|
+
: VideoPixelFormat::NV12;
|
|
160
|
+
auto player = _player;
|
|
161
|
+
jmethodID closeImageMethod = _closeImage;
|
|
162
|
+
handle.deleter = [player, closeImageMethod, imageRef, buffer]() {
|
|
163
|
+
JNIEnv *env = attach();
|
|
164
|
+
env->CallVoidMethod(player->get(), closeImageMethod, imageRef);
|
|
165
|
+
if (env->ExceptionCheck()) {
|
|
166
|
+
env->ExceptionClear();
|
|
167
|
+
}
|
|
168
|
+
env->DeleteGlobalRef(imageRef);
|
|
169
|
+
AHardwareBuffer_release(buffer);
|
|
170
|
+
};
|
|
171
|
+
return handle;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
void play() override { callVoid(_play); }
|
|
175
|
+
void pause() override { callVoid(_pause); }
|
|
176
|
+
bool paused() override { return callBool(_getPaused); }
|
|
177
|
+
|
|
178
|
+
double currentTime() override { return callDouble(_getCurrentTime); }
|
|
179
|
+
void seek(double seconds) override {
|
|
180
|
+
JNIEnv *env = attach();
|
|
181
|
+
env->CallVoidMethod(_player->get(), _seek, static_cast<jdouble>(seconds));
|
|
182
|
+
clearException(env);
|
|
183
|
+
}
|
|
184
|
+
double duration() override { return callDouble(_getDuration); }
|
|
185
|
+
|
|
186
|
+
double volume() override { return callDouble(_getVolume); }
|
|
187
|
+
void setVolume(double volume) override {
|
|
188
|
+
JNIEnv *env = attach();
|
|
189
|
+
env->CallVoidMethod(_player->get(), _setVolume,
|
|
190
|
+
static_cast<jdouble>(volume));
|
|
191
|
+
clearException(env);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
bool loop() override { return callBool(_getLoop); }
|
|
195
|
+
void setLoop(bool loop) override {
|
|
196
|
+
JNIEnv *env = attach();
|
|
197
|
+
env->CallVoidMethod(_player->get(), _setLoop, static_cast<jboolean>(loop));
|
|
198
|
+
clearException(env);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
uint32_t videoWidth() override {
|
|
202
|
+
return static_cast<uint32_t>(callInt(_getVideoWidth));
|
|
203
|
+
}
|
|
204
|
+
uint32_t videoHeight() override {
|
|
205
|
+
return static_cast<uint32_t>(callInt(_getVideoHeight));
|
|
206
|
+
}
|
|
207
|
+
int rotation() override { return callInt(_getRotation); }
|
|
208
|
+
double frameRate() override { return callDouble(_getFrameRate); }
|
|
209
|
+
|
|
210
|
+
private:
|
|
211
|
+
static JNIEnv *attach() {
|
|
212
|
+
facebook::jni::Environment::ensureCurrentThreadIsAttached();
|
|
213
|
+
JNIEnv *env = facebook::jni::Environment::current();
|
|
214
|
+
if (env == nullptr) {
|
|
215
|
+
throw std::runtime_error("VideoPlayer: no JNI environment");
|
|
216
|
+
}
|
|
217
|
+
return env;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static jmethodID method(JNIEnv *env, jclass cls, const char *name,
|
|
221
|
+
const char *signature) {
|
|
222
|
+
jmethodID id = env->GetMethodID(cls, name, signature);
|
|
223
|
+
if (id == nullptr) {
|
|
224
|
+
env->ExceptionClear();
|
|
225
|
+
throw std::runtime_error(std::string("VideoPlayer: method ") + name +
|
|
226
|
+
" not found");
|
|
227
|
+
}
|
|
228
|
+
return id;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
static void clearException(JNIEnv *env) {
|
|
232
|
+
if (env->ExceptionCheck()) {
|
|
233
|
+
env->ExceptionClear();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Single-plane RGB buffers sample as regular textures; everything else
|
|
238
|
+
// (YUV 4:2:0, P010, implementation-defined codec formats) goes through
|
|
239
|
+
// Vulkan's YCbCr conversion as an external texture.
|
|
240
|
+
static bool isRgbFormat(uint32_t format) {
|
|
241
|
+
switch (format) {
|
|
242
|
+
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
|
|
243
|
+
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
|
|
244
|
+
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
|
|
245
|
+
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
|
|
246
|
+
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
|
|
247
|
+
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
|
|
248
|
+
return true;
|
|
249
|
+
default:
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
void closeImage(JNIEnv *env, jobject image) {
|
|
255
|
+
env->CallVoidMethod(_player->get(), _closeImage, image);
|
|
256
|
+
clearException(env);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
void callVoid(jmethodID id) {
|
|
260
|
+
JNIEnv *env = attach();
|
|
261
|
+
env->CallVoidMethod(_player->get(), id);
|
|
262
|
+
clearException(env);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
bool callBool(jmethodID id) {
|
|
266
|
+
JNIEnv *env = attach();
|
|
267
|
+
bool result = env->CallBooleanMethod(_player->get(), id) == JNI_TRUE;
|
|
268
|
+
clearException(env);
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
int callInt(jmethodID id) {
|
|
273
|
+
JNIEnv *env = attach();
|
|
274
|
+
int result = env->CallIntMethod(_player->get(), id);
|
|
275
|
+
clearException(env);
|
|
276
|
+
return result;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
double callDouble(jmethodID id) {
|
|
280
|
+
JNIEnv *env = attach();
|
|
281
|
+
double result = env->CallDoubleMethod(_player->get(), id);
|
|
282
|
+
clearException(env);
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
std::shared_ptr<JavaVideoPlayerRef> _player;
|
|
287
|
+
jmethodID _copyLatestFrame;
|
|
288
|
+
jmethodID _closeImage;
|
|
289
|
+
jmethodID _play;
|
|
290
|
+
jmethodID _pause;
|
|
291
|
+
jmethodID _getPaused;
|
|
292
|
+
jmethodID _getCurrentTime;
|
|
293
|
+
jmethodID _seek;
|
|
294
|
+
jmethodID _getDuration;
|
|
295
|
+
jmethodID _getVolume;
|
|
296
|
+
jmethodID _setVolume;
|
|
297
|
+
jmethodID _getLoop;
|
|
298
|
+
jmethodID _setLoop;
|
|
299
|
+
jmethodID _getVideoWidth;
|
|
300
|
+
jmethodID _getVideoHeight;
|
|
301
|
+
jmethodID _getRotation;
|
|
302
|
+
jmethodID _getFrameRate;
|
|
303
|
+
jmethodID _release;
|
|
304
|
+
jmethodID _getHardwareBuffer;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
} // namespace rnwgpu
|
|
@@ -115,4 +115,14 @@ public class WebGPUModule extends NativeWebGPUModuleSpec {
|
|
|
115
115
|
|
|
116
116
|
@DoNotStrip
|
|
117
117
|
private native void onViewSnapshot(long callback, Bitmap bitmap, String error);
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Called from C++ (AndroidPlatformContext::createVideoPlayer) for
|
|
121
|
+
* RNWebGPU.createVideoPlayer. Throws when the source cannot be opened; the
|
|
122
|
+
* caller turns the exception into a JS error.
|
|
123
|
+
*/
|
|
124
|
+
@DoNotStrip
|
|
125
|
+
WebGPUVideoPlayer createVideoPlayer(String source) {
|
|
126
|
+
return new WebGPUVideoPlayer(getReactApplicationContext(), source);
|
|
127
|
+
}
|
|
118
128
|
}
|