@stepincto/expo-video 1.0.1 → 1.0.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.
@@ -17,6 +17,8 @@ class CachableRequest: Equatable, Hashable {
17
17
  var response: URLResponse?
18
18
  private(set) var receivedData = Data()
19
19
  private let dataOffset: Int64
20
+ private static var fileLocks: [String: NSLock] = [:]
21
+ private static let fileLocksQueue = DispatchQueue(label: "expo-video-cache-file-locks")
20
22
 
21
23
  init(loadingRequest: AVAssetResourceLoadingRequest, dataTask: URLSessionDataTask, dataRequest: AVAssetResourceLoadingDataRequest) {
22
24
  self.loadingRequest = loadingRequest
@@ -30,8 +32,41 @@ class CachableRequest: Equatable, Hashable {
30
32
  }
31
33
 
32
34
  func saveData(to cachedResource: CachedResource) {
33
- // Disabled: Player is now read-only with respect to the cache.
34
- // Do nothing.
35
+ // 1. Check if file is fully cached
36
+ if let mediaInfo = cachedResource.mediaInfo {
37
+ let expectedLength = Int(mediaInfo.expectedContentLength)
38
+ let ranges = mediaInfo.loadedDataRanges
39
+ if ranges.count == 1, ranges[0].0 == 0, ranges[0].1 == expectedLength - 1 {
40
+ // Already fully cached, do not write
41
+ return
42
+ }
43
+ }
44
+
45
+ // 2. Acquire per-file lock
46
+ let filePath = cachedResource.dataPath
47
+ let lock: NSLock = Self.fileLocksQueue.sync {
48
+ if let l = Self.fileLocks[filePath] { return l }
49
+ let l = NSLock()
50
+ Self.fileLocks[filePath] = l
51
+ return l
52
+ }
53
+ if !lock.try() {
54
+ // Another writer is active, skip this write
55
+ return
56
+ }
57
+ defer { lock.unlock() }
58
+
59
+ // 3. Write only missing data
60
+ let offset = dataOffset
61
+ let length = receivedData.count
62
+ let end = offset + Int64(length) - 1
63
+ if cachedResource.canRespondWithData(from: offset, to: end) {
64
+ // This range is already cached, skip
65
+ return
66
+ }
67
+ Task {
68
+ await cachedResource.writeData(data: receivedData, offset: offset)
69
+ }
35
70
  }
36
71
 
37
72
  static func == (lhs: CachableRequest, rhs: CachableRequest) -> Bool {
@@ -10,7 +10,7 @@ import ExpoModulesCore
10
10
  */
11
11
  class CachedResource {
12
12
  private let url: URL
13
- private let dataPath: String
13
+ internal let dataPath: String
14
14
  private let fileHandle: MediaFileHandle
15
15
  private(set) var mediaInfo: MediaInfo?
16
16
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stepincto/expo-video",
3
3
  "title": "Expo Video",
4
- "version": "1.0.1",
4
+ "version": "1.0.3",
5
5
  "originalUpstreamVersion": "2.2.2",
6
6
  "description": "A cross-platform, performant video component for React Native and Expo with Web support",
7
7
  "main": "build/index.js",