2

I am using a SurfaceView which shows the stream of the drone on my smartphone and what I want is to record the stream of the drone, but it's not that easy. So I think I could use MediaRecorder for this. For this problem I have read many posts, but they didn't help me out.

In the OnCreate I am creating the SurfaceView:

        mPreview = FindViewById<SurfaceView>(Resource.Id.surfaceView1);
        holder = mPreview.Holder;
        holder.AddCallback(this);
        holder.SetFormat(Format.Rgba8888);

In the SurfaceCreated override I added the SetPreviewDisplay:

        mRecorder = new Android.Media.MediaRecorder();
        mRecorder.SetPreviewDisplay(mPreview.Holder.Surface);

So, when I click on the record button I start the following method in a new thread, otherwise the SurfaceView will be stuck:

    private void StartRecord()
    {
        var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
        string path = System.IO.Path.Combine(sdCardPath, "test.mp4");

        file = new File(path);

        mRecorder.SetVideoSource(Android.Media.VideoSource.Surface);
        mRecorder.SetOutputFormat(Android.Media.OutputFormat.Mpeg4);
        mRecorder.SetVideoEncoder(Android.Media.VideoEncoder.H264);
        mRecorder.SetVideoEncodingBitRate(512 * 1000);
        mRecorder.SetVideoFrameRate(30);
        mRecorder.SetOutputFile(file.AbsolutePath);
        mRecorder.SetVideoSize(mPreview.Width, mPreview.Height);

        mRecorder.Prepare();
        mRecorder.Start();
    }

There are no errors until the mRecorder.Stop() will be called:

    private void StopRecord()
    {
        if(mRecorder != null)
        {
            try
            {
                mRecorder.Stop();
            }
            catch (Java.Lang.RuntimeException e)
            {
                // Here he always comes
                file.Delete();
                System.Console.WriteLine(e);
            }
            finally
            {
                mRecorder.Release();
                mRecorder = null;
            }
        }
    }

When I check into the mRecorder variable, it's saying at the surface object: failed to get surface. That's strange because when I check the mRecorder variable after the mRecorder started, it just has a surface object.

What am I doing wrong?

Jamie
  • 363
  • 7
  • 19
  • FWIW, a `Surface` is the producer endpoint of a producer-consumer pair. For a SurfaceView, you write to the Surface, and they are displayed by the system graphics compositor (SurfaceFlinger). Saying "record a SurfaceView" doesn't make any sense, unless you're talking about a virtual display. (I'm not familiar with Xamarin, so I can't offer anything more specific.) – fadden May 21 '16 at 23:53
  • @fadden, that's right, I meant record the stream of the drone which is viewable on my SurfaceView on my smartphone. It's already creating a file on my smartphone named `test.mp4`, but it will be deleted, because I've got a `RuntimeException`. I just don't know why `mRecorder.Stop()` is crashing... – Jamie May 22 '16 at 00:04
  • @fadden, I see you have also a lot of experience with encoding and decoding of videos. What I am trying right now is to convert the bitmaps to a .mp4 file. I need the MediaCodec which converts it firstly to a raw .h264 file. After that I need to use the MediaMuxer which provides a way to convert it to a mp4 (http://stackoverflow.com/questions/17096726/how-to-encode-bitmaps-into-a-video-using-mediacodec). My question is: where can I set the output path from the .h264 file? Because I need to put it somewhere on the phone, right? – Jamie May 24 '16 at 13:05
  • The buffers of encoded video from MediaCodec are fed into MediaMuxer. You provide a filename to MediaMuxer. There's no H.264 file. You can find various examples on bigflake (http://bigflake.com/mediacodec/) and in Grafika (https://github.com/google/grafika). Exceptions and error codes from MediaCodec tend to be less than useful, but sometimes the error messages from logcat are informative. – fadden May 24 '16 at 15:43

0 Answers0