@shopify/react-native-skia 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +59 -1
- package/android/cpp/rnskia-android/RNSkAndroidVideo.h +4 -0
- package/android/src/main/java/com/shopify/reactnative/skia/RNSkVideo.java +80 -7
- package/cpp/api/JsiVideo.h +32 -7
- package/cpp/rnskia/RNSkVideo.h +4 -0
- package/ios/RNSkia-iOS/RNSkiOSVideo.h +13 -4
- package/ios/RNSkia-iOS/RNSkiOSVideo.mm +65 -67
- package/lib/commonjs/dom/nodes/datatypes/Fitting.js +42 -30
- package/lib/commonjs/dom/nodes/datatypes/Fitting.js.map +1 -1
- package/lib/commonjs/external/reanimated/useVideo.d.ts +16 -4
- package/lib/commonjs/external/reanimated/useVideo.js +76 -14
- package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
- package/lib/commonjs/renderer/components/shapes/FitBox.d.ts +2 -10
- package/lib/commonjs/renderer/components/shapes/FitBox.js +32 -3
- package/lib/commonjs/renderer/components/shapes/FitBox.js.map +1 -1
- package/lib/commonjs/skia/core/Matrix.js +5 -1
- package/lib/commonjs/skia/core/Matrix.js.map +1 -1
- package/lib/commonjs/skia/types/Matrix.js +2 -0
- package/lib/commonjs/skia/types/Matrix.js.map +1 -1
- package/lib/commonjs/skia/types/Video/Video.d.ts +9 -1
- package/lib/commonjs/skia/types/Video/Video.js.map +1 -1
- package/lib/module/dom/nodes/datatypes/Fitting.js +41 -29
- package/lib/module/dom/nodes/datatypes/Fitting.js.map +1 -1
- package/lib/module/external/reanimated/useVideo.d.ts +16 -4
- package/lib/module/external/reanimated/useVideo.js +76 -14
- package/lib/module/external/reanimated/useVideo.js.map +1 -1
- package/lib/module/renderer/components/shapes/FitBox.d.ts +2 -10
- package/lib/module/renderer/components/shapes/FitBox.js +32 -3
- package/lib/module/renderer/components/shapes/FitBox.js.map +1 -1
- package/lib/module/skia/core/Matrix.js +5 -1
- package/lib/module/skia/core/Matrix.js.map +1 -1
- package/lib/module/skia/types/Matrix.js +2 -0
- package/lib/module/skia/types/Matrix.js.map +1 -1
- package/lib/module/skia/types/Video/Video.d.ts +9 -1
- package/lib/module/skia/types/Video/Video.js.map +1 -1
- package/lib/typescript/src/external/reanimated/useVideo.d.ts +16 -4
- package/lib/typescript/src/renderer/components/shapes/FitBox.d.ts +2 -10
- package/lib/typescript/src/skia/types/Video/Video.d.ts +9 -1
- package/package.json +1 -1
- package/src/dom/nodes/datatypes/Fitting.ts +28 -21
- package/src/external/reanimated/useVideo.ts +90 -29
- package/src/renderer/components/shapes/FitBox.tsx +38 -4
- package/src/skia/core/Matrix.ts +4 -2
- package/src/skia/types/Matrix.ts +1 -0
- package/src/skia/types/Video/Video.ts +7 -1
- package/lib/commonjs/external/reanimated/video.d.ts +0 -16
- package/lib/commonjs/external/reanimated/video.js +0 -54
- package/lib/commonjs/external/reanimated/video.js.map +0 -1
- package/lib/module/external/reanimated/video.d.ts +0 -16
- package/lib/module/external/reanimated/video.js +0 -46
- package/lib/module/external/reanimated/video.js.map +0 -1
- package/lib/typescript/src/external/reanimated/video.d.ts +0 -16
- package/src/external/reanimated/video.ts +0 -82
@@ -9,6 +9,7 @@
|
|
9
9
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
10
10
|
|
11
11
|
#include "include/core/SkImage.h"
|
12
|
+
#include "include/core/SkSize.h"
|
12
13
|
|
13
14
|
#pragma clang diagnostic pop
|
14
15
|
|
@@ -82,7 +83,7 @@ double RNSkAndroidVideo::framerate() {
|
|
82
83
|
void RNSkAndroidVideo::seek(double timestamp) {
|
83
84
|
JNIEnv *env = facebook::jni::Environment::current();
|
84
85
|
jclass cls = env->GetObjectClass(_jniVideo.get());
|
85
|
-
jmethodID mid = env->GetMethodID(cls, "seek", "(
|
86
|
+
jmethodID mid = env->GetMethodID(cls, "seek", "(D)V");
|
86
87
|
if (!mid) {
|
87
88
|
RNSkLogger::logToConsole("seek method not found");
|
88
89
|
return;
|
@@ -102,4 +103,61 @@ float RNSkAndroidVideo::getRotationInDegrees() {
|
|
102
103
|
return static_cast<float>(rotation);
|
103
104
|
}
|
104
105
|
|
106
|
+
SkISize RNSkAndroidVideo::getSize() {
|
107
|
+
JNIEnv *env = facebook::jni::Environment::current();
|
108
|
+
jclass cls = env->GetObjectClass(_jniVideo.get());
|
109
|
+
jmethodID mid =
|
110
|
+
env->GetMethodID(cls, "getSize", "()Landroid/graphics/Point;");
|
111
|
+
if (!mid) {
|
112
|
+
RNSkLogger::logToConsole("getSize method not found");
|
113
|
+
return SkISize::Make(0, 0);
|
114
|
+
}
|
115
|
+
jobject jPoint = env->CallObjectMethod(_jniVideo.get(), mid);
|
116
|
+
jclass pointCls = env->GetObjectClass(jPoint);
|
117
|
+
|
118
|
+
jfieldID xFid = env->GetFieldID(pointCls, "x", "I");
|
119
|
+
jfieldID yFid = env->GetFieldID(pointCls, "y", "I");
|
120
|
+
if (!xFid || !yFid) {
|
121
|
+
RNSkLogger::logToConsole("Point class fields not found");
|
122
|
+
return SkISize::Make(0, 0);
|
123
|
+
}
|
124
|
+
|
125
|
+
jint width = env->GetIntField(jPoint, xFid);
|
126
|
+
jint height = env->GetIntField(jPoint, yFid);
|
127
|
+
|
128
|
+
return SkISize::Make(width, height);
|
129
|
+
}
|
130
|
+
|
131
|
+
void RNSkAndroidVideo::play() {
|
132
|
+
JNIEnv *env = facebook::jni::Environment::current();
|
133
|
+
jclass cls = env->GetObjectClass(_jniVideo.get());
|
134
|
+
jmethodID mid = env->GetMethodID(cls, "play", "()V");
|
135
|
+
if (!mid) {
|
136
|
+
RNSkLogger::logToConsole("play method not found");
|
137
|
+
return;
|
138
|
+
}
|
139
|
+
env->CallVoidMethod(_jniVideo.get(), mid);
|
140
|
+
}
|
141
|
+
|
142
|
+
void RNSkAndroidVideo::pause() {
|
143
|
+
JNIEnv *env = facebook::jni::Environment::current();
|
144
|
+
jclass cls = env->GetObjectClass(_jniVideo.get());
|
145
|
+
jmethodID mid = env->GetMethodID(cls, "pause", "()V");
|
146
|
+
if (!mid) {
|
147
|
+
RNSkLogger::logToConsole("pause method not found");
|
148
|
+
return;
|
149
|
+
}
|
150
|
+
env->CallVoidMethod(_jniVideo.get(), mid);
|
151
|
+
}
|
152
|
+
|
153
|
+
void RNSkAndroidVideo::setVolume(float volume) {
|
154
|
+
JNIEnv *env = facebook::jni::Environment::current();
|
155
|
+
jclass cls = env->GetObjectClass(_jniVideo.get());
|
156
|
+
jmethodID mid = env->GetMethodID(cls, "setVolume", "(F)V");
|
157
|
+
if (!mid) {
|
158
|
+
RNSkLogger::logToConsole("setVolume method not found");
|
159
|
+
return;
|
160
|
+
}
|
161
|
+
env->CallVoidMethod(_jniVideo.get(), mid, volume);
|
162
|
+
}
|
105
163
|
} // namespace RNSkia
|
@@ -32,6 +32,10 @@ public:
|
|
32
32
|
double framerate() override;
|
33
33
|
void seek(double timestamp) override;
|
34
34
|
float getRotationInDegrees() override;
|
35
|
+
SkISize getSize() override;
|
36
|
+
void play() override;
|
37
|
+
void pause() override;
|
38
|
+
void setVolume(float volume) override;
|
35
39
|
};
|
36
40
|
|
37
41
|
} // namespace RNSkia
|
@@ -3,14 +3,19 @@ package com.shopify.reactnative.skia;
|
|
3
3
|
import android.content.Context;
|
4
4
|
import android.graphics.ImageFormat;
|
5
5
|
import android.hardware.HardwareBuffer;
|
6
|
-
import android.media.
|
7
|
-
import android.media.
|
6
|
+
import android.media.AudioAttributes;
|
7
|
+
import android.media.AudioManager;
|
8
8
|
import android.media.MediaCodec;
|
9
9
|
import android.media.MediaExtractor;
|
10
10
|
import android.media.MediaFormat;
|
11
|
+
import android.media.MediaPlayer;
|
12
|
+
import android.media.MediaSync;
|
13
|
+
import android.media.Image;
|
14
|
+
import android.media.ImageReader;
|
11
15
|
import android.net.Uri;
|
12
16
|
import android.os.Build;
|
13
17
|
import android.view.Surface;
|
18
|
+
import android.graphics.Point;
|
14
19
|
|
15
20
|
import androidx.annotation.RequiresApi;
|
16
21
|
|
@@ -27,9 +32,15 @@ public class RNSkVideo {
|
|
27
32
|
private MediaCodec decoder;
|
28
33
|
private ImageReader imageReader;
|
29
34
|
private Surface outputSurface;
|
35
|
+
private MediaPlayer mediaPlayer;
|
36
|
+
private MediaSync mediaSync;
|
30
37
|
private double durationMs;
|
31
38
|
private double frameRate;
|
32
39
|
private int rotationDegrees = 0;
|
40
|
+
private int width = 0;
|
41
|
+
private int height = 0;
|
42
|
+
|
43
|
+
private boolean isPlaying = false;
|
33
44
|
|
34
45
|
RNSkVideo(Context context, String localUri) {
|
35
46
|
this.uri = Uri.parse(localUri);
|
@@ -47,6 +58,18 @@ public class RNSkVideo {
|
|
47
58
|
}
|
48
59
|
extractor.selectTrack(trackIndex);
|
49
60
|
MediaFormat format = extractor.getTrackFormat(trackIndex);
|
61
|
+
|
62
|
+
// Initialize MediaPlayer
|
63
|
+
mediaPlayer = new MediaPlayer();
|
64
|
+
mediaPlayer.setDataSource(context, uri);
|
65
|
+
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
66
|
+
mediaPlayer.setOnPreparedListener(mp -> {
|
67
|
+
durationMs = mp.getDuration();
|
68
|
+
mp.start();
|
69
|
+
isPlaying = true;
|
70
|
+
});
|
71
|
+
mediaPlayer.prepareAsync();
|
72
|
+
|
50
73
|
// Retrieve and store video properties
|
51
74
|
if (format.containsKey(MediaFormat.KEY_DURATION)) {
|
52
75
|
durationMs = format.getLong(MediaFormat.KEY_DURATION) / 1000; // Convert microseconds to milliseconds
|
@@ -57,8 +80,8 @@ public class RNSkVideo {
|
|
57
80
|
if (format.containsKey(MediaFormat.KEY_ROTATION)) {
|
58
81
|
rotationDegrees = format.getInteger(MediaFormat.KEY_ROTATION);
|
59
82
|
}
|
60
|
-
|
61
|
-
|
83
|
+
width = format.getInteger(MediaFormat.KEY_WIDTH);
|
84
|
+
height = format.getInteger(MediaFormat.KEY_HEIGHT);
|
62
85
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
63
86
|
imageReader = ImageReader.newInstance(
|
64
87
|
width,
|
@@ -116,15 +139,38 @@ public class RNSkVideo {
|
|
116
139
|
}
|
117
140
|
|
118
141
|
@DoNotStrip
|
119
|
-
public void seek(
|
120
|
-
//
|
121
|
-
|
142
|
+
public void seek(double timestamp) {
|
143
|
+
// Log the values for debugging
|
144
|
+
|
145
|
+
long timestampUs = (long)(timestamp * 1000); // Convert milliseconds to microseconds
|
146
|
+
|
147
|
+
extractor.seekTo(timestampUs, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
|
148
|
+
if (mediaPlayer != null) {
|
149
|
+
int timestampMs = (int) timestamp; // Convert to milliseconds
|
150
|
+
mediaPlayer.seekTo(timestampMs, MediaPlayer.SEEK_CLOSEST);
|
151
|
+
}
|
152
|
+
|
122
153
|
// Flush the codec to reset internal state and buffers
|
123
154
|
if (decoder != null) {
|
124
155
|
decoder.flush();
|
156
|
+
|
157
|
+
// Decode frames until reaching the exact timestamp
|
158
|
+
boolean isSeeking = true;
|
159
|
+
while (isSeeking) {
|
160
|
+
decodeFrame();
|
161
|
+
long currentTimestampUs = extractor.getSampleTime();
|
162
|
+
if (currentTimestampUs >= timestampUs) {
|
163
|
+
isSeeking = false;
|
164
|
+
}
|
165
|
+
}
|
125
166
|
}
|
126
167
|
}
|
127
168
|
|
169
|
+
@DoNotStrip
|
170
|
+
public Point getSize() {
|
171
|
+
return new Point(width, height);
|
172
|
+
}
|
173
|
+
|
128
174
|
private int selectVideoTrack(MediaExtractor extractor) {
|
129
175
|
int numTracks = extractor.getTrackCount();
|
130
176
|
for (int i = 0; i < numTracks; i++) {
|
@@ -179,7 +225,34 @@ public class RNSkVideo {
|
|
179
225
|
}
|
180
226
|
}
|
181
227
|
|
228
|
+
@DoNotStrip
|
229
|
+
public void play() {
|
230
|
+
if (mediaPlayer != null && !isPlaying) {
|
231
|
+
mediaPlayer.start();
|
232
|
+
isPlaying = true;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
@DoNotStrip
|
237
|
+
public void pause() {
|
238
|
+
if (mediaPlayer != null && isPlaying) {
|
239
|
+
mediaPlayer.pause();
|
240
|
+
isPlaying = false;
|
241
|
+
}
|
242
|
+
}
|
243
|
+
|
244
|
+
@DoNotStrip
|
245
|
+
public void setVolume(float volume) {
|
246
|
+
if (mediaPlayer != null) {
|
247
|
+
mediaPlayer.setVolume(volume, volume);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
182
251
|
public void release() {
|
252
|
+
if (mediaPlayer != null) {
|
253
|
+
mediaPlayer.release();
|
254
|
+
mediaPlayer = null;
|
255
|
+
}
|
183
256
|
if (decoder != null) {
|
184
257
|
decoder.stop();
|
185
258
|
decoder.release();
|
package/cpp/api/JsiVideo.h
CHANGED
@@ -53,18 +53,43 @@ public:
|
|
53
53
|
return jsi::Value::undefined();
|
54
54
|
}
|
55
55
|
|
56
|
-
JSI_HOST_FUNCTION(
|
56
|
+
JSI_HOST_FUNCTION(rotation) {
|
57
57
|
auto context = getContext();
|
58
58
|
auto rot = getObject()->getRotationInDegrees();
|
59
59
|
return jsi::Value(static_cast<double>(rot));
|
60
60
|
}
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
JSI_HOST_FUNCTION(size) {
|
63
|
+
auto context = getContext();
|
64
|
+
auto size = getObject()->getSize();
|
65
|
+
auto result = jsi::Object(runtime);
|
66
|
+
result.setProperty(runtime, "width", static_cast<double>(size.width()));
|
67
|
+
result.setProperty(runtime, "height", static_cast<double>(size.height()));
|
68
|
+
return result;
|
69
|
+
}
|
70
|
+
|
71
|
+
JSI_HOST_FUNCTION(play) {
|
72
|
+
getObject()->play();
|
73
|
+
return jsi::Value::undefined();
|
74
|
+
}
|
75
|
+
|
76
|
+
JSI_HOST_FUNCTION(pause) {
|
77
|
+
getObject()->pause();
|
78
|
+
return jsi::Value::undefined();
|
79
|
+
}
|
80
|
+
|
81
|
+
JSI_HOST_FUNCTION(setVolume) {
|
82
|
+
auto volume = arguments[0].asNumber();
|
83
|
+
getObject()->setVolume(static_cast<float>(volume));
|
84
|
+
return jsi::Value::undefined();
|
85
|
+
}
|
86
|
+
|
87
|
+
JSI_EXPORT_FUNCTIONS(
|
88
|
+
JSI_EXPORT_FUNC(JsiVideo, nextImage), JSI_EXPORT_FUNC(JsiVideo, duration),
|
89
|
+
JSI_EXPORT_FUNC(JsiVideo, framerate), JSI_EXPORT_FUNC(JsiVideo, seek),
|
90
|
+
JSI_EXPORT_FUNC(JsiVideo, rotation), JSI_EXPORT_FUNC(JsiVideo, size),
|
91
|
+
JSI_EXPORT_FUNC(JsiVideo, play), JSI_EXPORT_FUNC(JsiVideo, pause),
|
92
|
+
JSI_EXPORT_FUNC(JsiVideo, setVolume), JSI_EXPORT_FUNC(JsiVideo, dispose))
|
68
93
|
|
69
94
|
JsiVideo(std::shared_ptr<RNSkPlatformContext> context,
|
70
95
|
std::shared_ptr<RNSkVideo> video)
|
package/cpp/rnskia/RNSkVideo.h
CHANGED
@@ -19,6 +19,10 @@ public:
|
|
19
19
|
virtual double framerate() = 0;
|
20
20
|
virtual void seek(double timestamp) = 0;
|
21
21
|
virtual float getRotationInDegrees() = 0;
|
22
|
+
virtual SkISize getSize() = 0;
|
23
|
+
virtual void play() = 0;
|
24
|
+
virtual void pause() = 0;
|
25
|
+
virtual void setVolume(float volume) = 0;
|
22
26
|
};
|
23
27
|
|
24
28
|
} // namespace RNSkia
|
@@ -9,6 +9,7 @@
|
|
9
9
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
10
10
|
|
11
11
|
#include "include/core/SkImage.h"
|
12
|
+
#include "include/core/SkSize.h"
|
12
13
|
|
13
14
|
#pragma clang diagnostic pop
|
14
15
|
|
@@ -20,14 +21,18 @@ namespace RNSkia {
|
|
20
21
|
class RNSkiOSVideo : public RNSkVideo {
|
21
22
|
private:
|
22
23
|
std::string _url;
|
23
|
-
|
24
|
-
|
24
|
+
AVPlayer *_player = nullptr;
|
25
|
+
AVPlayerItem *_playerItem = nullptr;
|
26
|
+
AVPlayerItemVideoOutput *_videoOutput = nullptr;
|
25
27
|
RNSkPlatformContext *_context;
|
26
28
|
double _duration = 0;
|
27
29
|
double _framerate = 0;
|
28
|
-
|
29
|
-
|
30
|
+
float _videoWidth = 0;
|
31
|
+
float _videoHeight = 0;
|
30
32
|
CGAffineTransform _preferredTransform;
|
33
|
+
bool _isPlaying = false;
|
34
|
+
void setupPlayer();
|
35
|
+
NSDictionary *getOutputSettings();
|
31
36
|
|
32
37
|
public:
|
33
38
|
RNSkiOSVideo(std::string url, RNSkPlatformContext *context);
|
@@ -36,7 +41,11 @@ public:
|
|
36
41
|
double duration() override;
|
37
42
|
double framerate() override;
|
38
43
|
void seek(double timestamp) override;
|
44
|
+
void play();
|
45
|
+
void pause();
|
39
46
|
float getRotationInDegrees() override;
|
47
|
+
SkISize getSize() override;
|
48
|
+
void setVolume(float volume);
|
40
49
|
};
|
41
50
|
|
42
51
|
} // namespace RNSkia
|
@@ -16,78 +16,60 @@ namespace RNSkia {
|
|
16
16
|
|
17
17
|
RNSkiOSVideo::RNSkiOSVideo(std::string url, RNSkPlatformContext *context)
|
18
18
|
: _url(std::move(url)), _context(context) {
|
19
|
-
|
19
|
+
setupPlayer();
|
20
20
|
}
|
21
21
|
|
22
|
-
RNSkiOSVideo::~RNSkiOSVideo() {
|
22
|
+
RNSkiOSVideo::~RNSkiOSVideo() {
|
23
|
+
if (_player) {
|
24
|
+
[_player pause];
|
25
|
+
}
|
26
|
+
}
|
23
27
|
|
24
|
-
void RNSkiOSVideo::
|
25
|
-
|
28
|
+
void RNSkiOSVideo::setupPlayer() {
|
29
|
+
NSURL *videoURL = [NSURL URLWithString:@(_url.c_str())];
|
30
|
+
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:videoURL];
|
31
|
+
_player = [AVPlayer playerWithPlayerItem:playerItem];
|
32
|
+
_playerItem = playerItem;
|
26
33
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
error:&error];
|
32
|
-
if (error) {
|
33
|
-
NSLog(@"Error initializing asset reader: %@", error.localizedDescription);
|
34
|
-
return;
|
35
|
-
}
|
34
|
+
NSDictionary *outputSettings = getOutputSettings();
|
35
|
+
_videoOutput =
|
36
|
+
[[AVPlayerItemVideoOutput alloc] initWithOutputSettings:outputSettings];
|
37
|
+
[playerItem addOutput:_videoOutput];
|
36
38
|
|
37
|
-
CMTime time =
|
38
|
-
if (time.timescale
|
39
|
-
|
40
|
-
return;
|
39
|
+
CMTime time = playerItem.asset.duration;
|
40
|
+
if (time.timescale != 0) {
|
41
|
+
_duration = CMTimeGetSeconds(time) * 1000; // Store duration in milliseconds
|
41
42
|
}
|
42
43
|
|
43
|
-
_duration = CMTimeGetSeconds(time) * 1000; // Store duration in milliseconds
|
44
44
|
AVAssetTrack *videoTrack =
|
45
|
-
[[asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
outputSettings:outputSettings];
|
53
|
-
|
54
|
-
assetReader.timeRange = timeRange;
|
55
|
-
if ([assetReader canAddOutput:trackOutput]) {
|
56
|
-
[assetReader addOutput:trackOutput];
|
57
|
-
[assetReader startReading];
|
58
|
-
} else {
|
59
|
-
NSLog(@"Cannot add output to asset reader.");
|
60
|
-
return;
|
45
|
+
[[playerItem.asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
|
46
|
+
if (videoTrack) {
|
47
|
+
_framerate = videoTrack.nominalFrameRate;
|
48
|
+
_preferredTransform = videoTrack.preferredTransform;
|
49
|
+
CGSize videoSize = videoTrack.naturalSize;
|
50
|
+
_videoWidth = videoSize.width;
|
51
|
+
_videoHeight = videoSize.height;
|
61
52
|
}
|
62
|
-
|
63
|
-
_reader = assetReader;
|
64
|
-
_trackOutput = trackOutput;
|
53
|
+
play();
|
65
54
|
}
|
66
55
|
|
67
56
|
sk_sp<SkImage> RNSkiOSVideo::nextImage(double *timeStamp) {
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
}
|
73
|
-
|
74
|
-
// Extract the pixel buffer from the sample buffer
|
75
|
-
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
57
|
+
CMTime currentTime = [_player currentTime];
|
58
|
+
CVPixelBufferRef pixelBuffer =
|
59
|
+
[_videoOutput copyPixelBufferForItemTime:currentTime
|
60
|
+
itemTimeForDisplay:nullptr];
|
76
61
|
if (!pixelBuffer) {
|
77
62
|
NSLog(@"No pixel buffer.");
|
78
|
-
CFRelease(sampleBuffer);
|
79
63
|
return nullptr;
|
80
64
|
}
|
81
65
|
|
82
|
-
auto skImage = _context->makeImageFromNativeBuffer(
|
83
|
-
reinterpret_cast<void *>(pixelBuffer));
|
66
|
+
auto skImage = _context->makeImageFromNativeBuffer((void *)pixelBuffer);
|
84
67
|
|
85
68
|
if (timeStamp) {
|
86
|
-
|
87
|
-
*timeStamp = CMTimeGetSeconds(time);
|
69
|
+
*timeStamp = CMTimeGetSeconds(currentTime);
|
88
70
|
}
|
89
71
|
|
90
|
-
|
72
|
+
CVPixelBufferRelease(pixelBuffer);
|
91
73
|
return skImage;
|
92
74
|
}
|
93
75
|
|
@@ -104,36 +86,52 @@ float RNSkiOSVideo::getRotationInDegrees() {
|
|
104
86
|
// Determine the rotation angle in radians
|
105
87
|
if (transform.a == 0 && transform.b == 1 && transform.c == -1 &&
|
106
88
|
transform.d == 0) {
|
107
|
-
rotationAngle =
|
89
|
+
rotationAngle = 90;
|
108
90
|
} else if (transform.a == 0 && transform.b == -1 && transform.c == 1 &&
|
109
91
|
transform.d == 0) {
|
110
|
-
rotationAngle =
|
92
|
+
rotationAngle = 270;
|
111
93
|
} else if (transform.a == -1 && transform.b == 0 && transform.c == 0 &&
|
112
94
|
transform.d == -1) {
|
113
|
-
rotationAngle =
|
114
|
-
} else if (transform.a == 1 && transform.b == 0 && transform.c == 0 &&
|
115
|
-
transform.d == 1) {
|
116
|
-
rotationAngle = 0.0; // 0 degrees
|
95
|
+
rotationAngle = 180;
|
117
96
|
}
|
118
|
-
|
119
|
-
return rotationAngle * 180 / M_PI;
|
97
|
+
return rotationAngle;
|
120
98
|
}
|
121
99
|
|
122
100
|
void RNSkiOSVideo::seek(double timeInMilliseconds) {
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
101
|
+
CMTime seekTime =
|
102
|
+
CMTimeMakeWithSeconds(timeInMilliseconds / 1000.0, NSEC_PER_SEC);
|
103
|
+
[_player seekToTime:seekTime
|
104
|
+
toleranceBefore:kCMTimeZero
|
105
|
+
toleranceAfter:kCMTimeZero
|
106
|
+
completionHandler:^(BOOL finished) {
|
107
|
+
if (!finished) {
|
108
|
+
NSLog(@"Seek failed or was interrupted.");
|
109
|
+
}
|
110
|
+
}];
|
111
|
+
}
|
112
|
+
|
113
|
+
void RNSkiOSVideo::play() {
|
114
|
+
if (_player) {
|
115
|
+
[_player play];
|
116
|
+
_isPlaying = true;
|
127
117
|
}
|
118
|
+
}
|
128
119
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
120
|
+
void RNSkiOSVideo::pause() {
|
121
|
+
if (_player) {
|
122
|
+
[_player pause];
|
123
|
+
_isPlaying = false;
|
124
|
+
}
|
133
125
|
}
|
134
126
|
|
135
127
|
double RNSkiOSVideo::duration() { return _duration; }
|
136
128
|
|
137
129
|
double RNSkiOSVideo::framerate() { return _framerate; }
|
138
130
|
|
131
|
+
SkISize RNSkiOSVideo::getSize() {
|
132
|
+
return SkISize::Make(_videoWidth, _videoHeight);
|
133
|
+
}
|
134
|
+
|
135
|
+
void RNSkiOSVideo::setVolume(float volume) { _player.volume = volume; }
|
136
|
+
|
139
137
|
} // namespace RNSkia
|
@@ -5,12 +5,18 @@ Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
});
|
6
6
|
exports.size = exports.rect2rect = exports.fitRects = void 0;
|
7
7
|
var _typeddash = require("../../../renderer/typeddash");
|
8
|
-
const size = (width = 0, height = 0) =>
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
const size = (width = 0, height = 0) => {
|
9
|
+
"worklet";
|
10
|
+
|
11
|
+
return {
|
12
|
+
width,
|
13
|
+
height
|
14
|
+
};
|
15
|
+
};
|
12
16
|
exports.size = size;
|
13
17
|
const rect2rect = (src, dst) => {
|
18
|
+
"worklet";
|
19
|
+
|
14
20
|
const scaleX = dst.width / src.width;
|
15
21
|
const scaleY = dst.height / src.height;
|
16
22
|
const translateX = dst.x - src.x * scaleX;
|
@@ -26,36 +32,12 @@ const rect2rect = (src, dst) => {
|
|
26
32
|
}];
|
27
33
|
};
|
28
34
|
exports.rect2rect = rect2rect;
|
29
|
-
const fitRects = (fit, rect, {
|
30
|
-
x,
|
31
|
-
y,
|
32
|
-
width,
|
33
|
-
height
|
34
|
-
}) => {
|
35
|
-
const sizes = applyBoxFit(fit, {
|
36
|
-
width: rect.width,
|
37
|
-
height: rect.height
|
38
|
-
}, {
|
39
|
-
width,
|
40
|
-
height
|
41
|
-
});
|
42
|
-
const src = inscribe(sizes.src, rect);
|
43
|
-
const dst = inscribe(sizes.dst, {
|
44
|
-
x,
|
45
|
-
y,
|
46
|
-
width,
|
47
|
-
height
|
48
|
-
});
|
49
|
-
return {
|
50
|
-
src,
|
51
|
-
dst
|
52
|
-
};
|
53
|
-
};
|
54
|
-
exports.fitRects = fitRects;
|
55
35
|
const inscribe = ({
|
56
36
|
width,
|
57
37
|
height
|
58
38
|
}, rect) => {
|
39
|
+
"worklet";
|
40
|
+
|
59
41
|
const halfWidthDelta = (rect.width - width) / 2.0;
|
60
42
|
const halfHeightDelta = (rect.height - height) / 2.0;
|
61
43
|
return {
|
@@ -66,6 +48,8 @@ const inscribe = ({
|
|
66
48
|
};
|
67
49
|
};
|
68
50
|
const applyBoxFit = (fit, input, output) => {
|
51
|
+
"worklet";
|
52
|
+
|
69
53
|
let src = size(),
|
70
54
|
dst = size();
|
71
55
|
if (input.height <= 0.0 || input.width <= 0.0 || output.height <= 0.0 || output.width <= 0.0) {
|
@@ -126,4 +110,32 @@ const applyBoxFit = (fit, input, output) => {
|
|
126
110
|
dst
|
127
111
|
};
|
128
112
|
};
|
113
|
+
const fitRects = (fit, rect, {
|
114
|
+
x,
|
115
|
+
y,
|
116
|
+
width,
|
117
|
+
height
|
118
|
+
}) => {
|
119
|
+
"worklet";
|
120
|
+
|
121
|
+
const sizes = applyBoxFit(fit, {
|
122
|
+
width: rect.width,
|
123
|
+
height: rect.height
|
124
|
+
}, {
|
125
|
+
width,
|
126
|
+
height
|
127
|
+
});
|
128
|
+
const src = inscribe(sizes.src, rect);
|
129
|
+
const dst = inscribe(sizes.dst, {
|
130
|
+
x,
|
131
|
+
y,
|
132
|
+
width,
|
133
|
+
height
|
134
|
+
});
|
135
|
+
return {
|
136
|
+
src,
|
137
|
+
dst
|
138
|
+
};
|
139
|
+
};
|
140
|
+
exports.fitRects = fitRects;
|
129
141
|
//# sourceMappingURL=Fitting.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["_typeddash","require","size","width","height","exports","rect2rect","src","dst","scaleX","scaleY","translateX","x","translateY","y","
|
1
|
+
{"version":3,"names":["_typeddash","require","size","width","height","exports","rect2rect","src","dst","scaleX","scaleY","translateX","x","translateY","y","inscribe","rect","halfWidthDelta","halfHeightDelta","applyBoxFit","fit","input","output","Math","min","aspectRatio","exhaustiveCheck","fitRects","sizes"],"sources":["Fitting.ts"],"sourcesContent":["import { exhaustiveCheck } from \"../../../renderer/typeddash\";\nimport type { SkRect } from \"../../../skia/types\";\nimport type { Fit } from \"../../types\";\n\nexport interface Size {\n width: number;\n height: number;\n}\n\nexport const size = (width = 0, height = 0) => {\n \"worklet\";\n return { width, height };\n};\n\nexport const rect2rect = (\n src: SkRect,\n dst: SkRect\n): [\n { translateX: number },\n { translateY: number },\n { scaleX: number },\n { scaleY: number }\n] => {\n \"worklet\";\n const scaleX = dst.width / src.width;\n const scaleY = dst.height / src.height;\n const translateX = dst.x - src.x * scaleX;\n const translateY = dst.y - src.y * scaleY;\n return [{ translateX }, { translateY }, { scaleX }, { scaleY }];\n};\n\nconst inscribe = (\n { width, height }: Size,\n rect: { x: number; y: number; width: number; height: number }\n) => {\n \"worklet\";\n const halfWidthDelta = (rect.width - width) / 2.0;\n const halfHeightDelta = (rect.height - height) / 2.0;\n return {\n x: rect.x + halfWidthDelta,\n y: rect.y + halfHeightDelta,\n width,\n height,\n };\n};\n\nconst applyBoxFit = (fit: Fit, input: Size, output: Size) => {\n \"worklet\";\n let src = size(),\n dst = size();\n if (\n input.height <= 0.0 ||\n input.width <= 0.0 ||\n output.height <= 0.0 ||\n output.width <= 0.0\n ) {\n return { src, dst };\n }\n switch (fit) {\n case \"fill\":\n src = input;\n dst = output;\n break;\n case \"contain\":\n src = input;\n if (output.width / output.height > src.width / src.height) {\n dst = size((src.width * output.height) / src.height, output.height);\n } else {\n dst = size(output.width, (src.height * output.width) / src.width);\n }\n break;\n case \"cover\":\n if (output.width / output.height > input.width / input.height) {\n src = size(input.width, (input.width * output.height) / output.width);\n } else {\n src = size((input.height * output.width) / output.height, input.height);\n }\n dst = output;\n break;\n case \"fitWidth\":\n src = size(input.width, (input.width * output.height) / output.width);\n dst = size(output.width, (src.height * output.width) / src.width);\n break;\n case \"fitHeight\":\n src = size((input.height * output.width) / output.height, input.height);\n dst = size((src.width * output.height) / src.height, output.height);\n break;\n case \"none\":\n src = size(\n Math.min(input.width, output.width),\n Math.min(input.height, output.height)\n );\n dst = src;\n break;\n case \"scaleDown\":\n src = input;\n dst = input;\n const aspectRatio = input.width / input.height;\n if (dst.height > output.height) {\n dst = size(output.height * aspectRatio, output.height);\n }\n if (dst.width > output.width) {\n dst = size(output.width, output.width / aspectRatio);\n }\n break;\n default:\n exhaustiveCheck(fit);\n }\n return { src, dst };\n};\n\nexport const fitRects = (\n fit: Fit,\n rect: SkRect,\n { x, y, width, height }: SkRect\n) => {\n \"worklet\";\n const sizes = applyBoxFit(\n fit,\n { width: rect.width, height: rect.height },\n { width, height }\n );\n const src = inscribe(sizes.src, rect);\n const dst = inscribe(sizes.dst, {\n x,\n y,\n width,\n height,\n });\n return { src, dst };\n};\n"],"mappings":"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"}
|