原因:由于涉及到yuv的编码故使用android自带的MediaCodec模块进行硬件编码

概况:通过获取编码设备信息创建编码对象,然后设置编码参数,通过输入输出缓冲区进行数据的传递和读取。

流程如下:

首先获取当前设备支持的编解码设备信息:首先获取codc个数,然后判断是否是编码codec.

 m_codeccount = MediaCodecList.getCodecCount();//获取codec个数for(int i=0;i<m_codeccount;i++)
{MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);//获取codecinfoif(info.isEncoder())//判断当前codec是否支持编码{String[] str = info.getSupportedTypes();//获取支持的类型}
}

通过上面获取的Codec类型有如下:

Type==audio/3gpp       Name==OMX.google.amrnb.encoder
Type==audio/amr-wb     Name==OMX.google.amrwb.encoder
Type==video/hevc       Name==OMX.qcom.video.encoder.hevc
Type==video/mp4v-es    Name==OMX.qcom.video.encoder.mpeg4
Type==video/avc        Name==OMX.qcom.video.encoder.avc

根据获取的Codec类型和名字创建编码设备如下:可以看出有两种方式进行创建Codec.当前设备小米5S,如果使用ByName则会发现最后关键帧间隔设施不起作用,且最终输出的帧没有B帧.而使用ByType则可以使关键帧间隔生效和生成B帧.具体内部原因希望有了解的同学解惑。

m_codec = MediaCodec.createByCodecName(m_strName);m_codec = MediaCodec.createEncoderByType(m_strType);

创建完成Codec后就是设置编码参数,此时涉及到有些参数没有设置最终Configure失败的问题:

vformat.setInteger(MediaFormat.KEY_FRAME_RATE,m_Fps);//帧率
vformat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,m_Gop);//关键帧间隔单位为秒
vformat.setInteger(MediaFormat.KEY_WIDTH,m_W);//宽
vformat.setInteger(MediaFormat.KEY_HEIGHT,m_H);//高
vformat.setInteger(MediaFormat.KEY_BITRATE_MODE,m_Mode);//编码模式 目前使用CBR
vformat.setInteger(MediaFormat.KEY_BIT_RATE,m_BitRate * 1000);//单位为bps
vformat.setInteger(MediaFormat.KEY_COLOR_FORMAT,m_Color);//样本类型,目前只有420p和420sp两种.
vformat.setInteger(MediaFormat.KEY_PROFILE,m_Profile);//目前使用main
vformat.setInteger(MediaFormat.KEY_LEVEL,m_Level);//目前使用2.0m_codec.configure(vformat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);//配置编码信息

配置完成后需要使流程启动:通过介绍可以看出该方法必须在configure之后调用

m_codec.start();//成功配置完成后调用开始

获取输入和输出队列缓存区,用于输入和输出数据:通过介绍可以看出必须在start之后调用。可以简单理解为start内部完成了缓冲区的初始化和连接。

 m_InputBuffer = m_codec.getInputBuffers();//获取输入缓冲区 需要start之后调用.m_OutputBuffer = m_codec.getOutputBuffers();//获取输出缓冲区

接下来进行输入数据进行编码,此时涉及到两种方式一种为同步,一种为异步,异步的话需要实现MeidaCodec.Callback接口,通过内部提供的接口函数实现数据的传递和读取,而同步则只需进行同步调用即可如下:细节为时间戳设置,如果时间戳没有设置那么就会导致取数据失败的问题。

int iIndex = m_codec.dequeueInputBuffer(m_TimeDelay);//获取一个可用的输入缓冲区,当前延时时间手动设置,-1:表示INFINITE
if (iIndex >= 0) {ByteBuffer input = m_InputBuffer[iIndex];//获取输入队列中一个空闲的成员input.clear();input.put(data, 0, iSize);//填充数据long presentationtimeus =1000 * (iCount * 20);//用于设置时间戳 microsecondsm_codec.queueInputBuffer(iIndex, 0, iSize, presentationtimeus,0);//填充一个ByteBuffer到输入队列,最后一个参数}else{Log.d(TAG,"dequeueInputBuffer Failed.");return false;}

数据读取如下:细节为缓存的回收,否则会导致传入数据时获取缓存阻塞.

 //同步获取编码后数据
int iIndex2 = m_codec.dequeueOutputBuffer(m_pBufferInfo, m_TimeDelay);
if (iIndex2 >= 0)
{ByteBuffer output = m_OutputBuffer[iIndex2];output.position(m_pBufferInfo.offset);//设置缓冲区起始位置output.limit(m_pBufferInfo.offset + m_pBufferInfo.size);//设置缓冲区有效区间output.get(outData,0,m_pBufferInfo.size);//将有效数据写入数组iLen[0] = m_pBufferInfo.size;Log.d(TAG,"output offset="+m_pBufferInfo.offset+"Size"+m_pBufferInfo.size);m_codec.releaseOutputBuffer(iIndex2,false);//回收缓存
}

关键帧强制输出代码:设置一次后将会一直输出I帧,如何取消?

if(iCount % 10 == 0)设置一次将会一直输出I帧
{     Bundle params = new Bundle();params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);m_codec.setParameters(params);//app level 19  //强制I帧Log.d(TAG,"setParameters");
}

问题:利用MediaCodec如何设置B帧输出?强制关键帧输出?

总结:以上就是利用MeidaCodec实现的编码和遇到的问题,暂时没法解决,后续解决,如果有道友知道希望能够告知。

MediaCodec编码相关推荐

  1. MediaCodec 编码H264 编码一帧后dequeueOutputBuffer为-1的问题

    在用android MediaCodec编码h264的时候,会遇到,dequeueOutputBuffer在成功获取到config帧(sps pps)及第一个I帧后,dequeueOutputBuff ...

  2. (二)音视频:MediaCodec编码桌面信息 完整Demo 进一步理解H264

    (一)音视频:解码H264文件流程 渲染和拿到解码后源数据YUV 完整Demo] (二)音视频:MediaCodec编码桌面信息 完整Demo 进一步理解H264 (三)音视频:解析H264 SPS ...

  3. 研究Android音视频-3-在Android设备上采集音视频并使用MediaCodec编码为H.264

    原文 : https://juejin.cn/post/69601302052266311754 本文解决的问题 本文主要使用 MediaCodec 硬编码器对 Android 设备采集的音视频编码 ...

  4. MediaCodec 编码时间戳问题

    在MediaCodec 的编码时候,需要调用queueInputBuffer( int index, int offset, int size, long presentationTimeUs, in ...

  5. YUV通过MediaCodec编码H264

    Camear_MainActivity.java,主界面类 import android.app.Activity; import android.graphics.ImageFormat; impo ...

  6. 从原理到实践:使用Mediacodec编码H265并实现解码H265码流

    H265 H265,也称为HEVC(High Efficiency Video Coding),是一种高效视频编码格式.它是H264(AVC)的后继者,也是ITU-T和ISO/IEC联合开发的标准.相 ...

  7. Android MediaCodec 编码使用介绍

    想要了解安卓的编解码,首先要从api的使用开始,下面介绍一下使用MediaCodec的使用流程. Java层API使用介绍 编码篇: 1.获取编解码器信息 首先我们需要获取Codec的信息,通过Med ...

  8. Android用MediaCodec将相机预览帧编码成MP4视频

    文章目录 知识预备 实现思路 获取图像数据帧 编码视频 初始化编码器 编码转换 编码视频 问题记录 最近项目中,有一个在扫码同时录视频的需求.扫码框架是通过摄像头 onPreviewFrame方法获取 ...

  9. EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式

    EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式 最近在研究EasyDarwin的Push库EasyPusher,EasyPusher可以推送H264视频到 ...

最新文章

  1. Cookie和Session-学习笔记03【Session快速入门、Session细节】
  2. Teams Bot开发系列:Bot验证
  3. 我从参加#PerfMatters会议中学到的东西
  4. oracle13001,安装oracle11g 遇到INS-13001环境不知足最低要求 解决方法
  5. 跨平台的报表生成器控件Stimulsoft Reports.Fx for Flex
  6. python 并行_python并行处理任务时 该用多进程?还是该用多线程?
  7. AndroidTelephony学习大纲
  8. 00 后的 AI 开发者进阶之道:从入门到鏖战 MIT 编程大赛 | 人物志
  9. 浅谈输入阻抗、输出阻抗和阻抗匹配
  10. python 卡方检验 特征选择_特征选择:卡方检验
  11. 论文阅读:Neural Motifs: Scene Graph Parsing with Global Context
  12. 解决The following packages have unmet dependencies问题!!!
  13. java实现生成水印照片
  14. 局域网SDN技术硬核内幕 二 云网CP的日常恩爱——硬件VXLAN转发平面
  15. docker容器 如何精简镜像减小体积
  16. python名片管理器实验报告_名片管理系统——实验报告.doc
  17. if else python格式_python 基本的if_else使用
  18. [neovim/nvim] LSP 与代码补全配置笔记
  19. 超级高铁原型机现身迪拜,时速高达1200公里!
  20. 超级轻量级: KV存储引擎实现

热门文章

  1. sql 中 FROM_UNIXTIME 使用方法
  2. java xms xmx 设置_java 虚拟机设置 Xms Xmx PermSize MaxPermSize
  3. java Xms Xmx
  4. 网络前端第六次培训笔记(js)
  5. centos下安装scrot
  6. Linux磁盘列阵分区
  7. 被遗忘的图灵:一文溯源AI研究(附下载)
  8. win10应用商店edge等无法联网 错误代码为 0x8000FFFF
  9. 随机森林RF原理总结
  10. OpenLayers基础教程——popup弹出框