不插usb声卡时,录像机无法关闭


问题:

当不插usb声卡时,打开录像机,点录像键,几秒钟后系统提示错误,退出,再次点击录像键或照相机,均打不开

 

用录像机录像时,要打开音频输入设备

在AudioFlinger层

frameworks/base/services/audioflinger/AudioFlinger.cpp

[cpp] view plain copy print ?
  1. int AudioFlinger::openInput(uint32_t *pDevices,  
  2.                                 uint32_t *pSamplingRate,  
  3.                                 uint32_t *pFormat,  
  4.                                 uint32_t *pChannels,  
  5.                                 uint32_t acoustics)  
  6. {  
  7.     status_t status;  
  8.     RecordThread *thread = NULL;  
  9.     uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;  
  10.     uint32_t format = pFormat ? *pFormat : 0;  
  11.     uint32_t channels = pChannels ? *pChannels : 0;  
  12.     uint32_t reqSamplingRate = samplingRate;  
  13.     uint32_t reqFormat = format;  
  14.     uint32_t reqChannels = channels;  
  15.     audio_stream_in_t *inStream;  
  16.     audio_hw_device_t *inHwDev;  
  17.   
  18.     if (pDevices == NULL || *pDevices == 0) {  
  19.         return 0;  
  20.     }  
  21.   
  22.     Mutex::Autolock _l(mLock);  
  23.   
  24.     inHwDev = findSuitableHwDev_l(*pDevices);  
  25.     if (inHwDev == NULL)  
  26.         return 0;  
  27.   
  28.     status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,  
  29.                                         &channels, &samplingRate,  
  30.                                         (audio_in_acoustics_t)acoustics,  
  31.                                         &inStream); //问题出在这,当没有USB声卡时,这个函数没有返回。   
  32.     LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",  
  33.             inStream,  
  34.             samplingRate,  
  35.             format,  
  36.             channels,  
  37.             acoustics,  
  38.             status);  
  39.   
  40.     // If the input could not be opened with the requested parameters and we can handle the conversion internally,   
  41.     // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo   
  42.     // or stereo to mono conversions on 16 bit PCM inputs.   
  43.     if (inStream == NULL && status == BAD_VALUE &&  
  44.         reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&  
  45.         (samplingRate <= 2 * reqSamplingRate) &&  
  46.         (getInputChannelCount(channels) < 3) && (getInputChannelCount(reqChannels) < 3)) {  
  47.         LOGV("openInput() reopening with proposed sampling rate and channels");  
  48.         status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,  
  49.                                             &channels, &samplingRate,  
  50.                                             (audio_in_acoustics_t)acoustics,  
  51.                                             &inStream);  
  52.     }  
  53.   
  54.     if (inStream != NULL) {  
  55.         AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);  
  56.   
  57.         int id = nextUniqueId();  
  58.         // Start record thread   
  59.         // RecorThread require both input and output device indication to forward to audio   
  60.         // pre processing modules   
  61.         uint32_t device = (*pDevices) | primaryOutputDevice_l();  
  62.         thread = new RecordThread(this,  
  63.                                   input,  
  64.                                   reqSamplingRate,  
  65.                                   reqChannels,  
  66.                                   id,  
  67.                                   device);  
  68.         mRecordThreads.add(id, thread);  
  69.         LOGV("openInput() created record thread: ID %d thread %p", id, thread);  
  70.         if (pSamplingRate) *pSamplingRate = reqSamplingRate;  
  71.         if (pFormat) *pFormat = format;  
  72.         if (pChannels) *pChannels = reqChannels;  
  73.   
  74.         input->stream->common.standby(&input->stream->common);  
  75.   
  76.         // notify client processes of the new input creation   
  77.         thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);  
  78.         return id;  
  79.     }  
  80.   
  81.     return 0;  
  82. }  
int AudioFlinger::openInput(uint32_t *pDevices, uint32_t *pSamplingRate, uint32_t *pFormat, uint32_t *pChannels, uint32_t acoustics) { status_t status; RecordThread *thread = NULL; uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0; uint32_t format = pFormat ? *pFormat : 0; uint32_t channels = pChannels ? *pChannels : 0; uint32_t reqSamplingRate = samplingRate; uint32_t reqFormat = format; uint32_t reqChannels = channels; audio_stream_in_t *inStream; audio_hw_device_t *inHwDev; if (pDevices == NULL || *pDevices == 0) { return 0; } Mutex::Autolock _l(mLock); inHwDev = findSuitableHwDev_l(*pDevices); if (inHwDev == NULL) return 0; status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format, &channels, &samplingRate, (audio_in_acoustics_t)acoustics, &inStream); //问题出在这,当没有USB声卡时,这个函数没有返回。 LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d", inStream, samplingRate, format, channels, acoustics, status); // If the input could not be opened with the requested parameters and we can handle the conversion internally, // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo // or stereo to mono conversions on 16 bit PCM inputs. if (inStream == NULL && status == BAD_VALUE && reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT && (samplingRate <= 2 * reqSamplingRate) && (getInputChannelCount(channels) < 3) && (getInputChannelCount(reqChannels) < 3)) { LOGV("openInput() reopening with proposed sampling rate and channels"); status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format, &channels, &samplingRate, (audio_in_acoustics_t)acoustics, &inStream); } if (inStream != NULL) { AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream); int id = nextUniqueId(); // Start record thread // RecorThread require both input and output device indication to forward to audio // pre processing modules uint32_t device = (*pDevices) | primaryOutputDevice_l(); thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id, device); mRecordThreads.add(id, thread); LOGV("openInput() created record thread: ID %d thread %p", id, thread); if (pSamplingRate) *pSamplingRate = reqSamplingRate; if (pFormat) *pFormat = format; if (pChannels) *pChannels = reqChannels; input->stream->common.standby(&input->stream->common); // notify client processes of the new input creation thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED); return id; } return 0; }



  

在AudioHardware层

hardware/qcom/media/audio/msm8660/audio_hw_hal.cpp

[cpp] view plain copy print ?
  1. static int qcom_adev_open(const hw_module_t* module, const char* name,  
  2.                             hw_device_t** device)  
  3. {  
  4.     struct qcom_audio_device *qadev;  
  5.     int ret;  
  6.   
  7.     if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)  
  8.         return -EINVAL;  
  9.   
  10.     qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev));  
  11.     if (!qadev)  
  12.         return -ENOMEM;  
  13.   
  14.     qadev->device.common.tag = HARDWARE_DEVICE_TAG;  
  15.     qadev->device.common.version = 0;  
  16.     qadev->device.common.module = const_cast<hw_module_t*>(module);  
  17.     qadev->device.common.close = qcom_adev_close;  
  18.   
  19.     qadev->device.get_supported_devices = adev_get_supported_devices;  
  20.     qadev->device.init_check = adev_init_check;  
  21.     qadev->device.set_voice_volume = adev_set_voice_volume;  
  22.     qadev->device.set_master_volume = adev_set_master_volume;  
  23.     qadev->device.set_fm_volume = adev_set_fm_volume;  
  24.     qadev->device.set_mode = adev_set_mode;  
  25.     qadev->device.set_mic_mute = adev_set_mic_mute;  
  26.     qadev->device.get_mic_mute = adev_get_mic_mute;  
  27.     qadev->device.set_parameters = adev_set_parameters;  
  28.     qadev->device.get_parameters = adev_get_parameters;  
  29.     qadev->device.get_input_buffer_size = adev_get_input_buffer_size;  
  30.     qadev->device.open_output_stream = adev_open_output_stream;  
  31.     qadev->device.open_output_session = adev_open_output_session;  
  32.     qadev->device.close_output_stream = adev_close_output_stream;  
  33.     qadev->device.open_input_stream = adev_open_input_stream; //指向adev_open_input_stream()   
  34.     qadev->device.close_input_stream = adev_close_input_stream;  
  35.     qadev->device.dump = adev_dump;  
  36.   
  37.     qadev->hwif = createAudioHardware();  
  38.     if (!qadev->hwif) {  
  39.         ret = -EIO;  
  40.         goto err_create_audio_hw;  
  41.     }  
  42.   
  43.     *device = &qadev->device.common;  
  44.   
  45.     return 0;  
  46.   
  47. err_create_audio_hw:  
  48.     free(qadev);  
  49.     return ret;  
  50. }  
static int qcom_adev_open(const hw_module_t* module, const char* name, hw_device_t** device) { struct qcom_audio_device *qadev; int ret; if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL; qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev)); if (!qadev) return -ENOMEM; qadev->device.common.tag = HARDWARE_DEVICE_TAG; qadev->device.common.version = 0; qadev->device.common.module = const_cast<hw_module_t*>(module); qadev->device.common.close = qcom_adev_close; qadev->device.get_supported_devices = adev_get_supported_devices; qadev->device.init_check = adev_init_check; qadev->device.set_voice_volume = adev_set_voice_volume; qadev->device.set_master_volume = adev_set_master_volume; qadev->device.set_fm_volume = adev_set_fm_volume; qadev->device.set_mode = adev_set_mode; qadev->device.set_mic_mute = adev_set_mic_mute; qadev->device.get_mic_mute = adev_get_mic_mute; qadev->device.set_parameters = adev_set_parameters; qadev->device.get_parameters = adev_get_parameters; qadev->device.get_input_buffer_size = adev_get_input_buffer_size; qadev->device.open_output_stream = adev_open_output_stream; qadev->device.open_output_session = adev_open_output_session; qadev->device.close_output_stream = adev_close_output_stream; qadev->device.open_input_stream = adev_open_input_stream; //指向adev_open_input_stream() qadev->device.close_input_stream = adev_close_input_stream; qadev->device.dump = adev_dump; qadev->hwif = createAudioHardware(); if (!qadev->hwif) { ret = -EIO; goto err_create_audio_hw; } *device = &qadev->device.common; return 0; err_create_audio_hw: free(qadev); return ret; }


[cpp] view plain copy print ?
  1. /** This method creates and opens the audio hardware input stream */  
  2. static int adev_open_input_stream(struct audio_hw_device *dev,  
  3.                                   uint32_t devices, int *format,  
  4.                                   uint32_t *channels, uint32_t *sample_rate,  
  5.                                   audio_in_acoustics_t acoustics,  
  6.                                   struct audio_stream_in **stream_in)  
  7. {  
  8.     struct legacy_audio_device *ladev = to_ladev(dev);  
  9.     status_t status;  
  10.     struct legacy_stream_in *in;  
  11.     int ret;  
  12.   
  13.     in = (struct legacy_stream_in *)calloc(1, sizeof(*in));  
  14.     if (!in)  
  15.         return -ENOMEM;  
  16.   
  17.     in->legacy_in = ladev->hwif->openInputStream(devices, format, channels,  
  18.                                     sample_rate, &status,  
  19.                                     (AudioSystem::audio_in_acoustics)acoustics); //这里没有返回   
  20.     if (!in->legacy_in) {  
  21.         ret = status;  
  22.         goto err_open;  
  23.     }  
  24.   
  25.     in->stream.common.get_sample_rate = in_get_sample_rate;  
  26.     in->stream.common.set_sample_rate = in_set_sample_rate;  
  27.     in->stream.common.get_buffer_size = in_get_buffer_size;  
  28.     in->stream.common.get_channels = in_get_channels;  
  29.     in->stream.common.get_format = in_get_format;  
  30.     in->stream.common.set_format = in_set_format;  
  31.     in->stream.common.standby = in_standby;  
  32.     in->stream.common.dump = in_dump;  
  33.     in->stream.common.set_parameters = in_set_parameters;  
  34.     in->stream.common.get_parameters = in_get_parameters;  
  35.     in->stream.common.add_audio_effect = in_add_audio_effect;  
  36.     in->stream.common.remove_audio_effect = in_remove_audio_effect;  
  37.     in->stream.set_gain = in_set_gain;  
  38.     in->stream.read = in_read;  
  39.     in->stream.get_input_frames_lost = in_get_input_frames_lost;  
  40.   
  41.     *stream_in = &in->stream;  
  42.     return 0;  
  43.   
  44. err_open:  
  45.     free(in);  
  46.     *stream_in = NULL;  
  47.     return ret;  
  48. }  
/** This method creates and opens the audio hardware input stream */ static int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices, int *format, uint32_t *channels, uint32_t *sample_rate, audio_in_acoustics_t acoustics, struct audio_stream_in **stream_in) { struct legacy_audio_device *ladev = to_ladev(dev); status_t status; struct legacy_stream_in *in; int ret; in = (struct legacy_stream_in *)calloc(1, sizeof(*in)); if (!in) return -ENOMEM; in->legacy_in = ladev->hwif->openInputStream(devices, format, channels, sample_rate, &status, (AudioSystem::audio_in_acoustics)acoustics); //这里没有返回 if (!in->legacy_in) { ret = status; goto err_open; } in->stream.common.get_sample_rate = in_get_sample_rate; in->stream.common.set_sample_rate = in_set_sample_rate; in->stream.common.get_buffer_size = in_get_buffer_size; in->stream.common.get_channels = in_get_channels; in->stream.common.get_format = in_get_format; in->stream.common.set_format = in_set_format; in->stream.common.standby = in_standby; in->stream.common.dump = in_dump; in->stream.common.set_parameters = in_set_parameters; in->stream.common.get_parameters = in_get_parameters; in->stream.common.add_audio_effect = in_add_audio_effect; in->stream.common.remove_audio_effect = in_remove_audio_effect; in->stream.set_gain = in_set_gain; in->stream.read = in_read; in->stream.get_input_frames_lost = in_get_input_frames_lost; *stream_in = &in->stream; return 0; err_open: free(in); *stream_in = NULL; return ret; }



 


 hardware/qcom/media/audio/msm8660/AudioHardware.cpp 

[cpp] view plain copy print ?
  1. 887 AudioStreamIn* AudioHardware::openInputStream(  
  2. 888         uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,  
  3. 889         AudioSystem::audio_in_acoustics acoustic_flags)  
  4. 890 {  
  5. 891     // check for valid input source   
  6. 892     if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {  
  7. 893         return 0;  
  8. 894     }  
  9. 895   
  10. 896 #if 1   //WNC:WJ Wang 20110719: Add USB-Mic path: BEGIN   
  11. 897     if (devices == AudioSystem::DEVICE_IN_USB_MIC)  
  12. 898     {          
  13. 899         Mutex::Autolock lock(mLock);  
  14. 900           
  15. 901         AudioStreamInUSBMic *in_usb = new AudioStreamInUSBMic();  
  16. 902         status_t lStatus = in_usb->set(this, devices, format, channels, sampleRate, acoustic_flags);  
  17. 903           
  18. 904         if (status) {   
  19. 906             *status = lStatus;  
  20. 907         }  
  21. 908         if (lStatus != NO_ERROR)        //If open USB-Mic failed, continue to open the analog Mic   
  22. 909         {     
  23. 910             LOGE("before delete in_usb\n");   
  24. 911             delete in_usb; //这句之后的log没有打出来。delete in_usb对象时,进入AudioStreamInUSBMic的析构函数   
  25. 912             LOGE("delete in_usb\n");    
  26. 913         }  
  27. 914         else  
  28. 915         {     
  29. 916             mUsbInputs.add(in_usb);  
  30. 917             return in_usb;  
  31. 918         }  
  32. 919     }  
  33. 920 #endif  //WNC:WJ Wang 20110719: Add USB-Mic path: END   
  34. 922     mLock.lock();   
  35. 923     if(devices == AudioSystem::DEVICE_IN_COMMUNICATION) {  
  36. 924         LOGE("Create Audio stream Voip \n");  
  37. 925         AudioStreamInVoip* inVoip = new AudioStreamInVoip();  
  38. 926         status_t lStatus = NO_ERROR;   
  39. 927         lStatus =  inVoip->set(this, devices, format, channels, sampleRate, acoustic_flags);  
  40. 928         if (status) {   
  41. 929             *status = lStatus;  
  42. 930         }  
  43. 931         if (lStatus != NO_ERROR) {  
  44. 932             LOGE(" Error creating voip input \n");  
  45. 933             mLock.unlock();  
  46. 934             delete inVoip;  
  47. 935             return 0;  
  48. 936         }  
  49. 937         mVoipInputs.add(inVoip);  
  50. 938         mLock.unlock();  
  51. 939         return inVoip;  
  52. 940     } else {  
  53. 941         AudioStreamInMSM72xx* in72xx = new AudioStreamInMSM72xx();  
  54. 942         status_t lStatus = in72xx->set(this, devices, format, channels, sampleRate, acoustic_flags);  
  55. 943         if (status) {  
  56. 944             *status = lStatus;  
  57. 945         }  
  58. 946         if (lStatus != NO_ERROR) {  
  59. 947             LOGE("Error creating Audio stream AudioStreamInMSM72xx \n");  
  60. 948             mLock.unlock();  
  61. 949             delete in72xx;  
  62. 950             return 0;  
  63. 951         }  
  64. 952         mInputs.add(in72xx);  
  65. 953         mLock.unlock();  
  66. 954         return in72xx;  
  67. 955     }  
  68. 956 }  
887 AudioStreamIn* AudioHardware::openInputStream( 888 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status, 889 AudioSystem::audio_in_acoustics acoustic_flags) 890 { 891 // check for valid input source 892 if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) { 893 return 0; 894 } 895 896 #if 1 //WNC:WJ Wang 20110719: Add USB-Mic path: BEGIN 897 if (devices == AudioSystem::DEVICE_IN_USB_MIC) 898 { 899 Mutex::Autolock lock(mLock); 900 901 AudioStreamInUSBMic *in_usb = new AudioStreamInUSBMic(); 902 status_t lStatus = in_usb->set(this, devices, format, channels, sampleRate, acoustic_flags); 903 904 if (status) { 906 *status = lStatus; 907 } 908 if (lStatus != NO_ERROR) //If open USB-Mic failed, continue to open the analog Mic 909 { 910 LOGE("before delete in_usb\n"); 911 delete in_usb; //这句之后的log没有打出来。delete in_usb对象时,进入AudioStreamInUSBMic的析构函数 912 LOGE("delete in_usb\n"); 913 } 914 else 915 { 916 mUsbInputs.add(in_usb); 917 return in_usb; 918 } 919 } 920 #endif //WNC:WJ Wang 20110719: Add USB-Mic path: END 922 mLock.lock(); 923 if(devices == AudioSystem::DEVICE_IN_COMMUNICATION) { 924 LOGE("Create Audio stream Voip \n"); 925 AudioStreamInVoip* inVoip = new AudioStreamInVoip(); 926 status_t lStatus = NO_ERROR; 927 lStatus = inVoip->set(this, devices, format, channels, sampleRate, acoustic_flags); 928 if (status) { 929 *status = lStatus; 930 } 931 if (lStatus != NO_ERROR) { 932 LOGE(" Error creating voip input \n"); 933 mLock.unlock(); 934 delete inVoip; 935 return 0; 936 } 937 mVoipInputs.add(inVoip); 938 mLock.unlock(); 939 return inVoip; 940 } else { 941 AudioStreamInMSM72xx* in72xx = new AudioStreamInMSM72xx(); 942 status_t lStatus = in72xx->set(this, devices, format, channels, sampleRate, acoustic_flags); 943 if (status) { 944 *status = lStatus; 945 } 946 if (lStatus != NO_ERROR) { 947 LOGE("Error creating Audio stream AudioStreamInMSM72xx \n"); 948 mLock.unlock(); 949 delete in72xx; 950 return 0; 951 } 952 mInputs.add(in72xx); 953 mLock.unlock(); 954 return in72xx; 955 } 956 }
[cpp] view plain copy print ?
  1. <pre class="cpp" name="code">AudioHardware::AudioStreamInUSBMic::~AudioStreamInUSBMic()  
  2. {  
  3.     standby();  
  4. }  
<pre class="cpp" name="code">AudioHardware::AudioStreamInUSBMic::~AudioStreamInUSBMic() { standby(); }
[cpp] view plain copy print ?
  1. <pre class="html" name="code"><pre class="cpp" name="code">  status_t AudioHardware::AudioStreamInUSBMic::standby()  
  2. {  
  3.     AudioHardware *hw = mHardware;  
  4.   
  5.     if (!mHardware) return -1;  
  6.   
  7.     hw->mLock.lock();  
  8.   
  9.     if (mState > AUDIO_INPUT_CLOSED)  
  10.     {  
  11.         if (mHandle != 0)  
  12.         {  
  13.             snd_pcm_close(mHandle);  
  14.             mHandle = 0;  
  15.             if (mHardware != 0)  
  16.             {  
  17.                 if(mHardware->mNumPcmRec > 0 && mFormat == AUDIO_HW_IN_FORMAT)  
  18.                     mHardware->mNumPcmRec--;  
  19.             }  
  20.         }  
  21.   
  22.         mState = AUDIO_INPUT_CLOSED;  
  23.     }  
  24.   
  25.     hw->mLock.unlock();  
  26.     return NO_ERROR;  
  27. }  
<pre class="html" name="code"><pre class="cpp" name="code"> status_t AudioHardware::AudioStreamInUSBMic::standby() { AudioHardware *hw = mHardware; if (!mHardware) return -1; hw->mLock.lock(); if (mState > AUDIO_INPUT_CLOSED) { if (mHandle != 0) { snd_pcm_close(mHandle); mHandle = 0; if (mHardware != 0) { if(mHardware->mNumPcmRec > 0 && mFormat == AUDIO_HW_IN_FORMAT) mHardware->mNumPcmRec--; } } mState = AUDIO_INPUT_CLOSED; } hw->mLock.unlock(); return NO_ERROR; }


找到问题了:

在执行delete in_usb之前,执行了Mutex::Autolock lock(mLock); mLock被锁住了,所以在析构函数所调用的standby函数里,调用hw->mLock.lock();时,就获取不到锁,导致死锁!

 

AutoLock类是定义在Mutex内部的一个类,AutoLock的定义代码如下所示:

[-->Thread.h Mutex::Autolock声明和实现]  

 

[cpp] view plain copy print ?
  1. class Autolock {  
  2.  public:  
  3.      //构造的时候调用lock。   
  4.      inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }  
  5.      inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }  
  6.      //析构的时候调用unlock。   
  7.      inline ~Autolock() { mLock.unlock(); }  
  8.  private:  
  9.      Mutex& mLock;  
  10.  };  
class Autolock { public: //构造的时候调用lock。 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } //析构的时候调用unlock。 inline ~Autolock() { mLock.unlock(); } private: Mutex& mLock; };


 

AutoLock的用法很简单: 先定义一个Mutex,如 Mutex xlock。 在使用xlock的地方,定义一个AutoLock,如 AutoLock autoLock(xlock)。由于C++对象的构造和析构函数都是自动被调用的,所以在AutoLock的生命周期内,xlock的lock和unlock也就自动被调用了,这样就省去了重复书写unlock的麻烦,而且lock和unlock的调用肯定是一一对应的,这样就绝对不会出错。

在作用域里加锁,脱离作用域就会自动解锁。作用域是指同级{}范围。

 

Mutex::Autolock lock(mLock)的mLock在class AudioHardware中定义,所以和hw->mLock.lock();中的mLock是同一个锁。

 

 

 

 

 

相关代码:

set函数由openInputStream()调用,没有usb声卡时返回BAD_VALUE,否则返回NO_ERROR。

[cpp] view plain copy print ?
  1. <pre class="cpp" name="code">status_t AudioHardware::AudioStreamInUSBMic::set(  
  2.         AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate,  
  3.         AudioSystem::audio_in_acoustics acoustic_flags)  
  4. {  
  5.     char cap_pcm[16];  
  6.     LOGD("AudioHardware::AudioStreamInUSBMic::set(%d)...mState=%d", *pFormat, *pChannels);  
  7.   
  8.     if (pFormat == 0 || pRate == 0 || pChannels == 0) {  
  9.         return BAD_VALUE;  
  10.     }  
  11.     uint32_t rate = hw->getInputSampleRate(*pRate);  
  12.     if (rate != *pRate) {  
  13.         *pRate = rate;  
  14.         return BAD_VALUE;  
  15.     }  
  16. //Eaddy temp   
  17.     if (rate != 16000)  
  18.         rate = 16000;  
  19.   
  20.     if ((*pChannels & (AudioSystem::CHANNEL_IN_MONO | AudioSystem::CHANNEL_IN_STEREO)) == 0) {  
  21.         *pChannels = AUDIO_HW_IN_CHANNELS;  
  22.         return BAD_VALUE;  
  23.     }  
  24.   
  25.     if (mHandle != 0) {  
  26.         LOGE("Audio record already set");  
  27.         return NO_ERROR;  
  28.     }  
  29.   
  30.     mHardware = hw;  
  31.     if(mHardware->mNumPcmRec > 0) {  
  32.         /* Only one PCM recording is allowed at a time */  
  33.         LOGE("Multiple PCM recordings is not allowed");  
  34.         return -1;  
  35.     }  
  36.   
  37.     status_t status = NO_ERROR;  
  38.     int dir = 0;  
  39.     snd_pcm_t *handle = 0;  
  40.     snd_pcm_hw_params_t *params = 0;  
  41.   
  42.         status = getCaptureDevice(cap_pcm);  
  43.         if (status < 0) {  
  44.                 LOGE("No USB-Audio:");  
  45.         return BAD_VALUE;  
  46.         }  
  47.   
  48.     /* Open PCM device for recording (capture). Old setting == "hw:2,0,0" */  
  49.     status = snd_pcm_open(&handle, cap_pcm, SND_PCM_STREAM_CAPTURE, 0);  
  50.     if (status < 0) {  
  51.         LOGE("unable to open pcm device");  
  52.         return status;  
  53.     }  
  54.   
  55.     mHandle = handle;  
  56.     mHardware->mNumPcmRec++;  
  57.     mDevices = devices;  
  58.     mFormat = AUDIO_HW_IN_FORMAT;  
  59.     mChannels = *pChannels;  
  60.     mChannelCount = AudioSystem::popCount(mChannels);  
  61.     mSampleRate = rate;  
  62.     mAcoustics = acoustic_flags;  
  63.     mBufferSize = mHardware->getInputBufferSize(mSampleRate, AUDIO_HW_IN_FORMAT, mChannelCount);  
  64.     mBufferSize <<= 1;        // We double the size of input buffer for ping pong use of record buffer.   
  65.   
  66.     LOGD("AudioStreamInUSBMic::set(%d)...(%d, %d, %d)", __LINE__, mChannelCount, mSampleRate, mBufferSize);  
  67.   
  68.     /* Allocate a hardware parameters object. */  
  69.     snd_pcm_hw_params_alloca(¶ms);  
  70.     if (params == 0)  
  71.     {  
  72.         LOGE("unable to allocate parameter memory");  
  73.         goto Error;  
  74.     }  
  75.   
  76.     /* Fill it in with default values. */  
  77.     snd_pcm_hw_params_any(handle, params);  
  78.   
  79.     /* Set the desired hardware parameters. */  
  80.     /* Interleaved mode */  
  81.     snd_pcm_hw_params_set_access(handle, params,  
  82.             SND_PCM_ACCESS_RW_INTERLEAVED);  
  83.   
  84.     /* Signed 16-bit little-endian format */  
  85.     snd_pcm_hw_params_set_format(handle, params,  
  86.             SND_PCM_FORMAT_S16_LE);  
  87.   
  88.     /* Two channels (stereo) */  
  89.     snd_pcm_hw_params_set_channels(handle, params, mChannelCount);  
  90.   
  91.     snd_pcm_uframes_t lvFrames;  
  92.   
  93.     /* Set period size to frames. */  
  94.     lvFrames = 32;  
  95.     snd_pcm_hw_params_set_period_size_near(handle, params, &lvFrames, &dir);  
  96.   
  97.     /* Write the parameters to the driver */  
  98.     status = snd_pcm_hw_params(handle, params);  
  99.     if (status < 0) {  
  100.         LOGE("unable to set hw params");  
  101.         goto Error;  
  102.     }  
  103.   
  104.     mState = AUDIO_INPUT_OPENED;  
  105.   
  106.     return NO_ERROR;  
  107.   
  108. Error:  
  109.     if (mHandle != 0) {  
  110.         snd_pcm_close(mHandle);  
  111.         mHandle = 0;  
  112.     }  
  113.   
  114.     return -1;  
  115. }  
<pre class="cpp" name="code">status_t AudioHardware::AudioStreamInUSBMic::set( AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustic_flags) { char cap_pcm[16]; LOGD("AudioHardware::AudioStreamInUSBMic::set(%d)...mState=%d", *pFormat, *pChannels); if (pFormat == 0 || pRate == 0 || pChannels == 0) { return BAD_VALUE; } uint32_t rate = hw->getInputSampleRate(*pRate); if (rate != *pRate) { *pRate = rate; return BAD_VALUE; } //Eaddy temp if (rate != 16000) rate = 16000; if ((*pChannels & (AudioSystem::CHANNEL_IN_MONO | AudioSystem::CHANNEL_IN_STEREO)) == 0) { *pChannels = AUDIO_HW_IN_CHANNELS; return BAD_VALUE; } if (mHandle != 0) { LOGE("Audio record already set"); return NO_ERROR; } mHardware = hw; if(mHardware->mNumPcmRec > 0) { /* Only one PCM recording is allowed at a time */ LOGE("Multiple PCM recordings is not allowed"); return -1; } status_t status = NO_ERROR; int dir = 0; snd_pcm_t *handle = 0; snd_pcm_hw_params_t *params = 0; status = getCaptureDevice(cap_pcm); if (status < 0) { LOGE("No USB-Audio:"); return BAD_VALUE; } /* Open PCM device for recording (capture). Old setting == "hw:2,0,0" */ status = snd_pcm_open(&handle, cap_pcm, SND_PCM_STREAM_CAPTURE, 0); if (status < 0) { LOGE("unable to open pcm device"); return status; } mHandle = handle; mHardware->mNumPcmRec++; mDevices = devices; mFormat = AUDIO_HW_IN_FORMAT; mChannels = *pChannels; mChannelCount = AudioSystem::popCount(mChannels); mSampleRate = rate; mAcoustics = acoustic_flags; mBufferSize = mHardware->getInputBufferSize(mSampleRate, AUDIO_HW_IN_FORMAT, mChannelCount); mBufferSize <<= 1; // We double the size of input buffer for ping pong use of record buffer. LOGD("AudioStreamInUSBMic::set(%d)...(%d, %d, %d)", __LINE__, mChannelCount, mSampleRate, mBufferSize); /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); if (params == 0) { LOGE("unable to allocate parameter memory"); goto Error; } /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, mChannelCount); snd_pcm_uframes_t lvFrames; /* Set period size to frames. */ lvFrames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &lvFrames, &dir); /* Write the parameters to the driver */ status = snd_pcm_hw_params(handle, params); if (status < 0) { LOGE("unable to set hw params"); goto Error; } mState = AUDIO_INPUT_OPENED; return NO_ERROR; Error: if (mHandle != 0) { snd_pcm_close(mHandle); mHandle = 0; } return -1; }
 

 

getCaptureDevice,找到USB-Audio时,返回0,找不到时返回-1

 

[cpp] view plain copy print ?
  1. int AudioHardware::AudioStreamInUSBMic::getCaptureDevice(char * cap_pcm_str)  
  2. {  
  3.     int rc,idx,dev;  
  4.         snd_ctl_t *handle;  
  5.     snd_pcm_hw_params_t *params;  
  6.     snd_ctl_card_info_t *info;  
  7.         snd_pcm_info_t *pcminfo;  
  8.     char str[16];  
  9.     char usb_card_str[16];  
  10.     int cap_pcm_dev;  
  11.     int cap_pcm_sub_dev;  
  12.   
  13.         snd_ctl_card_info_alloca(&info);  
  14.     snd_pcm_info_alloca(&pcminfo);  
  15.   
  16.     idx = -1;  
  17.     while (1)  
  18.     {  
  19.         if ((rc = snd_card_next(&idx)) < 0) {  
  20.             LOGE("Card next error ");  
  21.             break;  
  22.         }  
  23.         if (idx < 0)  
  24.             break;  
  25.   
  26.         /* Check sound card */  
  27.         sprintf(str, "hw:CARD=%i", idx);  
  28.         if ((rc = snd_ctl_open(&handle, str, 0)) < 0) {  
  29.             LOGE("Open error: card = %s\n", str);  
  30.             continue;  
  31.         }  
  32.   
  33.         if ((rc = snd_ctl_card_info(handle, info)) < 0) {  
  34.             LOGE("HW info error:");  
  35.             continue;  
  36.         }  
  37.   
  38.         /* Find "USB-Audio" */  
  39.         sprintf(usb_card_str, "%s", snd_ctl_card_info_get_driver(info));  
  40.         LOGI("Soundcard Driver = %s", usb_card_str);  
  41.   
  42.         if ((rc = strncmp(usb_card_str, "USB-Audio", 9)) == 0)  
  43.         {  
  44.             LOGI("[--------------Got USB-Audio--------------]");  
  45.             dev = -1;  
  46.             while (1) {  
  47.                 snd_pcm_sync_id_t sync;  
  48.                 if ((rc = snd_ctl_pcm_next_device(handle, &dev)) < 0) {  
  49.                     LOGE("  PCM next device error ");  
  50.                     break;  
  51.                 }  
  52.                 if (dev < 0)  
  53.                     break;  
  54.                 snd_pcm_info_set_device(pcminfo, dev);  
  55.                 snd_pcm_info_set_subdevice(pcminfo, 0);  
  56.                 snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);  
  57.                 if ((rc = snd_ctl_pcm_info(handle, pcminfo)) < 0) {  
  58.                     LOGE("  PCM info error");  
  59.                     continue;  
  60.                 }  
  61.   
  62.                 /* Find the PCM capture device */  
  63.                 cap_pcm_dev = snd_pcm_info_get_device(pcminfo);  
  64.                 cap_pcm_sub_dev = snd_pcm_info_get_subdevice(pcminfo);  
  65.                 sprintf(cap_pcm_str, "hw:%i,%i,%i", idx, cap_pcm_dev, cap_pcm_sub_dev);  
  66.                 LOGD("Open capture pcm device [%s]\n", cap_pcm_str);  
  67.   
  68.                 return 0;  
  69.             }  
  70.   
  71.         }else{  
  72.             continue;  
  73.         }  
  74.     }  
  75.     return idx;  
  76. }  
  77.   
  78.      
int AudioHardware::AudioStreamInUSBMic::getCaptureDevice(char * cap_pcm_str) { int rc,idx,dev; snd_ctl_t *handle; snd_pcm_hw_params_t *params; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; char str[16]; char usb_card_str[16]; int cap_pcm_dev; int cap_pcm_sub_dev; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); idx = -1; while (1) { if ((rc = snd_card_next(&idx)) < 0) { LOGE("Card next error "); break; } if (idx < 0) break; /* Check sound card */ sprintf(str, "hw:CARD=%i", idx); if ((rc = snd_ctl_open(&handle, str, 0)) < 0) { LOGE("Open error: card = %s\n", str); continue; } if ((rc = snd_ctl_card_info(handle, info)) < 0) { LOGE("HW info error:"); continue; } /* Find "USB-Audio" */ sprintf(usb_card_str, "%s", snd_ctl_card_info_get_driver(info)); LOGI("Soundcard Driver = %s", usb_card_str); if ((rc = strncmp(usb_card_str, "USB-Audio", 9)) == 0) { LOGI("[--------------Got USB-Audio--------------]"); dev = -1; while (1) { snd_pcm_sync_id_t sync; if ((rc = snd_ctl_pcm_next_device(handle, &dev)) < 0) { LOGE(" PCM next device error "); break; } if (dev < 0) break; snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); if ((rc = snd_ctl_pcm_info(handle, pcminfo)) < 0) { LOGE(" PCM info error"); continue; } /* Find the PCM capture device */ cap_pcm_dev = snd_pcm_info_get_device(pcminfo); cap_pcm_sub_dev = snd_pcm_info_get_subdevice(pcminfo); sprintf(cap_pcm_str, "hw:%i,%i,%i", idx, cap_pcm_dev, cap_pcm_sub_dev); LOGD("Open capture pcm device [%s]\n", cap_pcm_str); return 0; } }else{ continue; } } return idx; }


 class AudioHardware定义:

hardware/qcom/media/audio/msm8660/AudioHardware.h

[cpp] view plain copy print ?
  1.    
  2.   
  3. class AudioHardware : public  AudioHardwareBase  
  4. {  
  5.     class AudioStreamOutMSM72xx;  
  6.     class AudioStreamInMSM72xx;  
  7.   
  8. public:  
  9.                         AudioHardware();  
  10.     virtual             ~AudioHardware();  
  11.     virtual status_t    initCheck();  
  12.   
  13.     virtual status_t    setVoiceVolume(float volume);  
  14.     virtual status_t    setMasterVolume(float volume);  
  15.   
  16.     virtual status_t    setMode(int mode);  
  17.   
  18.     // mic mute   
  19.     virtual status_t    setMicMute(bool state);  
  20.     virtual status_t    getMicMute(bool* state);  
  21.   
  22.     virtual status_t    setParameters(const String8& keyValuePairs);  
  23.     virtual String8     getParameters(const String8& keys);  
  24.   
  25.     // create I/O streams   
  26.     virtual AudioStreamOut* openOutputStream(  
  27.                                 uint32_t devices,  
  28.                                 int *format=0,  
  29.                                 uint32_t *channels=0,  
  30.                                 uint32_t *sampleRate=0,  
  31.                                 status_t *status=0);  
  32.   
  33.     virtual AudioStreamIn* openInputStream(  
  34.   
  35.                                 uint32_t devices,  
  36.                                 int *format,  
  37.                                 uint32_t *channels,  
  38.                                 uint32_t *sampleRate,  
  39.                                 status_t *status,  
  40.                                 AudioSystem::audio_in_acoustics acoustics);  
  41.   
  42.     virtual    void        closeOutputStream(AudioStreamOut* out);  
  43.     virtual    void        closeInputStream(AudioStreamIn* in);  
  44.   
  45.     virtual    size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);  
  46.                void        clearCurDevice() { mCurSndDevice = -1; }  
  47.   
  48. protected:  
  49.     virtual status_t    dump(int fd, const Vector<String16>& args);  
  50.   
  51. private:  
  52.   
  53.     status_t    doAudioRouteOrMute(uint32_t device);  
  54.     status_t    setMicMute_nosync(bool state);  
  55.     status_t    checkMicMute();  
  56.     status_t    dumpInternals(int fd, const Vector<String16>& args);  
  57.     uint32_t    getInputSampleRate(uint32_t sampleRate);  
  58.     bool        checkOutputStandby();  
  59.     status_t    doRouting(AudioStreamInMSM72xx *input);  
  60.     AudioStreamInMSM72xx*   getActiveInput_l();  
  61.   
  62.     class AudioStreamOutMSM72xx : public AudioStreamOut {  
  63.     public:  
  64.                             AudioStreamOutMSM72xx();  
  65.         virtual             ~AudioStreamOutMSM72xx();  
  66.                 status_t    set(AudioHardware* mHardware,  
  67.                                 uint32_t devices,  
  68.                                 int *pFormat,  
  69.                                 uint32_t *pChannels,  
  70.                                 uint32_t *pRate);  
  71.         virtual uint32_t    sampleRate() const { return 44100; }  
  72.         // must be 32-bit aligned - driver only seems to like 4800   
  73.         virtual size_t      bufferSize() const { return 4800; }  
  74.         virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }  
  75.         virtual int         format() const { return AudioSystem::PCM_16_BIT; }  
  76.         virtual uint32_t    latency() const { return (1000*AUDIO_HW_NUM_OUT_BUF*(bufferSize()/frameSize()))/sampleRate()+AUDIO_HW_OUT_LATENCY_MS; }  
  77.         virtual status_t    setVolume(float left, float right) { return INVALID_OPERATION; }  
  78.         virtual ssize_t     write(const void* buffer, size_t bytes);  
  79.         virtual status_t    standby();  
  80.         virtual status_t    dump(int fd, const Vector<String16>& args);  
  81.                 bool        checkStandby();  
  82.         virtual status_t    setParameters(const String8& keyValuePairs);  
  83.         virtual String8     getParameters(const String8& keys);  
  84.                 uint32_t    devices() { return mDevices; }  
  85.         virtual status_t    getRenderPosition(uint32_t *dspFrames);  
  86.   
  87.     private:  
  88.                 AudioHardware* mHardware;  
  89.                 int         mFd;  
  90.                 int         mStartCount;  
  91.                 int         mRetryCount;  
  92.                 bool        mStandby;  
  93.                 uint32_t    mDevices;  
  94.     };  
  95.   
  96.     class AudioStreamInMSM72xx : public AudioStreamIn {  
  97.     public:  
  98.         enum input_state {  
  99.             AUDIO_INPUT_CLOSED,  
  100.             AUDIO_INPUT_OPENED,  
  101.             AUDIO_INPUT_STARTED  
  102.         };  
  103.   
  104.                             AudioStreamInMSM72xx();  
  105.         virtual             ~AudioStreamInMSM72xx();  
  106.                 status_t    set(AudioHardware* mHardware,  
  107.                                 uint32_t devices,  
  108.                                 int *pFormat,  
  109.                                 uint32_t *pChannels,  
  110.                                 uint32_t *pRate,  
  111.                                 AudioSystem::audio_in_acoustics acoustics);  
  112.         virtual size_t      bufferSize() const { return mBufferSize; }  
  113.         virtual uint32_t    channels() const { return mChannels; }  
  114.         virtual int         format() const { return mFormat; }  
  115.         virtual uint32_t    sampleRate() const { return mSampleRate; }  
  116.         virtual status_t    setGain(float gain) { return INVALID_OPERATION; }  
  117.         virtual ssize_t     read(void* buffer, ssize_t bytes);  
  118.         virtual status_t    dump(int fd, const Vector<String16>& args);  
  119.         virtual status_t    standby();  
  120.         virtual status_t    setParameters(const String8& keyValuePairs);  
  121.         virtual String8     getParameters(const String8& keys);  
  122.         virtual unsigned int  getInputFramesLost() const { return 0; }  
  123.                 uint32_t    devices() { return mDevices; }  
  124.                 int         state() const { return mState; }  
  125.         virtual status_t    addAudioEffect(effect_interface_s**) { return 0;}  
  126.         virtual status_t    removeAudioEffect(effect_interface_s**) { return 0;}  
  127.   
  128.     private:  
  129.                 AudioHardware* mHardware;  
  130.                 int         mFd;  
  131.                 int         mState;  
  132.                 int         mRetryCount;  
  133.                 int         mFormat;  
  134.                 uint32_t    mChannels;  
  135.                 uint32_t    mSampleRate;  
  136.                 size_t      mBufferSize;  
  137.                 AudioSystem::audio_in_acoustics mAcoustics;  
  138.                 uint32_t    mDevices;  
  139.                 bool        mFirstread;  
  140.     };  
  141.   
  142.             static const uint32_t inputSamplingRates[];  
  143.             bool        mInit;  
  144.             bool        mMicMute;  
  145.             bool        mBluetoothNrec;  
  146.             uint32_t    mBluetoothId;  
  147.             AudioStreamOutMSM72xx*  mOutput;  
  148.             SortedVector <AudioStreamInMSM72xx*>   mInputs;  
  149.   
  150.             msm_snd_endpoint *mSndEndpoints;  
  151.             int mNumSndEndpoints;  
  152.             int mCurSndDevice;  
  153.             int m7xsnddriverfd;  
  154.             bool        mDualMicEnabled;  
  155.             int         mTtyMode;  
  156.   
  157.      friend class AudioStreamInMSM72xx;  
  158.             Mutex       mLock;  
  159. };  
  160.   

你可能感兴趣的:(thread,Stream,input,Parameters,audio,output)