mirror of
https://github.com/HaishinKit/HaishinKit.swift.git
synced 2026-05-07 20:12:28 +00:00
80 lines
2.3 KiB
Swift
80 lines
2.3 KiB
Swift
import AVFoundation
|
|
import CoreMedia
|
|
import Foundation
|
|
|
|
protocol RTMPTimeConvertible {
|
|
var seconds: TimeInterval { get }
|
|
}
|
|
|
|
private let kRTMPTimestamp_defaultTimeInterval: TimeInterval = 0
|
|
|
|
struct RTMPTimestamp<T: RTMPTimeConvertible> {
|
|
enum Error: Swift.Error {
|
|
case invalidSequence
|
|
}
|
|
|
|
private var startedAt = kRTMPTimestamp_defaultTimeInterval
|
|
private var updatedAt = kRTMPTimestamp_defaultTimeInterval
|
|
private var timedeltaFraction: TimeInterval = kRTMPTimestamp_defaultTimeInterval
|
|
|
|
mutating func update(_ value: T) throws -> UInt32 {
|
|
guard updatedAt < value.seconds else {
|
|
throw Error.invalidSequence
|
|
}
|
|
if startedAt == 0 {
|
|
startedAt = value.seconds
|
|
updatedAt = value.seconds
|
|
return 0
|
|
}
|
|
var timedelta = (value.seconds - updatedAt) * 1000
|
|
timedeltaFraction += timedelta.truncatingRemainder(dividingBy: 1)
|
|
if 1 <= timedeltaFraction {
|
|
timedeltaFraction -= 1
|
|
timedelta += 1
|
|
}
|
|
updatedAt = value.seconds
|
|
return UInt32(timedelta)
|
|
}
|
|
|
|
mutating func update(_ message: some RTMPMessage, chunkType: RTMPChunkType) {
|
|
switch chunkType {
|
|
case .zero:
|
|
if startedAt == 0 {
|
|
startedAt = TimeInterval(message.timestamp) / 1000
|
|
updatedAt = TimeInterval(message.timestamp) / 1000
|
|
} else {
|
|
updatedAt = TimeInterval(message.timestamp) / 1000
|
|
}
|
|
default:
|
|
updatedAt += TimeInterval(message.timestamp) / 1000
|
|
}
|
|
}
|
|
|
|
mutating func clear() {
|
|
startedAt = kRTMPTimestamp_defaultTimeInterval
|
|
updatedAt = kRTMPTimestamp_defaultTimeInterval
|
|
timedeltaFraction = kRTMPTimestamp_defaultTimeInterval
|
|
}
|
|
}
|
|
|
|
extension AVAudioTime: RTMPTimeConvertible {
|
|
var seconds: TimeInterval {
|
|
AVAudioTime.seconds(forHostTime: hostTime)
|
|
}
|
|
}
|
|
|
|
extension RTMPTimestamp where T == AVAudioTime {
|
|
var value: AVAudioTime {
|
|
return AVAudioTime(hostTime: AVAudioTime.hostTime(forSeconds: updatedAt))
|
|
}
|
|
}
|
|
|
|
extension CMTime: RTMPTimeConvertible {
|
|
}
|
|
|
|
extension RTMPTimestamp where T == CMTime {
|
|
var value: CMTime {
|
|
return CMTime(seconds: updatedAt, preferredTimescale: 1000)
|
|
}
|
|
}
|