android流媒体初探索(一)----获取视频数据
最近在做一个项目,简单说一下需求吧:
android手机做前端视频采集入口,能捕获实时的视频流并传到服务器并且分发到pc客户端实时的进行视频的观看。
就这个看似简单的需求,由于我之前对流媒体全无了解,也因为接入了XX平台进行数据中转,导致开发过程一再受阻。
但就目前已基本将该项目流程走通,所以必须在这里来作个小结。
在这里有几个关键点:
a、视频数据如何获取。
b、获取到的数据如何重新编码,以何种形式编码。
c、以什么协议进行传输。
d、视频最后的解码播放。
android充当摄像头,进行流媒体传输的开源项目有spydroid。这个项目是研究android流媒体处理目前来说最好的切入点。网上也有很多对该项目源码解析的文章,这里不再多说。我就上面提到的几个关键点简单说一下做法。
a获取视频数据
用android来实现还算是简单。毕竟有丰富的sdk封装。那么就会用到MediaRecorder。跟它相关的几个类还有Camera、SurfaceHolder。
MediaRecorder用于录像,相关设置如下:
if (mMediaRecorder == null) {
mMediaRecorder = new MediaRecorder(); } else { mMediaRecorder.reset(); } camera = getCamera();
camera.startPreview();
camera.unlock();
mMediaRecorder.setCamera(camera); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); <!--以上和以下顺序不能颠倒,否则出错> mMediaRecorder.setVideoSize(reX, reY); mMediaRecorder.setVideoFrameRate(fr); mMediaRecorder.setMaxDuration(0); mMediaRecorder.setMaxFileSize(Integer.MAX_VALUE); mMediaRecorder.setVideoEncodingBitRate(bit * 1000); mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); mMediaRecorder.setOrientationHint(90);//竖屏播放,但貌似只有在android手机上播放有效,在pc上播放无效。 mMediaRecorder.setOutputFile(sender.getFileDescriptor());//设置输出为本地socket
然后就是Camera的获取和设置:
1 public Camera getCamera(){ 2 if(camera==null){ 3 try{ 4 camera = Camera.open(); 5 Parameters paramters = camera.getParameters(); 6 paramters.setPreviewSize(Integer.parseInt(getPreferences().resolution.split("×")[0]),Integer.parseInt(getPreferences().resolutio n.split("×")[1])); 7 }catch(Exception e){ 8 e.printStackTrace(); 9 try { 10 if(camera!=null){ 11 camera.reconnect(); 12 }else{ 13 Toast.makeText(this, "连接摄像头服务失败!请重启手机后再试。", Toast.LENGTH_SHORT).show(); 14 } 15 } catch (IOException e1) { 16 e1.printStackTrace(); 17 } 18 } 19 if (camera!=null) { 20 camera.setDisplayOrientation(90);
camera.setPreviewDisplay(mSurfaceHolder); 21 } 22 } 23 return camera; 24 }
负责预览的SurfaceView和SurfaceHolder:
/** * 初始化surfaceView */ private void InitSurfaceView() { mSurfaceView = (SurfaceView) this.findViewById(R.id.surface_camera); mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.setKeepScreenOn(true); mSurfaceHolder.addCallback(this); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//兼容低版本 }
打开录像:
try { mMediaRecorder.prepare(); mMediaRecorder.start(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); releaseMediaRecorder(); }
到这里,已经可以在本地socket中拿到摄像头获取的流了。当然根据我的参数设置,获得的流是系统MP4、h264编码后的码流。