使用MediaCodec和Camera2 API录制视频 [英] Recording video using MediaCodec with Camera2 API

查看:213
本文介绍了使用MediaCodec和Camera2 API录制视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用MediaCodec在onImageAvailable回调中记录来自ImageReader的原始帧,但是无法编写有效的代码.大多数示例都使用Camera 1 API或MediaRecorder.我的目的是捕获处理单个帧并从中创建一个mp4

I am trying to use MediaCodec to record raw frames from ImageReader in onImageAvailable callback but unable to write a working code. Most of the examples are using Camera 1 API or MediaRecorder. My aim is to capture individual frames process it and create an mp4 out of it

原始YUV帧

        @Override
        public void onImageAvailable(ImageReader reader) {
            Image i = reader.acquireLatestImage();
            processImage(i);
            i.close();
            Log.d("hehe", "onImageAvailable");
        }
    };

MediaCodec

MediaCodec

MediaCodec codec = MediaCodec.createByCodecName(name);
 MediaFormat mOutputFormat; // member variable
 codec.setCallback(new MediaCodec.Callback() {
   @Override
   void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {
     ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
     // fill inputBuffer with valid data
     …
     codec.queueInputBuffer(inputBufferId, …);
   }

   @Override
   void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {
     ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
     MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
     // bufferFormat is equivalent to mOutputFormat
     // outputBuffer is ready to be processed or rendered.
     …
     codec.releaseOutputBuffer(outputBufferId, …);
   }

   @Override
   void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {
     // Subsequent data will conform to new format.
     // Can ignore if using getOutputFormat(outputBufferId)
     mOutputFormat = format; // option B
   }

   @Override
   void onError(…) {
     …
   }
 });
 codec.configure(format, …);
 mOutputFormat = codec.getOutputFormat(); // option B
 codec.start();
 // wait for processing to complete
 codec.stop();
 codec.release();

我无法关联 https://developer.android.com上给出的代码/reference/android/media/MediaCodec .请帮助

推荐答案

您必须创建一个

You have to create a Queue, push your image's buffer created from Image planes into the Queue and process it in the void onInputBufferAvailable(MediaCodec mc, int inputBufferId)

1)创建一个用于包装缓冲区数据的类:

class MyData{
    byte[] buffer;
    long presentationTimeUs;
    // to tell your encoder that is a EOS, otherwise you can not know when to stop
    boolean isEOS; 
    public MyData(byte[] buffer,long presentationTimeUs, boolean isEOS){
        this.buffer = new byte[buffer.length];
        System.arraycopy(buffer, 0, this.buffer, 0, buffer.length);
        this.presentationTimeUs = presentationTimeUs;
        this.isEOS = isEOS;
    }

    public byte[] getBuffer() {
        return buffer;
    }

    public void setBuffer(byte[] buffer) {
        this.buffer = buffer;
    }

    public long getPresentationTimeUs() {
        return presentationTimeUs;
    }

    public void setPresentationTimeUs(long presentationTimeUs) {
        this.presentationTimeUs = presentationTimeUs;
    }

    public boolean isEOS() {
        return isEOS;
    }

    public void setEOS(boolean EOS) {
        isEOS = EOS;
    }

}


2)创建队列:

Queue<MyData> mQueue = new LinkedList<MyData>();


3)使用本机代码将图像平面转换为字节数组(byte []):

  • 向Gradle文件添加本机支持:

android{

compileSdkVersion 27

defaultConfig {
    ...

    externalNativeBuild {
        cmake {
            arguments "-DANDROID_STL=stlport_static"
            cppFlags "-std=c++11"
        }
    }
}

externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}
...
}

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆