@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.
Files changed (53) hide show
  1. package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +59 -1
  2. package/android/cpp/rnskia-android/RNSkAndroidVideo.h +4 -0
  3. package/android/src/main/java/com/shopify/reactnative/skia/RNSkVideo.java +80 -7
  4. package/cpp/api/JsiVideo.h +32 -7
  5. package/cpp/rnskia/RNSkVideo.h +4 -0
  6. package/ios/RNSkia-iOS/RNSkiOSVideo.h +13 -4
  7. package/ios/RNSkia-iOS/RNSkiOSVideo.mm +65 -67
  8. package/lib/commonjs/dom/nodes/datatypes/Fitting.js +42 -30
  9. package/lib/commonjs/dom/nodes/datatypes/Fitting.js.map +1 -1
  10. package/lib/commonjs/external/reanimated/useVideo.d.ts +16 -4
  11. package/lib/commonjs/external/reanimated/useVideo.js +76 -14
  12. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  13. package/lib/commonjs/renderer/components/shapes/FitBox.d.ts +2 -10
  14. package/lib/commonjs/renderer/components/shapes/FitBox.js +32 -3
  15. package/lib/commonjs/renderer/components/shapes/FitBox.js.map +1 -1
  16. package/lib/commonjs/skia/core/Matrix.js +5 -1
  17. package/lib/commonjs/skia/core/Matrix.js.map +1 -1
  18. package/lib/commonjs/skia/types/Matrix.js +2 -0
  19. package/lib/commonjs/skia/types/Matrix.js.map +1 -1
  20. package/lib/commonjs/skia/types/Video/Video.d.ts +9 -1
  21. package/lib/commonjs/skia/types/Video/Video.js.map +1 -1
  22. package/lib/module/dom/nodes/datatypes/Fitting.js +41 -29
  23. package/lib/module/dom/nodes/datatypes/Fitting.js.map +1 -1
  24. package/lib/module/external/reanimated/useVideo.d.ts +16 -4
  25. package/lib/module/external/reanimated/useVideo.js +76 -14
  26. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  27. package/lib/module/renderer/components/shapes/FitBox.d.ts +2 -10
  28. package/lib/module/renderer/components/shapes/FitBox.js +32 -3
  29. package/lib/module/renderer/components/shapes/FitBox.js.map +1 -1
  30. package/lib/module/skia/core/Matrix.js +5 -1
  31. package/lib/module/skia/core/Matrix.js.map +1 -1
  32. package/lib/module/skia/types/Matrix.js +2 -0
  33. package/lib/module/skia/types/Matrix.js.map +1 -1
  34. package/lib/module/skia/types/Video/Video.d.ts +9 -1
  35. package/lib/module/skia/types/Video/Video.js.map +1 -1
  36. package/lib/typescript/src/external/reanimated/useVideo.d.ts +16 -4
  37. package/lib/typescript/src/renderer/components/shapes/FitBox.d.ts +2 -10
  38. package/lib/typescript/src/skia/types/Video/Video.d.ts +9 -1
  39. package/package.json +1 -1
  40. package/src/dom/nodes/datatypes/Fitting.ts +28 -21
  41. package/src/external/reanimated/useVideo.ts +90 -29
  42. package/src/renderer/components/shapes/FitBox.tsx +38 -4
  43. package/src/skia/core/Matrix.ts +4 -2
  44. package/src/skia/types/Matrix.ts +1 -0
  45. package/src/skia/types/Video/Video.ts +7 -1
  46. package/lib/commonjs/external/reanimated/video.d.ts +0 -16
  47. package/lib/commonjs/external/reanimated/video.js +0 -54
  48. package/lib/commonjs/external/reanimated/video.js.map +0 -1
  49. package/lib/module/external/reanimated/video.d.ts +0 -16
  50. package/lib/module/external/reanimated/video.js +0 -46
  51. package/lib/module/external/reanimated/video.js.map +0 -1
  52. package/lib/typescript/src/external/reanimated/video.d.ts +0 -16
  53. 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", "(J)V");
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.Image;
7
- import android.media.ImageReader;
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
- int width = format.getInteger(MediaFormat.KEY_WIDTH);
61
- int height = format.getInteger(MediaFormat.KEY_HEIGHT);
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(long timestamp) {
120
- // Seek to the closest sync frame at or before the specified time
121
- extractor.seekTo(timestamp * 1000, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
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();
@@ -53,18 +53,43 @@ public:
53
53
  return jsi::Value::undefined();
54
54
  }
55
55
 
56
- JSI_HOST_FUNCTION(getRotationInDegrees) {
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
- JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiVideo, nextImage),
63
- JSI_EXPORT_FUNC(JsiVideo, duration),
64
- JSI_EXPORT_FUNC(JsiVideo, framerate),
65
- JSI_EXPORT_FUNC(JsiVideo, seek),
66
- JSI_EXPORT_FUNC(JsiVideo, getRotationInDegrees),
67
- JSI_EXPORT_FUNC(JsiVideo, dispose))
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)
@@ -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
- AVAssetReader *_reader = nullptr;
24
- AVAssetReaderTrackOutput *_trackOutput = nullptr;
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
- void setupReader(CMTimeRange timeRange);
29
- NSDictionary *getOutputSettings();
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
- setupReader(CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity));
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::setupReader(CMTimeRange timeRange) {
25
- NSError *error = nil;
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
- AVURLAsset *asset =
28
- [AVURLAsset URLAssetWithURL:[NSURL URLWithString:@(_url.c_str())]
29
- options:nil];
30
- AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:asset
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 = [asset duration];
38
- if (time.timescale == 0) {
39
- NSLog(@"Error: Timescale of the asset is zero.");
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
- _framerate = videoTrack.nominalFrameRate;
47
- _preferredTransform = videoTrack.preferredTransform;
48
-
49
- NSDictionary *outputSettings = getOutputSettings();
50
- AVAssetReaderTrackOutput *trackOutput =
51
- [[AVAssetReaderTrackOutput alloc] initWithTrack:videoTrack
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
- CMSampleBufferRef sampleBuffer = [_trackOutput copyNextSampleBuffer];
69
- if (!sampleBuffer) {
70
- NSLog(@"No sample buffer.");
71
- return nullptr;
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
- CMTime time = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
87
- *timeStamp = CMTimeGetSeconds(time);
69
+ *timeStamp = CMTimeGetSeconds(currentTime);
88
70
  }
89
71
 
90
- CFRelease(sampleBuffer);
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 = M_PI_2; // 90 degrees
89
+ rotationAngle = 90;
108
90
  } else if (transform.a == 0 && transform.b == -1 && transform.c == 1 &&
109
91
  transform.d == 0) {
110
- rotationAngle = -M_PI_2; // -90 degrees
92
+ rotationAngle = 270;
111
93
  } else if (transform.a == -1 && transform.b == 0 && transform.c == 0 &&
112
94
  transform.d == -1) {
113
- rotationAngle = M_PI; // 180 degrees
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
- // Convert the rotation angle from radians to degrees
119
- return rotationAngle * 180 / M_PI;
97
+ return rotationAngle;
120
98
  }
121
99
 
122
100
  void RNSkiOSVideo::seek(double timeInMilliseconds) {
123
- if (_reader) {
124
- [_reader cancelReading];
125
- _reader = nil;
126
- _trackOutput = nil;
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
- CMTime startTime =
130
- CMTimeMakeWithSeconds(timeInMilliseconds / 1000.0, NSEC_PER_SEC);
131
- CMTimeRange timeRange = CMTimeRangeMake(startTime, kCMTimePositiveInfinity);
132
- setupReader(timeRange);
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
- width,
10
- height
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","fitRects","fit","rect","sizes","applyBoxFit","inscribe","halfWidthDelta","halfHeightDelta","input","output","Math","min","aspectRatio","exhaustiveCheck"],"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) => ({ width, height });\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 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\nexport const fitRects = (\n fit: Fit,\n rect: SkRect,\n { x, y, width, height }: SkRect\n) => {\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\nconst inscribe = (\n { width, height }: Size,\n rect: { x: number; y: number; width: number; height: number }\n) => {\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 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"],"mappings":"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"}
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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"}