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

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

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

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

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

 public class VideoCameraView extends SurfaceView  implements SurfaceHolder.Callback,
android.hardware.Camera.PreviewCallback { ... private android.hardware.Camera mCamera = null ; private double mAspectRatio = 3.0 / 3.0; private int preview_w ;
private int preview_h ;
private int preview_yuvbytes ;
private byte[] bu ; private boolean buffFilled = false ; private boolean mRec = false ; public void openCamera(int w , int h){ mRec = false ; if( surfaceHolder == null )
return ;
mCamera = android.hardware.Camera.open() ;
try {
mCamera.setPreviewDisplay(surfaceHolder);
}catch(IOException e ){
Log.e(TAG,"mCamera.setPreviewDisplay( " + surfaceHolder +") fail" ) ;
return ;
} android.hardware.Camera.Parameters p = mCamera.getParameters() ; ////得到最接近要求的尺寸
List<android.hardware.Camera.Size> listPreview = p.getSupportedPreviewSizes() ;
Log.v(TAG, "preview size is "+listPreview) ;
int ii = - ;
int delta = 0x7fffff ;
for( int i = ; i < listPreview.size() ; i ++) {
android.hardware.Camera.Size size = listPreview.get(i) ;
String ws = Integer.toString(size.width);
String hs = Integer.toString(size.height) ;
Log.v(TAG, "elements "+i+":"+ws+"x"+hs) ;
if( java.lang.Math.abs(size.width - w ) < delta ) {
delta = java.lang.Math.abs(size.width - w ) ;
ii = i ;
}
}
preview_w = listPreview.get(ii).width ;
preview_h = listPreview.get(ii).height ;
preview_yuvbytes = preview_w*preview_h*/ ; mAspectRatio = (double)preview_w / preview_h;
p.setPreviewSize( preview_w , preview_h ) ; List<int[]> fpRange = p.getSupportedPreviewFpsRange() ;
int max = ;
int min = ;
for(int i = ; i < fpRange.size() ; i ++ ) {
int[] fpr = fpRange.get(i) ;
Log.v(TAG, "min "+ fpr[]+ " max " + fpr[]) ;
} mCamera.setParameters(p);
bu = new byte[preview_yuvbytes] ; mCamera.setPreviewCallbackWithBuffer( this ) ; android.hardware.Camera.CameraInfo cameraInfo = new android.hardware.Camera.CameraInfo() ;
mCamera.getCameraInfo( , cameraInfo ) ;
rotateAngle = cameraInfo.orientation ;
Log.v(TAG,"Camera.CameraInfo.orientation="+ cameraInfo.orientation );
//mCamera.setDisplayOrientation(cameraInfo.orientation) ;
//prepareCapture();
requestLayout() ;
timeStart = System.currentTimeMillis() ;
onPreviewCalled = ;
mCamera.startPreview();
} }

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

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

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

   protected void onMeasure(int widthSpec, int heightSpec) {
int previewWidth = MeasureSpec.getSize(widthSpec);
int previewHeight = MeasureSpec.getSize(heightSpec); if (previewWidth > previewHeight * mAspectRatio) {
previewWidth = (int) (previewHeight * mAspectRatio + .);
} else {
previewHeight = (int) (previewWidth / mAspectRatio + .);
} // Ask children to follow the new preview dimension.
super.onMeasure(MeasureSpec.makeMeasureSpec(previewWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(previewHeight, MeasureSpec.EXACTLY));
}

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

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

 public void startRec() {
mRec = true ;
mCamera.addCallbackBuffer( bu ) ;
} public void onPreviewFrame (byte[] data, android.hardware.Camera camera){
if( mRec )
buffFilled = true ;
} public int encodeOneFrame(byte[] bitstream , int bitStreamLength){
int i = ;
while( (i++ < ) && (buffFilled == false) ) {
try {
Thread.sleep() ;
}catch( InterruptedException e) { }
}
if( buffFilled == false )
return ;
int nn = nativeEncodeOneFrameH264( bu , bitstream , bitStreamLength ,..... ) ;
buffFilled = false ;
mCamera.addCallbackBuffer( bu ) ;
return nn ;
}

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

原文链接:http://blog.csdn.net/brooknew/article/details/7998833

Android Camera 使用一例,视频聊天app的更多相关文章

  1. Android 极光IM-高级篇-玩聊天app诞生

    距离上一次写 基础篇有了4个月,终于我写了一个 功能完善的即时通讯app,作为高级篇的担当出现.废话不多说,上图 app预览 ​​​​ ​​​​ ​​ 实现功能 1.用户的登录注册 2.单聊,能清空聊 ...

  2. 视频聊天APP

    1 通讯 P2P 1.1 关键字[java udp 打洞] 参考文章 http://www.oschina.net/code/snippet_165555_17279 关键代码 package org ...

  3. Android Camera 使用小结。两种方法:一是调用系统camera app,二是自己写camera程序。

    源文链接:http://www.cnblogs.com/franksunny/archive/2011/11/17/2252926.html Android Camera 使用小结 Android手机 ...

  4. Android Camera系列开发 (二)通过Intent录制视频

    Android Camera系列开发 (二)通过Intent录制视频 作者:雨水  2013-8-18 CSDN博客:http://blog.csdn.net/gobitan/ 概述 使用Camera ...

  5. Android Camera API2中采用CameraMetadata用于从APP到HAL的参数交互

    前沿: 在全新的Camera API2架构下,常常会有人疑问再也看不到熟悉的SetParameter/Paramters等相关的身影,取而代之的是一种全新的CameraMetadata结构的出现,他不 ...

  6. Android音乐、视频类APP常用控件:DraggablePanel(1)

     Android音乐.视频类APP常用控件:DraggablePanel(1) Android的音乐视频类APP开发中,常涉及到用户拖曳视频.音乐播放器产生一定交互响应的设计需求,最典型的以You ...

  7. Android音乐、视频类APP常用控件:DraggablePanel(2)

     Android音乐.视频类APP常用控件:DraggablePanel(2) 附录文章1主要演示了如何使用DraggablePanel 的DraggableView.DraggablePanel ...

  8. Android/iOS微信6.3.5同时发布更新 支持群视频聊天、群公告

    下午微信6.3.5发布更新,新版最大变化就是支持群视频聊天,又一次向手机QQ靠拢.在群管理方面,支持发布群公告,支持群主转让给其他群成员,同样都是QQ玩剩下的功能.另外,新版支持微信运动查看步数图表. ...

  9. 如何基于 ZEGO SDK 实现 Flutter 一对一音视频聊天应用?

    之前的文章发布了ZEGO SDK实现Android端音视频通话应用的开发教程,不少开发者反馈很实用,能不能也出一版Flutter的教程. 有求必应,这不小编来了- 我们封装了ZEGO Flutter ...

随机推荐

  1. django-orm-standalone

    django-orm-standalone script via:https://github.com/masnun/django-orm-standalone/ # Django specific ...

  2. python之json

    import json import requests re = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=成都') re.en ...

  3. IOS设计模式之三:MVC模式

    IOS设计模式之三:MVC模式   模型-视图-控制器 这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存在,没有任何瓜葛,他们就像一个团 ...

  4. Eclipse 代码自动补全

    使用Eclipse开发Android时,发现代码补全功能太差,完全不像VS似的,输入一个字母就出现代码提示. 下面是在Eclipse中实现类似VS代码补全的方法: ①打开Eclipse->Win ...

  5. 【Java】详解Java解析XML的四种方法

    XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML.本文将详细介绍用Java解析XML的四种方法. AD: XML现在已经成为一种通用的数据交换格式,它的平台无关性,语 ...

  6. 在 C++Builder 工程里使用 Visual C++ DLL(3个工具) good

    译者序: 第一次读这篇文章是在 2001 年 10 月,帮我解决了一点小问题.本来不好意思翻译,因为英语水平实在太差.最近发现不少网友在问在 C++Builder 的工程里调用 Visual C++  ...

  7. 几个Uboot命令

    1 nand scrub 这个命令会擦除坏块信息,将坏块标识成好的,但此时这个坏块有潜在有危险,在特定条件下仍会造成数据的丢失,所以应该谨慎使用. Run U-boot and then use th ...

  8. vijos1514天才的记忆

    P1514天才的记忆 背景 神仙飞啊飞 描述 从前有个人名叫W and N and B,他有着天才般的记忆力,他珍藏了许多许多的宝藏.在他离世之后留给后人一个难题(专门考验记忆力的啊!),如果谁能轻松 ...

  9. (转载)Mysql使用Describe命令判断字段是否存在

    (转载)http://www.jz123.cn/plus/view.php?aid=39200 工作时需要取得MySQL中一个表的字段是否存在 于是就使用Describe命令来判断 mysql_con ...

  10. (转载)PHP静态方法

    (转载)Lamp兄弟连PHP 6.静态方法(static修饰的方法),不能访问非静态成员(在非静态的方法中,可以访问静态成员).因为非静态的成员,就必须用对象来访问,访问内部的成员使用的就是$this ...