最近我们公司的产品,在一款Android平板上遇到一个奇怪的问题,现象是本地视频预览画面显示是黑屏,监听VideoFrame无输出。下面我来描述一下这个故事。

在WebRTC Android SDK源码的Camera2Session.java这个文件里,有这样一段代码:

private class CaptureSessionCallback extends CameraCaptureSession.StateCallback {//...@Overridepublic void onConfigured(CameraCaptureSession session) {final CaptureRequest.Builder captureRequestBuilder =cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);//...chooseStabilizationMode(captureRequestBuilder);//...}//...
}

为了节省篇幅,我只摘取了关键的部分。
上面代码中,通过 createCaptureRequest 传递了常量 CameraDevice.TEMPLATE_RECORD。在Android的CameraDevice.java中,一共定义了6种TEMPLATE:

TEMPLATE_PREVIEW,
TEMPLATE_STILL_CAPTURE,
TEMPLATE_RECORD,
TEMPLATE_VIDEO_SNAPSHOT,
TEMPLATE_ZERO_SHUTTER_LAG,
TEMPLATE_MANUAL

通过实验,我把这里的 TEMPLATE_RECORD 换成了 TEMPLATE_PREVIEW,获得了更大的视野范围(相当于调小焦距),更改以后,放到了产品里一段时间,似乎也没遇到过什么问题(我们公司的产品是音视频实时通讯类的)。

但有一天我们有一个客户突然丢给我们一个平板(华为荣耀Waterplay),告诉我们说这个机器上,使用我们的产品无法显示自己的摄像头画面,而系统照相机是OK的。我第一时间就意识到是不是因为修改了这个Request template导致的?

问题的排查过程就不细说了,其实问题不是发生在 CameraDevice.createCaptureRequest() 这句上,而是在下方的 chooseStabilizationMode 这个函数里。下面是WebRTC中这个函数的实现:

// Prefers optical stabilization over software stabilization if available. Only enables one of
// the stabilization modes at a time because having both enabled can cause strange results.
private void chooseStabilizationMode(CaptureRequest.Builder captureRequestBuilder) {final int[] availableOpticalStabilization = cameraCharacteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION);if (availableOpticalStabilization != null) {for (int mode : availableOpticalStabilization) {if (mode == CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON) {captureRequestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON);captureRequestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF);Logging.d(TAG, "Using optical stabilization.");return;}}}// If no optical mode is available, try software.final int[] availableVideoStabilization = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES);for (int mode : availableVideoStabilization) {if (mode == CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON) {captureRequestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON);captureRequestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_OFF);Logging.d(TAG, "Using video stabilization.");return;}}Logging.d(TAG, "Stabilization not available.");
}

代码写的很清楚,先检测设备是否支持光学视频稳定,支持的话启用之,函数返回。否则继续查询是否支持软件视频稳定,如果查询到支持的话,启用之。

虽然说我们公司有很多测试设备,但后来发现大多数设备要么是Camera1,不会走到Camera2里来,要么就是支持光学视频稳定,直接就在第一个if就返回了。唯独遇到华为荣耀Waterplay这个平板,是走到了第2个if,并且执行了关键的一句:

captureRequestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON);

问题原因就是:当使用 TEMPLATE_PREVIEW 时,如果同时再尝试通过这一句开启软件视频稳定特性,就会出现我遇到的问题(预览黑屏、没有视频帧回调通知)!

通过翻看Android Developer,我找到了已经被标记为Deprecated的API: setVideoStabilization。它的描述是这样的:

Enables and disables video stabilization. Use isVideoStabilizationSupported() to determine if calling this method is valid.
Video stabilization reduces the shaking due to the motion of the camera in both the preview stream and in recorded videos, including data received from the preview callback. It does not reduce motion blur in images captured with Camera#takePicture.
Video stabilization can be enabled and disabled while preview or recording is active, but toggling it may cause a jump in the video stream that may be undesirable in a recorded video.

这里并没有描述可能出现什么兼容性问题呢……

导致这个问题的基本原因已经找到了,但这并不是根本原因。还有一些疑问摆在面前:

  • 所有支持Camera2的设备,在TEMPLATE_PREVIEW模式下,开启软件视频稳定特性都会出现这个问题吗?(因为我手头只有一台这样的设备,无法考证)
  • 这个问题是因为设备硬件导致的,还是软件导致的,还是软硬件实现不规范、不匹配导致的?
  • 如果软件视频稳定特性存在问题,为什么在TEMPLATE_RECORD模式下没事?

如果想再往下挖掘深层次的原因,就需要顺着 cameraCharacteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES) 这句,去到Android源码中探索了,因为我手边没有Android的源代码,下载一份太费劲。或者到 AndroidXef 在线搜索也都是可以尝试的。有时间的话,再深入看一下。

Android : WebRTC中设置 Video Stabilization 遇到的一个兼容性问题相关推荐

  1. android线程改变布局,Android线程中设置控件的值提示报错的解决方法

    本文实例讲述了Android线程中设置控件的值提示报错的解决方法.分享给大家供大家参考,具体如下: 在Android线程中设置控件的值一般会与Handler联合使用,如下: package com.y ...

  2. android 设置字体大小和不同颜色,Android代码中设置字体大小,字体颜色,显示两种颜色.倒计时效果...

    Android代码中设置字体大小,字体颜色,显示两种颜色 在xml文件中字体大小用的像素 android:id="@+id/uppaid_time" android:layout_ ...

  3. android如何设置自动补,Android Studio 中设置代码块自动补齐

    AS中很多提示键,并不如Eclipse中做的好,需要我们自己去自定义.这里以switch...case为例,讲解一下如何设置代码自动补全. 1.进入settings -->  Editor -- ...

  4. android studio创建md,如何在Android Studio中设置*md文件打开方式

    最近在Android Studio中写一些Demo的时候,会顺便在里面创建一个.md文件用来进行Demo笔记的书写.然而Android Studio不带有markdown预览功能,所以我就琢磨如何在A ...

  5. Android系统中设置TextView的行间距

    Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...

  6. android 动态设置margin,android 代码中设置margin

    场景:Android怎么在java代码中设置margin Android如何在java代码中设置margin 原创帖,转发请注明出处:http://thierry-xing.iteye.com/blo ...

  7. android studio资产目录,在Android Studio中设置单元测试的自定义资产目录

    我们对使用仅需要进行单元测试的资产的Android应用程序执行单元测试是不常见的要求. 使用基于Eclipse的SDK这是简单明了的 – 测试项目是一个单独的项目,其自有资产文件夹.使用Android ...

  8. android RadioGroup中设置selector后出现多个别选中的RadioButton的解决办法

    在一个RadioGroup组中假如有三个或者以上的RadioButton,当然你需要给这些RadioButton设置selector.设置其中的一个为默认选中状态(在xml中设置).当程序在手机上运行 ...

  9. Android开发中父类与子类通讯的一个简单实现

    在给出解决方案之前,提出一个问题:Android开发中如何将父类的改变及时通知给子类? 好吧,开始抓耳挠腮,可算是找出了解决方案: 1.在子类内注册父类的监听器 2.通过广播接收者(Broadcast ...

最新文章

  1. java data使用_@Data注解详解及使用方法-Fun言
  2. python切片语法-彻底搞懂Python切片操作
  3. ASP.net之策略模式
  4. 程序的内存分配之堆和栈的区别
  5. MySQL数据库查询时间段的两种方法
  6. 科技部成立新一代人工智能发展研究中心
  7. jqprint控件使用
  8. Flume监听端口,输出端口数据案例
  9. Splash广告界面
  10. eclipse安装Maven插件M2E
  11. android 阻止来电号码,4种方法来在安卓手机上阻止来电
  12. 相同风格,牛仔裤和青花瓷风行世界
  13. 从零开始学Java——基础篇
  14. make 与makefile(会不会写 makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。)...
  15. springboot集成Stream上传插件+图片缩略图+视频缩略图
  16. CF417D--- Cunning Gena(排序+状压dp)
  17. java 动态表头_java如何生成可变表头的excel
  18. Ubuntu包依赖损坏的解决unmet dependencies
  19. CSS 列表样式(ul)
  20. oeasy教您玩转vim - 59 - # 编辑总结

热门文章

  1. 动画css ---无限旋转
  2. Redis:Redis的简单使用
  3. 数据库完整性(实体完整性、参照完整性、用户定义的完整性、完整性约束命名字句、断言、触发器)
  4. 在Java中实现两数相乘
  5. 地图poi兴趣点下载
  6. API管理工具对比,制定您的API管理平台
  7. 安装Emscripten编译环境
  8. 安卓应用层与底层驱动之间的调用
  9. php服务器文件直链,如何获取百度网盘储存文件直链下载(PHP版)·站内下载
  10. 站长爆料:部分地区备案需提供纳税证明