Video Recorder using MediaCodec in Xamarin.Android Produces Tiled Video Output

Gurucharan Vijayakumar 0 Reputation points
2024-07-17T08:57:06.95+00:00

I am working on a video recording feature in a Xamarin.Android app using MediaCodec for encoding. My goal is to record video and save it in H.264 format. However, the output video appears tiled, as shown in the image below.

tiled_output

Here is my code:

using Android.Media;
using Android.Util;
using Java.IO;
using Java.Nio;
using System;
using System.IO;
using static Android.Media.MediaCodec;
namespace Record.Droid
{
    public class VideoRecorder
    {
        private const string TAG = "VideoRecorder";
        private const string MIMETYPE = "video/avc";
        private const int WAITTIME = 10000; // Adjust as needed
        private MediaCodec codec;
        private DataOutputStream dos;
        public bool SetupEncoder(int width, int height, string outputPath)
        {
            try
            {
                try
                {
                    FileStream fileStream = new FileStream(outputPath, FileMode.Create);
                    dos = new DataOutputStream(fileStream);
                }
                catch (System.IO.IOException e)
                {
                    Log.Error(TAG, "Failed to open output file: " + e.Message);
                    return false;
                }
                MediaFormat mediaFormat = MediaFormat.CreateVideoFormat(MIMETYPE, width, height);
                mediaFormat.SetInteger(MediaFormat.KeyBitRate, 700000);
                mediaFormat.SetInteger(MediaFormat.KeyFrameRate, 30);
                mediaFormat.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecCapabilities.Formatyuv420planar);
                mediaFormat.SetInteger(MediaFormat.KeyIFrameInterval, 5);
                codec = MediaCodec.CreateEncoderByType(MIMETYPE);
                codec.Configure(mediaFormat, null, null, MediaCodecConfigFlags.Encode);
                codec.Start();
                return true;
            }
            catch (System.IO.IOException e)
            {
                Log.Error(TAG, "Failed to set up encoder: " + e.Message);
                ReleaseEncoder();
                return false;
            }
        }
        public void EncodeFrame(byte[] data, long presentationTimeUs)
        {
            try
            {
                ByteBuffer[] inputBuffers = codec.GetInputBuffers();
                ByteBuffer[] outputBuffers = codec.GetOutputBuffers();
                bool sawInputEOS = false;
                int inputBufferIndex = -1, outputBufferIndex = -1;
                BufferInfo info = new BufferInfo();
                inputBufferIndex = codec.DequeueInputBuffer(WAITTIME);
                if (inputBufferIndex >= 0)
                {
                    ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
                    inputBuffer.Clear();
                    inputBuffer.Put(data);
                    codec.QueueInputBuffer(inputBufferIndex, 0, data.Length, presentationTimeUs, 0);
                }
                outputBufferIndex = codec.DequeueOutputBuffer(info, WAITTIME);
                if (outputBufferIndex >= 0)
                {
                    ByteBuffer outputBuffer = codec.GetOutputBuffer(outputBufferIndex).Duplicate();
                    outputBuffer.Position(info.Offset);
                    outputBuffer.Limit(info.Offset + info.Size);
                    byte[] array = new byte[info.Size];
                    outputBuffer.Get(array);
                    dos.Write(array);
                    codec.ReleaseOutputBuffer(outputBufferIndex, false);
                    if ((info.Flags & MediaCodecBufferFlags.EndOfStream) != 0)
                    {
                        ReleaseEncoder();
                    }
                }
            }
            catch (System.IO.IOException e)
            {
                Log.Error(TAG, "Error encoding frame: " + e.Message);
            }
        }
        public void ReleaseEncoder()
        {
            try
            {
                if (dos != null)
                {
                    dos.Flush();
                    dos.Close();
                }
            }
            catch (System.IO.IOException e)
            {
                Log.Error(TAG, "Failed to release encoder: " + e.Message);
            }
            if (codec != null)
            {
                codec.Stop();
                codec.Release();
                codec = null;
            }
        }
    }
}
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,349 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.