Skip to content

Commit

Permalink
fix(core): only create codec surface once
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibaultBee committed Apr 17, 2024
1 parent c4133e1 commit 8fb0a27
Showing 1 changed file with 62 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ abstract class BaseStreamer(
protected var videoConfig: VideoConfig? = null
private var audioConfig: AudioConfig? = null

private val sourceOrientationProvider: ISourceOrientationProvider?
get() = videoSource?.orientationProvider
private val sourceOrientationProvider = videoSource?.orientationProvider

// Only handle stream error (error on muxer, endpoint,...)
/**
Expand Down Expand Up @@ -164,7 +163,8 @@ abstract class BaseStreamer(

protected var audioEncoder: MediaCodecEncoder? = null
protected var videoEncoder: MediaCodecEncoder? = null
protected var codecSurface: CodecSurface? = null
protected val codecSurface =
if (videoSource?.hasSurface == true) CodecSurface(sourceOrientationProvider) else null

override val settings = BaseStreamerSettings()

Expand Down Expand Up @@ -203,12 +203,16 @@ abstract class BaseStreamer(
val audioEncoder =
MediaCodecEncoder(AudioEncoderConfig(audioConfig), listener = audioEncoderListener)
audioEncoder.configure()
(audioEncoder.input as MediaCodecEncoder.ByteBufferInput).listener =
object : IEncoder.IByteBufferInput.OnFrameRequestedListener {
override fun onFrameRequested(buffer: ByteBuffer): Frame {
return audioSource.getFrame(buffer)
if (audioEncoder.input is MediaCodecEncoder.ByteBufferInput) {
audioEncoder.input.listener =
object : IEncoder.IByteBufferInput.OnFrameRequestedListener {
override fun onFrameRequested(buffer: ByteBuffer): Frame {
return audioSource.getFrame(buffer)
}
}
}
} else {
throw UnsupportedOperationException("Audio encoder only support ByteBuffer mode")
}

this.audioEncoder = audioEncoder

Expand All @@ -219,6 +223,46 @@ abstract class BaseStreamer(
}
}

private fun buildVideoEncoder(
videoConfig: VideoConfig,
videoSource: IVideoSource
): MediaCodecEncoder {
val videoEncoder = MediaCodecEncoder(
VideoEncoderConfig(
videoConfig,
videoSource.hasSurface,
videoSource.orientationProvider
), listener = videoEncoderListener
)

when (videoEncoder.input) {
is MediaCodecEncoder.SurfaceInput -> {
codecSurface!!.useHighBitDepth = videoConfig.isHdr
videoEncoder.input.listener =
object : IEncoder.ISurfaceInput.OnSurfaceUpdateListener {
override fun onSurfaceUpdated(surface: Surface) {
Logger.d(TAG, "Updating with new encoder surface input")
codecSurface.outputSurface = surface
}
}
}

is MediaCodecEncoder.ByteBufferInput -> {
videoEncoder.input.listener =
object : IEncoder.IByteBufferInput.OnFrameRequestedListener {
override fun onFrameRequested(buffer: ByteBuffer): Frame {
return videoSource.getFrame(buffer)
}
}
}

else -> {
throw UnsupportedOperationException("Unknown input type")
}
}
return videoEncoder
}

/**
* Configures video settings.
* It is the first method to call after a [BaseStreamer] instantiation.
Expand All @@ -242,44 +286,11 @@ abstract class BaseStreamer(
try {
videoSource.configure(videoConfig)

this.videoEncoder?.release()
val videoEncoder = MediaCodecEncoder(
VideoEncoderConfig(
videoConfig,
videoSource.hasSurface,
videoSource.orientationProvider
), listener = videoEncoderListener
)

when (videoEncoder.input) {
is MediaCodecEncoder.SurfaceInput -> {
codecSurface = CodecSurface(videoSource.orientationProvider)
videoEncoder.input.listener =
object : IEncoder.ISurfaceInput.OnSurfaceUpdateListener {
override fun onSurfaceUpdated(surface: Surface) {
Logger.d(TAG, "Updating with new encoder surface input")
codecSurface?.outputSurface = surface
}
}
}

is MediaCodecEncoder.ByteBufferInput -> {
videoEncoder.input.listener =
object : IEncoder.IByteBufferInput.OnFrameRequestedListener {
override fun onFrameRequested(buffer: ByteBuffer): Frame {
return videoSource.getFrame(buffer)
}
}
}

else -> {
throw UnsupportedOperationException("Unknown input type")
}
videoEncoder?.release()
videoEncoder = buildVideoEncoder(videoConfig, videoSource).apply {
configure()
}

videoEncoder.configure()
this.videoEncoder = videoEncoder

endpoint.configure(videoConfig.startBitrate + (audioConfig?.startBitrate ?: 0))
} catch (e: Exception) {
release()
Expand Down Expand Up @@ -391,7 +402,6 @@ abstract class BaseStreamer(
audioEncoder?.release()
audioEncoder = null
codecSurface?.release()
codecSurface = null
videoEncoder?.release()
videoEncoder = null

Expand Down Expand Up @@ -422,14 +432,16 @@ abstract class BaseStreamer(
* @return video bitrate in bps
* @throws [UnsupportedOperationException] if audio encoder is not set
*/
get() = videoEncoder?.bitrate ?: throw UnsupportedOperationException("Video encoder is not set")

get() = videoEncoder?.bitrate
?: throw UnsupportedOperationException("Video encoder is not set")
/**
* @param value video bitrate in bps
* @throws [UnsupportedOperationException] if audio encoder is not set
*/
set(value) {
videoEncoder?.let { it.bitrate = value } ?: throw UnsupportedOperationException("Video encoder is not set")
videoEncoder?.let { it.bitrate = value } ?: throw UnsupportedOperationException(
"Video encoder is not set"
)
}
}

Expand All @@ -443,7 +455,8 @@ abstract class BaseStreamer(
* @return audio bitrate in bps
* @throws [UnsupportedOperationException] if audio encoder is not set
*/
get() = audioEncoder?.bitrate ?: throw UnsupportedOperationException("Audio encoder is not set")
get() = audioEncoder?.bitrate
?: throw UnsupportedOperationException("Audio encoder is not set")

/**
* Gets/sets audio mute.
Expand Down

0 comments on commit 8fb0a27

Please sign in to comment.