Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android video recorder: failed to get surface

Hi I am trying to use the camera v2 API to record video using a Raspberry Pi 3 device that uses the Raspberry Pi camera module attached to it.

I am developing this using Android Things with Kotlin.

Here is how my video recording code looks like.

  override fun startRecording(videoCameraCallback: VideoCameraCallback) {
    val cameraIdList = cameraManager.cameraIdList
    cameraManager.openCamera(cameraIdList[0], cameraStateCalback, null)

    Log.d("JJJ", "start recording called")
}

    var cameraStateCalback = object : CameraDevice.StateCallback() {
    override fun onOpened(camera: CameraDevice?) {
        if (camera != null) {
            Log.d("JJJ", "onOpened and will now create handler and capture session")
            //create handler thread
            val thread = HandlerThread("MyHandlerThread")
            thread.start()
            val handler = Handler(thread.looper)

            //create capture session
            val mediaRecorderSurface = setMediaOutputSurface()
            val surfaces = ArrayList<Surface>()
            surfaces.add(mediaRecorderSurface)
            captureRequest =  camera.createCaptureRequest(TEMPLATE_RECORD).build()
            camera.createCaptureSession(surfaces, cameraCaptureSessionCallBack,handler)
            Log.d("JJJ", "Created thread handler and capture session")
        }
    }

    override fun onDisconnected(camera: CameraDevice?) {
        Log.d("JJJ", "on disconnected")
    }

    override fun onError(camera: CameraDevice?, error: Int) {
        Log.d("JJJ", "on error")
    }
}



 var  cameraCaptureSessionCallBack = object :  CameraCaptureSession.StateCallback(){

    override fun onConfigureFailed(session: CameraCaptureSession?) {
        Log.d("JJJ", "on configured failed")
    }

    override fun onConfigured(session: CameraCaptureSession?) {
        Log.d("JJJ", "start recording")
        mediaRecorder.start()

    }
}


    private fun setMediaOutputSurface(): Surface {
          var file = File(context.filesDir.absolutePath)
        if(file.canWrite() && file.canRead()){
            Log.d("JJJ", "File location is fine")
        }

        mediaRecorder = MediaRecorder()
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE) //changed this to surface from camera and it fixed the cant get surface error

        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
        mediaRecorder.setVideoSize(600,600)


//        mediaRecorder.setVideoEncodingBitRate(10000000)
//        mediaRecorder.setVideoEncodingBitRate(512 * 1000)
        mediaRecorder.setOutputFile(context.filesDir.absolutePath + "/"+System.currentTimeMillis() + ".mp4")
        mediaRecorder.setVideoFrameRate(30)

        mediaRecorder.prepare()
//        mediaRecorder.start()
        return mediaRecorder.surface

}

This is my strategy

  1. Get list of Camera ID's using the camera manager.
  2. Open the first camera from the list(there is only one camera attached
  3. when opened successfully, create handler thread
  4. Create mediaRecorder with all the necessary parameters(video source, framerate etc
  5. Get the surface object from the mediaRecorder(where it fails)
  6. Create capture request with the surface from the media player and the hanlder created previously
  7. on configured successfully, call mediaRecorder.start to start recording video.

The full stacktrace error i get is below:

  12-01 09:58:23.981 8776-8776/com.jr.survailancedropboxcam W/CameraDevice-JV-0: Stream configuration failed due to: endConfigure:372: Camera 0: Unsupported set of inputs/outputs provided
12-01 09:58:23.985 8776-8958/com.jr.survailancedropboxcam D/JJJ: on configured failed
12-01 09:58:23.985 8776-8776/com.jr.survailancedropboxcam E/CameraCaptureSession: Session 0: Failed to create capture session; configuration failed

Thanks in advance

like image 897
Jonathan Avatar asked Nov 30 '17 21:11

Jonathan


1 Answers

With the latest release (AndroidThings DP 6) you can use the Camera v2 APIs

https://android-developers.googleblog.com/2017/11/android-things-developer-preview-6.html

This should work: https://github.com/googlesamples/android-Camera2Basic

You need to make sure you have the flag set to true in the manifest

<activity

    ...
    android:hardwareAccelerated="true">

the Camera2Basic sample using the Camera2 API and TextureView now works on both NXP and Raspberry Pi based devices (with the hardwareAccelerated flag set to true)

like image 64
Blundell Avatar answered Nov 08 '22 05:11

Blundell