海思hi3716c机顶盒接usb摄像头和usb无线耳机时,无线耳机有时没有声音
两个USB设备各自是:
A:USB摄像头带录音功能,但不带放音功能。
B:USB无线耳机是使用USB转2.4G的无线耳机。
详细现象:
1, A,B两者同一时候插上机顶盒,并开机进入android,此时去播放音乐或电影,声音是从HDMI出来的,并不是从无线耳机出来。
此时又一次插拔一下2.4G无线耳机,声音就会从耳机中出来。
2, 机顶盒上电。进入android系统,然后播放音乐或电影,此时声音从HDMI中出来。这个时候接上USB摄像头,声音还是从HDMI出来。
再接上无线耳机。这时候声音却还是从HDMI中出来,此时应该要从耳机出来。又一次插拔一下耳机就恢复正常了。
总结现象,基本能够得出一个结论:开机后。先插上USB摄像头再插上2.4G耳麦,声音并不会从耳机出来,仅仅有又一次插拔一次USB耳麦后才会正常。
从现象能够看出,出现异常的原因是音频系统没有从摄像头切换到麦克风。
细致查看日志,发现正常时会有一段以下的打印。不正常时并没有。
V/AudioService( 1582): Broadcast Receiver: Got ACTION_USB_ANLG_HEADSET_PLUG, state = 1
I/AudioPolicyManagerBase( 1059): setDeviceConnectionState() device: 800, state 1, address
I/AudioPolicyManagerBase( 1059): [setDeviceConnectionState : 245] device already connected: 16777216
V/WiredAccessoryObserver( 1582): Headset UEVENT: {SUBSYSTEM=switch, SWITCH_STATE=1, DEVPATH=/devices/virtual/switch/usb_audio, SEQNUM=1271, ACTION=change, SWITCH_NAME=usb_audio}
V/WiredAccessoryObserver( 1582): newState = 4, headsetState = 4,mHeadsetState = 0
V/WiredAccessoryObserver( 1582): Intent.ACTION_USB_HEADSET_PLUG: state: 1 name: usb_audio
从日志能够看出,AudioService收到了ACTION_USB_ANLG_HEADSET_PLUG广播消息。才干正常。在源代码中搜索发出ACTION_USB_ANLG_HEADSET_PLUG广播的地方,查得在WiredAccessoryObserver.java文件里sendIntent()函数调用了。
private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
.......
intent = new Intent(Intent.ACTION_USB_ANLG_HEADSET_PLUG);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra("state", state);
intent.putExtra("name", headsetName);
ActivityManagerNative.broadcastStickyIntent(intent, null);
.......
}
此函数被sendIntents()调用,接着被mHandler的handleMessage()调用。
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
sendIntents(msg.arg1, msg.arg2, (String)msg.obj);
mWakeLock.release();
}
};
接着被update()调用
private synchronized final void update(String newName, int newState) {
........
mHandler.sendMessageDelayed(mHandler.obtainMessage(0,
mHeadsetState,
mPrevHeadsetState,
mHeadsetName),
delay);
}
接着被updateState()调用。然后被onUEvent()调用。
onUEvent()重载了UEventObserver.java中的相应函数。细致查看该文件源代码能够得知当中有个线程会读取netlink消息。并由相应的Observer去处理。
在run()函数中增加打印日志的函数。将uevent打印出来。
public void run() {
native_setup();
byte[] buffer = new byte[1024];
int len;
while (true) {
len = next_event(buffer);
if (len > 0) {
String bufferStr = new String(buffer, 0, len); // easier to search a String
Log.d (TAG,"uevent:"+bufferStr);
synchronized (mObservers) {
for (int i = 0; i < mObservers.size(); i += 2) {
if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
((UEventObserver)mObservers.get(i+1))
.onUEvent(new UEvent(bufferStr));
}
}
}
}
}
}
改完后编译frameworks/base。将core.jar文件push到机顶盒进行測试。当正常时会有例如以下打印
D/UEventObserver( 1582): uevent:change@/devices/virtual/switch/usb_audio��ACTION=change��DEVPATH=/devices/virtual/switch/usb_audio��SUBSYSTEM=switch��SWITCH_NAME=usb_audio��SWITCH_STATE=1��SEQNUM=1271��
V/AudioService( 1582): Broadcast Receiver: Got ACTION_USB_ANLG_HEADSET_PLUG, state = 1
I/AudioPolicyManagerBase( 1059): setDeviceConnectionState() device: 800, state 1, address
I/AudioPolicyManagerBase( 1059): [setDeviceConnectionState : 245] device already connected: 16777216
V/WiredAccessoryObserver( 1582): Headset UEVENT: {SUBSYSTEM=switch, SWITCH_STATE=1, DEVPATH=/devices/virtual/switch/usb_audio, SEQNUM=1271, ACTION=change, SWITCH_NAME=usb_audio}
V/WiredAccessoryObserver( 1582): newState = 4, headsetState = 4,mHeadsetState = 0
V/WiredAccessoryObserver( 1582): Intent.ACTION_USB_HEADSET_PLUG: state: 1 name: usb_audio
从日志能够知道,不正常的原因在于kernel并没有发出uevent。google去查uevent机制,了解到change这个ACTION由KOBJ_CHANGE来控制。
依据uevent中SWITCH_NAME和SWITCH_STATE对kernel/下进行搜索,得到drivers/switch/switch_class.c文件。同一时候也依据KOBJ_CHANGE对drivers下进行搜索。也发现switch/switch_class.c文件,推測这个文件是关键。在switch_set_state()函数中增加打印,又一次编译内核,执行,查看日志,果然发现都调了这里。
void switch_set_state(struct switch_dev *sdev, int state)
{
......
if (sdev->state != state) {
sdev->state = state;
......
}
......
}
继续搜索调用switch_set_state()的地方,发如今sound/usb/card.c的snd_usb_audio_probe()函数中调用了。
static void *snd_usb_audio_probe(struct usb_device *dev,
struct usb_interface *intf,
const struct usb_device_id *usb_id)
{
......
//switch_set_state(&sdev, STATE_DISCONNECTED);
switch_set_state(&sdev, STATE_CONNECTED);
......
}
能够知道多个usb音频设备通过switch进行管理。一个时刻仅仅使用一个。
当带录音功能的usb摄像头插上时。sdev的状态改为已连接。
当usb耳麦接上后,相同会调用switch_set_state(),但由于先前已经连了一个usb音频设备。sdev->state已经变为1,不再继续发消息。于是我凝视掉推断语句:if (sdev->state != state) 。再次进行測试,发现uevent已经上报了,但声音仍然没有从usb耳麦中出来。
继续回到Android层,查看WiredAccessoryObserver.java中update()函数
private synchronized final void update(String newName, int newState) {
......
if (LOG) Slog.v(TAG, "newState = "+newState+", headsetState = "+headsetState+","
+ "mHeadsetState = "+mHeadsetState);
if (mHeadsetState == headsetState || ((h2w_headset & (h2w_headset - 1)) != 0)) {
Log.e(TAG, "unsetting h2w flag");
h2wStateChange = false;
}
// - c: 0 usb headset to 1 usb headset
// - d: 1 usb headset to 0 usb headset
if ((usb_headset_anlg >> 2) == 1 && (usb_headset_dgtl >> 3) == 1) {
Log.e(TAG, "unsetting usb flag");
usbStateChange = false;
}
if (!h2wStateChange && !usbStateChange) {
Log.e(TAG, "invalid transition, returning ...");
return;
}
.......
}
分析代码可知,因为上报的消息跟上次一样,此函数并未继续运行。
为了简单起见,我想直接在内核载入新的usb音频设备时先将switch断开原来的。再连接新的。于是在snd_usb_audio_probe()函数中,先运行switch_set_state(&sdev, STATE_DISCONNECTED);欺骗系统switch已经断开。然后再运行switch_set_state(&sdev, STATE_CONNECTED);
编译,烧录,測试后发现一切都正常了。录音与放音都正常。
当USB耳麦连接时用耳麦进行录音和放音。
当USB耳麦不在时用USB摄像头进行录音,由HDMI进行放音。
对这个结果感到非常意外。意想之中的状况应该是始终使用后插上的那个设备。查看日志后得知,由摄像头没有放音功能,在open这个设备进行放音的时候会失败。于是就会使用下一个设备,直到找到能放音的设备,查看日志发现这是alsa-lib这么设计的。为何录音也总是优先使用USB耳麦,没有深究,应该也是alsa-lib完毕了。
海思hi3716c机顶盒接usb摄像头和usb无线耳机时,无线耳机有时没有声音的更多相关文章
- 2.7 usb摄像头之usb摄像头描述符打印
学习目标:参考lsusb源码,打印USB摄像头的设备描述符.配置描述符.接口联合描述符.端点描述符: 一.lsusb命令和源码 使用命令lsusb可以看看设备的id,并执行 # lsusb -v -d ...
- RTSP流和USB摄像头转MJPEG使用VLC
测试环境: 系统: Ubuntu14.04 LTS Desktop 设备:海康IP摄像头和USB摄像头 1.需要先安装vlc包,命令行运行 sudo apt-get update sudo apt-g ...
- 主流芯片解决方案Ambarella的高清网络摄像机、德州仪器和控制海思
(本文由四川艾普作为数码科技有限公司 苏斌.范清华 收集) 高清网络视频监控发展到今天.正的高清时代.诸多有实力的高清摄像机厂家的产品线也逐渐完好起来,高清网络视频监控的配套产品有更加丰富和成熟.与此 ...
- 海思HI3518EV200+AR0130开发板DIY——前篇
海思HI3518EV200+AR0130开发板DIY 今天开始要围绕这个项目学习了(还是得从C开始学 ) 缘起(这段主要水废话)相关开发资料 →_→ 原理图设计 原理图整体框架 一.电源部分 HI35 ...
- [转帖]IPC网络高清摄像机基础知识1(IPC芯片市场分析以及“搅局者”华为海思 “来自2013年”)
IPC网络高清摄像机基础知识1(IPC芯片市场分析以及“搅局者”华为海思 “来自2013年”) 2016-06-02 14:23:49 Times_poem 阅读数 9734更多 分类专栏: IPC网 ...
- Hi3516开发笔记(一):海思HI3516DV300芯片介绍,入手开发板以及Demo测试
前言 目前主流国产芯片为RV11XX.RK33XX.Hi35XX系列,本系列开启Hi3516系列的开发教程. Hi3516DV300芯片介绍 Hi3516DV300为专业行Smart IP ...
- 海思3516系列芯片SPI速率慢问题深入分析与优化(基于PL022 SPI 控制器)
海思3516系列芯片SPI速率慢问题深入分析与优化(基于PL022 SPI 控制器) 我在某个海思主控的项目中需要使用SPI接口来驱动一块液晶屏,液晶屏主控为 st7789,分辨率 240x240,图 ...
- 海思h264解码库
海思的dll,解码h264 解码后转出yuv12 dll自己百度下载 hi_h264dec.dll hi_h264dec_w.dll 调用方法: if (H264Dec.Hi264DecA ...
- 海思H264解码库 hi_h264dec_w.dll 水印问题
上一篇 海思h264解码库 , 实现了H264帧的简单解码,但更换相机后,出现了解码视频中央出现水印的问题,水印如下图 查找网络,基本就这一篇相关的,还没给出好的解决办法. http://bbs. ...
随机推荐
- canvas和svg区别
什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canvas 拥有多种绘制路径.矩形.圆形.字符以 ...
- vim学习2
进入插入模式: 在插入模式下删除: 寄存器
- Unity5中的粒子缩放(附测试源码)
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/49363241 作者:car ...
- 【Educational Codeforces Round 35 D】Inversion Counting
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 排列中交换任意两个数字. 排列的逆序对个数的奇偶性会发生变化. 翻转这个过程其实就是len/2对数字发生交换. 交换了偶数次的话,不 ...
- 【2017"百度之星"程序设计大赛 - 初赛(A)】数据分割
[链接]http://acm.hdu.edu.cn/showproblem.php?pid=6109 [题意] 在这里写题意 [题解] 要处理的关系越多,肯定就越容易错. ->单调性. 根据这个 ...
- Mysql多实例安装+主从复制+读写分离 -学习笔记
Mysql多实例安装+主从复制+读写分离 -学习笔记 .embody{ padding:10px 10px 10px; margin:0 -20px; border-bottom:solid 1px ...
- 让我们彻底看清MVC、MVP
这里開始记录下来自己对MVC.MVP.MVVM这三种框架模式的理解,本文从以下几个方面来梳理. 架构的目的 框架模式.设计模式 MVC设计的介绍 MVC在Android中的应用 MVC该怎样设计 MV ...
- Maven搭建Spring Security3.2项目详解
本来是打算在上一篇SpringMVC+Hibernate上写的,结果发现上面那篇 一起整合的,结果发现上一篇内容实在是太长了,就另起一篇,这篇主要是采用 Maven搭建Spring+SpringMVC ...
- echarts+百度地图+vue 填坑记(一)(百度地图、鼠标移入移出标注,信息框会产生闪烁)
大概七月底开始实习,到现在经历了两个完整的项目(c2b). 因为开发时间紧,任务重,所以在开发过程踩到的坑都没时间去记录. 现在在开发一个某链运输监控系统,到了收尾阶段,有时间写博客了!开心! 一.鼠 ...
- echarts3.0 仪表盘实例更改完成占用率实例
需要完成的项目效果 官方实例效果 基本思路: 首先引入jquery和echarts3.0库. 需要两个仪表盘,一个仪表盘是纯色灰色,在底部.startAngle 和endAngle永远是最大值,默认为 ...