Skip to content

Commit 9a9ca12

Browse files
authored
Merge pull request #2161 from pedroSG94/refactor-videosources-fix-leaks
refactor and fix leaks on vide sources
2 parents e89f86c + 6638025 commit 9a9ca12

17 files changed

Lines changed: 160 additions & 112 deletions

encoder/src/main/java/com/pedro/encoder/input/sources/audio/AudioFileSource.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class AudioFileSource(
7979

8080
override fun start(getMicrophoneData: GetMicrophoneData) {
8181
this.getMicrophoneData = getMicrophoneData
82+
if (isRunning()) return
8283
audioDecoder.prepareAudio()
8384
audioDecoder.start()
8485
running = true
@@ -89,6 +90,7 @@ class AudioFileSource(
8990
}
9091

9192
override fun stop() {
93+
this.getMicrophoneData = null
9294
running = false
9395
audioDecoder.stop()
9496
}

encoder/src/main/java/com/pedro/encoder/input/sources/audio/BufferAudioSource.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class BufferAudioSource(
9090

9191
override fun start(getMicrophoneData: GetMicrophoneData) {
9292
this.getMicrophoneData = getMicrophoneData
93+
if (isRunning()) return
9394
synchronized(lock) {
9495
buffer.fill(0)
9596
readIndex = 0
@@ -221,6 +222,7 @@ class BufferAudioSource(
221222
}
222223

223224
override fun stop() {
225+
this.getMicrophoneData = null
224226
running = false
225227
runBlocking { job?.cancelAndJoin() }
226228
}

encoder/src/main/java/com/pedro/encoder/input/sources/audio/InternalAudioSource.kt

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,35 +60,31 @@ class InternalAudioSource(
6060

6161
override fun start(getMicrophoneData: GetMicrophoneData) {
6262
this.getMicrophoneData = getMicrophoneData
63-
if (!isRunning()) {
64-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
65-
handlerThread = HandlerThread(TAG)
66-
handlerThread.start()
67-
MediaProjectionHandler.mediaProjection?.registerCallback(mediaProjectionCallback, Handler(handlerThread.looper))
68-
val config = AudioPlaybackCaptureConfiguration.Builder(MediaProjectionHandler.mediaProjection!!)
69-
.addMatchingUsage(AudioAttributes.USAGE_MEDIA)
70-
.addMatchingUsage(AudioAttributes.USAGE_GAME)
71-
.addMatchingUsage(AudioAttributes.USAGE_UNKNOWN).build()
72-
try {
73-
val result = microphone.createInternalMicrophone(config, sampleRate, isStereo,
74-
echoCanceler, noiseSuppressor)
75-
if (!result) throw IllegalArgumentException("Failed to create internal audio source")
76-
} catch (e: UnsupportedOperationException) {
77-
throw IllegalArgumentException("invalid MediaProjection used")
78-
}
79-
} else {
80-
throw IllegalStateException("Using internal audio in a invalid Android version. Android 10+ is necessary")
81-
}
82-
microphone.start()
63+
if (isRunning()) return
64+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
65+
throw IllegalStateException("Using internal audio in a invalid Android version. Android 10+ is necessary")
8366
}
67+
handlerThread = HandlerThread(TAG)
68+
handlerThread.start()
69+
MediaProjectionHandler.mediaProjection?.registerCallback(mediaProjectionCallback, Handler(handlerThread.looper))
70+
val config = AudioPlaybackCaptureConfiguration.Builder(MediaProjectionHandler.mediaProjection!!)
71+
.addMatchingUsage(AudioAttributes.USAGE_MEDIA)
72+
.addMatchingUsage(AudioAttributes.USAGE_GAME)
73+
.addMatchingUsage(AudioAttributes.USAGE_UNKNOWN).build()
74+
try {
75+
val result = microphone.createInternalMicrophone(config, sampleRate, isStereo,
76+
echoCanceler, noiseSuppressor)
77+
if (!result) throw IllegalArgumentException("Failed to create internal audio source")
78+
} catch (_: UnsupportedOperationException) {
79+
throw IllegalArgumentException("invalid MediaProjection used")
80+
}
81+
microphone.start()
8482
}
8583

8684
override fun stop() {
87-
if (isRunning()) {
88-
this.getMicrophoneData = null
89-
microphone.stop()
90-
handlerThread.quitSafely()
91-
}
85+
this.getMicrophoneData = null
86+
microphone.stop()
87+
handlerThread.quitSafely()
9288
}
9389

9490
override fun isRunning(): Boolean = microphone.isRunning

encoder/src/main/java/com/pedro/encoder/input/sources/audio/MicrophoneSource.kt

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,20 @@ class MicrophoneSource(
5252

5353
override fun start(getMicrophoneData: GetMicrophoneData) {
5454
this.getMicrophoneData = getMicrophoneData
55-
if (!isRunning()) {
56-
val result = microphone.createMicrophone(audioSource, sampleRate, isStereo, echoCanceler, noiseSuppressor)
57-
if (!result) {
58-
throw IllegalArgumentException("Failed to create microphone audio source")
59-
}
60-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
61-
microphone.setPreferredDevice(preferredDevice)
62-
}
63-
microphone.start()
55+
if (isRunning()) return
56+
val result = microphone.createMicrophone(audioSource, sampleRate, isStereo, echoCanceler, noiseSuppressor)
57+
if (!result) {
58+
throw IllegalArgumentException("Failed to create microphone audio source")
6459
}
60+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
61+
microphone.setPreferredDevice(preferredDevice)
62+
}
63+
microphone.start()
6564
}
6665

6766
override fun stop() {
68-
if (isRunning()) {
69-
this.getMicrophoneData = null
70-
microphone.stop()
71-
}
67+
this.getMicrophoneData = null
68+
microphone.stop()
7269
}
7370

7471
override fun isRunning(): Boolean = microphone.isRunning

encoder/src/main/java/com/pedro/encoder/input/sources/audio/MixAudioSource.kt

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,31 +82,29 @@ class MixAudioSource(
8282

8383
override fun start(getMicrophoneData: GetMicrophoneData) {
8484
this.getMicrophoneData = getMicrophoneData
85-
if (!isRunning()) {
86-
handlerThread = HandlerThread(TAG)
87-
handlerThread.start()
88-
MediaProjectionHandler.mediaProjection?.registerCallback(mediaProjectionCallback, Handler(handlerThread.looper))
89-
val config = AudioPlaybackCaptureConfiguration.Builder(MediaProjectionHandler.mediaProjection!!)
90-
.addMatchingUsage(AudioAttributes.USAGE_MEDIA)
91-
.addMatchingUsage(AudioAttributes.USAGE_GAME)
92-
.addMatchingUsage(AudioAttributes.USAGE_UNKNOWN).build()
93-
val result = microphone.createMixMicrophone(microphoneAudioSource, config, sampleRate, isStereo, echoCanceler, noiseSuppressor)
94-
if (!result) {
95-
throw IllegalArgumentException("Failed to create microphone audio source")
96-
}
97-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
98-
microphone.setPreferredDevice(preferredDevice)
99-
}
100-
microphone.start()
85+
if (isRunning()) return
86+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
87+
throw IllegalStateException("Using mix audio in a invalid Android version. Android 10+ is necessary")
10188
}
89+
handlerThread = HandlerThread(TAG)
90+
handlerThread.start()
91+
MediaProjectionHandler.mediaProjection?.registerCallback(mediaProjectionCallback, Handler(handlerThread.looper))
92+
val config = AudioPlaybackCaptureConfiguration.Builder(MediaProjectionHandler.mediaProjection!!)
93+
.addMatchingUsage(AudioAttributes.USAGE_MEDIA)
94+
.addMatchingUsage(AudioAttributes.USAGE_GAME)
95+
.addMatchingUsage(AudioAttributes.USAGE_UNKNOWN).build()
96+
val result = microphone.createMixMicrophone(microphoneAudioSource, config, sampleRate, isStereo, echoCanceler, noiseSuppressor)
97+
if (!result) {
98+
throw IllegalArgumentException("Failed to create microphone audio source")
99+
}
100+
microphone.setPreferredDevice(preferredDevice)
101+
microphone.start()
102102
}
103103

104104
override fun stop() {
105-
if (isRunning()) {
106-
getMicrophoneData = null
107-
microphone.stop()
108-
handlerThread.quitSafely()
109-
}
105+
getMicrophoneData = null
106+
microphone.stop()
107+
handlerThread.quitSafely()
110108
}
111109

112110
override fun isRunning(): Boolean = microphone.isRunning

encoder/src/main/java/com/pedro/encoder/input/sources/audio/SilenceAudioSource.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import kotlinx.coroutines.cancelAndJoin
2929
import kotlinx.coroutines.delay
3030
import kotlinx.coroutines.launch
3131
import kotlinx.coroutines.runBlocking
32+
import kotlin.time.Duration.Companion.milliseconds
3233

3334
/**
3435
* Created by pedro on 25/7/25.
@@ -48,16 +49,18 @@ class SilenceAudioSource: AudioSource(), GetMicrophoneData {
4849

4950
override fun start(getMicrophoneData: GetMicrophoneData) {
5051
this.getMicrophoneData = getMicrophoneData
52+
if (isRunning()) return
5153
running = true
5254
job = CoroutineScope(Dispatchers.IO).launch {
5355
while (running) {
5456
getMicrophoneData.inputPCMData(Frame(buffer, 0, buffer.size, TimeUtils.getCurrentTimeMicro()))
55-
delay(sleepTime)
57+
delay(sleepTime.milliseconds)
5658
}
5759
}
5860
}
5961

6062
override fun stop() {
63+
this.getMicrophoneData = null
6164
running = false
6265
runBlocking { job?.cancelAndJoin() }
6366
}

encoder/src/main/java/com/pedro/encoder/input/sources/video/BitmapSource.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import kotlinx.coroutines.cancelAndJoin
2727
import kotlinx.coroutines.delay
2828
import kotlinx.coroutines.launch
2929
import kotlinx.coroutines.runBlocking
30+
import kotlin.time.Duration.Companion.milliseconds
3031

3132
/**
3233
* Created by pedro on 19/3/24.
@@ -44,6 +45,8 @@ class BitmapSource(private val bitmap: Bitmap): VideoSource() {
4445
}
4546

4647
override fun start(surfaceTexture: SurfaceTexture) {
48+
this.surfaceTexture = surfaceTexture
49+
if (isRunning()) return
4750
val scaledBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true)
4851
surfaceTexture.setDefaultBufferSize(width, height)
4952
surface = Surface(surfaceTexture)
@@ -56,7 +59,7 @@ class BitmapSource(private val bitmap: Bitmap): VideoSource() {
5659
surface?.unlockCanvasAndPost(canvas)
5760
} catch (_: Exception) { }
5861
//sleep to emulate fps
59-
delay(1000 / fps.toLong())
62+
delay((1000 / fps.toLong()).milliseconds)
6063
}
6164
}
6265
}

encoder/src/main/java/com/pedro/encoder/input/sources/video/BufferVideoSource.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class BufferVideoSource(
8888
}
8989

9090
override fun start(surfaceTexture: SurfaceTexture) {
91+
this.surfaceTexture = surfaceTexture
92+
if (isRunning()) return
9193
scope = CoroutineScope(Dispatchers.IO)
9294
queue.clear()
9395
running = true
@@ -116,6 +118,7 @@ class BufferVideoSource(
116118
decoder.stop()
117119
queue.clear()
118120
surface?.release()
121+
surface = null
119122
}
120123

121124
override fun release() { }

encoder/src/main/java/com/pedro/encoder/input/sources/video/Camera1Source.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,15 @@ class Camera1Source(context: Context): VideoSource() {
5050

5151
override fun start(surfaceTexture: SurfaceTexture) {
5252
this.surfaceTexture = surfaceTexture
53-
if (!isRunning()) {
54-
surfaceTexture.setDefaultBufferSize(width, height)
55-
camera.setSurfaceTexture(surfaceTexture)
56-
camera.start(facing, width, height, fps)
57-
camera.setPreviewOrientation(90) // necessary to use the same orientation than camera2
58-
}
53+
if (isRunning()) return
54+
surfaceTexture.setDefaultBufferSize(width, height)
55+
camera.setSurfaceTexture(surfaceTexture)
56+
camera.start(facing, width, height, fps)
57+
camera.setPreviewOrientation(90) // necessary to use the same orientation than camera2
5958
}
6059

6160
override fun stop() {
62-
if (isRunning()) camera.stop()
61+
camera.stop()
6362
}
6463

6564
override fun release() {}

encoder/src/main/java/com/pedro/encoder/input/sources/video/Camera2Source.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,14 @@ class Camera2Source(context: Context): VideoSource() {
5555

5656
override fun start(surfaceTexture: SurfaceTexture) {
5757
this.surfaceTexture = surfaceTexture
58-
if (!isRunning()) {
59-
surfaceTexture.setDefaultBufferSize(width, height)
60-
camera.prepareCamera(surfaceTexture, width, height, fps, facing)
61-
camera.openCameraFacing(facing)
62-
}
58+
if (isRunning()) return
59+
surfaceTexture.setDefaultBufferSize(width, height)
60+
camera.prepareCamera(surfaceTexture, width, height, fps, facing)
61+
camera.openCameraFacing(facing)
6362
}
6463

6564
override fun stop() {
66-
if (isRunning()) camera.closeCamera()
65+
camera.closeCamera()
6766
}
6867

6968
override fun release() {}

0 commit comments

Comments
 (0)