Android使用MediaCodec将摄像头采集的视频编码为h264

  

本文实例为大家分享了Android使用MediaCodec将摄像头采集的视频编码为h364,供大家参考,具体内容如下

  

MainActivity.java         进口android.app.Activity;   进口android.graphics.ImageFormat;   进口android.hardware.Camera;   进口android.hardware.Camera.Parameters;   进口android.hardware.Camera.PreviewCallback;   进口android.os.Bundle;   进口android.view.SurfaceHolder;   进口android.view.SurfaceView;      进口java.io.IOException;   进口java.util.concurrent.ArrayBlockingQueue;      公共类MainActivity扩展活动实现SurfaceHolder.Callback PreviewCallback {      私人SurfaceView SurfaceView;      私人SurfaceHolder SurfaceHolder;      私人相机相机;      私人参数参数;      int宽度=1280;      int高度=720;      int帧速率=30;      int biterate=8500 * 1000;      私有静态int yuvqueuesize=10;//待解码视频缓冲队列,静态成员!   公共静态ArrayBlockingQueue   进口android.media.MediaCodec;   进口android.media.MediaCodecInfo;   进口android.media.MediaFormat;   进口android.os.Environment;      进口java.io.BufferedOutputStream;   进口java.io.File;   进口java.io.FileOutputStream;   进口java.io.IOException;   进口java.nio.ByteBuffer;      进口静态android.media.MediaCodec.BUFFER_FLAG_CODEC_CONFIG;   进口静态android.media.MediaCodec.BUFFER_FLAG_KEY_FRAME;         公开课AvcEncoder   {   私人标签的静态字符串=" MeidaCodec”;      私人int TIMEOUT_USEC=12000;      私人MediaCodec MediaCodec;   int m_width;   int m_height;   int m_framerate;      公共byte [] configbyte;         公共AvcEncoder (int宽度,int高度,int帧速率,int比特率){      m_width=宽度;   m_height=身高;   m_framerate=帧速率;   MediaFormat MediaFormat=MediaFormat。createVideoFormat(视频/avc、宽度、高度);   mediaFormat.setInteger (MediaFormat。KEY_COLOR_FORMAT MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);   mediaFormat.setInteger (MediaFormat。KEY_BIT_RATE、宽*高* 5);   mediaFormat.setInteger (MediaFormat。KEY_FRAME_RATE 30);   mediaFormat.setInteger (MediaFormat。KEY_I_FRAME_INTERVAL, 1);   尝试{   mediaCodec=MediaCodec.createEncoderByType(视频/avc);   }捕捉(IOException e) {   e.printStackTrace ();   }//配置编码器参数   mediaCodec。配置(mediaFormat空,空,MediaCodec.CONFIGURE_FLAG_ENCODE);//启动编码器   mediaCodec.start ();//创建保存编码后数据的文件   它仅仅();   }      私有静态字符串路径=Environment.getExternalStorageDirectory () .getAbsolutePath () +“/test1.h364”;   私人BufferedOutputStream outputStream;      私人空间它仅仅(){   文件文件=新文件(路径);   如果(file.exists ()) {   file.delete ();   }   尝试{   outputStream=new BufferedOutputStream(新FileOutputStream(文件);   }捕捉(异常e) {   e.printStackTrace ();   }   }      私人空间StopEncoder () {   尝试{   mediaCodec.stop ();   mediaCodec.release ();   }捕捉(异常e) {   e.printStackTrace ();   }   }      公共布尔isRuning=false;      公共空间StopThread () {   isRuning=false;   尝试{   StopEncoder ();   outputStream.flush ();   outputStream.close ();   }捕捉(IOException e) {   e.printStackTrace ();   }   }      int数=0;      公共空间StartEncoderThread () {   线程EncoderThread=新线程(新Runnable () {      @Override   公共空间run () {   isRuning=true;   byte[]输入=零;   长分=0;   长generateIndex=0;      而(isRuning) {//访问MainActivity用来缓冲待解码数据的队列   如果(MainActivity.YUVQueue.size()在0){//从缓冲队列中取出一帧   输入=MainActivity.YUVQueue.poll ();   byte [] yuv420sp=new字节(m_width * m_height * 3/2);//把待编码的视频帧转换为YUV420格式   NV21ToNV12(输入、yuv420sp m_width m_height);   输入=yuv420sp;   }   如果(输入!=null) {   尝试{   长startMs=System.currentTimeMillis ();//编码器输入缓冲区   ByteBuffer [] inputBuffers=mediaCodec.getInputBuffers ();//编码器输出缓冲区   ByteBuffer [] outputBuffers=mediaCodec.getOutputBuffers ();   int inputBufferIndex=mediaCodec.dequeueInputBuffer (1);   如果(inputBufferIndex祝辞=0){   分=computePresentationTime (generateIndex);   ByteBuffer inputBuffer=inputBuffers [inputBufferIndex];   inputBuffer.clear ();//把转换后的YUV420格式的视频帧放到编码器输入缓冲区中   inputBuffer.put(输入);   mediaCodec。queueInputBuffer (inputBufferIndex 0输入。长度、分0);   generateIndex +=1;   }      MediaCodec。BufferInfo BufferInfo=new MediaCodec.BufferInfo ();   int outputBufferIndex=mediaCodec.dequeueOutputBuffer (bufferInfo TIMEOUT_USEC);   而(outputBufferIndex祝辞=0){//日志。我(“AvcEncoder”、“H264缓冲成功!国旗=" + bufferInfo。旗帜+”,分=" + bufferInfo.presentationTimeUs + " ");   ByteBuffer outputBuffer=outputBuffers [outputBufferIndex];   byte [] outData=https://www.yisu.com/zixun/new字节(bufferInfo.size);   outputBuffer.get (outData);   如果(bufferInfo。标志==BUFFER_FLAG_CODEC_CONFIG) {   configbyte=新字节(bufferInfo.size);   configbyte=outData;   如果(bufferInfo}其他。标志==BUFFER_FLAG_KEY_FRAME) {   byte [] [bufferInfo关键?new字节。大小+ configbyte.length];   系统。arraycopy (configbyte 0,关键帧,0,configbyte.length);//把编码后的视频帧从编码器输出缓冲区中拷贝出来   系统。configbyte arraycopy (outData 0,关键帧。长度,outData.length);      outputStream。写(关键帧,0,keyframe.length);   其他}{//写到文件中   outputStream。写(outData 0 outData.length);   }      mediaCodec。releaseOutputBuffer (outputBufferIndex假);   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null

Android使用MediaCodec将摄像头采集的视频编码为h264