Buffering status

This commit is contained in:
Ali 2020-07-17 22:54:34 +04:00
parent 7fc078d315
commit 082e77a8d5
17 changed files with 56 additions and 41 deletions

View File

@ -626,7 +626,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
case .playing:
isPaused = false
playing = true
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
initialBuffering = true
isPaused = !whilePlaying
var isStreaming = false

View File

@ -292,12 +292,12 @@ private final class MediaPlayerContext {
duration = max(duration, CMTimeGetSeconds(audioTrackFrameBuffer.duration))
}
loadedDuration = duration
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play), soundEnabled: self.enableSound)
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play, progress: 0.0), soundEnabled: self.enableSound)
self.playerStatus.set(.single(status))
let _ = self.playerStatusValue.swap(status)
} else {
let duration = seekState?.duration ?? 0.0
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play), soundEnabled: self.enableSound)
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play, progress: 0.0), soundEnabled: self.enableSound)
self.playerStatus.set(.single(status))
let _ = self.playerStatusValue.swap(status)
}
@ -778,7 +778,7 @@ private final class MediaPlayerContext {
}
var rate: Double
var buffering = false
var bufferingProgress: Float?
if let worstStatus = worstStatus, case let .full(fullUntil) = worstStatus, fullUntil.isFinite {
if case .playing = self.state {
@ -811,8 +811,18 @@ private final class MediaPlayerContext {
rate = 0.0
}
}
} else if case let .buffering(progress) = worstStatus {
bufferingProgress = Float(progress)
rate = 0.0
print("bufferingProgress = \(progress)")
let tickTimer = SwiftSignalKit.Timer(timeout: 0.1, repeat: false, completion: { [weak self] in
self?.tick()
}, queue: self.queue)
self.tickTimer = tickTimer
tickTimer.start()
} else {
buffering = true
bufferingProgress = 0.0
rate = 0.0
}
@ -854,12 +864,12 @@ private final class MediaPlayerContext {
var statusTimestamp = CACurrentMediaTime()
let playbackStatus: MediaPlayerPlaybackStatus
if buffering {
if let bufferingProgress = bufferingProgress {
var whilePlaying = false
if case .playing = self.state {
whilePlaying = true
}
playbackStatus = .buffering(initial: false, whilePlaying: whilePlaying)
playbackStatus = .buffering(initial: false, whilePlaying: whilePlaying, progress: Float(bufferingProgress))
} else if !rate.isZero {
if reportRate.isZero {
//playbackStatus = .buffering(initial: false, whilePlaying: true)
@ -910,7 +920,7 @@ private final class MediaPlayerContext {
public enum MediaPlayerPlaybackStatus: Equatable {
case playing
case paused
case buffering(initial: Bool, whilePlaying: Bool)
case buffering(initial: Bool, whilePlaying: Bool, progress: Float)
public static func ==(lhs: MediaPlayerPlaybackStatus, rhs: MediaPlayerPlaybackStatus) -> Bool {
switch lhs {
@ -926,8 +936,8 @@ public enum MediaPlayerPlaybackStatus: Equatable {
} else {
return false
}
case let .buffering(initial, whilePlaying):
if case .buffering(initial, whilePlaying) = rhs {
case let .buffering(initial, whilePlaying, progress):
if case .buffering(initial, whilePlaying, progress) = rhs {
return true
} else {
return false

View File

@ -781,7 +781,7 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
default:
break
}
if case .buffering(true, _) = statusValue.status {
if case .buffering(true, _, _) = statusValue.status {
//initialBuffering = true
} else if Double(0.0).isLess(than: statusValue.duration) {
if let scrubbingTimestampValue = self.scrubbingTimestampValue {

View File

@ -3,7 +3,7 @@ import SwiftSignalKit
import CoreMedia
public enum MediaTrackFrameBufferStatus {
case buffering
case buffering(progress: Double)
case full(until: Double)
case finished(at: Double)
}
@ -123,7 +123,12 @@ public final class MediaTrackFrameBuffer {
if traceEvents {
print("buffered duration: \(bufferedDuration), requesting until \(timestamp) + \(self.highWaterDuration - bufferedDuration)")
}
self.frameSource.generateFrames(until: timestamp + self.highWaterDuration)
let delayIncrement = 0.3
var generateUntil = timestamp + delayIncrement
while generateUntil < timestamp + self.highWaterDuration {
self.frameSource.generateFrames(until: min(timestamp + self.highWaterDuration, generateUntil))
generateUntil += delayIncrement
}
if bufferedDuration > self.stallDuration {
if traceEvents {
@ -131,7 +136,7 @@ public final class MediaTrackFrameBuffer {
}
return .full(until: timestamp + self.highWaterDuration)
} else {
return .buffering
return .buffering(progress: max(0.0, bufferedDuration / self.stallDuration))
}
} else {
if traceEvents {

View File

@ -331,7 +331,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
switch status {
case .paused:
paused = true
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
paused = !whilePlaying
case .playing:
paused = false

View File

@ -176,7 +176,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self {
switch status.status {
case .playing, .buffering(_, true):
case .playing, .buffering(_, true, _):
strongSelf.playButton.isHidden = true
default:
strongSelf.playButton.isHidden = false

View File

@ -60,7 +60,7 @@ func messageFileMediaResourceStatus(context: AccountContext, file: TelegramMedia
mediaStatus = .playbackStatus(.playing)
case .paused:
mediaStatus = .playbackStatus(.paused)
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
if whilePlaying {
mediaStatus = .playbackStatus(.playing)
} else {
@ -84,7 +84,7 @@ func messageFileMediaResourceStatus(context: AccountContext, file: TelegramMedia
mediaStatus = .playbackStatus(.playing)
case .paused:
mediaStatus = .playbackStatus(.paused)
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
if whilePlaying {
mediaStatus = .playbackStatus(.playing)
} else {

View File

@ -149,7 +149,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
switch value.status.status {
case .playing:
isPlaying = true
case .buffering(_, true):
case .buffering(_, true, _):
isPlaying = true
default:
break
@ -229,7 +229,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
updatedGlobalControlOptions.insert(.next)
updatedGlobalControlOptions.insert(.seek)
switch state.status.status {
case .playing, .buffering(_, true):
case .playing, .buffering(_, true, _):
updatedGlobalControlOptions.insert(.pause)
default:
updatedGlobalControlOptions.insert(.play)
@ -383,7 +383,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
switch state.status.status {
case .playing:
isPlaying = true
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
isPlaying = whilePlaying
default:
break

View File

@ -304,7 +304,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
isPaused = false
case .paused:
isPaused = true
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
isPaused = !whilePlaying
}
if strongSelf.currentIsPaused != isPaused {

View File

@ -14,7 +14,7 @@ final class GenericEmbedImplementation: WebEmbedImplementation {
init(url: String) {
self.url = url
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true), soundEnabled: true)
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
}
func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String, ((Any?) -> Void)?) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) {

View File

@ -37,7 +37,7 @@ final class PictureInPictureVideoControlsNode: ASDisplayNode {
case .playing:
self.playButton.isHidden = true
self.pauseButton.isHidden = false
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
if whilePlaying {
self.playButton.isHidden = true
self.pauseButton.isHidden = false

View File

@ -315,7 +315,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
self.isBuffering = false
}
if self.isBuffering {
status = .buffering(initial: false, whilePlaying: isPlaying)
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
} else {
status = isPlaying ? .playing : .paused
}
@ -326,7 +326,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
let status: MediaPlayerPlaybackStatus
self.isBuffering = true
if self.isBuffering {
status = .buffering(initial: false, whilePlaying: isPlaying)
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
} else {
status = isPlaying ? .playing : .paused
}
@ -337,7 +337,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
let status: MediaPlayerPlaybackStatus
self.isBuffering = false
if self.isBuffering {
status = .buffering(initial: false, whilePlaying: isPlaying)
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
} else {
status = isPlaying ? .playing : .paused
}
@ -381,7 +381,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
func play() {
assert(Queue.mainQueue().isCurrent())
if !self.initializedStatus {
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true), soundEnabled: true))
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true))
}
if !self.hasAudioSession {
self.audioSessionDisposable.set(self.audioSessionManager.push(audioSessionType: .play, activate: { [weak self] _ in

View File

@ -44,7 +44,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
private let playbackCompletedListeners = Bag<() -> Void>()
private var initializedStatus = false
private var statusValue = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: false), soundEnabled: true)
private var statusValue = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: false, progress: 0.0), soundEnabled: true)
private var isBuffering = true
private let _status = ValuePromise<MediaPlayerStatus>()
var status: Signal<MediaPlayerStatus, NoError> {
@ -169,7 +169,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
let isPlaying = !self.player.rate.isZero
let status: MediaPlayerPlaybackStatus
if self.isBuffering {
status = .buffering(initial: false, whilePlaying: isPlaying)
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
} else {
status = isPlaying ? .playing : .paused
}
@ -180,7 +180,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
let status: MediaPlayerPlaybackStatus
self.isBuffering = true
if self.isBuffering {
status = .buffering(initial: false, whilePlaying: isPlaying)
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
} else {
status = isPlaying ? .playing : .paused
}
@ -191,7 +191,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
let status: MediaPlayerPlaybackStatus
self.isBuffering = false
if self.isBuffering {
status = .buffering(initial: false, whilePlaying: isPlaying)
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
} else {
status = isPlaying ? .playing : .paused
}
@ -219,7 +219,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
func play() {
assert(Queue.mainQueue().isCurrent())
if !self.initializedStatus {
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: self.seekId, status: .buffering(initial: true, whilePlaying: true), soundEnabled: true))
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: self.seekId, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true))
}
if !self.hasAudioSession {
self.audioSessionDisposable.set(self.audioSessionManager.push(audioSessionType: .play, activate: { [weak self] _ in

View File

@ -20,7 +20,7 @@ final class TwitchEmbedImplementation: WebEmbedImplementation {
init(url: String) {
self.url = url
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true), soundEnabled: true)
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
}
func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String, ((Any?) -> Void)?) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) {

View File

@ -97,7 +97,7 @@ final class VimeoEmbedImplementation: WebEmbedImplementation {
init(videoId: String, timestamp: Int = 0) {
self.videoId = videoId
self.timestamp = timestamp
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true), soundEnabled: true)
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
}
func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String, ((Any?) -> Void)?) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) {
@ -221,7 +221,7 @@ final class VimeoEmbedImplementation: WebEmbedImplementation {
playbackStatus = .paused
newTimestamp = 0.0
default:
playbackStatus = .buffering(initial: true, whilePlaying: false)
playbackStatus = .buffering(initial: true, whilePlaying: false, progress: 0.0)
}
self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: Double(duration), dimensions: self.status.dimensions, timestamp: newTimestamp, baseRate: 1.0, seekId: self.status.seekId, status: playbackStatus, soundEnabled: true)

View File

@ -121,7 +121,7 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation {
if self.timestamp > 0 {
self.ignoreEarlierTimestamps = true
}
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true), soundEnabled: true)
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
self.benchmarkStartTime = CFAbsoluteTimeGetCurrent()
}
@ -286,16 +286,16 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation {
playbackStatus = .paused
newTimestamp = 0.0
} else {
playbackStatus = .buffering(initial: false, whilePlaying: true)
playbackStatus = .buffering(initial: false, whilePlaying: true, progress: 0.0)
}
case 1:
playbackStatus = .playing
case 2:
playbackStatus = .paused
case 3:
playbackStatus = .buffering(initial: false, whilePlaying: true)
playbackStatus = .buffering(initial: false, whilePlaying: true, progress: 0.0)
default:
playbackStatus = .buffering(initial: true, whilePlaying: false)
playbackStatus = .buffering(initial: true, whilePlaying: false, progress: 0.0)
}
if case .playing = playbackStatus, !self.started {

View File

@ -198,7 +198,7 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode {
switch value.status {
case .playing:
isPaused = false
case let .buffering(_, whilePlaying):
case let .buffering(_, whilePlaying, _):
initialBuffering = true
isPaused = !whilePlaying
var isStreaming = false