博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Camera 使用一例,视频聊天app
阅读量:7093 次
发布时间:2019-06-28

本文共 4745 字,大约阅读时间需要 15 分钟。

 视频聊天的应用可以从下面的框图示意。 

 

 所以需要从camera获取视频数据(YUV420sp),压缩成H264/MPEG4/H263的包,再传递到对方。接收对方的压缩包,解压出来显示到LCD上。

里通过给camera设定 previewcallback函数可以获取每一个Peview帧的yuv数据。

我们现在看看如何按照你想要求的预览尺寸打开camera的并且获取视频数据的。

下面是打开camera的代码片断,他包在一个VideoCameraView类里面。

1 public class VideoCameraView extends SurfaceView  implements SurfaceHolder.Callback, 2         android.hardware.Camera.PreviewCallback { 3  4 ... 5  6   7  8 private android.hardware.Camera mCamera = null ; 9 10  private double mAspectRatio = 3.0 / 3.0;11 12  private int preview_w ;13  private int preview_h ;14  private int preview_yuvbytes ; 15  private byte[] bu  ;16 17  private boolean buffFilled = false ;18 19  private boolean mRec = false ;20 21  public void openCamera(int w , int h){22 23   mRec = false ;24   25   if( surfaceHolder == null  )26    return ;27   mCamera = android.hardware.Camera.open() ;28   try {29    mCamera.setPreviewDisplay(surfaceHolder);30   }catch(IOException e ){31    Log.e(TAG,"mCamera.setPreviewDisplay( " + surfaceHolder +") fail"  ) ;32    return ;33   }34 35   android.hardware.Camera.Parameters p = mCamera.getParameters() ;36 37 ////得到最接近要求的尺寸38   List
listPreview = p.getSupportedPreviewSizes() ;39 Log.v(TAG, "preview size is "+listPreview) ;40 int ii = -1 ; 41 int delta = 0x7fffff ;42 for( int i = 0 ; i < listPreview.size() ; i ++) {43 android.hardware.Camera.Size size = listPreview.get(i) ;44 String ws = Integer.toString(size.width);45 String hs = Integer.toString(size.height) ; 46 Log.v(TAG, "elements "+i+":"+ws+"x"+hs) ;47 if( java.lang.Math.abs(size.width - w ) < delta ) {48 delta = java.lang.Math.abs(size.width - w ) ;49 ii = i ;50 }51 }52 preview_w = listPreview.get(ii).width ;53 preview_h = listPreview.get(ii).height ;54 preview_yuvbytes = preview_w*preview_h*3/2 ;55 56 57 mAspectRatio = (double)preview_w / preview_h;58 p.setPreviewSize( preview_w , preview_h ) ;59 60 List
fpRange = p.getSupportedPreviewFpsRange() ;61 int max = 100 ;62 int min = 0 ;63 for(int i = 0 ; i < fpRange.size() ; i ++ ) {64 int[] fpr = fpRange.get(i) ;65 Log.v(TAG, "min "+ fpr[0]+ " max " + fpr[1]) ; 66 } 67 68 mCamera.setParameters(p); 69 bu = new byte[preview_yuvbytes] ;70 71 mCamera.setPreviewCallbackWithBuffer( this ) ; 72 73 android.hardware.Camera.CameraInfo cameraInfo = new android.hardware.Camera.CameraInfo() ; 74 mCamera.getCameraInfo( 0 , cameraInfo ) ;75 rotateAngle = cameraInfo.orientation ;76 Log.v(TAG,"Camera.CameraInfo.orientation="+ cameraInfo.orientation ); 77 //mCamera.setDisplayOrientation(cameraInfo.orientation) ;78 //prepareCapture();79 requestLayout() ; 80 timeStart = System.currentTimeMillis() ;81 onPreviewCalled = 0 ;82 mCamera.startPreview();83 }84 85 }

 

这里有几个问题需要说明一下:

1    你传进来的尺寸可能不是camera支持的,所以要找一个最靠近你要求的尺寸。

2    预览的长宽比可能和你开始布局的长宽比不一致,这样预览到的画面就会变形,所以需要requestLayout() ,并且要重写onMeasure函数,如下:

  

1   protected void onMeasure(int widthSpec, int heightSpec) { 2         int previewWidth = MeasureSpec.getSize(widthSpec); 3         int previewHeight = MeasureSpec.getSize(heightSpec); 4  5         if (previewWidth > previewHeight * mAspectRatio) { 6             previewWidth = (int) (previewHeight * mAspectRatio + .5); 7         } else { 8             previewHeight = (int) (previewWidth / mAspectRatio + .5); 9         }10 11         // Ask children to follow the new preview dimension.12         super.onMeasure(MeasureSpec.makeMeasureSpec(previewWidth, MeasureSpec.EXACTLY),13                 MeasureSpec.makeMeasureSpec(previewHeight, MeasureSpec.EXACTLY));14     }

 

  请注意:mAspectRatio 是我们在openCamera时计算得到的。

 需要在应用层new一个preview_yuvbytes大小的内存通过 addCallbackBuffer 传到android系统里去,然后使用setPreviewCallbackWithBuffer来设定回调函数。要是setPreviewCallback来设回调函数的话,那么GC会被频繁启动,因为回调送来的内存块是每次都重新分配的,很容易到达需要垃圾处理的门槛,性能会大大降低。而我们采用setPreviewCallbackWithBuffer并且在openCamera时分配这块内存,每次把这块内存压缩使用之后,又重新addCallbackBuffer 到系统里去,就不会大量分配内存,GC也不会启动。请看下面的代码片:

 

1 public void startRec() { 2   mRec = true ;  3   mCamera.addCallbackBuffer( bu ) ; 4  } 5  6  public void onPreviewFrame (byte[] data, android.hardware.Camera camera){ 7     if( mRec ) 8       buffFilled = true ;     9  }10 11  12 13  public int  encodeOneFrame(byte[] bitstream , int bitStreamLength){14   int i = 0 ;15   while( (i++ < 10) && (buffFilled == false) ) {16    try {17     Thread.sleep(10) ;18    }catch( InterruptedException e) {19     20    }   21   }22   if( buffFilled == false )23    return 0 ;24   int nn = nativeEncodeOneFrameH264( bu , bitstream ,  bitStreamLength ,..... ) ;25   buffFilled =  false ;26   mCamera.addCallbackBuffer( bu ) ;27   return nn ;28  }

 

 demo链接:http://nchc.dl.sourceforge.net/project/avccodecdemo/avccodecDemo-src-apk.zip

原文链接:

转载地址:http://yjiql.baihongyu.com/

你可能感兴趣的文章
MySQL索引原理及慢查询优化
查看>>
JNI开发示例
查看>>
从netty-example分析Netty组件
查看>>
[经验]无线鼠标和无线键盘真的不能用了?——雷柏的重生之路~
查看>>
HTTP协议
查看>>
eclipse 创建maven 项目 动态web工程完整示例 maven 整合springmvc整合mybatis
查看>>
[Unit Testing] AngularJS Unit Testing - Karma
查看>>
Java NIO和IO的区别(转)
查看>>
Integer与int的区别(转)
查看>>
JavaScript 解决 onblur 与 onclick 冲突
查看>>
cocos2d-x 事件分发机制 ——加速计事件监听
查看>>
物理层
查看>>
大型网站架构演变和知识体系
查看>>
vi 替换
查看>>
实例37foreach遍历数组
查看>>
性能测试
查看>>
js滚动到底部事件
查看>>
Newtonsoft.Json 用法
查看>>
Unity3D如何减少安装包大小
查看>>
漫游Kafka设计篇之数据持久化
查看>>