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

Support for video described by the AV1 Dependency Descriptor #1998

Merged
merged 151 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
151 commits
Select commit Hold shift + click to select a range
870fcea
Initial implementation of AV1 dependency descriptor.
JonathanLennox Feb 9, 2023
133925b
Fix values in exception text.
JonathanLennox Feb 16, 2023
4770584
Add some more DDs to the unit test.
JonathanLennox Feb 16, 2023
d6acba3
Merge branch 'master' into av1-dd
JonathanLennox Feb 17, 2023
9ee90ae
Restructure to make code cleaner.
JonathanLennox Feb 21, 2023
cc8d611
Add AV1 Dependency Descriptor extension to RtpExensions enum.
JonathanLennox Feb 21, 2023
c224c64
Add parseStateless to Av1DependencyDescriptorReader.
JonathanLennox Feb 22, 2023
3812272
Fix missing initialization.
JonathanLennox Feb 22, 2023
241bcf6
Test parseStateless, and adjust tests for API changes; also fixes fou…
JonathanLennox Feb 22, 2023
cd81963
Suppress Spotbugs warnings.
JonathanLennox Feb 23, 2023
13496f6
Add TreeCache object.
JonathanLennox Feb 23, 2023
b246d71
Add Av1DDPacket and Av1DDParser.
JonathanLennox Feb 27, 2023
3744f69
Remove unused field.
JonathanLennox Feb 28, 2023
623add8
Separate abstract RtpLayerDesc and concrete VpxRtpLayerDesc.
JonathanLennox Mar 1, 2023
9644185
Add indexString method to RtpLayerDesc.
JonathanLennox Mar 2, 2023
831e1c2
Change package of VpxRtpLayerDesc.
JonathanLennox Mar 2, 2023
205cf89
Add Av1DDRtpLayerDesc.
JonathanLennox Mar 2, 2023
3376f61
Convert rtp packet layer IDs and encoding IDs into sets.
JonathanLennox Mar 7, 2023
9afcb50
Remove some unnecessary nullability checks.
JonathanLennox Mar 7, 2023
a977dc2
Remove unused import.
JonathanLennox Mar 8, 2023
f007977
Use emptyList() rather than listOf().
JonathanLennox Mar 8, 2023
2b0f2c0
Use named arguments in VpxRtpLayerDesc.copy().
JonathanLennox Mar 8, 2023
f383535
Use a lazy delegate for Av1DependencyDescriptorHeaderExtension.frameInfo
JonathanLennox Mar 8, 2023
63092b9
Merge branch 'master' into av1-dd
JonathanLennox Mar 8, 2023
6e80e27
Put back the default layerId in VideoRtpPacket, it's important.
JonathanLennox Mar 8, 2023
31f7dbb
Add unit test for TreeCache.
JonathanLennox Mar 9, 2023
94a2921
One more test for TreeCacheTest.
JonathanLennox Mar 10, 2023
3383b57
Merge branch 'master' into av1-dd
JonathanLennox Mar 17, 2023
a4b666f
Merge branch 'master' into av1-dd
JonathanLennox Mar 20, 2023
0491c3f
Initial sketch of Av1DDAdaptiveSourceProjectionContext.
JonathanLennox Mar 22, 2023
900a568
Av1DDFrameMap.
JonathanLennox Mar 23, 2023
952b0d2
Add Av1DDFrameProjection.
JonathanLennox Mar 23, 2023
f1d72ae
Add Av1DependencyDescriptorHeaderExtension.encodedLength.
JonathanLennox Mar 24, 2023
c154ffd
Merge branch 'master' into av1-dd
JonathanLennox Apr 10, 2023
1851ee5
Fix typo in test name.
JonathanLennox Apr 10, 2023
7e298e7
Fixes to BitReader
JonathanLennox Apr 10, 2023
43e17a9
Make some AV1 DD fields mutable.
JonathanLennox Apr 10, 2023
a1195bd
Add BitWriter class.
JonathanLennox Apr 10, 2023
df0f003
Outline of Av1DependencyDescriptorHeaderExtension.write().
JonathanLennox Apr 11, 2023
fbd1fe3
Fix reading of activeDecodeTargetsBitmask.
JonathanLennox Apr 12, 2023
04d8e07
Finish activeDecodeTargetsBitmaskAv1DependencyDescriptorHeaderExtensi…
JonathanLennox Apr 12, 2023
5e5bb17
Suppress some Spotbugs complaints.
JonathanLennox Apr 12, 2023
6c20723
Add short desc to unit tests.
JonathanLennox Apr 13, 2023
1b1a59a
Fix framerate calculation for AV1 DD scalability structure.
JonathanLennox Apr 13, 2023
129f0dd
Rewrite DDs in Av1DDFrameProjection.
JonathanLennox Apr 13, 2023
1ef87e4
Fix maxTemporalId calculation, check it in tests.
JonathanLennox Apr 13, 2023
9b73fbb
Add Av1DDPacketTest.
JonathanLennox Apr 14, 2023
f9724c3
Add a test packet with activeDecodeTargets.
JonathanLennox Apr 14, 2023
4ca88ec
Add unit test for DD with custom fdiffs and chains; fix writeFrameFdi…
JonathanLennox Apr 18, 2023
a57aceb
Add some more fields of Av1DDAdaptiveSourceProjectionContext, sketch …
JonathanLennox Apr 18, 2023
2bab125
Merge branch 'master' into av1-dd
JonathanLennox Apr 20, 2023
6e790ed
Clean up rtp/spotbugs-exclude.
JonathanLennox Apr 21, 2023
471ea12
Merge branch 'master' into av1-dd
JonathanLennox Apr 21, 2023
89b240b
Encoding switching on keyframes for AV1.
JonathanLennox Apr 24, 2023
2ccdb9a
Add helper functions, and tests, to AV1 DD structures.
JonathanLennox Apr 25, 2023
f7d98a7
Core Av1DDQualityFilter logic.
JonathanLennox May 1, 2023
17a0729
Calculate marker bit properly in QualityFilter; include DT changes in…
JonathanLennox May 2, 2023
004bdae
Remove a TODO, not needed.
JonathanLennox May 2, 2023
f06b918
Add getDtBitmaskForDt, and tests.
JonathanLennox May 2, 2023
32a6078
Create frame projections in the unusual cases.
JonathanLennox May 2, 2023
8175a36
Add createInEncodingProjection.
JonathanLennox May 3, 2023
9bbb634
Minor cleanup.
JonathanLennox May 3, 2023
f735898
Adjust targetIndex format in Av1 trace output.
JonathanLennox May 3, 2023
d86b506
Base AdaptiveSourceProjection.getContext() on the parsed type of the …
JonathanLennox May 3, 2023
356655c
Create AV1 DD source projection contexts as appropriate.
JonathanLennox May 4, 2023
03b57a6
Add Av1DDQualityFilterTest, with initial test.
JonathanLennox May 4, 2023
726d4d3
Add unit tests for a temporally-scalable stream. Fix some bugs.
JonathanLennox May 5, 2023
cd13c56
Add full SVC test case to Av1DDQualityFilterTest. Fix bugs found by …
JonathanLennox May 8, 2023
e1f8e86
Add S3T3 (single-stream simulcast) to quality filter tests; fix bugs.
JonathanLennox May 9, 2023
c08593c
Add K-SVC unit tests.
JonathanLennox May 10, 2023
b6d291c
Add tests for L2T2_KEY_SHIFT mode.
JonathanLennox May 10, 2023
104d08e
Slight unit test tweak.
JonathanLennox May 10, 2023
6e03036
Add multi-encoding simlcast tests. Fix test scoping.
JonathanLennox May 10, 2023
1f83914
Change assert() to check() with a message.
JonathanLennox May 12, 2023
a8a02d6
Put labels on otherwise identically-named tests.
JonathanLennox May 12, 2023
e2ac37f
Make getDtFromIndex return SUSPENDED_DT for SUSPENDED_INDEX.
JonathanLennox May 12, 2023
9450662
Don't change index when a keyframe isn't accepted.
JonathanLennox May 12, 2023
fd6bb39
Correctly set isKeyframe for the SingleEncodingSimulcastGenerator.
JonathanLennox May 15, 2023
3d7a614
Fix BitWriter initial Arrays.fill.
JonathanLennox May 15, 2023
7d13717
Initial Av1DDAdaptiveSourceProjectionTest.
JonathanLennox May 15, 2023
23856d5
A number of additional Av1 source projection tests.
JonathanLennox May 15, 2023
8aef94b
Add K-SVC and SingleEncodingSimulcast tests.
JonathanLennox May 16, 2023
62b58a0
Framework for out-of-order tests, and first few tests.
JonathanLennox May 16, 2023
d59cd16
Add more outOfOrderTests, and add some conditions to that tester.
JonathanLennox May 17, 2023
9da4607
Simplify calculation of AV1 packet indices.
JonathanLennox May 18, 2023
0a32201
Make it possible to clone an RTP HeaderExtension.
JonathanLennox May 18, 2023
4ed7b9f
Pass a logger to Av1DDPacket constructor, to log problems parsing the…
JonathanLennox May 18, 2023
2e60627
Don't accept keyframes if subsequent required frames have not been ac…
JonathanLennox May 18, 2023
b15c1b6
Kotlin warning fix.
JonathanLennox May 18, 2023
3503a87
Spotbugs fix.
JonathanLennox May 18, 2023
48af2f5
Fix slightlyDelayedKeyframeTest.
JonathanLennox May 18, 2023
eca6d87
Stream switching and frame rewriting tests for AV1.
JonathanLennox May 22, 2023
315686f
Add Av1 TemporalLayerSwitchingTest.
JonathanLennox May 23, 2023
d969d2d
Port the rest of the VP9 source projection tests to AV1.
JonathanLennox May 23, 2023
a2aedce
Add method to set RTCP SR SenderInfo timestamp from Java time.
JonathanLennox May 23, 2023
d9493b6
Add (uncomment) RTCP SR rewriting tests for AV1.
JonathanLennox May 23, 2023
f1b27d3
Merge branch 'master' into av1-dd
JonathanLennox May 24, 2023
5f96bc3
Doc cleanup for BitReader, and remove an incorrect require
JonathanLennox May 25, 2023
f565f29
Cleanups for Av1DependencyDescriptorHeaderExtensionTest.
JonathanLennox May 25, 2023
555755d
Remove now-redundant @JvmOverloads.
JonathanLennox May 25, 2023
516c4d8
Limit the size of the DD State History cache; fix a comment typo.
JonathanLennox May 25, 2023
91abea3
Add a toString for Av1DDRtpLayerDesc; remove an incorrect XXX.
JonathanLennox May 25, 2023
7c6e747
Remove now-unused field from AdaptiveSourceProjection, and propagate …
JonathanLennox May 25, 2023
4fbcba1
Remove unused imports.
JonathanLennox May 25, 2023
d3c722c
Correct VP9->AV1 copy&paste errors.
JonathanLennox May 25, 2023
bbf685c
Use isNewerThan convenience function.
JonathanLennox May 25, 2023
fc9b04e
Fix method override.
JonathanLennox May 25, 2023
6045bc0
Avoid re-analyzing frame numbers in the history tracker.
JonathanLennox May 25, 2023
4dbb61e
Comment fixes.
JonathanLennox May 25, 2023
c8d3317
Distinguish log messages.
JonathanLennox May 25, 2023
241134a
Kotlin syntax cleanup.
JonathanLennox May 25, 2023
3fd283b
Make sure templateIdDelta is positive.
JonathanLennox May 25, 2023
b9a27cd
Retain Av1 DD Header Extension of Av1DDPackets.
JonathanLennox May 25, 2023
c68f04e
Set newDt if a frame's original descriptor specified decode targets.
JonathanLennox May 30, 2023
073a3ab
Improve tolerance of post-keyframe frame reordering.
JonathanLennox May 30, 2023
d85ebbe
Save templateId of frames, to report in validateConsistency.
JonathanLennox May 30, 2023
fdd8853
Improve frame frameinfo handling.
JonathanLennox May 31, 2023
bd13547
Improve TreeCache purging logic, to make sure we have a valid entry f…
JonathanLennox May 31, 2023
37a7954
Fixes to Av1DDTemplateHistory.
JonathanLennox Jun 1, 2023
3874464
Merge branch 'master' into av1-dd
JonathanLennox Jun 12, 2023
a8345a5
Add ssrc rewriting code for AV1.
JonathanLennox Jun 15, 2023
8c21966
Merge branch 'master' into av1-dd
JonathanLennox Jun 20, 2023
84ba47f
Adjust for ktlint update.
JonathanLennox Jun 20, 2023
21c28cc
Fix some tests.
JonathanLennox Jun 20, 2023
fc0b164
Add tracing to Av1DDParser.
JonathanLennox Jun 23, 2023
833eaa2
Force trace field to be a string.
JonathanLennox Jun 26, 2023
bc4a37e
Log warning if externalTargetDt is not included in a frame's DTI.
JonathanLennox Jun 26, 2023
1d52b79
Add toString() for Av1DDPacket.
JonathanLennox Jun 26, 2023
a3dcf8c
More debug logging.
JonathanLennox Jun 27, 2023
62a8a18
Clone Av1 template structure before handing it out from the parser.
JonathanLennox Jun 27, 2023
094b97b
Pass only encodingId to AdaptiveSourceProjectionContext.accept() rath…
JonathanLennox Jun 28, 2023
2d02a32
Log improvements.
JonathanLennox Jun 29, 2023
c182e17
Add DumpAv1DependencyDescriptor tool to print AV1 DDs as JSON.
JonathanLennox Jun 30, 2023
a87aa3d
Merge branch 'master' into av1-dd
JonathanLennox Jul 3, 2023
a596571
Keep track of the "nominal height" of an encoding.
JonathanLennox Jul 13, 2023
78f47eb
Handle all spatial layers being unknown in getNominalHeight.
JonathanLennox Jul 14, 2023
6ce057a
Move layer height assignment to the right place.
JonathanLennox Jul 18, 2023
92e3a0a
Merge branch 'master' into av1-dd
JonathanLennox Sep 12, 2023
1a6b236
Merge branch 'master' into av1-dd
JonathanLennox Sep 19, 2023
3951638
Fix some fields in the Av1DDQualityFilter.
JonathanLennox Sep 19, 2023
e2685f3
List the actual allocations in the BandwidthAllocation debug state.
JonathanLennox Sep 19, 2023
c186292
Improve AV1 timeseries tracing.
JonathanLennox Sep 22, 2023
25651c2
Merge branch 'master' into av1-dd
JonathanLennox Oct 3, 2023
3a145e8
Update branch for ktlint 1.0.0.
JonathanLennox Oct 3, 2023
7dc3234
Fix mistake in merge.
JonathanLennox Oct 3, 2023
ae57c39
Clone AV1 stateless descriptor when cloning AV1 packet, and/or keep i…
JonathanLennox Nov 2, 2023
b097ffe
Include height in VpxRtpLayerDesc.toString()
JonathanLennox Nov 2, 2023
5defcd3
Move package declaration after license header.
JonathanLennox Nov 2, 2023
a76cbb5
Comment fixes.
JonathanLennox Nov 2, 2023
c8364ce
Factor out getTemplateIdDelta and applyTemplateIdDelta.
JonathanLennox Nov 2, 2023
453dcc4
Fix inconsistent extFrameNum calculations in out-of-order projection …
JonathanLennox Nov 2, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,11 @@ class MediaSourceDesc
fun getRtpLayerByQualityIdx(idx: Int): RtpLayerDesc? = layersByIndex[idx]

@Synchronized
fun findRtpLayerDesc(videoRtpPacket: VideoRtpPacket): RtpLayerDesc? {
fun findRtpLayerDescs(videoRtpPacket: VideoRtpPacket): Collection<RtpLayerDesc> {
if (ArrayUtils.isNullOrEmpty(rtpEncodings)) {
return null
return emptyList()
}
val encodingId = videoRtpPacket.getEncodingId()
val desc = layersById[encodingId]
return desc
return videoRtpPacket.getEncodingIds().mapNotNull { layersById[it] }
}

@Synchronized
Expand Down Expand Up @@ -188,10 +186,14 @@ class MediaSourceDesc
*/
fun Array<MediaSourceDesc>.copy() = Array(this.size) { i -> this[i].copy() }

fun Array<MediaSourceDesc>.findRtpLayerDesc(packet: VideoRtpPacket): RtpLayerDesc? {
fun Array<MediaSourceDesc>.findRtpLayerDescs(packet: VideoRtpPacket): Collection<RtpLayerDesc> {
return this.flatMap { it.findRtpLayerDescs(packet) }
bgrozev marked this conversation as resolved.
Show resolved Hide resolved
}

fun Array<MediaSourceDesc>.findRtpEncodingId(packet: VideoRtpPacket): Int? {
for (source in this) {
source.findRtpLayerDesc(packet)?.let {
return it
source.findRtpEncodingDesc(packet.ssrc)?.let {
return it.eid
}
}
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,17 @@ constructor(
validateLayerEids(initialLayers)
}

private var nominalHeight = initialLayers.getNominalHeight()

internal var layers = initialLayers
set(newLayers) {
validateLayerEids(newLayers)
/* Check if the new layer set is a single spatial layer that doesn't specify a height - if so, we
* want to apply the nominal height to them.
*/
val useNominalHeight = nominalHeight != RtpLayerDesc.NO_HEIGHT &&
newLayers.all { it.sid == 0 } &&
bgrozev marked this conversation as resolved.
Show resolved Hide resolved
newLayers.all { it.height == RtpLayerDesc.NO_HEIGHT }
/* Copy the rate statistics objects from the old layers to the new layers
* with matching layer IDs.
*/
Expand All @@ -89,6 +97,15 @@ constructor(
oldLayerMap[newLayer.layerId]?.let {
newLayer.inheritFrom(it)
}
if (useNominalHeight) {
newLayer.height = nominalHeight
}
}
if (!useNominalHeight) {
val newNominalHeight = newLayers.getNominalHeight()
if (newNominalHeight != RtpLayerDesc.NO_HEIGHT) {
nominalHeight = newNominalHeight
}
}
field = newLayers
}
Expand Down Expand Up @@ -157,6 +174,7 @@ constructor(
addNumber("rtx_ssrc", getSecondarySsrc(SsrcAssociationType.RTX))
addNumber("fec_ssrc", getSecondarySsrc(SsrcAssociationType.FEC))
addNumber("eid", eid)
addNumber("nominal_height", nominalHeight)
for (layer in layers) {
addBlock(layer.getNodeStats())
}
Expand All @@ -167,6 +185,23 @@ constructor(
}
}

fun VideoRtpPacket.getEncodingId(): Long {
return RtpEncodingDesc.calcEncodingId(ssrc, this.layerId)
fun VideoRtpPacket.getEncodingIds(): Collection<Long> {
return this.layerIds.map { RtpEncodingDesc.calcEncodingId(ssrc, it) }
}

/**
* Get the "nominal" height of a set of layers - if they all indicate the same spatial layer and same height.
*/
private fun Array<RtpLayerDesc>.getNominalHeight(): Int {
if (isEmpty()) {
return RtpLayerDesc.NO_HEIGHT
}
val firstHeight = first().height
if (!(all { it.sid == 0 } || all { it.sid == -1 })) {
bgrozev marked this conversation as resolved.
Show resolved Hide resolved
return RtpLayerDesc.NO_HEIGHT
}
if (any { it.height != firstHeight }) {
return RtpLayerDesc.NO_HEIGHT
}
return firstHeight
}
131 changes: 21 additions & 110 deletions jitsi-media-transform/src/main/kotlin/org/jitsi/nlj/RtpLayerDesc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,106 +20,60 @@ import org.jitsi.nlj.transform.node.incoming.BitrateCalculator
import org.jitsi.nlj.util.Bandwidth
import org.jitsi.nlj.util.BitrateTracker
import org.jitsi.nlj.util.DataSize
import org.jitsi.nlj.util.sum
import org.jitsi.utils.OrderedJsonObject

/**
* Keeps track of its subjective quality index,
* its last stable bitrate and other useful things for adaptivity/routing.
*
* Note: this class and [getBitrate] are only open to allow to be overridden for testing. We found that mocking has
* severe overhead and is not suitable for performance tests.
*
* @author George Politis
*/
open class RtpLayerDesc
@JvmOverloads
abstract class RtpLayerDesc
constructor(
/**
* The index of this instance's encoding in the source encoding array.
*/
val eid: Int,
/**
* The temporal layer ID of this instance, or negative for unknown.
* The temporal layer ID of this instance.
*/
val tid: Int,
/**
* The spatial layer ID of this instance, or negative for unknown.
* The spatial layer ID of this instance.
*/
val sid: Int,
/**
* The max height of the bitstream that this instance represents. The actual
* height may be less due to bad network or system load.
* height may be less due to bad network or system load. [NO_HEIGHT] for unknown.
*
* XXX we should be able to sniff the actual height from the RTP packets.
bgrozev marked this conversation as resolved.
Show resolved Hide resolved
*/
val height: Int,
var height: Int,
/**
* The max frame rate (in fps) of the bitstream that this instance
* represents. The actual frame rate may be less due to bad network or
* system load.
* system load. [NO_FRAME_RATE] for unknown.
*/
val frameRate: Double,
/**
* The [RtpLayerDesc]s on which this layer definitely depends.
*/
private val dependencyLayers: Array<RtpLayerDesc> = emptyArray(),
/**
* The [RtpLayerDesc]s on which this layer possibly depends.
* (The intended use case is K-SVC mode.)
*/
private val softDependencyLayers: Array<RtpLayerDesc> = emptyArray()
) {
init {
require(tid < 8) { "Invalid temporal ID $tid" }
require(sid < 8) { "Invalid spatial ID $sid" }
}

/**
* Clone an existing layer desc, inheriting its statistics,
* modifying only specific values.
*/
fun copy(
eid: Int = this.eid,
tid: Int = this.tid,
sid: Int = this.sid,
height: Int = this.height,
frameRate: Double = this.frameRate,
dependencyLayers: Array<RtpLayerDesc> = this.dependencyLayers,
softDependencyLayers: Array<RtpLayerDesc> = this.softDependencyLayers
) = RtpLayerDesc(eid, tid, sid, height, frameRate, dependencyLayers, softDependencyLayers).also {
it.inheritFrom(this)
}

/**
* Whether softDependencyLayers are to be used.
*/
var useSoftDependencies = true
abstract fun copy(height: Int = this.height): RtpLayerDesc

/**
* The [BitrateTracker] instance used to calculate the receiving bitrate of this RTP layer.
*/
private var bitrateTracker = BitrateCalculator.createBitrateTracker()
protected var bitrateTracker = BitrateCalculator.createBitrateTracker()

/**
* @return the "id" of this layer within this encoding. This is a server-side id and should
* not be confused with any encoding id defined in the client (such as the
* rid).
*/
val layerId = getIndex(0, sid, tid)
abstract val layerId: Int

/**
* A local index of this track.
*/
val index = getIndex(eid, sid, tid)

/**
* {@inheritDoc}
*/
override fun toString(): String {
return "subjective_quality=" + index +
",temporal_id=" + tid +
",spatial_id=" + sid
}
abstract val index: Int

/**
* Inherit a [BitrateTracker] object
Expand All @@ -131,9 +85,8 @@ constructor(
/**
* Inherit another layer description's [BitrateTracker] object.
*/
internal fun inheritFrom(other: RtpLayerDesc) {
internal open fun inheritFrom(other: RtpLayerDesc) {
inheritStatistics(other.bitrateTracker)
useSoftDependencies = other.useSoftDependencies
}

/**
Expand All @@ -152,80 +105,38 @@ constructor(
/**
* Gets the cumulative bitrate (in bps) of this [RtpLayerDesc] and its dependencies.
*
* This is left open for use in testing.
*
* @param nowMs
* @return the cumulative bitrate (in bps) of this [RtpLayerDesc] and its dependencies.
*/
open fun getBitrate(nowMs: Long): Bandwidth = calcBitrate(nowMs).values.sum()
abstract fun getBitrate(nowMs: Long): Bandwidth

/**
* Expose [getBitrate] as a [Double] in order to make it accessible from java (since [Bandwidth] is an inline
* class).
*/
fun getBitrateBps(nowMs: Long): Double = getBitrate(nowMs).bps

/**
* Recursively adds the bitrate (in bps) of this [RTPLayerDesc] and
* its dependencies in the map passed in as an argument.
*
* This is necessary to ensure we don't double-count layers in cases
* of multiple dependencies.
*
* @param nowMs
*/
private fun calcBitrate(nowMs: Long, rates: MutableMap<Int, Bandwidth> = HashMap()): MutableMap<Int, Bandwidth> {
if (rates.containsKey(index)) {
return rates
}
rates[index] = bitrateTracker.getRate(nowMs)

dependencyLayers.forEach { it.calcBitrate(nowMs, rates) }

if (useSoftDependencies) {
softDependencyLayers.forEach { it.calcBitrate(nowMs, rates) }
}

return rates
}

/**
* Returns true if this layer, alone, has a zero bitrate.
*/
private fun layerHasZeroBitrate(nowMs: Long) = bitrateTracker.getAccumulatedSize(nowMs).bits == 0L

/**
* Recursively checks this layer and its dependencies to see if the bitrate is zero.
* Note that unlike [calcBitrate] this does not avoid double-visiting layers; the overhead
* of the hash table is usually more than the cost of any double-visits.
*
* This is left open for use in testing.
*/
open fun hasZeroBitrate(nowMs: Long): Boolean {
if (!layerHasZeroBitrate(nowMs)) {
return false
}
if (dependencyLayers.any { !it.layerHasZeroBitrate(nowMs) }) {
return false
}
if (useSoftDependencies && softDependencyLayers.any { !it.layerHasZeroBitrate(nowMs) }) {
return false
}
return true
}
abstract fun hasZeroBitrate(nowMs: Long): Boolean

/**
* Extracts a [NodeStatsBlock] from an [RtpLayerDesc].
*/
fun getNodeStats() = NodeStatsBlock(indexString(index)).apply {
open fun getNodeStats() = NodeStatsBlock(indexString()).apply {
addNumber("frameRate", frameRate)
addNumber("height", height)
addNumber("index", index)
addNumber("bitrate_bps", getBitrate(System.currentTimeMillis()).bps)
addNumber("tid", tid)
addNumber("sid", sid)
}

fun debugState(): OrderedJsonObject = getNodeStats().toJson().apply { put("indexString", indexString()) }

abstract fun indexString(): String
bgrozev marked this conversation as resolved.
Show resolved Hide resolved

companion object {
/**
* The index value that is used to represent that forwarding is suspended.
Expand Down Expand Up @@ -270,14 +181,14 @@ constructor(
fun getEidFromIndex(index: Int) = index shr 6

/**
* Get an spatial ID from a layer index. If the index is [SUSPENDED_INDEX],
* Get a spatial ID from a layer index. If the index is [SUSPENDED_INDEX],
* the value is unspecified.
*/
@JvmStatic
fun getSidFromIndex(index: Int) = (index and 0x38) shr 3

/**
* Get an temporal ID from a layer index. If the index is [SUSPENDED_INDEX],
* Get a temporal ID from a layer index. If the index is [SUSPENDED_INDEX],
* the value is unspecified.
*/
@JvmStatic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class RtpReceiverImpl @JvmOverloads constructor(
private val videoBitrateCalculator = VideoBitrateCalculator(parentLogger)
private val audioBitrateCalculator = BitrateCalculator("Audio bitrate calculator")

private val videoParser = VideoParser(streamInformationStore, logger)
private val videoParser = VideoParser(streamInformationStore, logger, diagnosticContext)

override fun isReceivingAudio() = audioBitrateCalculator.active
override fun isReceivingVideo() = videoBitrateCalculator.active
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ abstract class ParsedVideoPacket(
buffer: ByteArray,
offset: Int,
length: Int,
encodingIndex: Int?
) : VideoRtpPacket(buffer, offset, length, encodingIndex) {
encodingId: Int
) : VideoRtpPacket(buffer, offset, length, encodingId) {

abstract val isKeyframe: Boolean
abstract val isStartOfFrame: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,14 @@ enum class RtpExtensionType(val uri: String) {
/**
* The URN which identifies the RTP Header Extension for Video Orientation.
*/
VIDEO_ORIENTATION("urn:3gpp:video-orientation");
VIDEO_ORIENTATION("urn:3gpp:video-orientation"),

/**
* The URN which identifies the AV1 Dependency Descriptor RTP Header Extension
*/
AV1_DEPENDENCY_DESCRIPTOR(
"https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension"
);

companion object {
private val uriMap = RtpExtensionType.values().associateBy(RtpExtensionType::uri)
Expand Down
Loading
Loading