Skip to content

Commit fba0466

Browse files
committed
fix: prime sabr seek requests
1 parent 7644668 commit fba0466

3 files changed

Lines changed: 57 additions & 29 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package dev.typetype.server.services
2+
3+
import org.schabi.newpipe.extractor.localization.Localization
4+
import org.schabi.newpipe.extractor.services.youtube.sabr.SabrSegmentRequest
5+
import org.schabi.newpipe.extractor.services.youtube.sabr.YoutubeSabrFormat
6+
import org.schabi.newpipe.extractor.services.youtube.sabr.YoutubeSabrSession
7+
8+
internal fun YoutubeSabrSession.prepareForRequestedSegment(
9+
holder: SabrSessionHolder,
10+
request: SabrSegmentRequest,
11+
localization: Localization,
12+
) {
13+
if (request.isInitializationSegment) return
14+
if (request.sequenceNumber > 1) primeInitialMedia(holder, localization)
15+
prepareForRewind(request)
16+
prepareForForwardJump(request)
17+
streamState.setBufferedRangesOverride(emptyList())
18+
val startMs = streamState.getSegmentStartMs(request.format, request.sequenceNumber).coerceAtLeast(0L)
19+
streamState.setPlayerTimeMs(if (startMs == 0L) 0L else startMs + 1L)
20+
if (request.format.isAudio) {
21+
selectTargetFormat(holder.audioFormat, holder.videoFormat)
22+
} else {
23+
selectTargetFormat(holder.videoFormat, holder.audioFormat)
24+
}
25+
}
26+
27+
private fun YoutubeSabrSession.primeInitialMedia(holder: SabrSessionHolder, localization: Localization) {
28+
val requests = listOf(
29+
SabrSegmentRequest.initialization(holder.videoFormat),
30+
SabrSegmentRequest.initialization(holder.audioFormat),
31+
SabrSegmentRequest.media(holder.videoFormat, 1),
32+
SabrSegmentRequest.media(holder.audioFormat, 1),
33+
)
34+
for (request in requests) {
35+
if (getCachedSegment(request) == null && !isBeyondEnd(request)) {
36+
runCatching { fetchSegment(request, localization) }
37+
}
38+
}
39+
}
40+
41+
private fun YoutubeSabrSession.selectTargetFormat(target: YoutubeSabrFormat, companion: YoutubeSabrFormat) {
42+
if (target.isAudio) {
43+
streamState.setRequestTrackMode(AUDIO_ONLY_TRACKS, true, false)
44+
} else {
45+
streamState.setRequestTrackMode(VIDEO_ONLY_TRACKS, false, true)
46+
}
47+
streamState.setFullyBuffered(companion, true)
48+
streamState.setFullyBuffered(target, false)
49+
}
50+
51+
private const val AUDIO_ONLY_TRACKS = 1
52+
private const val VIDEO_ONLY_TRACKS = 2

src/main/kotlin/dev/typetype/server/services/SabrSessionPump.kt

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import kotlinx.coroutines.sync.withLock
55
import org.schabi.newpipe.extractor.localization.Localization
66
import org.schabi.newpipe.extractor.services.youtube.sabr.SabrMediaSegment
77
import org.schabi.newpipe.extractor.services.youtube.sabr.SabrSegmentRequest
8-
import org.schabi.newpipe.extractor.services.youtube.sabr.YoutubeSabrSession
98
import java.time.Instant
109

1110
internal class SabrSessionPump {
@@ -37,7 +36,7 @@ internal class SabrSessionPump {
3736
return@withLock segment
3837
}
3938
if (holder.session.isBeyondEnd(request)) return@withLock null
40-
holder.session.prepareForRequestedSegment(holder, request)
39+
holder.session.prepareForRequestedSegment(holder, request, localization)
4140
runCatching { holder.session.fetchSegment(request, localization) }
4241
.getOrNull()
4342
?.also { holder.markServed(it) }
@@ -55,7 +54,7 @@ internal class SabrSessionPump {
5554
return@withLock
5655
}
5756
signal?.let {
58-
holder.session.prepareForRequestedSegment(holder, signal)
57+
holder.session.prepareForRequestedSegment(holder, signal, localization)
5958
holder.pendingSignals.remove(signal)
6059
}
6160
holder.session.evictPlayed()
@@ -90,27 +89,4 @@ internal class SabrSessionPump {
9089
}
9190
}
9291
}
93-
94-
private fun YoutubeSabrSession.prepareForRequestedSegment(holder: SabrSessionHolder, request: SabrSegmentRequest) {
95-
if (request.isInitializationSegment) return
96-
prepareForRewind(request)
97-
prepareForForwardJump(request)
98-
streamState.setBufferedRangesOverride(emptyList())
99-
val startMs = streamState.getSegmentStartMs(request.format, request.sequenceNumber).coerceAtLeast(0L)
100-
streamState.setPlayerTimeMs(if (startMs == 0L) 0L else startMs + 1L)
101-
if (request.format.isAudio) {
102-
streamState.setRequestTrackMode(AUDIO_ONLY_TRACKS, true, false)
103-
streamState.setFullyBuffered(holder.videoFormat, true)
104-
streamState.setFullyBuffered(holder.audioFormat, false)
105-
} else {
106-
streamState.setRequestTrackMode(VIDEO_ONLY_TRACKS, false, true)
107-
streamState.setFullyBuffered(holder.audioFormat, true)
108-
streamState.setFullyBuffered(holder.videoFormat, false)
109-
}
110-
}
111-
112-
private companion object {
113-
const val AUDIO_ONLY_TRACKS = 1
114-
const val VIDEO_ONLY_TRACKS = 2
115-
}
11692
}

src/test/kotlin/dev/typetype/server/services/SabrSessionPumpTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ class SabrSessionPumpTest {
3232
val session = mockk<YoutubeSabrSession>()
3333
val streamState = mockk<YoutubeSabrStreamState>()
3434
val segment = mediaSegment(startMs, durationMs)
35-
every { session.getCachedSegment(request) } returns null
36-
every { session.isBeyondEnd(request) } returns false
35+
every { session.getCachedSegment(any()) } returns null
36+
every { session.isBeyondEnd(any()) } returns false
3737
every { session.prepareForRewind(request) } returns Unit
3838
every { session.prepareForForwardJump(request) } returns Unit
3939
every { session.streamState } returns streamState
@@ -43,7 +43,7 @@ class SabrSessionPumpTest {
4343
every { streamState.setRequestTrackMode(any(), any(), any()) } returns Unit
4444
every { streamState.setFullyBuffered(companion, true) } returns Unit
4545
every { streamState.setFullyBuffered(format, false) } returns Unit
46-
every { session.fetchSegment(request, any<Localization>()) } returns segment
46+
every { session.fetchSegment(any(), any<Localization>()) } returns segment
4747
every { session.setPlayHeadMs(startMs + durationMs) } returns Unit
4848
val holder = SabrSessionHolder(
4949
session = session,

0 commit comments

Comments
 (0)