Android Camera Video is blank with white lines

Viewed 213

I have implemented Camera2 API of Android using MediaRecorder to record video from the Camera. The Camera Previews are working fine and the video file is also created successfully without any errors. However, the output video is blank and has white flickering lines.

This is the output video I get.

Video output from MediaRecorder

The code for preparing MediaRecorder

val surface = MediaCodec.createPersistentInputSurface()
surface.release()

val outputFile = createFile(applicationContext,"mp4")
val mMediaRecorder = MediaRecorder()
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC)
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mMediaRecorder.setOutputFile(outputFile.absolutePath)
mMediaRecorder.setVideoEncodingBitRate(10_000_000)
mMediaRecorder.setVideoFrameRate(30)
mMediaRecorder.setVideoSize(matchedResolution.width, matchedResolution.height)
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
mMediaRecorder.setInputSurface(surface)

Creating the session.

val previewSurface = surfaceView2.holder.surface

val captureCallbackVideo =
    object : CameraCaptureSession.StateCallback() {
        override fun onConfigureFailed(session: CameraCaptureSession) {}
        override fun onConfigured(session: CameraCaptureSession) {
            // session configured
            val previewRequestBuilder =
                cameraDevice.createCaptureRequest(TEMPLATE_RECORD)
                    .apply {
                        addTarget(previewSurface)
                        addTarget(surface)
                        set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(30,30))
                    }
            session.setRepeatingRequest(
                previewRequestBuilder.build(),
                null,
                Handler { true }
            )
        }
    }

cameraDevice.createCaptureSession(mutableListOf(previewSurface, surface), captureCallbackVideo, Handler { true })

For starting the recording

mMediaRecorder.prepare()
mMediaRecorder.start()

For stopping

mMediaRecorder.stop()
mMediaRecorder.release()
2 Answers

I had figured it out. The problem was with the input surface of MediaRecorder. Apparently, the way of Google's code of camera2 at GitHub is not right in setting up the Surface for MediaRecorder correctly.

The solution is that we should not provide Surface as input to the MediaRecorder, but prepare the MediaRecorder without a Surface and then use its internal Surface for our CaptureRequest

mMediaRecorder = MediaRecorder()
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mMediaRecorder.setVideoEncodingBitRate(10_000_000)
//Uncomment on physical device, comment on emulator
//mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mMediaRecorder.setVideoSize(matchedResolution.width, matchedResolution.height)
mMediaRecorder.setVideoFrameRate(30)
mMediaRecorder.setOutputFile(outputFile.absolutePath)
try {
    mMediaRecorder.prepare()
} catch (e: java.lang.Exception) {
    e.printStackTrace()
    return
}

For creating session

val previewSurface = surfaceView2.holder.surface

val captureCallbackVideo =
    object : CameraCaptureSession.StateCallback() {
        override fun onConfigureFailed(session: CameraCaptureSession) {}
        override fun onConfigured(session: CameraCaptureSession) {
            // session configured
            val previewRequestBuilder =
                cameraDevice.createCaptureRequest(TEMPLATE_RECORD)
                    .apply {
                        addTarget(previewSurface)
                        addTarget(mMediaRecorder.surface)
                        set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(30,30))
                    }
            session.setRepeatingRequest(
                previewRequestBuilder.build(),
                null,
                Handler { true }
            )
        }
    }

cameraDevice.createCaptureSession(mutableListOf(previewSurface, mMediaRecorder.surface), captureCallbackVideo, Handler { true })

For starting recording:

mMediaRecorder.start()

For stopping a recording:

mMediaRecorder.stop()
mMediaRecorder.release()

You can used below code I think might be issue in setVideoEncodingBitRate

recorder.setVideoSize(640, 480);
recorder.setVideoFrameRate(16); //might be auto-determined due to lighting
recorder.setVideoEncodingBitRate(3000000);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
Related