Skip to content

Commit 33da7bc

Browse files
committed
refactor(core): make mutable frame and raw frame private to force user to use a pool
1 parent 15dd902 commit 33da7bc

File tree

5 files changed

+123
-104
lines changed

5 files changed

+123
-104
lines changed

core/src/main/java/io/github/thibaultbee/streampack/core/elements/data/Frame.kt

Lines changed: 1 addition & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -75,35 +75,6 @@ fun RawFrame.copy(
7575
})
7676
}
7777

78-
/**
79-
* A mutable [RawFrame] internal representation.
80-
*
81-
* The purpose is to get reusable [RawFrame]
82-
*/
83-
data class MutableRawFrame(
84-
/**
85-
* Contains an audio or video frame data.
86-
*/
87-
override var rawBuffer: ByteBuffer,
88-
89-
/**
90-
* Presentation timestamp in µs
91-
*/
92-
override var timestampInUs: Long,
93-
/**
94-
* A callback to call when frame is closed.
95-
*/
96-
override var onClosed: (MutableRawFrame) -> Unit = {}
97-
) : RawFrame, WithClosable<MutableRawFrame> {
98-
override fun close() {
99-
try {
100-
onClosed(this)
101-
} catch (_: Throwable) {
102-
// Nothing to do
103-
}
104-
}
105-
}
106-
10778
/**
10879
* Encoded frame representation
10980
*/
@@ -169,60 +140,6 @@ fun Frame.copy(
169140
})
170141
}
171142

172-
173-
/**
174-
* A mutable [Frame] internal representation.
175-
*
176-
* The purpose is to get reusable [Frame]
177-
*/
178-
data class MutableFrame(
179-
/**
180-
* Contains an audio or video frame data.
181-
*/
182-
override var rawBuffer: ByteBuffer,
183-
184-
/**
185-
* Presentation timestamp in µs
186-
*/
187-
override var ptsInUs: Long,
188-
189-
/**
190-
* Decoded timestamp in µs (not used).
191-
*/
192-
override var dtsInUs: Long?,
193-
194-
/**
195-
* `true` if frame is a key frame (I-frame for AVC/HEVC and audio frames)
196-
*/
197-
override var isKeyFrame: Boolean,
198-
199-
/**
200-
* Contains csd buffers for key frames and audio frames only.
201-
* Could be (SPS, PPS, VPS, etc.) for key video frames, null for non-key video frames.
202-
* ESDS for AAC frames,...
203-
*/
204-
override var extra: Extra?,
205-
206-
/**
207-
* Contains frame format..
208-
* TODO: to remove
209-
*/
210-
override var format: MediaFormat,
211-
212-
/**
213-
* A callback to call when frame is closed.
214-
*/
215-
override var onClosed: (MutableFrame) -> Unit = {}
216-
) : Frame, WithClosable<MutableFrame> {
217-
override fun close() {
218-
try {
219-
onClosed(this)
220-
} catch (_: Throwable) {
221-
// Nothing to do
222-
}
223-
}
224-
}
225-
226143
/**
227144
* Ensures that extra are not used at the same time.
228145
*
@@ -231,7 +148,7 @@ data class MutableFrame(
231148
class Extra(private val extraBuffers: List<ByteBuffer>) {
232149
private val lock = Any()
233150

234-
val _length by lazy { extraBuffers.sumOf { it.remaining() } }
151+
private val _length by lazy { extraBuffers.sumOf { it.remaining() } }
235152

236153
fun getLength(): Int {
237154
return synchronized(lock) {

core/src/main/java/io/github/thibaultbee/streampack/core/elements/endpoints/composites/muxers/ts/TsMuxer.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class TsMuxer : IMuxerInternal {
7878
override fun write(
7979
frame: Frame, streamPid: Int
8080
) {
81-
try {
81+
frame.use { frame ->
8282
val pes = getPes(streamPid.toShort())
8383
val mimeType = pes.stream.config.mimeType
8484
val newFrame = when {
@@ -169,8 +169,6 @@ class TsMuxer : IMuxerInternal {
169169
newFrame.close()
170170
}
171171
}
172-
} finally {
173-
frame.close()
174172
}
175173
}
176174

core/src/main/java/io/github/thibaultbee/streampack/core/elements/utils/pool/FramePool.kt

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,31 @@ package io.github.thibaultbee.streampack.core.elements.utils.pool
1717

1818
import android.media.MediaFormat
1919
import io.github.thibaultbee.streampack.core.elements.data.Extra
20-
import io.github.thibaultbee.streampack.core.elements.data.MutableFrame
20+
import io.github.thibaultbee.streampack.core.elements.data.Frame
21+
import io.github.thibaultbee.streampack.core.elements.data.WithClosable
2122
import java.nio.ByteBuffer
2223

2324

2425
/**
2526
* A pool of [MutableFrame].
2627
*/
27-
internal class FramePool() : ObjectPool<MutableFrame>() {
28+
internal class FramePool : IClearableObjectPool<Frame> {
29+
private val pool = ObjectPoolImpl<MutableFrame>()
30+
2831
fun get(
2932
rawBuffer: ByteBuffer,
3033
ptsInUs: Long,
3134
dtsInUs: Long?,
3235
isKeyFrame: Boolean,
3336
extra: Extra?,
3437
format: MediaFormat,
35-
onClosed: (MutableFrame) -> Unit
36-
): MutableFrame {
37-
val frame = get()
38+
onClosed: (Frame) -> Unit
39+
): Frame {
40+
val frame = pool.get()
3841

3942
val onClosedHook = { frame: MutableFrame ->
4043
onClosed(frame)
41-
put(frame)
44+
pool.put(frame)
4245
}
4346

4447
return if (frame != null) {
@@ -63,6 +66,63 @@ internal class FramePool() : ObjectPool<MutableFrame>() {
6366
}
6467
}
6568

69+
override fun clear() = pool.clear()
70+
71+
override fun close() = pool.close()
72+
73+
/**
74+
* A mutable [Frame] internal representation.
75+
*
76+
* The purpose is to get reusable [Frame]
77+
*/
78+
private data class MutableFrame(
79+
/**
80+
* Contains an audio or video frame data.
81+
*/
82+
override var rawBuffer: ByteBuffer,
83+
84+
/**
85+
* Presentation timestamp in µs
86+
*/
87+
override var ptsInUs: Long,
88+
89+
/**
90+
* Decoded timestamp in µs (not used).
91+
*/
92+
override var dtsInUs: Long?,
93+
94+
/**
95+
* `true` if frame is a key frame (I-frame for AVC/HEVC and audio frames)
96+
*/
97+
override var isKeyFrame: Boolean,
98+
99+
/**
100+
* Contains csd buffers for key frames and audio frames only.
101+
* Could be (SPS, PPS, VPS, etc.) for key video frames, null for non-key video frames.
102+
* ESDS for AAC frames,...
103+
*/
104+
override var extra: Extra?,
105+
106+
/**
107+
* Contains frame format..
108+
* TODO: to remove
109+
*/
110+
override var format: MediaFormat,
111+
112+
/**
113+
* A callback to call when frame is closed.
114+
*/
115+
override var onClosed: (MutableFrame) -> Unit = {}
116+
) : Frame, WithClosable<MutableFrame> {
117+
override fun close() {
118+
try {
119+
onClosed(this)
120+
} catch (_: Throwable) {
121+
// Nothing to do
122+
}
123+
}
124+
}
125+
66126
companion object {
67127
/**
68128
* The default frame pool.

core/src/main/java/io/github/thibaultbee/streampack/core/elements/utils/pool/ObjectPool.kt renamed to core/src/main/java/io/github/thibaultbee/streampack/core/elements/utils/pool/ObjectPoolImpl.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,18 @@
1515
*/
1616
package io.github.thibaultbee.streampack.core.elements.utils.pool
1717

18-
import io.github.thibaultbee.streampack.core.logger.Logger
1918
import java.io.Closeable
2019
import java.util.ArrayDeque
2120
import java.util.concurrent.atomic.AtomicBoolean
2221

22+
interface IClearableObjectPool<T> : Closeable {
23+
fun clear()
24+
}
25+
26+
interface IObjectPool<T> : IClearableObjectPool<T> {
27+
fun put(any: T)
28+
}
29+
2330
/**
2431
* A pool of objects.
2532
*
@@ -29,12 +36,12 @@ import java.util.concurrent.atomic.AtomicBoolean
2936
*
3037
* @param T the type of object to pool
3138
*/
32-
internal sealed class ObjectPool<T>() : Closeable {
39+
internal open class ObjectPoolImpl<T> : IObjectPool<T> {
3340
private val pool = ArrayDeque<T>()
3441

3542
private val isClosed = AtomicBoolean(false)
3643

37-
protected fun get(): T? {
44+
fun get(): T? {
3845
if (isClosed.get()) {
3946
throw IllegalStateException("ObjectPool is closed")
4047
}
@@ -53,7 +60,7 @@ internal sealed class ObjectPool<T>() : Closeable {
5360
*
5461
* @param any the object to put
5562
*/
56-
fun put(any: T) {
63+
override fun put(any: T) {
5764
if (isClosed.get()) {
5865
throw IllegalStateException("ObjectPool is closed")
5966
}
@@ -65,7 +72,7 @@ internal sealed class ObjectPool<T>() : Closeable {
6572
/**
6673
* Clears the pool.
6774
*/
68-
fun clear() {
75+
override fun clear() {
6976
if (isClosed.get()) {
7077
return
7178
}

core/src/main/java/io/github/thibaultbee/streampack/core/elements/utils/pool/RawFramePool.kt

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,27 @@
1515
*/
1616
package io.github.thibaultbee.streampack.core.elements.utils.pool
1717

18-
import io.github.thibaultbee.streampack.core.elements.data.MutableRawFrame
18+
import io.github.thibaultbee.streampack.core.elements.data.RawFrame
19+
import io.github.thibaultbee.streampack.core.elements.data.WithClosable
1920
import java.nio.ByteBuffer
2021

2122

2223
/**
2324
* A pool of [MutableRawFrame].
2425
*/
25-
internal class RawFramePool() : ObjectPool<MutableRawFrame>() {
26+
internal class RawFramePool : IClearableObjectPool<RawFrame> {
27+
private val pool = ObjectPoolImpl<MutableRawFrame>()
28+
2629
fun get(
2730
rawBuffer: ByteBuffer,
2831
timestampInUs: Long,
29-
onClosed: (MutableRawFrame) -> Unit = {}
30-
): MutableRawFrame {
31-
val frame = get()
32+
onClosed: (RawFrame) -> Unit = {}
33+
): RawFrame {
34+
val frame = pool.get()
3235

3336
val onClosedHook = { frame: MutableRawFrame ->
3437
onClosed(frame)
35-
put(frame)
38+
pool.put(frame)
3639
}
3740

3841
return if (frame != null) {
@@ -49,6 +52,40 @@ internal class RawFramePool() : ObjectPool<MutableRawFrame>() {
4952
}
5053
}
5154

55+
override fun clear() = pool.clear()
56+
57+
override fun close() = pool.close()
58+
59+
/**
60+
* A mutable [RawFrame] internal representation.
61+
*
62+
* The purpose is to get reusable [RawFrame]
63+
*/
64+
private data class MutableRawFrame(
65+
/**
66+
* Contains an audio or video frame data.
67+
*/
68+
override var rawBuffer: ByteBuffer,
69+
70+
/**
71+
* Presentation timestamp in µs
72+
*/
73+
override var timestampInUs: Long,
74+
/**
75+
* A callback to call when frame is closed.
76+
*/
77+
override var onClosed: (MutableRawFrame) -> Unit = {}
78+
) : RawFrame, WithClosable<MutableRawFrame> {
79+
override fun close() {
80+
try {
81+
onClosed(this)
82+
} catch (_: Throwable) {
83+
// Nothing to do
84+
}
85+
}
86+
}
87+
88+
5289
companion object {
5390
/**
5491
* The default frame pool.

0 commit comments

Comments
 (0)