海思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:[email protected]/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完毕了。

时间: 2024-12-17 22:00:06

海思hi3716c机顶盒接usb摄像头和usb无线耳机时,无线耳机有时没有声音的相关文章

海思Hi3516A(2)MIPI

1. 概述 这里讨论MIPI协议以及对应的发送端和接收端,发送端为smartsens的360万像素的SC3035-M,接收端为海思的Hi3516A. MIPI(Mobile Idustry Processor Interface)是MIPI联盟发起的移动应用处理器制定的标准,广泛应用于摄像头接口.显示屏接口等. 2. MIPI发送端 MIPI发送端为smartsens的SC3035-M摄像头芯片,支持1-4通道来传输8/10/12bit图像.MIPI底层数据包包含短包和长包数据,短包用来同步,长

(转)海思3515 Hi3515 ARM 核心板 最小系统板 留出所有接口 带 JTAG

海思Hi3515 为 ARM9的内核+DSP组成 可以H264编码 4路D1或者1路1080P 或 H264解码 4路D1或者1路1080P 同时芯片本身带丰富的外围接口 UARTx4 SATAx2 USB Hostx2 SD SPI LAN IR I2C VGA输出 CVBS输出 和大量的 GPIO 等 软件上,系统跑Linux 2.6.24 的系统,使用gcc/g++编译器 核心板组成 Hi3515 + DDR(2Gbit) + FLASH(256Mbit/32MByte) + RTL820

高清网络摄像机主流芯片方案之安霸、德仪和海思对比

(本文由四川艾普视达数码科技有限公司 苏彬.范清华 搜集整理) 高清网络视频监控发展到今天,市场也开始进入真正的高清时代,诸多有实力的高清摄像机厂家的产品线也逐渐完善起来,高清网络视频监控的配套产品有更加丰富和成熟.与此同时困扰很多人的高清网络摄像机与后端平台或者与后端NVR互联互通的问题也在逐渐迎刃而解,这得益于各个方案研发公司.生产厂家.平台商.标准协议组织都不遗余力的在网络摄像机协议对接这块投入了大量精力,使得高清网络摄像机与第三方设备或者软件平台的对接不再像早期那么尴尬.现阶段面向市场的

IPC网络高清摄像机基础知识1(IPC芯片市场分析以及“搅局者”华为海思 “来自2013年”)

需求说明:了解IPC(IP Camera)网络摄像头行业 来自:http://info.secu.hc360.com/2013/06/031051730705-all.shtml#m4 阅读精华整理: 1.对于网络摄像机(IPCamera以下简称:IPC)而言,它用到的解决方案包括成像方案和编解码芯片方案两部分. 成像方案上,商家在CCD或CMOS这两个图像传感器流派间选择.在网络高清方面,采用CMOS的居多,盖因其技术比 较成熟,低功耗.高集成度以及性价比高:而且,CCD做高清还有响应速度慢.

主流芯片解决方案Ambarella的高清网络摄像机、德州仪器和控制海思

(本文由四川艾普作为数码科技有限公司 苏斌.范清华 收集) 高清网络视频监控发展到今天.正的高清时代.诸多有实力的高清摄像机厂家的产品线也逐渐完好起来,高清网络视频监控的配套产品有更加丰富和成熟.与此同一时候困扰非常多人的高清网络摄像机与后端平台或者与后端NVR互联互通的问题也在逐渐迎刃而解,这得益于各个方案研发公司.生产厂家.平台商.标准协议组织都不遗余力的在网络摄像机协议对接这块投入了大量精力,使得高清网络摄像机与第三方设备或者软件平台的对接不再像早期那么尴尬.现阶段面向市场的高清推广商以及

[转帖]IPC网络高清摄像机基础知识1(IPC芯片市场分析以及“搅局者”华为海思 “来自2013年”)

IPC网络高清摄像机基础知识1(IPC芯片市场分析以及“搅局者”华为海思 “来自2013年”) 2016-06-02 14:23:49 Times_poem 阅读数 9734更多 分类专栏: IPC网络摄像头基础知识 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/Times_poem/article/details/51566877 需求说明:了解IPC(IP Camera)网络摄像头行

海思Hi3518EV200(2)开发环境

1. Linux开发环境 2. Linux开发环境描述 3. 搭建Linux开发环境 1) 安装Linux服务器 这里使用ubuntu 10.04 LTS 2) 安装交叉编译工具 海思SDK包中提供专门的编译工具链:arm-hisiv300-linux和arm-hisiv400-linux. 3) 安装SDK 将Hi3518E_V200R001XX.tgz拷贝到linux服务器上,解压tar后执行./sdk.unpack 4) 烧写uboot/内核/根文件系统 这里使用SDK包里面默认的uboo

ubuntu12.04+fuerte 下跑通lsd-slam——使用usb摄像头

上一篇介绍了如何使用数据集跑lsd-slam,这篇介绍如何用一个普通的usb摄像头跑lsd-slam,默认ubuntu12.04,fuerte已经安装好,workspace也已设置,如果没有,请参考上一篇数据集下跑lsd-slam的博文. 我使用的摄像头是罗技c310 usb摄像头,其他的usb摄像头应该也没什么问题. 1.测试摄像头好坏.安装cheese,执行 $ sudo apt-get install cheese 运行cheese,执行 $ cheese 确认摄像头是否能在ubuntu下

《通过Web远程浏览并控制Tiny6410上的usb摄像头》---实战篇

时间不早了,简单介绍直奔主题哈 一.介绍 软件:Mjpeg‐stream 是一个开源软件,用于把mjpeg格式的文件变成流媒体输出. 平台:Tiny6410 硬件:普通usb摄像头 二.编译.安装方法不多讲,网上写的比较好的博文很多 三.pc上测试效果(只能用火狐,ie.360浏览器均不正常显示) 1>地址栏输入:http://192.168.1.107:8080/?action=stream     (视频) 2>或者地址栏输入:http://192.168.1.107:8080/?acti