RK3288 Android7.1 接USB摄像头后扬声器无声音
生活随笔
收集整理的這篇文章主要介紹了
RK3288 Android7.1 接USB摄像头后扬声器无声音
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
問題
接入某些USB攝像頭后, 揚(yáng)聲器沒有聲音
2017-01-01 21:19:24.770 228-287/? E/AudioHardwareTiny: pcm_open(PCM_CARD_HDMI) failed: 222 cannot open device '/dev/snd/pcmC0D1p': No such file or directory原因
USB攝像頭包含有MIC輸入, 在啟動(dòng)初始化后, 會(huì)直接搶占card0, 而默認(rèn)的聲卡的初始化比這個(gè)慢, 導(dǎo)致card0中, 只有一個(gè)有效的輸入, 而沒有輸出;
主要的原因還是, 在HAL中, 并沒有對(duì)無(wú)效的輸出作處理, 有的, 只有上面一個(gè)錯(cuò)誤的LOG.
解決方案
-
方案一
修改USB上電順序, 延遲初始化到主板聲卡后 -
方案二
修改HAL, 在打開card0失敗后, 嘗試打開主板聲卡, 可能是card1, card2…
參考:
狀態(tài)信息
//聲卡 rk3288:/ # ll proc/asound/ total 0 lrwxrwxrwx 1 root root 5 2017-01-02 00:52 AMCAP -> card0 dr-xr-xr-x 3 root root 0 2017-01-02 00:52 card0 dr-xr-xr-x 5 root root 0 2017-01-02 00:52 card1 -r--r--r-- 1 root root 0 2017-01-02 00:52 cards -r--r--r-- 1 root root 0 2017-01-02 00:52 devices -r--r--r-- 1 root root 0 2017-01-02 00:52 hwdep -r--r--r-- 1 root root 0 2017-01-02 00:52 pcm lrwxrwxrwx 1 root root 5 2017-01-02 00:52 rockchipes8316c -> card1 -r--r--r-- 1 root root 0 2017-01-02 00:52 timers -r--r--r-- 1 root root 0 2017-01-02 00:52 version//聲卡信息, 0為USB攝像頭 rk3288:/ # cat /proc/asound/cards 0 [AMCAP ]: USB-Audio - USB 2.0 AMCAPSonix Technology Co., Ltd. USB 2.0 AMCAP at usb-ff540000.usb-1.2, high speed1 [rockchipes8316c]: rockchip_es8316 - rockchip,es8316-codecrockchip,es8316-codec//聲卡設(shè)備 rk3288:/ # cat /proc/asound/devices 2: [ 0] : control3: [ 0- 0]: digital audio capture4: [ 1] : control5: [ 1- 0]: digital audio playback6: [ 1- 0]: digital audio capture7: [ 1- 1]: digital audio playback33: : timer//設(shè)備節(jié)點(diǎn) rk3288:/dev/snd # ll total 0 crw-rw---- 1 system audio 116, 2 2017-01-02 00:26 controlC0 crw-rw---- 1 system audio 116, 4 2017-01-02 00:26 controlC1 crw-rw---- 1 system audio 116, 3 2017-01-02 00:26 pcmC0D0c crw-rw---- 1 system audio 116, 6 2017-01-02 00:26 pcmC1D0c crw-rw---- 1 system audio 116, 5 2017-01-02 00:26 pcmC1D0p crw-rw---- 1 system audio 116, 7 2017-01-02 00:26 pcmC1D1p crw-rw---- 1 system audio 116, 33 2017-01-02 00:26 timer //輸出PCM信息 rk3288:/ # tinypcminfo -D 0 Info for card 0, device 0:PCM out: cannot open device '/dev/snd/pcmC0D0p' Device does not exist.PCM in:Access: 0x000009Format[0]: 0x000004Format[1]: 00000000Format Name: S16_LESubformat: 0x000001Rate: min=8000Hz max=48000HzChannels: min=2 max=2Sample bits: min=16 max=16Period size: min=16 max=131072 Period count: min=2 max=1024rk3288:/ # tinypcminfo -D 1 Info for card 1, device 0:PCM out:Access: 0x000009Format[0]: 0x000044Format[1]: 00000000Format Name: S16_LE, S24_LESubformat: 0x000001Rate: min=8000Hz max=96000HzChannels: min=2 max=2Sample bits: min=16 max=32Period size: min=32 max=65536 Period count: min=2 max=4096PCM in:Access: 0x000009Format[0]: 0x000044Format[1]: 00000000Format Name: S16_LE, S24_LESubformat: 0x000001Rate: min=8000Hz max=96000HzChannels: min=2 max=2Sample bits: min=16 max=32Period size: min=32 max=65536 Period count: min=2 max=4096相關(guān)源碼
rk3288_n712$ ll hardware/rockchip/audio/tinyalsa_hal/ alsa_audio.h alsa_mixer.c alsa_route.c amix.c Android.mk asound.h audio_bitstream.c audio_bitstream.h audio_hw.c audio_hw.h audio_hw_hdmi.c audio_hw_hdmi.h audio_setting.c audio_setting.h codec_config/ voice_preprocess.c voice_preprocess.h|-- hardware/rockchip/audio/tinyalsa_hal/audio_hw.c
static int start_output_stream(struct stream_out *out) {ALOGD("start_output_stream");char value[PROPERTY_VALUE_MAX] = "";struct audio_device *adev = out->dev;int type;bool connect_hdmi = true;int ret = 0;ALOGD("%s",__FUNCTION__);if (out == adev->outputs[OUTPUT_HDMI_MULTI]) {force_non_hdmi_out_standby(adev);} else if (adev->outputs[OUTPUT_HDMI_MULTI] && !adev->outputs[OUTPUT_HDMI_MULTI]->standby) {out->disabled = true;return 0;}out->disabled = false;read_hdmi_audioinfo();int device = getOutputDevice();ALOGD("start_output_stream device=%x", device);ALOGD("start_output_stream out->device=%x", out->device);if (device == SPDIF_PASSTHROUGH_MODE) {out->device &= ~AUDIO_DEVICE_OUT_AUX_DIGITAL;out->device |= AUDIO_DEVICE_OUT_SPDIF;} else if (device == HDMI_BITSTREAM_MODE) {out->device &= ~AUDIO_DEVICE_OUT_SPDIF;out->device |= AUDIO_DEVICE_OUT_AUX_DIGITAL;} #ifdef BOX_HALif (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {/*BOX hdmi & codec use the same i2s,so only config the codec card*/out->device &= ~AUDIO_DEVICE_OUT_SPEAKER;}read_snd_card_info();if (out->config.flag == HW_PARAMS_FLAG_LPCM){if(hasSpdif() && ((out->device & AUDIO_DEVICE_OUT_SPDIF)==0)){out->device |= AUDIO_DEVICE_OUT_SPDIF;}} #ifdef RK3228if (out->config.flag == HW_PARAMS_FLAG_LPCM) {if (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {out->device |= AUDIO_DEVICE_OUT_SPEAKER;}} #endifout_dump(out, 0); #endifconnect_hdmi = true;route_pcm_open(getRouteFromDevice(out->device));if (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL) {if (connect_hdmi) { #ifdef BOX_HAL #ifdef USE_DRMint ret = 0;ret = mixer_mode_set(out);if (ret!=0) {ALOGE("mixer mode set error,ret=%d!",ret);} #endif #endifout->pcm_device = 1;out->pcm[PCM_CARD_HDMI] = pcm_open(PCM_CARD_HDMI, out->pcm_device,PCM_OUT | PCM_MONOTONIC, &out->config);if (out->pcm[PCM_CARD_HDMI] &&!pcm_is_ready(out->pcm[PCM_CARD_HDMI])) {ALOGE("pcm_open(PCM_CARD_HDMI) failed:111 %s",pcm_get_error(out->pcm[PCM_CARD_HDMI]));pcm_close(out->pcm[PCM_CARD_HDMI]);return -ENOMEM;}} else {ALOGD("The current HDMI is DVI mode");out->device |= AUDIO_DEVICE_OUT_SPEAKER;}}if (out->device & (AUDIO_DEVICE_OUT_SPEAKER |AUDIO_DEVICE_OUT_WIRED_HEADSET |AUDIO_DEVICE_OUT_WIRED_HEADPHONE |AUDIO_DEVICE_OUT_ALL_SCO)) {/* open & close hdmi card to mute hdmi audio */out->pcm_device = 1;out->pcm[PCM_CARD_HDMI] = pcm_open(PCM_CARD_HDMI, out->pcm_device,PCM_OUT | PCM_MONOTONIC, &out->config);if (out->pcm[PCM_CARD_HDMI] &&!pcm_is_ready(out->pcm[PCM_CARD_HDMI])) {ALOGE("pcm_open(PCM_CARD_HDMI) failed: 222 %s",pcm_get_error(out->pcm[PCM_CARD_HDMI]));pcm_close(out->pcm[PCM_CARD_HDMI]);return -ENOMEM;}if (out->pcm[PCM_CARD_HDMI])pcm_close(out->pcm[PCM_CARD_HDMI]);out->pcm_device = 0;out->pcm[PCM_CARD] = pcm_open(PCM_CARD, out->pcm_device,PCM_OUT | PCM_MONOTONIC, &out->config);if (out->pcm[PCM_CARD] && !pcm_is_ready(out->pcm[PCM_CARD])) {ALOGE("pcm_open(PCM_CARD) failed: %s",pcm_get_error(out->pcm[PCM_CARD]));pcm_close(out->pcm[PCM_CARD]);return -ENOMEM;}}if (out->device & AUDIO_DEVICE_OUT_SPDIF) {out->pcm_device = 0;out->pcm[PCM_CARD_SPDIF] = pcm_open(PCM_CARD_SPDIF, out->pcm_device,PCM_OUT | PCM_MONOTONIC, &out->config);if (out->pcm[PCM_CARD_SPDIF] &&!pcm_is_ready(out->pcm[PCM_CARD_SPDIF])) {ALOGE("pcm_open(PCM_CARD_SPDIF) failed: %s",pcm_get_error(out->pcm[PCM_CARD_SPDIF]));pcm_close(out->pcm[PCM_CARD_SPDIF]);return -ENOMEM;}}adev->out_device |= out->device;if (out->device & AUDIO_DEVICE_OUT_ALL_SCO) {start_bt_sco(adev); #ifdef BT_AP_SCO // HARD CODE FIXMEout->pcm[PCM_BT] = pcm_open(PCM_BT, 0,PCM_OUT | PCM_MONOTONIC, &pcm_config_ap_sco);ret = create_resampler(48000,8000,2,RESAMPLER_QUALITY_DEFAULT,NULL,&out->resampler);if (ret != 0) {ret = -EINVAL;} #endif}if(adev->hdmiin_state){ALOGD("%s HDMIin state open hdmiin route",__FUNCTION__);route_pcm_open(HDMI_IN_NORMAL_ROUTE);}return 0; }|-- external/tinyalsa/pcm.c(PCM結(jié)構(gòu)體)
struct pcm {int fd;unsigned int flags;int running:1;int prepared:1;int underruns;unsigned int buffer_size;unsigned int boundary;char error[PCM_ERROR_MAX];struct pcm_config config;struct snd_pcm_mmap_status *mmap_status;struct snd_pcm_mmap_control *mmap_control;struct snd_pcm_sync_ptr *sync_ptr;void *mmap_buffer;unsigned int noirq_frames_per_msec;int wait_for_avail_min; };struct pcm *pcm_open(unsigned int card, unsigned int device,unsigned int flags, struct pcm_config *config) {struct pcm *pcm;struct snd_pcm_info info;struct snd_pcm_hw_params params;struct snd_pcm_sw_params sparams;char fn[256];int rc;pcm = calloc(1, sizeof(struct pcm));if (!pcm || !config)return &bad_pcm; /* TODO: could support default config here */pcm->config = *config;snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,flags & PCM_IN ? 'c' : 'p');pcm->flags = flags;pcm->fd = open(fn, O_RDWR|O_NONBLOCK);if (pcm->fd < 0) {oops(pcm, errno, "cannot open device '%s'", fn);return pcm;}if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &~O_NONBLOCK) < 0) {oops(pcm, errno, "failed to reset blocking mode '%s'", fn);goto fail_close;}if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {oops(pcm, errno, "cannot get info");goto fail_close;}param_init(¶ms);param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT,pcm_format_to_alsa(config->format));param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT,SNDRV_PCM_SUBFORMAT_STD);param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, config->period_size);param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,pcm_format_to_bits(config->format));param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS,pcm_format_to_bits(config->format) * config->channels);param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS,config->channels);param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, config->period_count);param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, config->rate);param_set_flag(¶ms, config->flag);if (flags & PCM_NOIRQ) {if (!(flags & PCM_MMAP)) {oops(pcm, -EINVAL, "noirq only currently supported with mmap().");goto fail_close;}params.flags |= SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;pcm->noirq_frames_per_msec = config->rate / 1000;}if (flags & PCM_MMAP)param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS,SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);elseparam_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS,SNDRV_PCM_ACCESS_RW_INTERLEAVED);if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) {oops(pcm, errno, "cannot set hw params");goto fail_close;}/* get our refined hw_params */config->period_size = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);config->period_count = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS);pcm->buffer_size = config->period_count * config->period_size;if (flags & PCM_MMAP) {pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size),PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pcm->fd, 0);if (pcm->mmap_buffer == MAP_FAILED) {oops(pcm, -errno, "failed to mmap buffer %d bytes\n",pcm_frames_to_bytes(pcm, pcm->buffer_size));goto fail_close;}}memset(&sparams, 0, sizeof(sparams));sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;sparams.period_step = 1;if (!config->start_threshold) {if (pcm->flags & PCM_IN)pcm->config.start_threshold = sparams.start_threshold = 1;elsepcm->config.start_threshold = sparams.start_threshold =config->period_count * config->period_size / 2;} elsesparams.start_threshold = config->start_threshold;/* pick a high stop threshold - todo: does this need further tuning */if (!config->stop_threshold) {if (pcm->flags & PCM_IN)pcm->config.stop_threshold = sparams.stop_threshold =config->period_count * config->period_size * 10;elsepcm->config.stop_threshold = sparams.stop_threshold =config->period_count * config->period_size;}elsesparams.stop_threshold = config->stop_threshold;if (!pcm->config.avail_min) {if (pcm->flags & PCM_MMAP)pcm->config.avail_min = sparams.avail_min = pcm->config.period_size;elsepcm->config.avail_min = sparams.avail_min = 1;} elsesparams.avail_min = config->avail_min;sparams.xfer_align = config->period_size / 2; /* needed for old kernels */sparams.silence_threshold = config->silence_threshold;sparams.silence_size = config->silence_size;pcm->boundary = sparams.boundary = pcm->buffer_size;while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size)pcm->boundary *= 2;if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {oops(pcm, errno, "cannot set sw params");goto fail;}rc = pcm_hw_mmap_status(pcm);if (rc < 0) {oops(pcm, rc, "mmap status failed");goto fail;}#ifdef SNDRV_PCM_IOCTL_TTSTAMPif (pcm->flags & PCM_MONOTONIC) {int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;rc = ioctl(pcm->fd, SNDRV_PCM_IOCTL_TTSTAMP, &arg);if (rc < 0) {oops(pcm, rc, "cannot set timestamp type");goto fail;}} #endifpcm->underruns = 0;return pcm;fail:if (flags & PCM_MMAP)munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size)); fail_close:close(pcm->fd);pcm->fd = -1;return pcm; }int pcm_is_ready(struct pcm *pcm) {return pcm->fd >= 0; }資源
完整補(bǔ)丁下載
總結(jié)
以上是生活随笔為你收集整理的RK3288 Android7.1 接USB摄像头后扬声器无声音的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络空间搜索FOFA
- 下一篇: 彻底解决EMI问题,只需8秒