From e7b295546a0fca86b915ef47a9d96618f5a48863 Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 11 Dec 2025 10:04:18 -0800 Subject: [PATCH] fix: Add null safety checks in ChunkedRecordingManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace !! operators with proper null checks to prevent NullPointerExceptions when encodedFormat or muxerContext are null. This can happen if createNextMuxer is called before onOutputFormatChanged sets the format. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../mrousavy/camera/core/ChunkedRecorder.kt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/package/android/src/main/java/com/mrousavy/camera/core/ChunkedRecorder.kt b/package/android/src/main/java/com/mrousavy/camera/core/ChunkedRecorder.kt index 16266fb..9444216 100644 --- a/package/android/src/main/java/com/mrousavy/camera/core/ChunkedRecorder.kt +++ b/package/android/src/main/java/com/mrousavy/camera/core/ChunkedRecorder.kt @@ -105,6 +105,12 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu muxerContext?.finish() chunkIndex++ + val format = this.encodedFormat + if (format == null) { + Log.e(TAG, "Cannot create muxer: encodedFormat is null (onOutputFormatChanged not called yet)") + return + } + val newFileName = "$chunkIndex.mp4" val newOutputFile = File(this.outputDirectory, newFileName) Log.i(TAG, "Creating new muxer for file: $newFileName") @@ -114,7 +120,7 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu ) muxer.setOrientationHint(orientationHint) muxerContext = MuxerContext( - muxer, newOutputFile, chunkIndex, bufferInfo.presentationTimeUs, this.encodedFormat!!, this.callbacks + muxer, newOutputFile, chunkIndex, bufferInfo.presentationTimeUs, format, this.callbacks ) } @@ -123,7 +129,8 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu } private fun chunkLengthUs(bufferInfo: BufferInfo): Long { - return bufferInfo.presentationTimeUs - muxerContext!!.startTimeUs + val context = muxerContext ?: return 0L + return bufferInfo.presentationTimeUs - context.startTimeUs } fun start() { @@ -155,7 +162,13 @@ class ChunkedRecordingManager(private val encoder: MediaCodec, private val outpu if (muxerContext == null || (atKeyframe(bufferInfo) && chunkLengthUs(bufferInfo) >= targetDurationUs)) { this.createNextMuxer(bufferInfo) } - muxerContext!!.muxer.writeSampleData(muxerContext!!.videoTrack, encodedData, bufferInfo) + val context = muxerContext + if (context == null) { + Log.e(TAG, "Cannot write sample data: muxerContext is null") + encoder.releaseOutputBuffer(index, false) + return + } + context.muxer.writeSampleData(context.videoTrack, encodedData, bufferInfo) encoder.releaseOutputBuffer(index, false) } }