H264是一种很常见的视频编码方式。在做流媒体开发中,h264会经常遇到。由于之前对流媒体一无所知,在做项目时,绕了不少的弯。所幸,网上关于h264的资料很多,只要细细看,都能看懂。
Mediacodec相对MediaRecorder来说,比较偏底层一些,Mediacodec的API 解释说:MediaCodec类可以用于访问低级媒体编解码器。因此Mediacodec可以实现一些MediaRecorder不能实现的功能。

思路:创建SurfaceView,并且实现SurfaceHolder.Callback接口,该接口有三个抽象方法,常用的也就两个。在surfaceCreated方法中实例化相机,得到相机取得的视频数据,实例化Mediacodec并且开始编码。
surfaceDestroyed方法中,销毁相机,停止Mediacodec编码。
照相机要取得实时的数据,需要实现PreviewCallback接口,重写onPreviewFrame(byte[] data, android.hardware.Camera camera)()方法,这个方法里面的data参数,就是照相机输出的原始数据,我们编码的对象,就是它。

首先要实现下面的这两个接口,一个是SurfaceView必须要实现的接口,一个是相机输出数据的接口。

public class MainActivity extends Activity  implements SurfaceHolder.Callback,PreviewCallback

创建相机并且开启预览

    private void startcamera(Camera mCamera){if(mCamera != null){try {mCamera.setPreviewCallback(this);//mCamera.setDisplayOrientation(90);//旋转90if(parameters == null){parameters = mCamera.getParameters();}List<Camera.Size> sizes = parameters.getSupportedPictureSizes();//parameters = mCamera.getParameters();parameters.setPreviewFormat(ImageFormat.NV21);//输出的格式,最好不要修改parameters.setPreviewSize(width, height);mCamera.setParameters(parameters);mCamera.setPreviewDisplay(surfaceHolder);mCamera.startPreview();//开启预览} catch (IOException e) {e.printStackTrace();}}}

从摄像头获取数据:

   @Overridepublic void onPreviewFrame(byte[] data, android.hardware.Camera camera) {//data就是摄像头输出的数据,Mediacodec编码的对象就是data}

实例化Mediacodec并且开始编码
此方法在摄像头刚打开时就调用,保证摄像头刚开启时,编码就已经开始。

   private void initMediaCodec() {bitrate = 2 * width * height * framerate ;//码率try {mMediaCodec = MediaCodec.createEncoderByType("video/avc");MediaFormat  mediaFormat = MediaFormat.createVideoFormat("video/avc", height, width); //height和width一般都是照相机的height和width。   //描述平均位速率(以位/秒为单位)的键。 关联的值是一个整数mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);//描述视频格式的帧速率(以帧/秒为单位)的键。mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);//帧率,一般在15至30之内,太小容易造成视频卡顿。mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, 19);//色彩格式,具体查看相关API,不同设备支持的色彩格式不尽相同//关键帧间隔时间,单位是秒mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);mMediaCodec.start();//开始编码} catch (IOException e) {e.printStackTrace();}}

对onPreviewFrame(byte[] data, Camera camera)中的data进行编码:

 byte[] input = data;
byte[] yuv420sp = new byte[width*height*3/2];
NV21ToNV12(input,yuv420sp,width,height);
input = yuv420sp;if (input != null) {try {ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();//拿到输入缓冲区,用于传送数据进行编码ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();//拿到输出缓冲区,用于取到编码后的数据  int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);if (inputBufferIndex >= 0) {//当输入缓冲区有效时,就是>=0ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];inputBuffer.clear();inputBuffer.put(input);//往输入缓冲区写入数据,//                    //五个参数,第一个是输入缓冲区的索引,第二个数据是输入缓冲区起始索引,第三个是放入的数据大小,第四个是时间戳,保证递增就是mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, System.nanoTime() / 1000, 0);}MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC);//拿到输出缓冲区的索引while (outputBufferIndex >= 0) {ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];byte[] outData = new byte[bufferInfo.size];outputBuffer.get(outData);//outData就是输出的h264数据outputStream.write(outData, 0, outData.length);//将输出的h264数据保存为文件,用vlc就可以播放mediaCodec.releaseOutputBuffer(outputBufferIndex, false);outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC);}} catch (Throwable t) {t.printStackTrace();}}

创建文件夹

  private void createfile(){File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/test.h264");if(file.exists()){file.delete();}try {outputStream = new BufferedOutputStream(new FileOutputStream(file));} catch (Exception e){e.printStackTrace();}}

NV21格式转化为NV12格式

    private void NV21ToNV12(byte[] nv21,byte[] nv12,int width,int height){if(nv21 == null || nv12 == null)return;int framesize = width*height;int i = 0,j = 0;System.arraycopy(nv21, 0, nv12, 0, framesize);for(i = 0; i < framesize; i++){nv12[i] = nv21[i];}for (j = 0; j < framesize/2; j+=2){nv12[framesize + j-1] = nv21[j+framesize];}for (j = 0; j < framesize/2; j+=2){nv12[framesize + j] = nv21[j+framesize-1];}}

MediaCodec之H264编码相关推荐

  1. MediaCodec解码h264流

    上一篇博文介绍了如何用MediaCodec进行h264编码,这篇介绍如何用MediaCodec进行h264解码,解码时要注意的点就是要一帧一帧的喂给解码器,编码器是一帧一帧出数据的,网上有些demo居 ...

  2. OpenGL.ES在Android上的简单实践:21-水印录制(MediaCodec输出h264+MediaMuxer合成mp4 上)

    OpenGL.ES在Android上的简单实践:21-水印录制(MediaCodec输出h264+MediaMuxer合成mp4 上) 1.录制视频需要什么? 在上篇文章,我们已经成功的满足了需求,在 ...

  3. 采集音频和摄像头视频并实时H264编码及AAC编码

    0. 前言 我在前两篇文章中写了DirectShow捕获音视频然后生成avi,再进行264编码的方法.那种方法有一些局限性,不适合实时性质的应用,如:视频会议.视频聊天.视频监控等.本文所使用的技术, ...

  4. 采集音频和摄像头视频并实时H264编码及AAC编码[转]

    0. 前言 我在前两篇文章中写了DirectShow捕获音视频然后生成avi,再进行264编码的方法.那种方法有一些局限性,不适合实时性质的应用,如:视频会议.视频聊天.视频监控等.本文所使用的技术, ...

  5. ffmpeg的H264编码 视频逐渐模糊

    万能的互联网,又一次在临危之时解决了我的问题 最近在看ffmpeg里的H264编码,然后试着去做了一下.但是目前发现一个问题,就是编码写入的.264文件,用播放器(VLC,暴风都试过)播放后,发现编码 ...

  6. 使用MediaCodeC将图片集编码为视频

    原文地址 原创文章,转载请联系作者 绿生莺啼春正浓,钗头青杏小,绿成丛. 玉船风动酒鳞红.歌声咽,相见几时重? 提要 这是MediaCodeC系列的第三章,主题是如何使用MediaCodeC将图片集编 ...

  7. 海思Hi3519A 进行4k60 h264编码帧率不足的问题

    <!---title:海思Hi3519A 进行4k60 h264编码帧率不足的问题--> <!---keywords:海思,hi3519A, 4k60, h264--> 原始引 ...

  8. H264编码 封装成MP4格式 视频流 RTP封包

    From:http://www.cnblogs.com/ghw-NO1/archive/2012/08/28/2660848.html 一.概述 本文讲述的是对H264编码且封装成MP4格式的视频流进 ...

  9. Android音视频【一】H264编码基础

    人间观察 岁月催人,时间过的太快了 音视频编码解码就是指通过特定的压缩/解压技术,将某个音视频格式的数据转换为另一种音视频格式数据.目前在Android中的音视频用的最多的就是H264+aac的方式进 ...

最新文章

  1. C++ 类模板的使用
  2. SQL Server 2008杀数据库连接
  3. 两个音轨合并_webm格式视频文件合并+weba音频文件无损合并
  4. python fuzzy c-means demo
  5. pwntools语句的简单使用,包含例子
  6. Divan and Kostomuksha (H version) dp,gcd(2300)
  7. 在阿里巴巴工作是一种怎样的体验?
  8. 【pytest】命令行选项
  9. 一个开关电源PCB Layout设计流程
  10. 使用1*1卷积实现咖啡豆图像分类
  11. 我要换博客啦~Github+Hexo~Windows版本
  12. Java GUI实现简单弹珠游戏(新手入门练习项目)
  13. 计算机二级ms在线模拟,2018年全国计算机二级在线自测模拟考场/网页版:MS Office高级应用(含真题及答案)...
  14. 软件企业研发人员激励机制研究
  15. 基于Hololens开发---本地化空间锚点
  16. centOS最全下载地址
  17. Windows 8.1核心版通过注册表启用Guest账号的局域网共享
  18. 零售行业交易数据分析(1)——客户终身价值(CLTV)计算和回归预测模型(Python)
  19. 微信jssdk图片上传给服务器,使用微信JSSDK进行图片选择和上传
  20. 人脸识别机与服务器访问协议,人脸识别终端485通信协议.doc

热门文章

  1. STM32 USART串口通讯初试【查询方式】
  2. 2012-9-20nbsp;《考研词汇速记024》
  3. 家庭账务管理系统html,一种家庭财务管理信息系统的制作方法
  4. 如何用计算机计算平均年龄,使用Excel计算每日平均值(Calculating Daily Averages with Excel)...
  5. Linux虚拟机:Centos6.5设置锁屏时间
  6. java查询elasticsearch_JAVA使用ElasticSearch查询in和not in的实现方式
  7. 学了mysql能做什么的_学sql能干什么
  8. Lucene倒排索引简述 之索引表
  9. 认识java应用程序并使用
  10. AI做PPT,五分钟搞定别人一天的量,最喜欢卷PPT了