Skip to content

Commit

Permalink
to consider stabilization delay.
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo4405 committed Nov 13, 2024
1 parent 7a737c2 commit ee0728f
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 10 deletions.
4 changes: 4 additions & 0 deletions HaishinKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@
BCB976DF26107B5600C9A649 /* TSField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB976DE26107B5600C9A649 /* TSField.swift */; };
BCB9773F2621812800C9A649 /* ISOTypeBufferUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB9773E2621812800C9A649 /* ISOTypeBufferUtil.swift */; };
BCB9D79F2BF12AD8008C5B1B /* SampleVideo_360x240_5mb.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 29B876D91CD70CE700FC07DA /* SampleVideo_360x240_5mb.mp4 */; };
BCBF01762CE0AD1D00C63E7A /* FrameTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCBF01752CE0AD1900C63E7A /* FrameTracker.swift */; };
BCC1A72B264FAC1800661156 /* ESSpecificData.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCC1A72A264FAC1800661156 /* ESSpecificData.swift */; };
BCC2237E2C1468C700F5F234 /* SRTHaishinKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCCC45962AA289FA0016EFE8 /* SRTHaishinKit.framework */; };
BCC2237F2C1468C700F5F234 /* SRTHaishinKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BCCC45962AA289FA0016EFE8 /* SRTHaishinKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -714,6 +715,7 @@
BCABED202BDE23C600CC7E73 /* AudioNode+DebugExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AudioNode+DebugExtension.swift"; sourceTree = "<group>"; };
BCB976DE26107B5600C9A649 /* TSField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSField.swift; sourceTree = "<group>"; };
BCB9773E2621812800C9A649 /* ISOTypeBufferUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ISOTypeBufferUtil.swift; sourceTree = "<group>"; };
BCBF01752CE0AD1900C63E7A /* FrameTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameTracker.swift; sourceTree = "<group>"; };
BCC1A72A264FAC1800661156 /* ESSpecificData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ESSpecificData.swift; sourceTree = "<group>"; };
BCC4F4142AD6FC1100954EF5 /* IOTellyUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOTellyUnit.swift; sourceTree = "<group>"; };
BCC9E9082636FF7400948774 /* DataBufferTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataBufferTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -882,6 +884,7 @@
BC0D236C26331BAB001DDA0C /* DataBuffer.swift */,
29B876671CD70AB300FC07DA /* DataConvertible.swift */,
2976A4851D4903C300B53EF2 /* DeviceUtil.swift */,
BCBF01752CE0AD1900C63E7A /* FrameTracker.swift */,
BC32E88729C9971100051507 /* InstanceHolder.swift */,
2942424C1CF4C01300D65DCB /* MD5.swift */,
2942A4F721A9418A004E1BEE /* Running.swift */,
Expand Down Expand Up @@ -1861,6 +1864,7 @@
BC11023E2917C35B00D48035 /* CVPixelBufferPool+Extension.swift in Sources */,
29C2631C1D0083B50098D4EF /* IOVideoUnit.swift in Sources */,
29B876B41CD70B2800FC07DA /* RTMPSharedObject.swift in Sources */,
BCBF01762CE0AD1D00C63E7A /* FrameTracker.swift in Sources */,
2901A4EE1D437170002BBD23 /* MediaLink.swift in Sources */,
29B876941CD70AFE00FC07DA /* SoundTransform.swift in Sources */,
29DF20662312A436004057C3 /* RTMPSocketCompatible.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
disableMainThreadChecker = "YES"
disablePerformanceAntipatternChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down
6 changes: 6 additions & 0 deletions Sources/IO/IOVideoMixer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ final class IOVideoMixer<T: IOVideoMixerDelegate> {
for screen in screens where screen.track == track {
screen.enqueue(sampleBuffer)
}
if settings.mainTrack == track {
screen.videoPresentationTimeStamp = sampleBuffer.presentationTimeStamp
}
case .passthrough:
if settings.mainTrack == track {
outputSampleBuffer(sampleBuffer)
Expand All @@ -62,6 +65,9 @@ final class IOVideoMixer<T: IOVideoMixerDelegate> {
for screen in screens where screen.track == track {
screen.reset()
}
if settings.mainTrack == track {
screen.videoPresentationTimeStamp = .invalid
}
}

@inline(__always)
Expand Down
4 changes: 1 addition & 3 deletions Sources/IO/IOVideoUnit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,13 @@ final class IOVideoUnit: IOUnit {
}
let capture = self.capture(for: track)
configuration?(capture, nil)
videoMixer.reset(track)
try capture?.attachDevice(device, videoUnit: self)
}
if device != nil && view != nil {
// Start captureing if not running.
mixer?.session.startRunning()
}
if device == nil {
videoMixer.reset(track)
}
}

#if os(iOS) || os(tvOS) || os(macOS)
Expand Down
8 changes: 6 additions & 2 deletions Sources/Screen/Choreographer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,15 @@ final class DisplayLinkChoreographer: NSObject, Choreographer {
}
weak var delegate: (any ChoreographerDelegate)?
var isRunning: Atomic<Bool> = .init(false)
var preferredFramesPerSecond = DisplayLinkChoreographer.preferredFramesPerSecond
var preferredFramesPerSecond = DisplayLinkChoreographer.preferredFramesPerSecond {
didSet {
displayLink?.preferredFramesPerSecond = preferredFramesPerSecond
}
}
private var displayLink: DisplayLink? {
didSet {
oldValue?.invalidate()
guard let displayLink = displayLink else {
guard let displayLink else {
return
}
displayLink.isPaused = true
Expand Down
12 changes: 9 additions & 3 deletions Sources/Screen/Screen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public final class Screen: ScreenObjectContainerConvertible {
return choreographer.isRunning
}

public var delayTime: TimeInterval = (1 / 33)
var videoPresentationTimeStamp: CMTime = .invalid

#if os(macOS)
/// Specifies the background color.
Expand All @@ -81,6 +81,7 @@ public final class Screen: ScreenObjectContainerConvertible {
}
}
#endif

weak var observer: (any ScreenObserver)?
private var root: ScreenObjectContainer = .init()
private(set) var renderer = ScreenRendererByCPU()
Expand All @@ -89,7 +90,7 @@ public final class Screen: ScreenObjectContainerConvertible {
choreographer.delegate = self
return choreographer
}()
private var timeStamp: CMTime = .invalid
private var timeStamp: CMTime = .zero
private var attributes: [NSString: NSObject] {
return [
kCVPixelBufferPixelFormatTypeKey: NSNumber(value: kCVPixelFormatType_32ARGB),
Expand Down Expand Up @@ -177,7 +178,12 @@ extension Screen: ChoreographerDelegate {
if let dictionary = CVBufferGetAttachments(pixelBuffer, .shouldNotPropagate) {
CVBufferSetAttachments(pixelBuffer, dictionary, .shouldPropagate)
}
let now = CMTime(seconds: timestamp - delayTime, preferredTimescale: 1000000000)
let now = videoPresentationTimeStamp == .invalid ?
CMTime(seconds: timestamp, preferredTimescale: 1000000000) :
videoPresentationTimeStamp
guard timeStamp < now else {
return
}
var timingInfo = CMSampleTimingInfo(
duration: timeStamp == .invalid ? .zero : now - timeStamp,
presentationTimeStamp: now,
Expand Down
16 changes: 15 additions & 1 deletion Sources/Screen/ScreenObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ public final class VideoTrackScreenObject: ScreenObject, ChromaKeyProcessable {
}
}

public var frameRate: Int {
frameTracker.frameRate
}

override var blendMode: ScreenObject.BlendMode {
if 0.0 < cornerRadius || chromaKeyColor != nil {
return .alpha
Expand All @@ -239,6 +243,7 @@ public final class VideoTrackScreenObject: ScreenObject, ChromaKeyProcessable {

private var queue: TypedBlockQueue<CMSampleBuffer>?
private var effects: [VideoEffect] = .init()
private var frameTracker = FrameTracker()

/// Create a screen object.
override public init() {
Expand Down Expand Up @@ -270,10 +275,11 @@ public final class VideoTrackScreenObject: ScreenObject, ChromaKeyProcessable {
}

override public func makeImage(_ renderer: some ScreenRenderer) -> CGImage? {
guard let sampleBuffer = queue?.query(renderer.presentationTimeStamp),
guard let sampleBuffer = queue?.dequeue(renderer.presentationTimeStamp),
let pixelBuffer = sampleBuffer.imageBuffer else {
return nil
}
frameTracker.update(sampleBuffer.presentationTimeStamp)
// Resizing before applying the filter for performance optimization.
var image = CIImage(cvPixelBuffer: pixelBuffer).transformed(by: videoGravity.scale(
bounds.size,
Expand Down Expand Up @@ -306,12 +312,20 @@ public final class VideoTrackScreenObject: ScreenObject, ChromaKeyProcessable {
}
}

override public func draw(_ renderer: some ScreenRenderer) {
super.draw(renderer)
if queue?.isEmpty == false {
invalidateLayout()
}
}

func enqueue(_ sampleBuffer: CMSampleBuffer) {
try? queue?.enqueue(sampleBuffer)
invalidateLayout()
}

func reset() {
frameTracker.clear()
try? queue?.reset()
invalidateLayout()
}
Expand Down
27 changes: 27 additions & 0 deletions Sources/Util/FrameTracker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import CoreMedia

struct FrameTracker {
static let seconds = 1.0

private(set) var frameRate: Int = 0
private var count = 0
private var rotated: CMTime = .zero

init() {
}

mutating func update(_ time: CMTime) {
count += 1
if Self.seconds <= (time - rotated).seconds {
rotated = time
frameRate = count
count = 0
logger.info(frameRate)
}
}

mutating func clear() {
count = 0
rotated = .zero
}
}
2 changes: 1 addition & 1 deletion Sources/Util/TypedBlockQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ final class TypedBlockQueue<T: AnyObject> {
}

extension TypedBlockQueue where T == CMSampleBuffer {
func query(_ presentationTimeStamp: CMTime) -> CMSampleBuffer? {
func dequeue(_ presentationTimeStamp: CMTime) -> CMSampleBuffer? {
var result: CMSampleBuffer?
while !queue.isEmpty {
guard let head else {
Expand Down

0 comments on commit ee0728f

Please sign in to comment.