Compare commits

...

1 Commits

Author SHA1 Message Date
1ac1b045fe Tweak things to make segments a bit more regular 2024-05-15 15:50:01 -06:00
2 changed files with 22 additions and 17 deletions

View File

@ -12,26 +12,31 @@ import com.mrousavy.camera.types.Orientation
import com.mrousavy.camera.types.RecordVideoOptions
import java.io.File
import java.nio.ByteBuffer
import kotlin.math.ceil
class ChunkedRecordingManager(private val encoder: MediaCodec, private val outputDirectory: File, private val orientationHint: Int, private val iFrameInterval: Int, private val callbacks: CameraSession.Callback) :
class ChunkedRecordingManager(private val encoder: MediaCodec, private val outputDirectory: File, private val orientationHint: Int, private val iFrameInterval: Float, private val callbacks: CameraSession.Callback) :
MediaCodec.Callback() {
companion object {
private const val TAG = "ChunkedRecorder"
private fun roundIntervalLengthUp(fps: Float, interval: Float): Float {
return ceil(fps * interval) / fps
}
fun fromParams(
callbacks: CameraSession.Callback,
size: Size,
enableAudio: Boolean,
fps: Int? = null,
fps: Float = 30.0f,
cameraOrientation: Orientation,
bitRate: Int,
options: RecordVideoOptions,
outputDirectory: File,
iFrameInterval: Int = 5
iFrameInterval: Float = 5.0f
): ChunkedRecordingManager {
val mimeType = options.videoCodec.toMimeType()
val cameraOrientationDegrees = cameraOrientation.toDegrees()
val recordingOrientationDegrees = (options.orientation ?: Orientation.PORTRAIT).toDegrees();
val recordingOrientationDegrees = (options.orientation ?: Orientation.PORTRAIT).toDegrees()
val (width, height) = if (cameraOrientation.isLandscape()) {
size.height to size.width
} else {
@ -42,25 +47,25 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu
val codec = MediaCodec.createEncoderByType(mimeType)
val roundedInterval = roundIntervalLengthUp(fps, iFrameInterval)
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
format.setInteger(
MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
)
fps?.apply {
format.setInteger(MediaFormat.KEY_FRAME_RATE, this)
}
format.setFloat(MediaFormat.KEY_FRAME_RATE, fps)
// TODO: Pull this out into configuration
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval)
format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, roundedInterval)
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate)
Log.d(TAG, "Video Format: $format, camera orientation $cameraOrientationDegrees, recordingOrientation: $recordingOrientationDegrees")
Log.d(TAG, "Video Format: $format, camera orientation $cameraOrientationDegrees, recordingOrientation: $recordingOrientationDegrees, Set fps: $fps")
// Create a MediaCodec encoder, and configure it with our format. Get a Surface
// we can use for input and wrap it with a class that handles the EGL work.
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
return ChunkedRecordingManager(
codec, outputDirectory, recordingOrientationDegrees, iFrameInterval, callbacks
codec, outputDirectory, recordingOrientationDegrees, roundedInterval, callbacks
)
}
}
@ -69,7 +74,7 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu
private var currentFrameNumber: Int = 0
private var chunkIndex = -1
private var encodedFormat: MediaFormat? = null
private var recording = false;
private var recording = false
private val targetDurationUs = iFrameInterval * 1000000
@ -83,15 +88,15 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu
}
// Muxer specific
private class MuxerContext(val muxer: MediaMuxer, val filepath: File, val chunkIndex: Int, startTimeUs: Long, encodedFormat: MediaFormat) {
private class MuxerContext(
val muxer: MediaMuxer, val filepath: File, val chunkIndex: Int,
val startTimeUs: Long, encodedFormat: MediaFormat
) {
val videoTrack: Int = muxer.addTrack(encodedFormat)
val startTimeUs: Long = startTimeUs
init {
muxer.start()
}
fun finish() {
muxer.stop()
muxer.release()
@ -146,7 +151,7 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu
override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
}
override fun onOutputBufferAvailable(codec: MediaCodec, index: Int, bufferInfo: MediaCodec.BufferInfo) {
override fun onOutputBufferAvailable(codec: MediaCodec, index: Int, bufferInfo: BufferInfo) {
synchronized(this) {
if (!recording) {
return

View File

@ -45,7 +45,7 @@ class RecordingSession(
allCallbacks,
size,
enableAudio,
fps,
(fps ?: 30).toFloat(),
cameraOrientation,
bitRate,
options,