Compare commits

...

2 Commits

Author SHA1 Message Date
Dean
e7b295546a fix: Add null safety checks in ChunkedRecordingManager
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 <noreply@anthropic.com>
2025-12-11 10:04:18 -08:00
Dean
d87ed8ced2 fix: Handle null error message in promise rejection
Prevents crash when an exception with null message is caught and rejected
through the React Native bridge.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 09:48:32 -08:00
2 changed files with 17 additions and 4 deletions

View File

@@ -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)
}
}

View File

@@ -11,6 +11,6 @@ inline fun withPromise(promise: Promise, closure: () -> Any?) {
} catch (e: Throwable) {
e.printStackTrace()
val error = if (e is CameraError) e else UnknownCameraError(e)
promise.reject("${error.domain}/${error.id}", error.message, error.cause)
promise.reject("${error.domain}/${error.id}", error.message ?: "Unknown error", error.cause)
}
}