海思hi3716c机顶盒接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 ...
- RK3288 Android7.1 接USB摄像头后扬声器无声音
问题 接入某些USB摄像头后, 扬声器没有声音 2017-01-01 21:19:24.770 228-287/? E/AudioHardwareTiny: pcm_open(PCM_CARD_HDM ...
- 海思Hi3798MV200机顶盒芯片处理器简介
Hi3798MV200是用于IPTV/OTT机顶盒市场的支持4KP60解码的全4K高性能SOC芯片.集成4核64位高性能Cortex A53处理器和多核高性能2D/3D加速引擎:支持H.265 4Kx ...
- 【海思3798系列机顶盒NAS分区表修改软件】
修改软件下载地址:海思3798系列机顶盒NAS分区表修改软件-makebootargs.exe-Linux文档类资源-CSDN下载可以修改海思机顶盒hi3798mv系列机顶盒分区文件生成,可以修改分区 ...
- 海思一颗料暴涨7倍,全球芯片缺货真相:原厂38颗MCU掌控汽车产业链
origin: https://new.qq.com/omn/20210309/20210309A031G200.html 2020年一场前所未有的疫情灾难席卷全球,作为全球化分工最明确的半导体产业首 ...
- 如何用海思HI3516DV300/3518EV200推流H.264
一开始尝试用hi3518EV200, 后来为了给自己加难度, 就买了个hi3516的板子, 看看差异多大, 结论是, 不大... 前期准备: 你得有一个3516或者3518的开发板(淘宝有卖各种开发板 ...
- 【原创】IP摄像头技术纵览(一)---linux 内核编译,USB摄像头设备识别
IP摄像头技术纵览(一)- linux 内核编译,USB摄像头设备识别 开始正文之前先来认识一下我的开发环境: 系统:ubuntu 10.04 开发板:AT91SAM9260 + Linux-2.6. ...
- 1.gstreamer USB摄像头保存至图片及视频
目录 1.操作系统版本 2.USB摄像头驱动 3.usb摄像头预览 4.采集USB摄像头保存至图片 5.采集USB摄像头保存至mp4文件 1.操作系统版本 使用的虚拟机加ubuntu 20.04 2. ...
- php调用linux摄像头,Linux_Linux中开发USB摄像头驱动详解,USB摄像头以其良好的性能和低 - phpStudy...
Linux中开发USB摄像头驱动详解 USB摄像头以其良好的性能和低廉的价格得到广泛应用.同时因其灵活.方便的特性,易于集成到嵌入式系统中.但是如果使用现有的符合Video for Linux标准的驱 ...
最新文章
- 生命的礼赞,请记住我的名字,我叫科比-布莱恩特
- 从头开始写框架(一):浅谈JS模块化发展
- linux 云主机 卡顿 排查过程
- Quartz教程二:API,Job和Trigger
- C语言面向对象编程(一):封装与继承
- 浅谈数据中的偏差问题和推荐系统去偏最新研究进展
- html rotate()函数,CSS rotate()用法及代码示例
- mysql 5.7.11 x64_mysql 5.7.11 winx64安装配置教程
- Python+OpenCV:Canny边缘检测
- 《TCP IP 详解卷1:协议》阅读笔记 - 第十四章
- 深度理解Powell优化算法
- 微信小黄鸡php,微信表情包小黄鸡含义
- Power BI前置知识+ 一张报表制作的流程
- prisma2.0和nexus搭建graphql后端(1)—prisma2.0
- 关于iphone手机影片预览的格式 转自 我的恩师 郑哥
- 机器学习实战——绘制决策树(代码)
- Android实战(MediaPlayer填坑)
- 自己写小工具 让工作更简单更效率
- C语言 -统计并打印1000年-2000年之间的闰年
- 操作简单的影音文件播放工具-万能播放器下载
热门文章
- mips中的li_MIPS学习笔记(一)
- python 使用多个elif代码块 计算阶梯电费
- [转]设置IE背景色保护你的眼睛视力_鹤壁吧_贴吧
- 常见几个排序源码及二分查找源码
- matlab利用已知数据画图三维,Matlab三维数据画图和等高线数据提取
- 重磅:Mobileye官宣推迟IPO,营收增速放缓、市场竞争加剧
- 饭谈:盘点六种错误的技术问题提问
- 安卓玩机搞机-----没有第三方包 刷写第三方各种GSI系统 体验非官方系统
- 物联网卡要求实名认证的真正原因你知道吗?
- linux 无线网卡ping不同,请教高手,本地网卡和无线网卡均不能ping通网关