-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Create
TrackTimeline
to properly synchronize pause/resume/sta…
…rt/stop video/audio buffers (#2948) * feat: Create `ClockSession` * prepare? * https * feat: Create `TrackTimeline` * Update TrackTimeline.swift * Update TrackTimeline.swift * Update TrackTimeline.swift * Update TrackTimeline.swift * Create `Track` * finish recording? * Fix typos * chore: Lint * fix: Start asset writer * Log track type * Update RecordingSession.swift * feat: Add `addFollowingTrack` * Update TrackTimeline.swift * Update TrackTimeline.swift * fix: Always update `firstTimestamp` and `lastTimestamp` * Update TrackTimeline.swift * fix: Fix actual duration * Remove now unneeded following track loic * fix: More logs * Log better * fix: Fix `isPaused` not respected * fix: Subtract `pauseDuration` * fix: Also support consecutive pauses * fix: Use `CMTime` * fix: Remove logs * Create CMTime+invert.swift * Create CMSampleBuffer+copyWithTimestampOffset.swift * fix: Also account for open pauses * feat: Shift off Buffer timestamp if needed * fix: Lint * fix: Fix adjusting timestamp * fix: Fix pauses being left open * fix: Properly offset buffer inside write block * `inverted` * Log timeline after finish * Update CMSampleBuffer+copyWithTimestampOffset.swift
- Loading branch information
Showing
11 changed files
with
627 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
package/ios/Core/Extensions/CMSampleBuffer+copyWithTimestampOffset.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// | ||
// CMSampleBuffer+copyWithTimestampOffset.swift | ||
// VisionCamera | ||
// | ||
// Created by Marc Rousavy on 08.06.24. | ||
// | ||
|
||
import CoreMedia | ||
import Foundation | ||
|
||
// MARK: - TimestampAdjustmentError | ||
|
||
enum TimestampAdjustmentError: Error { | ||
case failedToCopySampleBuffer(status: OSStatus) | ||
case sampleBufferCopyIsNil | ||
case failedToGetTimingInfo(status: OSStatus) | ||
case noTimingEntriesFound | ||
} | ||
|
||
private let kSampleBufferError_NoError: OSStatus = 0 | ||
|
||
extension CMSampleBuffer { | ||
private func getTimingInfos() throws -> [CMSampleTimingInfo] { | ||
var count: CMItemCount = 0 | ||
let getCountStatus = CMSampleBufferGetSampleTimingInfoArray(self, | ||
entryCount: 0, | ||
arrayToFill: nil, | ||
entriesNeededOut: &count) | ||
guard getCountStatus == kSampleBufferError_NoError else { | ||
throw TimestampAdjustmentError.failedToGetTimingInfo(status: getCountStatus) | ||
} | ||
|
||
let emptyTimingInfo = CMSampleTimingInfo(duration: .invalid, | ||
presentationTimeStamp: .invalid, | ||
decodeTimeStamp: .invalid) | ||
var infos = [CMSampleTimingInfo](repeating: emptyTimingInfo, count: count) | ||
let getArrayStatus = CMSampleBufferGetSampleTimingInfoArray(self, | ||
entryCount: count, | ||
arrayToFill: &infos, | ||
entriesNeededOut: nil) | ||
guard getArrayStatus == kSampleBufferError_NoError else { | ||
throw TimestampAdjustmentError.failedToGetTimingInfo(status: getArrayStatus) | ||
} | ||
guard !infos.isEmpty else { | ||
throw TimestampAdjustmentError.noTimingEntriesFound | ||
} | ||
return infos | ||
} | ||
|
||
/** | ||
Returns a copy of the current CMSampleBuffer with the timing info adjusted by the given offset. | ||
The decode and presentation timestamps will be adjusted by the given offset (+). | ||
*/ | ||
func copyWithTimestampOffset(_ offset: CMTime) throws -> CMSampleBuffer { | ||
let timingInfos = try getTimingInfos() | ||
let newTimingInfos = timingInfos.map { timingInfo in | ||
return CMSampleTimingInfo(duration: timingInfo.duration, | ||
presentationTimeStamp: timingInfo.presentationTimeStamp + offset, | ||
decodeTimeStamp: timingInfo.decodeTimeStamp + offset) | ||
} | ||
|
||
var newBuffer: CMSampleBuffer? | ||
let copyResult = CMSampleBufferCreateCopyWithNewTiming(allocator: nil, | ||
sampleBuffer: self, | ||
sampleTimingEntryCount: newTimingInfos.count, | ||
sampleTimingArray: newTimingInfos, | ||
sampleBufferOut: &newBuffer) | ||
guard copyResult == kSampleBufferError_NoError else { | ||
throw TimestampAdjustmentError.failedToCopySampleBuffer(status: copyResult) | ||
} | ||
guard let newBuffer else { | ||
throw TimestampAdjustmentError.sampleBufferCopyIsNil | ||
} | ||
|
||
return newBuffer | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// CMTime+inverted.swift | ||
// VisionCamera | ||
// | ||
// Created by Marc Rousavy on 08.06.24. | ||
// | ||
|
||
import CoreMedia | ||
import Foundation | ||
|
||
extension CMTime { | ||
/** | ||
Inverts the time. | ||
e.g. 3.5 seconds -> -3.5 seconds | ||
*/ | ||
func inverted() -> CMTime { | ||
return CMTime(value: value * -1, timescale: timescale) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// | ||
// TimelineEvent.swift | ||
// VisionCamera | ||
// | ||
// Created by Marc Rousavy on 08.06.24. | ||
// | ||
|
||
import CoreMedia | ||
import Foundation | ||
|
||
/** | ||
Represents an Event inside a track timeline. | ||
Each event has a timestamp. | ||
*/ | ||
struct TimelineEvent { | ||
let type: EventType | ||
let timestamp: CMTime | ||
|
||
var description: String { | ||
switch type { | ||
case .start: | ||
return "\(timestamp.seconds): ⏺️ Started" | ||
case .pause: | ||
return "\(timestamp.seconds): ⏸️ Paused" | ||
case .resume: | ||
return "\(timestamp.seconds): ▶️ Resumed" | ||
case .stop: | ||
return "\(timestamp.seconds): ⏹️ Stopped" | ||
} | ||
} | ||
|
||
enum EventType { | ||
case start | ||
case pause | ||
case resume | ||
case stop | ||
} | ||
} |
Oops, something went wrong.