最近EasyPusher针对UVC摄像头做了适配.我们结合了UVCCamera与EasyPusher,支持将UVC摄像头的视频推送到RTSP服务器上.在此特别感谢UVCCamera这个牛逼的项目!

来看看是怎么操作UVC摄像头的吧.我们实现了一个专门检测UVC摄像头的服务:UVCCameraService类,主要代码如下:

监听

mUSBMonitor = new USBMonitor(this, new USBMonitor.OnDeviceConnectListener() {@Overridepublic void onAttach(final UsbDevice device) {Log.v(TAG, "onAttach:" + device);mUSBMonitor.requestPermission(device);}@Overridepublic void onConnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock, final boolean createNew) {releaseCamera();if (BuildConfig.DEBUG) Log.v(TAG, "onConnect:");try {final UVCCamera camera = new MyUVCCamera();camera.open(ctrlBlock);camera.setStatusCallback(new IStatusCallback() {// ... uvc 摄像头链接成功Toast.makeText(UVCCameraService.this, "UVCCamera connected!", Toast.LENGTH_SHORT).show();if (device != null)cameras.append(device.getDeviceId(), camera);}catch (Exception ex){ex.printStackTrace();}}@Overridepublic void onDisconnect(final UsbDevice device, final USBMonitor.UsbControlBlock ctrlBlock) {// ... uvc 摄像头断开链接if (device != null) {UVCCamera camera = cameras.get(device.getDeviceId());if (mUVCCamera == camera) {mUVCCamera = null;Toast.makeText(UVCCameraService.this, "UVCCamera disconnected!", Toast.LENGTH_SHORT).show();liveData.postValue(null);}cameras.remove(device.getDeviceId());}else {Toast.makeText(UVCCameraService.this, "UVCCamera disconnected!", Toast.LENGTH_SHORT).show();mUVCCamera = null;liveData.postValue(null);}}@Overridepublic void onCancel(UsbDevice usbDevice) {releaseCamera();}@Overridepublic void onDettach(final UsbDevice device) {Log.v(TAG, "onDettach:");releaseCamera();
//                AppContext.getInstance().bus.post(new UVCCameraDisconnect());}});

这个类主要实现UVC摄像头的监听\链接\销毁\反监听.当有UVC摄像头链接成功后,会创建一个mUVCCamera对象.

然后在MediaStream里, 我们改造了switchCamera,当参数传2时,表示要切换到UVCCamera(0,1分别表示切换到后置\前置摄像头).

创建

在创建摄像头时,如果是要创建uvc摄像头,那直接从服务里面获取之前创建的mUVCCamera实例:

 if (mCameraId == 2) {UVCCamera value = UVCCameraService.liveData.getValue();if (value != null) {// uvc camera.uvcCamera = value;value.setPreviewSize(width, height,1, 30, UVCCamera.PIXEL_FORMAT_YUV420SP,1.0f);return;//            value.startPreview();}else{Log.i(TAG, "NO UVCCamera");uvcError = new Exception("no uvccamera connected!");return;}//            mCameraId = 0;}

预览

在预览时,如果uvc摄像头已经创建了,那执行uvc摄像头的预览操作:

UVCCamera value = uvcCamera;
if (value != null) {SurfaceTexture holder = mSurfaceHolderRef.get();if (holder != null) {value.setPreviewTexture(holder);}try {value.setFrameCallback(uvcFrameCallback, UVCCamera.PIXEL_FORMAT_YUV420SP/*UVCCamera.PIXEL_FORMAT_NV21*/);value.startPreview();cameraPreviewResolution.postValue(new int[]{width, height});}catch (Throwable e){uvcError = e;}
}

这里我们选的colorFormat为PIXEL_FORMAT_YUV420SP 相当于标准摄像头的NV21格式.

关闭预览

同理,关闭时,调用的是uvc摄像头的关闭.

        UVCCamera value = uvcCamera;if (value != null) {value.stopPreview();}

销毁

因为我们这里并没有实质性的创建,所以销毁时也仅将实例置为null就可以了.

UVCCamera value = uvcCamera;
if (value != null) {//            value.destroy();uvcCamera = null;
}

有了这些操作,我们看看上层怎么调用,

首先需要在Manifest里面增加若干代码,具体详见UVCCamera工程说明.如下:

<activity android:name=".UVCActivity" android:launchMode="singleInstance"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter><action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /></intent-filter><intent-filter><action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" /></intent-filter><meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"android:resource="@xml/device_filter" /></activity>

然后,的代码在UVCActivity里,这个类可以在library分支的myapplication工程里找到.即这里.

启动或者停止UVC摄像头推送:

    public void onPush(View view) {// 异步获取到MediaStream对象.getMediaStream().subscribe(new Consumer<MediaStream>() {@Overridepublic void accept(final MediaStream mediaStream) throws Exception {// 判断当前的推送状态.MediaStream.PushingState state = mediaStream.getPushingState();if (state != null && state.state > 0) { // 当前正在推送,那终止推送和预览mediaStream.stopStream();mediaStream.closeCameraPreview();}else{// switch 0表示后置,1表示前置,2表示UVC摄像头// 异步开启UVC摄像头RxHelper.single(mediaStream.switchCamera(2), null).subscribe(new Consumer<Object>() {@Overridepublic void accept(Object o) throws Exception {// 开启成功,进行推送.// ...mediaStream.startStream("cloud.easydarwin.org", "554", id);}}, new Consumer<Throwable>() {@Overridepublic void accept(final Throwable t) throws Exception {// ooop...开启失败,提示下...t.printStackTrace();runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(UVCActivity.this, "UVC摄像头启动失败.." + t.getMessage(), Toast.LENGTH_SHORT).show();}});}});}}});}

这样,整个推送就完成了.如果一切顺利,应当能在VLC播放出来UVC摄像头的视频了~~

我们再看看如何录像.也非常简单…

    public void onRecord(View view) {       // 开始或结束录像.final TextView txt = (TextView) view;getMediaStream().subscribe(new Consumer<MediaStream>() {@Overridepublic void accept(MediaStream mediaStream) throws Exception {if (mediaStream.isRecording()){ // 如果正在录像,那停止.mediaStream.stopRecord();txt.setText("录像");}else { // 没在录像,开始录像...// 表示最大录像时长为30秒,30秒后如果没有停止,会生成一个新文件.依次类推...// 文件格式为test_uvc_0.mp4,test_uvc_1.mp4,test_uvc_2.mp4,test_uvc_3.mp4String path = getExternalFilesDir(Environment.DIRECTORY_MOVIES) + "/test_uvc.mp4";mediaStream.startRecord(path, 30000);final TextView pushingStateText = findViewById(R.id.pushing_state);pushingStateText.append("\n录像地址:" + path);txt.setText("停止");}}});}

UVC摄像头还支持后台推送,即不预览的情况下进行推送,同时再切换到前台继续预览.只需要调用一个接口即可实现,如下:

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {ms.setSurfaceTexture(surfaceTexture); // 设置预览的surfaceTexture
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {ms.setSurfaceTexture(null);           // 设置预览窗口为null,表示关闭预览功能return true;
}

如果要彻底退出uvc摄像头的预览\推送,那只需要同时退出服务即可.

public void onQuit(View view) {     // 退出finish();// 终止服务...Intent intent = new Intent(this, MediaStream.class);stopService(intent);
}

## 获取更多信息 ##

邮件:support@easydarwin.org

EasyDarwin开源流媒体服务器:www.EasyDarwin.org

EasyDSS商用流媒体解决方案:www.EasyDSS.com

EasyNVR无插件直播方案:www.EasyNVR.com

Copyright © EasyDarwin Team 2012-2017

EasyPusher进行Android UVC外接摄像头直播推送实现方法相关推荐

  1. Android集成阿里云消息推送的方法步骤

    一 创建App应用 1.1 在控制台发(https://mhub.console.aliyun.com)的App列表页,点击页面产品列表中"添加产品"的图标即可创建一个新的产品(产 ...

  2. EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式

    EasyPusher安卓Android手机直播推送之MediaCodec 硬编码H264格式 最近在研究EasyDarwin的Push库EasyPusher,EasyPusher可以推送H264视频到 ...

  3. EasyPusher安卓Android手机直播推送之RTSP流媒体协议流程

    EasyPusher移动端推送同我们平时用的RTSP直播推送流程一样,都是采用标准RTSP/RTP推送流程:ANNOUNCE->SETUP->PLAY->RTP/RTCP->T ...

  4. EasyPusher实现安卓Android手机直播推送同步录像功能(源码解析)

    EasyPusher是一款非常棒的推送客户端.稳定.高效.低延迟,音视频同步等都特别好.装在安卓上可作为一款单兵设备来用.说到单兵,在项目中通常都需要边传边录的功能,因此后来EasyPusher也加入 ...

  5. EasyDarwin开源手机直播方案:EasyPusher手机直播推送,EasyDarwin流媒体服务器,EasyPlayer手机播放器...

    在不断进行EasyDarwin开源流媒体服务器的功能和性能完善的同时,我们也配套实现了目前在安防和移动互联网行业比较火热的移动端手机直播方案,主要就是我们的 EasyPusher直播推送项目 和 Ea ...

  6. Unity Vuforia 之 简单实现Vuforia调用Android设备外接摄像头camera实现AR

    Unity Vuforia 之 简单实现Vuforia调用Android设备外接摄像头camera实现AR 目录 Unity Vuforia 之 简单实现Vuforia调用Android设备外接摄像头 ...

  7. 安卓Android手机直播推送同步录像功能设计与实现源码

    本文转自:http://blog.csdn.net/jyt0551/article/details/58714595 EasyPusher是一款非常棒的推送客户端.稳定.高效.低延迟,音视频同步等都特 ...

  8. Windows平台RTMP/RTSP直播推送模块设计和使用说明

    开发背景 好多开发者一直反馈,Windows平台,做个推屏或者推摄像头,推RTMP或者RTSP出去,不知道哪些功能是必须的,哪些设计是可有可无的,还有就是,不知道如何选技术方案,以下是基于我们设计的W ...

  9. Android socket 编程 实现消息推送(二)

    上篇文章Android socket 编程 实现消息推送(一)讲到socket编程的消息推送原理,现在我们来看看基于Android客户机socket编程实现消息推送的过程. 根据消息推送的原理图,我们 ...

最新文章

  1. 图灵2011年6月书讯【误区】【软件调试修炼之道】即将上市
  2. 【JOURNAL】《不思八九》 --和友腊八诗一首
  3. Nancy总结(三)Nancy资料介绍
  4. MySql中的运算符
  5. C#中通过单例模式以及Dictionary实现键值对的映射,通过key获取value
  6. 自学Springboot(一)
  7. 李宏毅机器学习作业2:Winner还是Losser(含训练数据)
  8. Syncthing vs BitTorrent Sync
  9. Matlab Tricks(四)—— remove DC
  10. Refactoring Page Head
  11. 二阶声波正演c语言程序_问:程序员怎么敲代码才不累?答:装上显示器支架之后...
  12. SQL SERVER 报表开发工具入门教程
  13. python实现进程调度算法
  14. azkaban 项目依赖
  15. 微信戴圣诞帽的一个简易实现程序
  16. 图书管理系统的数据库设计
  17. 数据库实体间关联关系:一对一、一对多、多对多
  18. 索骥馆-编程语言之《Android内核剖析》扫描版[PDF]
  19. 计算机算最大值如何操作,如何合理设置计算机的虚拟内存值(初始大小及最大值)?...
  20. 路由dns劫持,路由器DNS劫持简单实现和防范分析

热门文章

  1. 区别重要的事情及不要盲目增加计划提前期
  2. 保研夏令营、考研复试、出国时个人陈述模板与撰写注意事项
  3. 重庆专科计算机大学排名,重庆2017年专科大学排名一览表
  4. 多重网格法(multigrid)求解1d泊松方程--python
  5. 动词的时态(Les temps du verbe )
  6. android adguard教程,【2020.1.8更新Adguardhome完整使用教程】目测是新三区最完整的adguard最详细的教程了...
  7. 一文回顾 Java 入门知识(上)
  8. mysql-mysql介绍
  9. 【IOT】Thingsboard学习笔记(1):开源IOT平台thingsboard部署-windows平台
  10. 嵌入式菜单LCD简单版