@shopify/react-native-skia 1.3.2 → 1.3.3
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/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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"}
|