Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -95,6 +95,12 @@ class AndroidExtractor: Extractor {
return sleepTime
}

override fun resetTs() {
sleepTime = 0
accumulativeTs = 0
lastExtractorTs = 0
}

override fun seekTo(time: Long) {
mediaExtractor.seekTo(time, MediaExtractor.SEEK_TO_PREVIOUS_SYNC)
lastExtractorTs = getTimeStamp()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,19 @@ public void start() {
}

public void stop() {
stop(true);
}

public void stop(boolean release) {
Log.i(TAG, "stop decoder");
running = false;
stopDecoder();
startTs = 0;
extractor.resetTs();
if (release) releaseExtractor();
}

public void releaseExtractor() {
extractor.release();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ interface Extractor {

fun getSleepTime(ts: Long): Long

fun resetTs() {}

fun seekTo(time: Long)

fun release()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,13 @@ class AudioFileSource(
override fun stop() {
this.getMicrophoneData = null
running = false
audioDecoder.stop()
audioDecoder.stop(false)
}

override fun isRunning(): Boolean = running

override fun release() {
if (running) stop()
audioDecoder.releaseExtractor()
}

fun mute() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,12 @@ class InternalAudioSource(
this.getMicrophoneData = null
microphone.stop()
handlerThread.quitSafely()
MediaProjectionHandler.mediaProjection?.unregisterCallback(mediaProjectionCallback)
}

override fun isRunning(): Boolean = microphone.isRunning

override fun release() {
MediaProjectionHandler.mediaProjection?.unregisterCallback(mediaProjectionCallback)
}
override fun release() {}

override fun inputPCMData(frame: Frame) {
getMicrophoneData?.inputPCMData(frame)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class MixAudioSource(
getMicrophoneData = null
microphone.stop()
handlerThread.quitSafely()
MediaProjectionHandler.mediaProjection?.unregisterCallback(mediaProjectionCallback)
}

override fun isRunning(): Boolean = microphone.isRunning
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class BufferVideoSource(
surface = null
}

override fun release() { }
override fun release() {}

override fun isRunning(): Boolean = running
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,11 @@ class ScreenSource @JvmOverloads constructor(
surface?.release()
surface = null
handlerThread.quitSafely()
}

override fun release() {
MediaProjectionHandler.mediaProjection?.unregisterCallback(mediaProjectionCallback)
}

override fun release() {}

override fun isRunning(): Boolean = virtualDisplay != null

override fun getOrientationConfig(): OrientationConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ class VideoFileSource(

override fun stop() {
running = false
videoDecoder.stop()
videoDecoder.stop(false)
this.surface?.release()
this.surface = null
}

override fun release() {
if (running) stop()
videoDecoder.releaseExtractor()
}

override fun isRunning(): Boolean = running
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,35 @@ package com.pedro.extrasources

import android.media.AudioFormat
import androidx.media3.common.audio.AudioProcessor
import androidx.media3.common.audio.AudioProcessor.EMPTY_BUFFER
import androidx.media3.common.audio.BaseAudioProcessor
import androidx.media3.common.util.UnstableApi
import com.pedro.common.toByteArray
import java.nio.ByteBuffer

/**
* Capture the decoded PCM and forward it to the callback.
* The data is also written to the output buffer to keep the AudioSink writing to the AudioTrack.
* That write is what paces the player to real time, so it must not be skipped even if the
* player is muted.
*/
@UnstableApi
class AudioBufferProcessor(
private val callback: (ByteArray) -> Unit
) : AudioProcessor {
) : BaseAudioProcessor() {

private var inputEnded = false

override fun configure(inputAudioFormat: AudioProcessor.AudioFormat): AudioProcessor.AudioFormat {
return if (inputAudioFormat.encoding == AudioFormat.ENCODING_PCM_16BIT) inputAudioFormat
else AudioProcessor.AudioFormat.NOT_SET
override fun onConfigure(inputAudioFormat: AudioProcessor.AudioFormat): AudioProcessor.AudioFormat {
if (inputAudioFormat.encoding != AudioFormat.ENCODING_PCM_16BIT) {
throw AudioProcessor.UnhandledAudioFormatException(inputAudioFormat)
}
return inputAudioFormat
}

override fun isActive(): Boolean = true

override fun queueInput(inputBuffer: ByteBuffer) {
callback(inputBuffer.toByteArray())
}

override fun queueEndOfStream() {
inputEnded = true
}

override fun getOutput(): ByteBuffer {
return EMPTY_BUFFER
}

override fun isEnded(): Boolean = inputEnded

override fun flush() {
inputEnded = false
}

override fun reset() {
inputEnded = false
val size = inputBuffer.remaining()
if (size <= 0) return
val bytes = ByteArray(size)
//get consume the input buffer, required to indicate that the data was processed
inputBuffer.get(bytes)
callback(bytes)
replaceOutputBuffer(size).put(bytes).flip()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ class CameraUvcSource: VideoSource() {
running = false
}

override fun release() {
}
override fun release() {}

override fun isRunning(): Boolean = running

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class Media3AudioSource(
this.getMicrophoneData = getMicrophoneData
if (isRunning()) return
player = ExoPlayer.Builder(context, TracksRenderersFactory(context, MediaFrame.Type.AUDIO, processor)).build().also { exoPlayer ->
exoPlayer.volume = 0f
val mediaItem = MediaItem.fromUri(path)
exoPlayer.setMediaItem(mediaItem)
exoPlayer.playbackParameters = PlaybackParameters(speed)
Expand All @@ -77,9 +78,7 @@ class Media3AudioSource(
player = null
}

override fun release() {

}
override fun release() {}

override fun isRunning(): Boolean = running

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ class Media3VideoSource(
surface = null
}

override fun release() {

}
override fun release() {}

override fun isRunning(): Boolean = running

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ class Media3Extractor(private val context: Context): Extractor {
return sleepTime
}

override fun resetTs() {
sleepTime = 0
accumulativeTs = 0
lastExtractorTs = 0
}

override fun seekTo(time: Long) {
mediaExtractor.seekTo(time, MediaExtractorCompat.SEEK_TO_PREVIOUS_SYNC)
lastExtractorTs = getTimeStamp()
Expand Down
16 changes: 13 additions & 3 deletions library/src/main/java/com/pedro/library/base/StreamBase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,14 @@ abstract class StreamBase(
source.init(width, height, videoEncoder.fps, videoEncoder.rotation)
}
videoSource.stop()
videoSource.release()
if (glInterface.isRunning) glInterface.surfaceTexture.tryClear()
if (wasRunning) source.start(glInterface.surfaceTexture)
if (wasRunning) {
runCatching { source.start(glInterface.surfaceTexture) }.getOrElse {
runCatching { videoSource.start(glInterface.surfaceTexture) }
throw it
}
}
videoSource.release()
glInterface.setOrientationConfig(source.getOrientationConfig())
videoSource = source
}
Expand All @@ -429,8 +434,13 @@ abstract class StreamBase(
val wasCreated = audioSource.created
if (wasCreated) source.init(audioSource.sampleRate, audioSource.isStereo, audioSource.echoCanceler, audioSource.noiseSuppressor)
audioSource.stop()
if (wasRunning) {
runCatching { source.start(getMicrophoneData) }.getOrElse {
runCatching { audioSource.start(getMicrophoneData) }
throw it
}
}
audioSource.release()
if (wasRunning) source.start(getMicrophoneData)
audioSource = source
}

Expand Down
Loading