mirror of
https://github.com/dirtydishes/dreamio.git
synced 2026-06-06 21:38:15 +00:00
reprioritize range cache on vlc misses
This commit is contained in:
parent
5cd5d2f9ff
commit
6ac2062822
5 changed files with 244 additions and 2 deletions
|
|
@ -259,6 +259,7 @@ final class ProgressiveHTTPRangeCacheSession {
|
|||
private let responseChunkSize: Int64 = 1_048_576
|
||||
private var prefetchTask: Task<Void, Never>?
|
||||
private var activePrefetchWindow: HTTPByteRange?
|
||||
private var activePrefetchPreferredOffset: Int64?
|
||||
|
||||
init(fetcher: HTTPRangeRemoteFetcher, contentLength: Int64, durationProvider: @escaping () -> TimeInterval) {
|
||||
self.fetcher = fetcher
|
||||
|
|
@ -266,6 +267,10 @@ final class ProgressiveHTTPRangeCacheSession {
|
|||
self.durationProvider = durationProvider
|
||||
}
|
||||
|
||||
deinit {
|
||||
cancelPrefetch()
|
||||
}
|
||||
|
||||
func data(for requestedRange: HTTPByteRange) async throws -> Data {
|
||||
let bounded = clamp(requestedRange)
|
||||
if let data = store.data(for: bounded) {
|
||||
|
|
@ -278,9 +283,10 @@ final class ProgressiveHTTPRangeCacheSession {
|
|||
#if DEBUG
|
||||
print("[DreamioRangeCache] cache=miss range=\(bounded.start)-\(bounded.end)")
|
||||
#endif
|
||||
cancelPrefetchIfNeeded(forForegroundRange: bounded)
|
||||
let data = try await fetcher.fetch(range: bounded)
|
||||
store.insert(data: data, at: bounded.start)
|
||||
prefetch(aroundByteOffset: bounded.end + 1)
|
||||
prefetch(aroundByteOffset: bounded.end + 1, forceRestart: true)
|
||||
return store.data(for: bounded) ?? data
|
||||
}
|
||||
|
||||
|
|
@ -293,16 +299,22 @@ final class ProgressiveHTTPRangeCacheSession {
|
|||
}
|
||||
|
||||
func prefetch(aroundByteOffset offset: Int64) {
|
||||
if activePrefetchWindow?.contains(offset) == true, prefetchTask?.isCancelled == false {
|
||||
prefetch(aroundByteOffset: offset, forceRestart: false)
|
||||
}
|
||||
|
||||
func prefetch(aroundByteOffset offset: Int64, forceRestart: Bool) {
|
||||
if !forceRestart, activePrefetchWindow?.contains(offset) == true, prefetchTask?.isCancelled == false {
|
||||
return
|
||||
}
|
||||
|
||||
prefetchTask?.cancel()
|
||||
let window = targetWindow(aroundByteOffset: offset)
|
||||
activePrefetchWindow = window
|
||||
activePrefetchPreferredOffset = offset
|
||||
store.evict(keeping: window)
|
||||
guard !store.hasData(for: window) else {
|
||||
activePrefetchWindow = nil
|
||||
activePrefetchPreferredOffset = nil
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -333,14 +345,33 @@ final class ProgressiveHTTPRangeCacheSession {
|
|||
}
|
||||
}
|
||||
self.activePrefetchWindow = nil
|
||||
self.activePrefetchPreferredOffset = nil
|
||||
}
|
||||
}
|
||||
|
||||
func cancelPrefetch() {
|
||||
prefetchTask?.cancel()
|
||||
activePrefetchWindow = nil
|
||||
activePrefetchPreferredOffset = nil
|
||||
}
|
||||
|
||||
func byteOffset(for position: Float) -> Int64 {
|
||||
let clamped = max(0, min(1, position))
|
||||
return Int64(Float(contentLength) * clamped)
|
||||
}
|
||||
|
||||
private func cancelPrefetchIfNeeded(forForegroundRange range: HTTPByteRange) {
|
||||
guard activePrefetchWindow?.contains(range.start) == true,
|
||||
let preferredOffset = activePrefetchPreferredOffset,
|
||||
abs(range.start - preferredOffset) >= responseChunkSize else {
|
||||
return
|
||||
}
|
||||
#if DEBUG
|
||||
print("[DreamioRangeCache] prefetch reprioritize from=\(preferredOffset) to=\(range.start)")
|
||||
#endif
|
||||
cancelPrefetch()
|
||||
}
|
||||
|
||||
private func targetWindow(aroundByteOffset offset: Int64) -> HTTPByteRange {
|
||||
let bytesPerSecond = estimatedBytesPerSecond()
|
||||
let behind = max(prefetchChunkSize, bytesPerSecond * 30)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue