视频编解码,编的是什么码?解的又是什么码?有没有想过?现在主流的就是H264码流,Android 采集摄像头原始帧数据
这篇博客讲解的是如何从摄像头从提取YUV画面色值,然后由MediaCodec进行编码压缩,最后生成的就是H264码流,我们先了解下H264码流格式。

可以看到一个个NALU单元组成了H264码流,NALU单元又包含头数据部分和帧数据部分。
每一个头开始都包含0x 00000001或者0x000001.
我选取了上面讲的采集摄像头画面进行编码后的H264文件,打开其字节文件,码流格式数据如下

可以看到手机编码后的码流每个NAL开头起始码为0x00000001
所以我要做的工作就是提取出每一个NAL单元,然后送给MediaCodec进行解码。
提取出NAL 单元的代码函数如下

     private byte[] getNALU() {try {int curpos = 0;//一般NAL不超过100000字节byte[] bb = new byte[100000];//先读取4个字节rf.read(bb, 0, 4);//判断是否是0x00000001开头if (findStartCode4(bb, 0)) {curpos = 4;} else {rf.seek(0);rf.read(bb, 0, 3);//判断是否是0x000001开头if (findStartCode3(bb, 0)) {curpos = 3;}}//标志是否找到NAL单元开头boolean findNALStartCode = false;//下一个NAL单元的开始位置int nextNalStartPos = 0;//找到适合标记开头的长度int reWind = 0;while (!findNALStartCode) {int hex = rf.read();if (curpos >= bb.length) {break;}bb[curpos++] = (byte) hex;if (hex == -1) {nextNalStartPos = curpos;}if (findStartCode4(bb, curpos - 4)) {findNALStartCode = true;reWind = 4;nextNalStartPos = curpos - reWind;} else if (findStartCode3(bb, curpos - 3)) {findNALStartCode = true;reWind = 3;nextNalStartPos = curpos - reWind;}}byte[] nal = new byte[nextNalStartPos];System.arraycopy(bb, 0, nal, 0, nextNalStartPos);long pos = rf.getFilePointer();long setPos = pos - reWind;//退回rewind长度字节rf.seek(setPos);return nal;} catch (IOException e) {e.printStackTrace();}return null;}//find match "00 00 00 01"private boolean findStartCode4(byte[] bb, int offSet) {if (offSet < 0) {return false;}if (bb[offSet] == 0 && bb[offSet + 1] == 0 && bb[offSet + 2] == 0 && bb[offSet + 3] == 1) {return true;}return false;}//find match "00 00 01"private boolean findStartCode3(byte[] bb, int offSet) {if (offSet <= 0) {return false;}if (bb[offSet] == 0 && bb[offSet + 1] == 0 && bb[offSet + 2] == 1) {return true;}return false;}

封装其数据,读取每一NAL单元

 /*** 读取每一帧数据* @param buffer* @return*/public int readSampleData(ByteBuffer buffer) {byte[] nal = getNALU();buffer.put(nal);return nal.length;}

MediaCodec开启解码线程,和 Android MediaCodec,MediaExtractor解码播放MP4文件中解码一样,将NAL单元数据送给解码器即可。

  /***  解析播放H264码流*/private class DecoderH264Thread extends Thread {long pts = 0;@Overridepublic void run() {super.run();while (!isDecodeFinish) {int inputIndex = mediaCodec.dequeueInputBuffer(-1);if (inputIndex >= 0) {ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inputIndex);int sampSize = DecodeH264File.getInstance().readSampleData(byteBuffer);long time = computePresentationTime();if (sampSize > 0 && time > 0) {mediaCodec.queueInputBuffer(inputIndex, 0, sampSize, time, 0);try {sleep(30);} catch (InterruptedException e) {e.printStackTrace();}}}BufferInfo bufferInfo = new BufferInfo();int outIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);if (outIndex >= 0) {mediaCodec.releaseOutputBuffer(outIndex, true);}}}}

好了,到这里结束了,有什么不明白的,欢迎留言~~
GitHub
https://github.com/zxd1991/AndroidMedia

Android MediaCodec 解码H264码流播放相关推荐

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

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

  2. Ubuntu VLC 播放器播放本机h264码流

    1:打开VLC播放器. 2:选择媒体菜单,在下拉菜单栏中,选择打开网络串流(快捷键Ctrl + N),输入:1:打开VLC播放器. 3:点击播放按钮,使得VLC播放器处于等待码流状态. 4:使用udp ...

  3. 【H.264/AVC视频编解码技术】第二章【H264码流分析】

    H264码流分层 NAL层,视频数据网络抽象层,作用是控制二进制数据的传输,主要用于网络传输.  VCL层,视频数据编码层. VCL结构关系 NALU NAL Header (1B)+ RBSP H2 ...

  4. H264码流打包分析(精华)

    H264码流打包分析 SODB 数据比特串-->最原始的编码数据 RBSP 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit" ...

  5. RTP协议全解(H264码流和PS流)

    1 视频编码的原理 1.1 一个图像或者一个视频序列进行压缩,产生码流. 对图像的处理即是:帧内预测编码 其预测值P,是由已编码的图像做参考,经运动补偿得到的.预测图像P和当前帧Fn相减,得到两图像的 ...

  6. 原始 H.264 码流播放

    我们平时遇到的视频文件各式各样,五花八门.通常它们会根据格式的不同,而有着不同的扩展名,比如 avi,rmvb,mkv,mp4 等等等.这些格式代表的都是 封装格式. 这些文件通常产生的过程是这样的: ...

  7. 将H264码流打包成RTP包

    分类: 流媒体(25) 版权声明:本文为博主原创文章,未经博主允许不得转载. H264码流打包成RTP包的代码如下: [cpp] view plaincopy #include <stdio.h ...

  8. H264码流打包成RTP包

    http://blog.csdn.net/tanningzhong/article/details/53281986 H264码流打包成RTP包的代码如下: [cpp] view plaincopy ...

  9. 应用角度理解H264码流

    应用角度理解H264码流 前言 1.NAL 2.SPS.PPS 2.1 SPS 2.2 PPS 3.Slice&MB 3.1.Slice 3.2.MB 4.RTP负载 5.AUD 6.文献 前 ...

最新文章

  1. XamarinSQLite教程添加测试数据
  2. 前端学python有什么用-对于一个小白,前端和python哪个更适合?
  3. 时序预测:从两篇高影响力的论文谈起
  4. Java Jar包的压缩、解压使用指南
  5. 使用@JsonIdentityInfo的Spring自定义序列化器
  6. 屏幕取色工具ColorCat
  7. linux freemind字体,解决 ubuntu 18.04 lts freemind 或freeplane 乱码口口的问题
  8. tkinter GUI 客户端页面编程 登录注册案例开发
  9. WPS Excel表格安装宏插件
  10. 从百草园到三味书屋 鲁迅
  11. lisp 圆柱螺旋线_Visual LISP开发三维圆柱螺旋线程序
  12. 变量、函数、类等编程时常用英文命名和缩写
  13. 网上作业c语言第三章,c语言 第3章 作业 和部分答案.doc
  14. 评论式软文怎么写?学会这三招,让你轻松营造出客观的感觉
  15. M1001 4G/5G应急指挥箱
  16. Phonetic symbol 双元音 -- əʊ
  17. 退烧方法及退烧药的选择
  18. GEE 提取长系列NDVI像元值
  19. 精益生产制造的三要素,了解一下
  20. Packet_Tracer

热门文章

  1. 廖雪峰介绍Node.js
  2. 开启灯光就是近光吗_科目三考前必看!夜间灯光语音模拟+超全项目操作
  3. 成为百万富翁的25种方法
  4. 马斯克加入推特董事会引发员工担忧:可能改变审查规则
  5. iPhone 14 Pro渲染图曝光 网友:冲这个外观就可以买了
  6. 神州12号航天员确定:住110米“大平层” 有120种美食
  7. 金山办公:因个人原因 葛珂辞去公司董事长职务
  8. 天齐锂业高管减持后定增160亿 收到深交所关注函
  9. 头条搜索“美丽中国”,你为哪处风景胜地打过Call?
  10. 华为Mate 40系列或采用双处理器方案:国行版仍为麒麟芯