简体   繁体   English

使用 mediacodec 从位图文件创建视频

[英]Create video from bitmap files using mediacodec

I have list of Bitmap files on my sd card.我的 SD 卡上有位图文件列表。 Now, I want to create video using mediacodec.现在,我想使用 mediacodec 创建视频。 I have checked MediaCodec documents.I could not find a way to create video.我检查了MediaCodec文档。我找不到创建视频的方法。 I don't want to use FFmpeg.我不想使用 FFmpeg。 I have tried below code.我试过下面的代码。 Any help would be appreciated!!任何帮助,将不胜感激!!

protected void MergeVideo() throws IOException {
        // TODO Auto-generated method stub
        MediaCodec mMediaCodec;
        MediaFormat mMediaFormat;
        ByteBuffer[] mInputBuffers;
        mMediaCodec = MediaCodec.createEncoderByType("video/avc");
        mMediaFormat = MediaFormat.createVideoFormat("video/avc", 320, 240);
        mMediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
        mMediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
        mMediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
        mMediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
        mMediaCodec.configure(mMediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mMediaCodec.start();
        mInputBuffers = mMediaCodec.getInputBuffers();
        //for (int i = 0; i<50; i++) {
        int i=0;
            int j=String.valueOf(i).length()<1?Integer.parseInt("0"+i) : i;
           File imagesFile = new File(Environment.getExternalStorageDirectory() + "/VIDEOFRAME/","frame-"+j+".png");

         Bitmap bitmap = BitmapFactory.decodeFile(imagesFile.getAbsolutePath());
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream); // image is the bitmap
        byte[] input = byteArrayOutputStream.toByteArray();

        int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1);
        if (inputBufferIndex >= 0) {
            ByteBuffer inputBuffer = mInputBuffers[inputBufferIndex];
            inputBuffer.clear();
            inputBuffer.put(input);
            mMediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
        }

You're missing a few pieces.你少了几块。 The answer to this question has some of the information you need, but it was written for someone specifically wanting support in API 16. If you're willing to target API 18 and later, your life will be easier. 这个问题的答案包含您需要的一些信息,但它是为特别需要 API 16 支持的人编写的。如果您愿意以 API 18 及更高版本为目标,那么您的生活会更轻松。

The biggest problem with what you have is that MediaCodec input from a ByteBuffer is always in uncompressed YUV format, but you seem to be passing compressed PNG images in. You will need to convert the bitmap to YUV.您所拥有的最大问题是来自 ByteBuffer 的 MediaCodec 输入始终采用未压缩的 YUV 格式,但您似乎正在传递压缩的 PNG 图像。您需要将位图转换为 YUV。 The exact layout and best method for doing this varies between devices (some use planar, some use semi-planar), but you can find code for doing so.执行此操作的确切布局和最佳方法因设备而异(有些使用平面,有些使用半平面),但您可以找到这样做的代码。 Or just look at the way frames are generated in the buffer-to-buffer parts of EncodeDecodeTest .或者只是看看在EncodeDecodeTest的缓冲区到缓冲区部分中生成帧的方式。

Alternatively, use Surface input to the MediaCodec.或者,使用 Surface 输入到 MediaCodec。 Attach a Canvas to the input surface and draw the bitmap on it.将 Canvas 附加到输入表面并在其上绘制位图。 The EncodeAndMuxTest does essentially this, but with OpenGL ES. EncodeAndMuxTest本质上是这样做的,但使用 OpenGL ES。

One potential issue is that you're passing in 0 for the frame timestamps.一个潜在的问题是您为帧时间戳传入 0。 You should pass a real (generated) timestamp in, so that the value gets forwarded to MediaMuxer along with the encoded frame.您应该传入一个真实的(生成的)时间戳,以便该值与编码帧一起转发到 MediaMuxer。

On very recent devices (API 21+), MediaRecorder can accept Surface input.在最新的设备 (API 21+) 上,MediaRecorder 可以接受 Surface 输入。 This may be easier to work with than MediaCodec.这可能比 MediaCodec 更容易使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM