1
+ package com.otaliastudios.transcoder.internal.codec
2
+
3
+ import com.otaliastudios.transcoder.internal.utils.Logger
4
+
5
+ // Hard to read class that takes decoder input frames along with their render boolean,
6
+ // and decides which output frames should be rendered, and with which timestamp.
7
+ internal class DecoderDropper {
8
+
9
+ private val log = Logger (" DecoderDropper" )
10
+ private val closedDeltas = mutableMapOf<LongRange , Long >()
11
+ private val closedRanges = mutableListOf<LongRange >()
12
+ private var pendingRange: LongRange ? = null
13
+
14
+ private var firstInputUs: Long? = null
15
+ private var firstOutputUs: Long? = null
16
+
17
+ private fun debug (message : String , important : Boolean = false) {
18
+ val full = " $message pendingRangeUs=${pendingRange} firstInputUs=$firstInputUs " +
19
+ " validInputUs=[${closedRanges.joinToString {
20
+ " $it (deltaUs=${closedDeltas[it]} )"
21
+ }} ]"
22
+ if (important) log.w(full) else log.v(full)
23
+ }
24
+
25
+ fun input (timeUs : Long , render : Boolean ) {
26
+ if (firstInputUs == null ) {
27
+ firstInputUs = timeUs
28
+ }
29
+ if (render) {
30
+ debug(" INPUT: inputUs=$timeUs " )
31
+ if (pendingRange == null ) pendingRange = timeUs.. Long .MAX_VALUE
32
+ else pendingRange = pendingRange!! .first.. timeUs
33
+ } else {
34
+ debug(" INPUT: Got SKIPPING input! inputUs=$timeUs " )
35
+ if (pendingRange != null && pendingRange!! .last != Long .MAX_VALUE ) {
36
+ closedRanges.add(pendingRange!! )
37
+ closedDeltas[pendingRange!! ] = if (closedRanges.size >= 2 ) {
38
+ pendingRange!! .first - closedRanges[closedRanges.lastIndex - 1 ].last
39
+ } else 0L
40
+ }
41
+ pendingRange = null
42
+ }
43
+ }
44
+
45
+ fun output (timeUs : Long ): Long? {
46
+ if (firstOutputUs == null ) {
47
+ firstOutputUs = timeUs
48
+ }
49
+ val timeInInputScaleUs = firstInputUs!! + (timeUs - firstOutputUs!! )
50
+ var deltaUs = 0L
51
+ closedRanges.forEach {
52
+ deltaUs + = closedDeltas[it]!!
53
+ if (it.contains(timeInInputScaleUs)) {
54
+ debug(" OUTPUT: Rendering! outputTimeUs=$timeUs newOutputTimeUs=${timeUs - deltaUs} deltaUs=$deltaUs " )
55
+ return timeUs - deltaUs
56
+ }
57
+ }
58
+ if (pendingRange != null && pendingRange!! .last != Long .MAX_VALUE ) {
59
+ if (pendingRange!! .contains(timeInInputScaleUs)) {
60
+ if (closedRanges.isNotEmpty()) {
61
+ deltaUs + = pendingRange!! .first - closedRanges.last().last
62
+ }
63
+ debug(" OUTPUT: Rendering! outputTimeUs=$timeUs newOutputTimeUs=${timeUs - deltaUs} deltaUs=$deltaUs " )
64
+ return timeUs - deltaUs
65
+ }
66
+ }
67
+ debug(" OUTPUT: SKIPPING! outputTimeUs=$timeUs " , important = true )
68
+ return null
69
+ }
70
+ }
0 commit comments