Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjustable buffer #467

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Decimus.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
9B131E332B7E4A1C00B29D77 /* ApplicationHEVCSEIs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B131E322B7E4A1C00B29D77 /* ApplicationHEVCSEIs.swift */; };
9B131E352B7E548700B29D77 /* CMSampleBuffer+Attachments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B131E342B7E548700B29D77 /* CMSampleBuffer+Attachments.swift */; };
9B165A1529840B610017079F /* CallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B165A1429840B610017079F /* CallController.swift */; };
9B3D773E2C64B70200858313 /* SlidingWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B3D773D2C64B70200858313 /* SlidingWindow.swift */; };
9B3F86852C58F4B800B5B8BA /* CircularBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B3F86842C58F4B800B5B8BA /* CircularBuffer.swift */; };
9B4788D42B972F990056CE7E /* TestVideoSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4788D32B972F990056CE7E /* TestVideoSubscription.swift */; };
9B480662297EAF170040F5D4 /* InCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B480661297EAF170040F5D4 /* InCallView.swift */; };
Expand Down Expand Up @@ -221,6 +222,7 @@
9B131E322B7E4A1C00B29D77 /* ApplicationHEVCSEIs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationHEVCSEIs.swift; sourceTree = "<group>"; };
9B131E342B7E548700B29D77 /* CMSampleBuffer+Attachments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CMSampleBuffer+Attachments.swift"; sourceTree = "<group>"; };
9B165A1429840B610017079F /* CallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallController.swift; sourceTree = "<group>"; };
9B3D773D2C64B70200858313 /* SlidingWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlidingWindow.swift; sourceTree = "<group>"; };
9B3F86842C58F4B800B5B8BA /* CircularBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularBuffer.swift; sourceTree = "<group>"; };
9B4788D32B972F990056CE7E /* TestVideoSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestVideoSubscription.swift; sourceTree = "<group>"; };
9B480661297EAF170040F5D4 /* InCallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InCallView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -520,6 +522,7 @@
9B131E342B7E548700B29D77 /* CMSampleBuffer+Attachments.swift */,
9BC53C9B2BFE075300BB39C6 /* VarianceCalculator.swift */,
9B3F86842C58F4B800B5B8BA /* CircularBuffer.swift */,
9B3D773D2C64B70200858313 /* SlidingWindow.swift */,
);
path = Decimus;
sourceTree = "<group>";
Expand Down Expand Up @@ -940,6 +943,7 @@
1867635D2B2B6BB000339421 /* H264Publication+Measurement.swift in Sources */,
FF2498B42A55E8CC00C6D66D /* SubscriptionFactory.swift in Sources */,
186397A12ADE0B9100FBF877 /* VideoDevices.swift in Sources */,
9B3D773E2C64B70200858313 /* SlidingWindow.swift in Sources */,
9B52EE332B763157006E9C58 /* PublicationPopover.swift in Sources */,
18C89A3C2A13D30B005B333B /* MetricsSubmitter.swift in Sources */,
FFD1CFF02A214FA60034CDD0 /* SubscriberDelegate.swift in Sources */,
Expand Down
8 changes: 8 additions & 0 deletions Decimus/Measurements/VideoJitterBuffer+Measurement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ extension VideoJitterBuffer {
record(field: "currentDepth", value: UInt32(depth * 1000) as AnyObject, timestamp: timestamp)
}

func targetDepth(depth: TimeInterval, timestamp: Date) {
record(field: "targetDepth", value: depth, timestamp: timestamp)
}

func idealTargetDepth(depth: TimeInterval, timestamp: Date) {
record(field: "idealDepth", value: depth, timestamp: timestamp)
}

func underrun(timestamp: Date?) {
self.underruns += 1
record(field: "underruns", value: self.underruns as AnyObject, timestamp: timestamp)
Expand Down
47 changes: 47 additions & 0 deletions Decimus/SlidingWindow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import DequeModule

class SlidingWindow<T: Numeric> {
private var values: Deque<(timestamp: Date, value: T)> = []
private let length: TimeInterval

init(length: TimeInterval) {
self.length = length
}

func add(timestamp: Date, value: T) {
// Remove values that are too old.
while let first = self.values.first,
timestamp.timeIntervalSince(first.timestamp) > self.length {
_ = self.values.popFirst()
}

self.values.append((timestamp, value))
}

func get(from: Date) -> [T] {
self.values.compactMap {
from.timeIntervalSince($0.timestamp) <= self.length ? $0.value : nil
}
}
}

class SlidingTimeWindow {
private let window: SlidingWindow<TimeInterval>
private var lastSubmit: Date?

init(length: TimeInterval) {
self.window = .init(length: length)
}

func add(timestamp: Date) {
if let lastSubmit = self.lastSubmit {
let elapsed = timestamp.timeIntervalSince(lastSubmit)
self.window.add(timestamp: timestamp, value: elapsed)
}
self.lastSubmit = timestamp
}

func max(from: Date) -> TimeInterval? {
self.window.get(from: from).max()
}
}
18 changes: 16 additions & 2 deletions Decimus/Subscriptions/VideoHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Atomics
import os

// swiftlint:disable type_body_length

Check notice on line 5 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoHandler.swift#L5

Blanket Disable Command Violation: Use 'next', 'this' or 'previous' instead to disable the 'type_body_length' rule once, or re-enable it as soon as possible` (blanket_disable_command)

Check notice on line 5 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoHandler.swift#L5

Blanket Disable Command Violation: Use 'next', 'this' or 'previous' instead to disable the 'type_body_length' rule once, or re-enable it as soon as possible` (blanket_disable_command)

Check notice on line 5 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoHandler.swift#L5

Blanket Disable Command Violation: Use 'next', 'this' or 'previous' instead to disable the 'type_body_length' rule once, or re-enable it as soon as possible` (blanket_disable_command)

enum DecimusVideoRotation: UInt8 {
case portrait = 1
Expand Down Expand Up @@ -56,6 +56,7 @@

private var duration: TimeInterval? = 0
private let variances: VarianceCalculator
private var currentTargetDepth: TimeInterval

/// Create a new video handler.
/// - Parameters:
Expand Down Expand Up @@ -100,6 +101,7 @@
self.metricsSubmitter = metricsSubmitter
self.description = self.namespace
self.variances = variances
self.currentTargetDepth = jitterBufferConfig.minDepth

if jitterBufferConfig.mode != .layer {
// Create the decoder.
Expand Down Expand Up @@ -250,8 +252,9 @@
self.jitterBuffer = try .init(namespace: self.namespace,
metricsSubmitter: self.metricsSubmitter,
sort: !self.reliable,
minDepth: self.jitterBufferConfig.minDepth,
capacity: Int(floor(self.jitterBufferConfig.capacity / duration)))
minDepth: self.currentTargetDepth,
capacity: self.jitterBufferConfig.capacity,
duration: duration)
self.duration = duration
}

Expand Down Expand Up @@ -318,6 +321,17 @@
ordering: .acquiringAndReleasing)
}

/// Update the target depth of this handler's jitter buffer, if any.
/// - Parameter depth: Target depth in seconds.
func setTargetDepth(_ depth: TimeInterval, from: Date) {
self.currentTargetDepth = depth
guard let buffer = self.jitterBuffer else {
Self.logger.warning("Set target depth on nil buffer!?")
return
}
buffer.setTargetDepth(depth, from: from)
}

private func decode(sample: DecimusVideoFrame, from: Date) throws {
// Should we feed this frame to the decoder?
// get groupId and objectId from the frame (1st frame)
Expand Down Expand Up @@ -442,7 +456,7 @@
throw "Missing sample format"
}
let size = format.dimensions
return "\(self.namespace): \(String(describing: config.codec)) \(size.width)x\(size.height) \(fps)fps \(Float(config.bitrate) / pow(10, 6))Mbps"

Check notice on line 459 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoHandler.swift#L459

Line Length Violation: Line should be 120 characters or less; currently it has 152 characters (line_length)

Check notice on line 459 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoHandler.swift#L459

Line Length Violation: Line should be 120 characters or less; currently it has 152 characters (line_length)

Check notice on line 459 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoHandler.swift#L459

Line Length Violation: Line should be 120 characters or less; currently it has 152 characters (line_length)
}
}

Expand Down Expand Up @@ -489,4 +503,4 @@
public static func == (lhs: CMVideoDimensions, rhs: CMVideoDimensions) -> Bool {
lhs.width == rhs.width && lhs.height == rhs.height
}
}

Check notice on line 506 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoHandler.swift#L506

File Length Violation: File should contain 400 lines or less: currently contains 506 (file_length)

Check notice on line 506 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoHandler.swift#L506

File Length Violation: File should contain 400 lines or less: currently contains 506 (file_length)

Check notice on line 506 in Decimus/Subscriptions/VideoHandler.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoHandler.swift#L506

File Length Violation: File should contain 400 lines or less: currently contains 506 (file_length)
27 changes: 27 additions & 0 deletions Decimus/Subscriptions/VideoSubscription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@
private let decodedVariances: VarianceCalculator
private var formats: [QuicrNamespace: CMFormatDescription?] = [:]
private var timestampTimeDiff: TimeInterval?
private var suspension = SlidingTimeWindow(length: 60)
private var currentMax: TimeInterval?

init(sourceId: SourceIDType,

Check notice on line 56 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L56

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 68 lines (function_body_length)

Check notice on line 56 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L56

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 68 lines (function_body_length)

Check notice on line 56 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L56

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 68 lines (function_body_length)
profileSet: QClientProfileSet,
participants: VideoParticipants,
metricsSubmitter: MetricsSubmitter?,
Expand Down Expand Up @@ -121,7 +123,7 @@
guard let self = self else { return }
self.handlerLock.withLock {
// Remove any expired handlers.
for handler in self.lastUpdateTimes where Date.now.timeIntervalSince(handler.value) >= self.cleanupTimer {

Check notice on line 126 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L126

Line Length Violation: Line should be 120 characters or less; currently it has 126 characters (line_length)

Check notice on line 126 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L126

Line Length Violation: Line should be 120 characters or less; currently it has 126 characters (line_length)

Check notice on line 126 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L126

Line Length Violation: Line should be 120 characters or less; currently it has 126 characters (line_length)
self.lastUpdateTimes.removeValue(forKey: handler.key)
if let video = self.videoHandlers.removeValue(forKey: handler.key),
let last = self.last,
Expand Down Expand Up @@ -163,7 +165,7 @@
return SubscriptionError.noDecoder.rawValue
}

func subscribedObject(_ name: String!,

Check notice on line 168 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L168

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 75 lines (function_body_length)

Check notice on line 168 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L168

Cyclomatic Complexity Violation: Function should have complexity 10 or less; currently complexity is 15 (cyclomatic_complexity)

Check notice on line 168 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L168

Cyclomatic Complexity Violation: Function should have complexity 10 or less; currently complexity is 15 (cyclomatic_complexity)

Check notice on line 168 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L168

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 75 lines (function_body_length)

Check notice on line 168 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L168

Cyclomatic Complexity Violation: Function should have complexity 10 or less; currently complexity is 15 (cyclomatic_complexity)

Check notice on line 168 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L168

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 75 lines (function_body_length)
data: UnsafeRawPointer!,
length: Int,
groupId: UInt32,
Expand Down Expand Up @@ -211,6 +213,13 @@
startRenderTask()
}

// Suspension tracking.
if self.currentMax == nil {
// Ensure that we take into account our configured value.
self.suspension.add(timestamp: now.addingTimeInterval(-self.jitterBufferConfig.minDepth))
}
self.suspension.add(timestamp: now)

let handler: VideoHandler
do {
handler = try self.handlerLock.withLock {
Expand All @@ -221,15 +230,33 @@
self.videoHandlers[name] = handler
return handler
}

// While we're here, set depth for everyone.
if self.jitterBufferConfig.adaptive {
if let thisMax = self.suspension.max(from: now) {
if let currentMax = self.currentMax,
thisMax != currentMax {
for handler in self.videoHandlers {
handler.value.setTargetDepth(thisMax, from: now)
}
}
self.currentMax = thisMax
}
}

return lookup
}
} catch {
Self.logger.error("Failed to fetch/create handler: \(error.localizedDescription)")
return SubscriptionError.none.rawValue
}

// Set timestamp diff.
if let diff = self.timestampTimeDiff {
handler.setTimeDiff(diff: diff)
}

// Submit the data.
do {
try handler.submitEncodedData(frame, from: now)
} catch {
Expand Down Expand Up @@ -293,7 +320,7 @@
case highestRes(item: SimulreceiveItem, pristine: Bool)
}

internal static func makeSimulreceiveDecision(choices: inout any Collection<SimulreceiveItem>) -> SimulreceiveReason? {

Check notice on line 323 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L323

Line Length Violation: Line should be 120 characters or less; currently it has 123 characters (line_length)

Check notice on line 323 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L323

Line Length Violation: Line should be 120 characters or less; currently it has 123 characters (line_length)

Check notice on line 323 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L323

Line Length Violation: Line should be 120 characters or less; currently it has 123 characters (line_length)
// Early return.
guard choices.count > 1 else {
if let first = choices.first {
Expand All @@ -310,7 +337,7 @@

// We want the highest non-discontinous frame.
// If all are non-discontinous, we'll take the highest quality.
let sorted = choices.sorted { $0.image.image.formatDescription!.dimensions.width > $1.image.image.formatDescription!.dimensions.width }

Check notice on line 340 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L340

Line Length Violation: Line should be 120 characters or less; currently it has 143 characters (line_length)

Check notice on line 340 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L340

Line Length Violation: Line should be 120 characters or less; currently it has 143 characters (line_length)

Check notice on line 340 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L340

Line Length Violation: Line should be 120 characters or less; currently it has 143 characters (line_length)
let pristine = sorted.filter { !$0.image.discontinous }
if let pristine = pristine.first {
return .highestRes(item: pristine, pristine: true)
Expand All @@ -324,7 +351,7 @@
// Caller must lock handlerLock.
// swiftlint:disable cyclomatic_complexity
// swiftlint:disable function_body_length
private func makeSimulreceiveDecision(at: Date) throws -> TimeInterval {

Check notice on line 354 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L354

Identifier Name Violation: Variable name 'at' should be between 3 and 40 characters long (identifier_name)

Check notice on line 354 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L354

Identifier Name Violation: Variable name 'at' should be between 3 and 40 characters long (identifier_name)

Check notice on line 354 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L354

Identifier Name Violation: Variable name 'at' should be between 3 and 40 characters long (identifier_name)
guard !self.videoHandlers.isEmpty else {
throw "No handlers"
}
Expand Down Expand Up @@ -389,7 +416,7 @@
let incomingWidth = selectedSample.formatDescription!.dimensions.width
var wouldStepDown = false
if let last = self.lastImage,
incomingWidth < last.image.formatDescription!.dimensions.width || selected.image.discontinous && !last.discontinous {

Check notice on line 419 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L419

Line Length Violation: Line should be 120 characters or less; currently it has 128 characters (line_length)

Check notice on line 419 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L419

Line Length Violation: Line should be 120 characters or less; currently it has 128 characters (line_length)

Check notice on line 419 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L419

Line Length Violation: Line should be 120 characters or less; currently it has 128 characters (line_length)
wouldStepDown = true
}

Expand All @@ -409,7 +436,7 @@
}

let newValue = pauseCandidateCount.value + 1
Self.logger.warning("Incremented pause count for: \(pauseCandidate.config.width), now: \(newValue)/\(self.pauseMissThreshold)")

Check notice on line 439 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L439

Line Length Violation: Line should be 120 characters or less; currently it has 143 characters (line_length)

Check notice on line 439 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L439

Line Length Violation: Line should be 120 characters or less; currently it has 143 characters (line_length)

Check notice on line 439 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L439

Line Length Violation: Line should be 120 characters or less; currently it has 143 characters (line_length)
if newValue >= self.pauseMissThreshold {
// Pause this subscription.
Self.logger.warning("Pausing subscription: \(pauseCandidate.config.width)")
Expand All @@ -435,13 +462,13 @@
case .highestRes(let item, let pristine):
if choice.namespace == item.namespace {
assert(choice.namespace == selected.namespace)
report.append(.init(item: choice, selected: true, reason: "Highest \(pristine ? "Pristine" : "Discontinous")", displayed: !qualitySkip))

Check notice on line 465 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L465

Line Length Violation: Line should be 120 characters or less; currently it has 160 characters (line_length)

Check notice on line 465 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L465

Line Length Violation: Line should be 120 characters or less; currently it has 160 characters (line_length)

Check notice on line 465 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L465

Line Length Violation: Line should be 120 characters or less; currently it has 160 characters (line_length)
continue
}
case .onlyChoice(let item):
if choice.namespace == item.namespace {
assert(choice.namespace == selected.namespace)
report.append(.init(item: choice, selected: true, reason: "Only choice", displayed: !qualitySkip))

Check notice on line 471 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L471

Line Length Violation: Line should be 120 characters or less; currently it has 122 characters (line_length)

Check notice on line 471 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L471

Line Length Violation: Line should be 120 characters or less; currently it has 122 characters (line_length)

Check notice on line 471 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L471

Line Length Violation: Line should be 120 characters or less; currently it has 122 characters (line_length)
}
continue
}
Expand Down Expand Up @@ -532,7 +559,7 @@
let seiData: ApplicationSeiData
}

private func depacketize(namespace: QuicrNamespace,

Check notice on line 562 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L562

Cyclomatic Complexity Violation: Function should have complexity 10 or less; currently complexity is 12 (cyclomatic_complexity)

Check notice on line 562 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L562

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 74 lines (function_body_length)

Check notice on line 562 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L562

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 74 lines (function_body_length)

Check notice on line 562 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L562

Cyclomatic Complexity Violation: Function should have complexity 10 or less; currently complexity is 12 (cyclomatic_complexity)

Check notice on line 562 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L562

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 74 lines (function_body_length)

Check notice on line 562 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L562

Cyclomatic Complexity Violation: Function should have complexity 10 or less; currently complexity is 12 (cyclomatic_complexity)
data: Data,
groupId: UInt32,
objectId: UInt16) throws -> DecimusVideoFrame? {
Expand Down Expand Up @@ -619,4 +646,4 @@
captureDate: captureDate)
}
}
// swiftlint:enable type_body_length

Check notice on line 649 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Subscriptions/VideoSubscription.swift#L649

File Length Violation: File should contain 400 lines or less: currently contains 649 (file_length)

Check notice on line 649 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Subscriptions/VideoSubscription.swift#L649

File Length Violation: File should contain 400 lines or less: currently contains 649 (file_length)

Check notice on line 649 in Decimus/Subscriptions/VideoSubscription.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Subscriptions/VideoSubscription.swift#L649

File Length Violation: File should contain 400 lines or less: currently contains 649 (file_length)
37 changes: 31 additions & 6 deletions Decimus/VideoJitterBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import AVFoundation
import Atomics

// swiftlint:disable force_cast

Check notice on line 6 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/VideoJitterBuffer.swift#L6

Blanket Disable Command Violation: Use 'next', 'this' or 'previous' instead to disable the 'force_cast' rule once, or re-enable it as soon as possible` (blanket_disable_command)

Check notice on line 6 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/VideoJitterBuffer.swift#L6

Blanket Disable Command Violation: Use 'next', 'this' or 'previous' instead to disable the 'force_cast' rule once, or re-enable it as soon as possible` (blanket_disable_command)

Check notice on line 6 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/VideoJitterBuffer.swift#L6

Blanket Disable Command Violation: Use 'next', 'this' or 'previous' instead to disable the 'force_cast' rule once, or re-enable it as soon as possible` (blanket_disable_command)

/// A very simplified jitter buffer designed to contain compressed video frames in order.
class VideoJitterBuffer {
Expand All @@ -12,6 +12,7 @@
var mode: Mode = .none
var minDepth: TimeInterval = 0.2
var capacity: TimeInterval = 2
var adaptive: Bool = false
}

enum Mode: CaseIterable, Identifiable, Codable {
Expand All @@ -23,24 +24,27 @@
}

private static let logger = DecimusLogger(VideoJitterBuffer.self)
private let minDepth: TimeInterval
private var minDepth: TimeInterval
private var buffer: CMBufferQueue
private let measurement: MeasurementRegistration<VideoJitterBufferMeasurement>?
private var play: Bool = false
private var lastSequenceRead = ManagedAtomic<UInt64>(0)
private var lastSequenceSet = ManagedAtomic<Bool>(false)
private let capacity: TimeInterval
private let originalDepth: TimeInterval

/// Create a new video jitter buffer.
/// - Parameter namespace The namespace of the video this buffer is used for, for identification purposes.
/// - Parameter metricsSubmitter Optionally, an object to submit metrics through.
/// - Parameter sort True to actually sort on sequence number, false if they're already in order.
/// - Parameter minDepth Fixed initial delay in seconds.
/// - Parameter capacity Capacity in buffers / elements.
/// - Parameter capacity Capacity in time.
init(namespace: QuicrNamespace,

Check notice on line 42 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/VideoJitterBuffer.swift#L42

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 56 lines (function_body_length)

Check notice on line 42 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/VideoJitterBuffer.swift#L42

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 56 lines (function_body_length)

Check notice on line 42 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/VideoJitterBuffer.swift#L42

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 56 lines (function_body_length)
metricsSubmitter: MetricsSubmitter?,
sort: Bool,
minDepth: TimeInterval,
capacity: Int) throws {
capacity: TimeInterval,
duration: TimeInterval) throws {
let handlers = CMBufferQueue.Handlers { builder in
builder.compare {
if !sort {
Expand Down Expand Up @@ -76,18 +80,27 @@
($0 as! DecimusVideoFrame).samples.reduce(0) { $0 + $1.totalSampleSize }
}
builder.isDataReady {
($0 as! DecimusVideoFrame).samples.reduce(true) { $0 && $1.dataReadiness == .ready }

Check notice on line 83 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/VideoJitterBuffer.swift#L83

Reduce Boolean Violation: Use `allSatisfy` instead (reduce_boolean)

Check notice on line 83 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/VideoJitterBuffer.swift#L83

Reduce Boolean Violation: Use `allSatisfy` instead (reduce_boolean)

Check notice on line 83 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/VideoJitterBuffer.swift#L83

Reduce Boolean Violation: Use `allSatisfy` instead (reduce_boolean)
}
}
self.buffer = try .init(capacity: capacity, handlers: handlers)
let elementCapacity = CMItemCount(round(capacity / duration))
self.buffer = try .init(capacity: elementCapacity, handlers: handlers)
guard minDepth <= capacity else {
throw "Target depth cannot be > capacity"
}
self.minDepth = minDepth
self.originalDepth = minDepth
self.capacity = capacity
if let metricsSubmitter = metricsSubmitter {
let measurement = VideoJitterBufferMeasurement(namespace: namespace)
self.measurement = .init(measurement: measurement, submitter: metricsSubmitter)
let now = Date.now
Task(priority: .utility) {
await measurement.targetDepth(depth: self.minDepth, timestamp: now)
}
} else {
self.measurement = nil
}

self.minDepth = minDepth
}

/// Write a video frame into the jitter buffer.
Expand All @@ -112,6 +125,18 @@
}
}

func setTargetDepth(_ depth: TimeInterval, from: Date) {
// TODO(RichLogan): For now, don't exceed original declared depth.

Check notice on line 129 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/VideoJitterBuffer.swift#L129

Todo Violation: TODOs should be resolved ((RichLogan): For now, don't ex...) (todo)

Check notice on line 129 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/VideoJitterBuffer.swift#L129

Todo Violation: TODOs should be resolved ((RichLogan): For now, don't ex...) (todo)

Check notice on line 129 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/VideoJitterBuffer.swift#L129

Todo Violation: TODOs should be resolved ((RichLogan): For now, don't ex...) (todo)
let clampedDepth = min(depth, self.originalDepth)
self.minDepth = clampedDepth
if let measurement = self.measurement {
Task(priority: .utility) {
await measurement.measurement.targetDepth(depth: clampedDepth, timestamp: from)
await measurement.measurement.idealTargetDepth(depth: depth, timestamp: from)
}
}
}

/// Attempt to read a frame from the front of the buffer.
/// - Returns Either the oldest available frame, or nil.
func read(from: Date) -> DecimusVideoFrame? {
Expand Down Expand Up @@ -164,7 +189,7 @@
offset: TimeInterval,
since: Date = .init(timeIntervalSinceReferenceDate: 0)) -> TimeInterval {
guard let sample = frame.samples.first else {
// TODO: Ensure we cannot enqueue a frame with no samples to make this a valid error.

Check notice on line 192 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/VideoJitterBuffer.swift#L192

Todo Violation: TODOs should be resolved (Ensure we cannot enqueue a fra...) (todo)

Check notice on line 192 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/VideoJitterBuffer.swift#L192

Todo Violation: TODOs should be resolved (Ensure we cannot enqueue a fra...) (todo)

Check notice on line 192 in Decimus/VideoJitterBuffer.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/VideoJitterBuffer.swift#L192

Todo Violation: TODOs should be resolved (Ensure we cannot enqueue a fra...) (todo)
fatalError()
}
let timestamp = sample.presentationTimeStamp
Expand Down
4 changes: 4 additions & 0 deletions Decimus/Views/Settings/SubscriptionSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"Depth (s)",
value: $subscriptionConfig.value.jitterDepthTime,
format: .number)
.onChange(of: subscriptionConfig.value.jitterDepthTime) {

Check notice on line 33 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L33

'onChange(of:perform:)' was deprecated in tvOS 17.0: Use `onChange` with a two or zero parameter action closure instead.

Check notice on line 33 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L33

'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead.

Check notice on line 33 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L33

'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead.
subscriptionConfig.value.videoJitterBuffer.minDepth = $0
subscriptionConfig.value.jitterMaxTime = $0
}
Expand All @@ -41,6 +41,10 @@
value: $subscriptionConfig.value.videoJitterBuffer.capacity,
format: .number)
}
HStack {
Text("Video Jitter - Adaptive")
Toggle(isOn: $subscriptionConfig.value.videoJitterBuffer.adaptive) {}
}
Picker("Opus Window Size (s)", selection: $subscriptionConfig.value.opusWindowSize) {
ForEach(OpusWindowSize.allCases) {
Text(String(describing: $0))
Expand Down Expand Up @@ -68,7 +72,7 @@
ForEach(devices.cameras, id: \.uniqueID) {
Text($0.localizedName)
.tag($0.uniqueID)
}.onChange(of: preferredCamera) { _ in

Check notice on line 75 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L75

'onChange(of:perform:)' was deprecated in tvOS 17.0: Use `onChange` with a two or zero parameter action closure instead.

Check notice on line 75 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L75

'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead.

Check notice on line 75 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L75

'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead.
guard self.preferredCamera != self.noPreference else {
AVCaptureDevice.userPreferredCamera = nil
return
Expand Down Expand Up @@ -103,13 +107,13 @@
}
}
.pickerStyle(.segmented)
.onChange(of: subscriptionConfig.value.videoJitterBuffer.mode) {

Check notice on line 110 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L110

'onChange(of:perform:)' was deprecated in tvOS 17.0: Use `onChange` with a two or zero parameter action closure instead.

Check notice on line 110 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L110

'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead.

Check notice on line 110 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L110

'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead.
if $0 == .layer && subscriptionConfig.value.simulreceive != .none {
subscriptionConfig.value.simulreceive = .none
}
}
.onAppear {
if subscriptionConfig.value.videoJitterBuffer.mode == .layer && subscriptionConfig.value.simulreceive != .none {

Check notice on line 116 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - tvOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L116

Line Length Violation: Line should be 120 characters or less; currently it has 136 characters (line_length)

Check notice on line 116 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | Build - iOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L116

Line Length Violation: Line should be 120 characters or less; currently it has 136 characters (line_length)

Check notice on line 116 in Decimus/Views/Settings/SubscriptionSettingsView.swift

View check run for this annotation

Xcode Cloud / Decimus | PR | TestPlan - macOS

Decimus/Views/Settings/SubscriptionSettingsView.swift#L116

Line Length Violation: Line should be 120 characters or less; currently it has 136 characters (line_length)
subscriptionConfig.value.simulreceive = .none
}
}
Expand Down
Loading