分类:笔记音视频学习过程音视频 5623人阅读 评论(13) 收藏 举报

本人对android已无大爱,更新太快,就h264编码先后实现了 ffmpeg+x264软编 Mediarecoder提取,还没能稳定的又出了MediaCodec,更新太快。更新快也是好事,说明android生命力旺盛。

既然瞅了几眼,就发出来个测试版本吧。android编码h264, 用udp发送到vlc播放测试。代码上传至:http://download.csdn.net/detail/liuhongxiangm/6772629

上代码:

[java] view plain copy
  1. <spanstyle="font-size:18px;">packagecom.encode.androidencode;
  2. importjava.nio.ByteBuffer;
  3. importandroid.annotation.SuppressLint;
  4. importandroid.media.MediaCodec;
  5. importandroid.media.MediaCodecInfo;
  6. importandroid.media.MediaFormat;
  7. importandroid.util.Log;
  8. publicclassAvcEncoder
  9. {
  10. privateMediaCodecmediaCodec;
  11. intm_width;
  12. intm_height;
  13. byte[]m_info=null;
  14. privatebyte[]yuv420=null;
  15. @SuppressLint("NewApi")
  16. publicAvcEncoder(intwidth,intheight,intframerate,intbitrate){
  17. m_width=width;
  18. m_height=height;
  19. yuv420=newbyte[width*height*3/2];
  20. mediaCodec=MediaCodec.createEncoderByType("video/avc");
  21. MediaFormatmediaFormat=MediaFormat.createVideoFormat("video/avc",width,height);
  22. mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE,bitrate);
  23. mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE,framerate);
  24. mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
  25. mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,1);//关键帧间隔时间单位s
  26. mediaCodec.configure(mediaFormat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
  27. mediaCodec.start();
  28. }
  29. @SuppressLint("NewApi")
  30. publicvoidclose(){
  31. try{
  32. mediaCodec.stop();
  33. mediaCodec.release();
  34. }catch(Exceptione){
  35. e.printStackTrace();
  36. }
  37. }
  38. @SuppressLint("NewApi")
  39. publicintofferEncoder(byte[]input,byte[]output)
  40. {
  41. intpos=0;
  42. swapYV12toI420(input,yuv420,m_width,m_height);
  43. try{
  44. ByteBuffer[]inputBuffers=mediaCodec.getInputBuffers();
  45. ByteBuffer[]outputBuffers=mediaCodec.getOutputBuffers();
  46. intinputBufferIndex=mediaCodec.dequeueInputBuffer(-1);
  47. if(inputBufferIndex>=0)
  48. {
  49. ByteBufferinputBuffer=inputBuffers[inputBufferIndex];
  50. inputBuffer.clear();
  51. inputBuffer.put(yuv420);
  52. mediaCodec.queueInputBuffer(inputBufferIndex,0,yuv420.length,0,0);
  53. }
  54. MediaCodec.BufferInfobufferInfo=newMediaCodec.BufferInfo();
  55. intoutputBufferIndex=mediaCodec.dequeueOutputBuffer(bufferInfo,0);
  56. while(outputBufferIndex>=0)
  57. {
  58. ByteBufferoutputBuffer=outputBuffers[outputBufferIndex];
  59. byte[]outData=newbyte[bufferInfo.size];
  60. outputBuffer.get(outData);
  61. if(m_info!=null)
  62. {
  63. System.arraycopy(outData,0,output,pos,outData.length);
  64. pos+=outData.length;
  65. }
  66. else//保存ppssps只有开始时第一个帧里有,保存起来后面用
  67. {
  68. ByteBufferspsPpsBuffer=ByteBuffer.wrap(outData);
  69. if(spsPpsBuffer.getInt()==0x00000001)
  70. {
  71. m_info=newbyte[outData.length];
  72. System.arraycopy(outData,0,m_info,0,outData.length);
  73. }
  74. else
  75. {
  76. return-1;
  77. }
  78. }
  79. mediaCodec.releaseOutputBuffer(outputBufferIndex,false);
  80. outputBufferIndex=mediaCodec.dequeueOutputBuffer(bufferInfo,0);
  81. }
  82. if(output[4]==0x65)//keyframe编码器生成关键帧时只有0000000165没有ppssps,要加上
  83. {
  84. System.arraycopy(output,0,yuv420,0,pos);
  85. System.arraycopy(m_info,0,output,0,m_info.length);
  86. System.arraycopy(yuv420,0,output,m_info.length,pos);
  87. pos+=m_info.length;
  88. }
  89. }catch(Throwablet){
  90. t.printStackTrace();
  91. }
  92. returnpos;
  93. }
  94. //yv12转yuv420pyvu->yuv
  95. privatevoidswapYV12toI420(byte[]yv12bytes,byte[]i420bytes,intwidth,intheight)
  96. {
  97. System.arraycopy(yv12bytes,0,i420bytes,0,width*height);
  98. System.arraycopy(yv12bytes,width*height+width*height/4,i420bytes,width*height,width*height/4);
  99. System.arraycopy(yv12bytes,width*height,i420bytes,width*height+width*height/4,width*height/4);
  100. }
  101. }
  102. </span>


[java] view plain copy
  1. <spanstyle="font-size:18px;">packagecom.interfaces.androidencode;
  2. importjava.io.IOException;
  3. importjava.net.DatagramPacket;
  4. importjava.net.DatagramSocket;
  5. importjava.net.InetAddress;
  6. importjava.net.SocketException;
  7. importjava.net.UnknownHostException;
  8. importjava.util.List;
  9. importandroid.graphics.ImageFormat;
  10. importandroid.hardware.Camera;
  11. importandroid.hardware.Camera.PreviewCallback;
  12. importandroid.os.Bundle;
  13. importandroid.os.StrictMode;
  14. importandroid.annotation.SuppressLint;
  15. importandroid.app.Activity;
  16. importandroid.util.Log;
  17. importandroid.view.Menu;
  18. importandroid.view.SurfaceHolder;
  19. importandroid.view.SurfaceHolder.Callback;
  20. importandroid.view.SurfaceView;
  21. importcom.encode.androidencode.AvcEncoder;
  22. publicclassMainActivityextendsActivity
  23. implementsSurfaceHolder.Callback,PreviewCallback
  24. {
  25. DatagramSocketsocket;
  26. InetAddressaddress;
  27. AvcEncoderavcCodec;
  28. publicCameram_camera;
  29. SurfaceViewm_prevewview;
  30. SurfaceHolderm_surfaceHolder;
  31. intwidth=1280;
  32. intheight=720;
  33. intframerate=20;
  34. intbitrate=2500000;
  35. byte[]h264=newbyte[width*height*3/2];
  36. @SuppressLint("NewApi")
  37. @Override
  38. protectedvoidonCreate(BundlesavedInstanceState){
  39. StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder()
  40. .detectDiskReads()
  41. .detectDiskWrites()
  42. .detectAll()//or.detectAll()foralldetectableproblems
  43. .penaltyLog()
  44. .build());
  45. StrictMode.setVmPolicy(newStrictMode.VmPolicy.Builder()
  46. .detectLeakedSqlLiteObjects()
  47. .detectLeakedClosableObjects()
  48. .penaltyLog()
  49. .penaltyDeath()
  50. .build());
  51. super.onCreate(savedInstanceState);
  52. setContentView(R.layout.activity_main);
  53. avcCodec=newAvcEncoder(width,height,framerate,bitrate);
  54. m_prevewview=(SurfaceView)findViewById(R.id.SurfaceViewPlay);
  55. m_surfaceHolder=m_prevewview.getHolder();//绑定SurfaceView,取得SurfaceHolder对象
  56. m_surfaceHolder.setFixedSize(width,height);//预览大小設置
  57. m_surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  58. m_surfaceHolder.addCallback((Callback)this);
  59. try{
  60. socket=newDatagramSocket();
  61. address=InetAddress.getByName("192.168.12.124");
  62. }catch(SocketExceptione){
  63. //TODOAuto-generatedcatchblock
  64. e.printStackTrace();
  65. }catch(UnknownHostExceptione){
  66. //TODOAuto-generatedcatchblock
  67. e.printStackTrace();
  68. }
  69. }
  70. @Override
  71. publicbooleanonCreateOptionsMenu(Menumenu){
  72. //Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
  73. getMenuInflater().inflate(R.menu.main,menu);
  74. returntrue;
  75. }
  76. @Override
  77. publicvoidsurfaceChanged(SurfaceHolderarg0,intarg1,intarg2,intarg3)
  78. {
  79. }
  80. @SuppressLint("NewApi")
  81. @SuppressWarnings("deprecation")
  82. @Override
  83. publicvoidsurfaceCreated(SurfaceHolderarg0)
  84. {
  85. try
  86. {
  87. m_camera=Camera.open();
  88. m_camera.setPreviewDisplay(m_surfaceHolder);
  89. Camera.Parametersparameters=m_camera.getParameters();
  90. parameters.setPreviewSize(width,height);
  91. parameters.setPictureSize(width,height);
  92. parameters.setPreviewFormat(ImageFormat.YV12);
  93. m_camera.setParameters(parameters);
  94. m_camera.setPreviewCallback((PreviewCallback)this);
  95. m_camera.startPreview();
  96. }catch(IOExceptione)
  97. {
  98. e.printStackTrace();
  99. }
  100. }
  101. @Override
  102. publicvoidsurfaceDestroyed(SurfaceHolderarg0)
  103. {
  104. m_camera.setPreviewCallback(null);//!!这个必须在前,不然退出出错
  105. m_camera.stopPreview();
  106. m_camera.release();
  107. m_camera=null;
  108. avcCodec.close();
  109. }
  110. @Override
  111. publicvoidonPreviewFrame(byte[]data,Cameracamera)
  112. {
  113. Log.v("h264","h264start");
  114. intret=avcCodec.offerEncoder(data,h264);
  115. if(ret>0)
  116. {
  117. try{
  118. DatagramPacketpacket=newDatagramPacket(h264,ret,address,5000);
  119. socket.send(packet);
  120. }catch(IOExceptione)
  121. {
  122. }
  123. }
  124. Log.v("h264","h264end");
  125. }
  126. }
  127. </span>

vlc的设置:设置里面的去复用器设置成H264的就好了,然后打开网络串流:udp://@:5000 就好了



更多相关文章

  1. android基本动画,代码构建动画
  2. Android(安卓)6.0 运行时权限处理完全解析
  3. android实现在横竖屏切换时页面信息不被重置的示例分享
  4. android之逐帧动画
  5. Android(安卓)Shape控件美化实现代码
  6. ViewDragHelper与Transition的示例代码
  7. 【译】Android:更好的自定义字体方案
  8. 利用Bundle实现Android(安卓)Activity间消息的传递
  9. Android(安卓)数据库操作 以及命令行上操作sqlite

随机推荐

  1. Android学习笔记-界面和数据存储以及一些
  2. 仿春雨医生 安卓app(android)
  3. 二、ANDROID命令详解
  4. android的启动过程
  5. android交叉编译工具链接下载
  6. 高级组件之进度条
  7. android 底部Tab添加水波纹效果
  8. 错误parsing XML: ubound prefix
  9. 【进阶篇】Android学习笔记――TextInput
  10. Android毕设之Fragment+TabHost(三)