IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android yuv编码为h264 -> 正文阅读

[移动开发]Android yuv编码为h264

视频基础知识

音频编码和视频编码用的api是一样的,不一样的地方是对编码器的设置

public void init(Context context, int width,
                     int height,
                     String srcPath, String dstPath,
                     IHanlderCallback callback) {
        mWidth = width;
        mHeight = height;
        mSrcFilePath = srcPath;
        mDstFilePath = dstPath;
        mExecutorService = Executors.newCachedThreadPool();
        mCallback = callback;
        mBufferSize =mWidth * mHeight * 3 / 2;
        Log.e("yuanBuffer", "buffesize=" + mBufferSize + " nbsample=" + mBufferSize / 4);
        try {
            mEncorder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);

        } catch (Exception e) {
            e.printStackTrace();
        }
        MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC,
                mWidth,
                mHeight);
        format.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileMain);
        format.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel31);
        format.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * 1000);
        format.setInteger(MediaFormat.KEY_FRAME_RATE, 25);//帧率,一般在15至30之内,太小容易造成视频卡顿。
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);  //250帧一个关键帧
        format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, 3);
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);//色彩格式,具体查看相关API,不同设备支持的色彩格式不尽相同
        mEncorder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    }

这里的配置会根据

https://blog.csdn.net/qq_15255121/article/details/115552857

这篇文章进行配置

下面是完整的代码

package com.yuanxuzhen.androidmedia.encode;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Build;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.yuanxuzhen.androidmedia.IHanlderCallback;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class YuvEncoder {
    private int mWidth;
    private int mHeight;
    private String mDstFilePath = null;
    private String mSrcFilePath = null;
    MediaCodec mEncorder;
    ExecutorService mExecutorService;
    private int mBufferSize;
    private IHanlderCallback mCallback;
    private boolean isEncodeing = false;


    public void init(Context context, int width,
                     int height,
                     String srcPath, String dstPath,
                     IHanlderCallback callback) {
        mWidth = width;
        mHeight = height;
        mSrcFilePath = srcPath;
        mDstFilePath = dstPath;
        mExecutorService = Executors.newCachedThreadPool();
        mCallback = callback;
        mBufferSize =mWidth * mHeight * 3 / 2;
        Log.e("yuanBuffer", "buffesize=" + mBufferSize + " nbsample=" + mBufferSize / 4);
        try {
            mEncorder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);

        } catch (Exception e) {
            e.printStackTrace();
        }
        MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC,
                mWidth,
                mHeight);
        format.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileMain);
        format.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel31);
        format.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * 1000);
        format.setInteger(MediaFormat.KEY_FRAME_RATE, 25);//帧率,一般在15至30之内,太小容易造成视频卡顿。
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);  //250帧一个关键帧
        format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, 3);
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);//色彩格式,具体查看相关API,不同设备支持的色彩格式不尽相同
        mEncorder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    }
    public void startEncording() {
        mExecutorService.execute(new Runnable() {
            @Override
            public void run() {
                startEncordingV1();
            }
        });
    }

    /**
     * 开始编码
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void startEncordingV1() {
        if (mEncorder == null) {
            isEncodeing = false;
            if (mCallback != null) {
                mCallback.onFail();
            }
            return;
        }
        isEncodeing = true;
        mEncorder.start();
        try {
            FileInputStream inputStream = new FileInputStream(mSrcFilePath);
            FileOutputStream mFileStream = new FileOutputStream(mDstFilePath);
            MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
            while (true) {
                long a = System.currentTimeMillis();
                // 从队列中取出录音的一帧音频数据
                byte[] byteArray = new byte[mBufferSize];
                int readSize = inputStream.read(byteArray);
                if (readSize <= 0) {
                    break;
                }
                ByteBuffer buf = ByteBuffer.wrap(byteArray);
                // 取出InputBuffer,填充音频数据,然后输送到编码器进行编码
                int inputBufferIndex = mEncorder.dequeueInputBuffer(0);
                if (inputBufferIndex >= 0) {
                    ByteBuffer inputBuffer = mEncorder.getInputBuffer(inputBufferIndex);
                    inputBuffer.clear();
                    inputBuffer.put(buf);
                    mEncorder.queueInputBuffer(inputBufferIndex, 0, readSize, System.nanoTime(), 0);
                }

                // 取出编码好的一帧音频数据,然后给这一帧添加ADTS头
                int outputBufferIndex = mEncorder.dequeueOutputBuffer(mBufferInfo, 0);
                while (outputBufferIndex >= 0) {
                    ByteBuffer outputBuffer = mEncorder.getOutputBuffer(outputBufferIndex);
                    int outBufferSize = outputBuffer.limit();
                    byte[] aacBytes = new byte[outBufferSize];
                    outputBuffer.get(aacBytes, 0, outputBuffer.limit());
                    mFileStream.write(aacBytes);
                    mEncorder.releaseOutputBuffer(outputBufferIndex, false);
                    outputBufferIndex = mEncorder.dequeueOutputBuffer(mBufferInfo, 0);
                }

                long b = System.currentTimeMillis() - a;
                Log.i("AudioEncode", "编码耗时-毫秒==" + b);
            }
            if (mFileStream != null) {
                try {
                    mFileStream.flush();
                    mFileStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (inputStream != null) {
                try {
                    mFileStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (mEncorder != null) {
                mEncorder.stop();
            }
            if (mCallback != null) {
                mCallback.onSuccess();
            }
        } catch (FileNotFoundException e) {
            if (mCallback != null) {
                mCallback.onFail();
            }
            e.printStackTrace();
        } catch (IOException e) {
            if (mCallback != null) {
                mCallback.onFail();
            }
            e.printStackTrace();
        } finally {
            isEncodeing = false;
        }
    }



    public void release() {
        if (mEncorder == null) {
            return;
        }
        mEncorder.release();
        mEncorder = null;
        isEncodeing = false;
    }

    public boolean isEncodeing() {
        return isEncodeing;
    }
}

gitee地址:

https://gitee.com/creat151/android-media.git

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:43:16  更:2021-08-15 15:44:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 11:03:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码