android硬编码h264-MediaCodec
来源:互联网 发布:javascript中关键字 编辑:程序博客网 时间:2024/04/30 08:58
本人对android已无大爱,更新太快,就h264编码先后实现了 ffmpeg+x264软编 Mediarecoder提取,还没能稳定的又出了MediaCodec,更新太快。更新快也是好事,说明android生命力旺盛。
既然瞅了几眼,就发出来个测试版本吧。android编码h264, 用udp发送到vlc播放测试。代码上传至:http://download.csdn.net/detail/liuhongxiangm/6772629
上代码:
package com.encode.androidencode;import java.nio.ByteBuffer;import android.annotation.SuppressLint;import android.media.MediaCodec;import android.media.MediaCodecInfo;import android.media.MediaFormat;import android.util.Log;public class AvcEncoder {private MediaCodec mediaCodec;int m_width;int m_height;byte[] m_info = null;private byte[] yuv420 = null; @SuppressLint("NewApi")public AvcEncoder(int width, int height, int framerate, int bitrate) { m_width = width;m_height = height;yuv420 = new byte[width*height*3/2]; mediaCodec = MediaCodec.createEncoderByType("video/avc"); MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate); mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar); mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); //关键帧间隔时间 单位s mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mediaCodec.start();}@SuppressLint("NewApi")public void close() { try { mediaCodec.stop(); mediaCodec.release(); } catch (Exception e){ e.printStackTrace(); }}@SuppressLint("NewApi")public int offerEncoder(byte[] input, byte[] output) {int pos = 0;swapYV12toI420(input, yuv420, m_width, m_height); try { ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers(); ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers(); int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(yuv420); mediaCodec.queueInputBuffer(inputBufferIndex, 0, yuv420.length, 0, 0); } MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,0); while (outputBufferIndex >= 0) { ByteBuffer outputBuffer = outputBuffers[outputBufferIndex]; byte[] outData = new byte[bufferInfo.size]; outputBuffer.get(outData); if(m_info != null) { System.arraycopy(outData, 0, output, pos, outData.length); pos += outData.length; } else //保存pps sps 只有开始时 第一个帧里有, 保存起来后面用 { ByteBuffer spsPpsBuffer = ByteBuffer.wrap(outData); if (spsPpsBuffer.getInt() == 0x00000001) { m_info = new byte[outData.length]; System.arraycopy(outData, 0, m_info, 0, outData.length); } else { return -1; } } mediaCodec.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0); } if(output[4] == 0x65) //key frame 编码器生成关键帧时只有 00 00 00 01 65 没有pps sps, 要加上 { System.arraycopy(output, 0, yuv420, 0, pos); System.arraycopy(m_info, 0, output, 0, m_info.length); System.arraycopy(yuv420, 0, output, m_info.length, pos); pos += m_info.length; } } catch (Throwable t) { t.printStackTrace(); } return pos;} //yv12 转 yuv420p yvu -> yuv private void swapYV12toI420(byte[] yv12bytes, byte[] i420bytes, int width, int height) { System.arraycopy(yv12bytes, 0, i420bytes, 0,width*height); System.arraycopy(yv12bytes, width*height+width*height/4, i420bytes, width*height,width*height/4); System.arraycopy(yv12bytes, width*height, i420bytes, width*height+width*height/4,width*height/4); } }
package com.interfaces.androidencode;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;import java.util.List;import android.graphics.ImageFormat;import android.hardware.Camera;import android.hardware.Camera.PreviewCallback;import android.os.Bundle;import android.os.StrictMode;import android.annotation.SuppressLint;import android.app.Activity;import android.util.Log;import android.view.Menu;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import com.encode.androidencode.AvcEncoder;public class MainActivity extends Activityimplements SurfaceHolder.Callback, PreviewCallback {DatagramSocket socket;InetAddress address;AvcEncoder avcCodec; public Camera m_camera; SurfaceView m_prevewview; SurfaceHolder m_surfaceHolder; int width = 1280; int height = 720; int framerate = 20; int bitrate = 2500000; byte[] h264 = new byte[width*height*3/2];@SuppressLint("NewApi")@Overrideprotected void onCreate(Bundle savedInstanceState) {StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .detectAll() // or .detectAll() for all detectable problems .penaltyLog() .build());StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .detectLeakedClosableObjects() .penaltyLog() .penaltyDeath() .build());super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);avcCodec = new AvcEncoder(width,height,framerate,bitrate);m_prevewview = (SurfaceView) findViewById(R.id.SurfaceViewPlay);m_surfaceHolder = m_prevewview.getHolder(); // 绑定SurfaceView,取得SurfaceHolder对象m_surfaceHolder.setFixedSize(width, height); // 预览大小設置m_surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);m_surfaceHolder.addCallback((Callback) this);try {socket = new DatagramSocket();address = InetAddress.getByName("192.168.12.124");} catch (SocketException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}@SuppressLint("NewApi")@SuppressWarnings("deprecation")@Overridepublic void surfaceCreated(SurfaceHolder arg0) {try {m_camera = Camera.open();m_camera.setPreviewDisplay(m_surfaceHolder);Camera.Parameters parameters = m_camera.getParameters();parameters.setPreviewSize(width, height);parameters.setPictureSize(width, height);parameters.setPreviewFormat(ImageFormat.YV12);m_camera.setParameters(parameters);m_camera.setPreviewCallback((PreviewCallback) this);m_camera.startPreview();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {m_camera.setPreviewCallback(null); //!!这个必须在前,不然退出出错m_camera.stopPreview(); m_camera.release();m_camera = null; avcCodec.close();}@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {Log.v("h264", "h264 start");int ret = avcCodec.offerEncoder(data,h264);if(ret > 0){try {DatagramPacket packet=new DatagramPacket(h264,ret, address,5000);socket.send(packet);} catch (IOException e){}}Log.v("h264", "h264 end");}}
vlc的设置:设置里面的去复用器设置成H264的就好了,然后打开网络串流:udp://@:5000 就好了
1 2
- android硬编码h264-MediaCodec
- android硬编码h264-MediaCodec
- android硬编码h264-MediaCodec
- android硬编码h264-MediaCodec
- android硬编码h264-MediaCodec
- MediaCodec 硬编码 h264
- android硬编码h264——MediaCodec
- Android 利用MediaCodec 实现硬编码 h264
- MediaCodec硬编码成H264视频流
- Android MediaCodec h264硬件编码
- Android Mediacodec硬解H264并显示
- Android MediaCodec硬解码H264文件
- Android MediaCodec硬解码H264文件
- EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式
- EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式
- EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式
- android开发,通过摄像头实时采集视频并使用MediaCodec硬编码为H264
- EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式
- poj 1330 Nearest Common Ancestors(LCA模板)
- poi修改excel
- 转战github
- Ubuntu中启用关闭Network-manager网络设置问题!
- .a .so的相互包含
- android硬编码h264-MediaCodec
- python 第一步
- C++ dlopen mini HOWTO
- Spring 配置
- b/s和c/s
- sql分别用日期、月、年 分组 group by 分组,datepart函数
- 付盛访谈
- JSF + Primefaces表单验证
- windows I/O完成端口