audio_oss_source.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:6k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000-2002.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  * Dave Mackie dmackie@cisco.com
  20.  * Bill May  wmay@cisco.com
  21.  */
  22. #include "mp4live.h"
  23. #include "audio_oss_source.h"
  24. int COSSAudioSource::ThreadMain(void) 
  25. {
  26. while (true) {
  27. int rc;
  28. if (m_source) {
  29. rc = SDL_SemTryWait(m_myMsgQueueSemaphore);
  30. } else {
  31. rc = SDL_SemWait(m_myMsgQueueSemaphore);
  32. }
  33. // semaphore error
  34. if (rc == -1) {
  35. break;
  36. // message pending
  37. if (rc == 0) {
  38. CMsg* pMsg = m_myMsgQueue.get_message();
  39. if (pMsg != NULL) {
  40. switch (pMsg->get_value()) {
  41. case MSG_NODE_STOP_THREAD:
  42. DoStopCapture(); // ensure things get cleaned up
  43. delete pMsg;
  44. return 0;
  45. case MSG_NODE_START:
  46. case MSG_SOURCE_START_AUDIO:
  47. DoStartCapture();
  48. break;
  49. case MSG_NODE_STOP:
  50. DoStopCapture();
  51. break;
  52. }
  53. delete pMsg;
  54. }
  55. }
  56. if (m_source) {
  57. try {
  58. ProcessAudio();
  59. }
  60. catch (...) {
  61. DoStopCapture();
  62. break;
  63. }
  64. }
  65. }
  66. return -1;
  67. }
  68. void COSSAudioSource::DoStartCapture()
  69. {
  70. if (m_source) {
  71. return;
  72. }
  73. if (!Init()) {
  74. return;
  75. }
  76. m_source = true;
  77. }
  78. void COSSAudioSource::DoStopCapture()
  79. {
  80. if (!m_source) {
  81. return;
  82. }
  83. CMediaSource::DoStopAudio();
  84. close(m_audioDevice);
  85. m_audioDevice = -1;
  86. free(m_pcmFrameBuffer);
  87. m_pcmFrameBuffer = NULL;
  88. m_source = false;
  89. }
  90. bool COSSAudioSource::Init(void)
  91. {
  92. bool rc = InitAudio(
  93. true);
  94. if (!rc) {
  95. return false;
  96. }
  97. rc = SetAudioSrc(
  98. CMediaFrame::PcmAudioFrame,
  99. m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS),
  100. m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE));
  101. if (!rc) {
  102. return false;
  103. }
  104. if (!InitDevice()) {
  105. return false;
  106. }
  107. // for live capture we can match the source to the destination
  108. m_audioSrcSamplesPerFrame = m_audioDstSamplesPerFrame;
  109. m_pcmFrameSize = 
  110. m_audioSrcSamplesPerFrame * m_audioSrcChannels * sizeof(u_int16_t);
  111. m_pcmFrameBuffer = (u_int8_t*)malloc(m_pcmFrameSize);
  112. if (!m_pcmFrameBuffer) {
  113. goto init_failure;
  114. }
  115. // maximum number of passes in ProcessAudio, approx 1 sec.
  116. m_maxPasses = 
  117. m_audioSrcSampleRate / m_audioSrcSamplesPerFrame;
  118. return true;
  119. init_failure:
  120. debug_message("audio initialization failed");
  121. free(m_pcmFrameBuffer);
  122. m_pcmFrameBuffer = NULL;
  123. close(m_audioDevice);
  124. m_audioDevice = -1;
  125. return false;
  126. }
  127. bool COSSAudioSource::InitDevice(void)
  128. {
  129. int rc;
  130. char* deviceName = m_pConfig->GetStringValue(CONFIG_AUDIO_SOURCE_NAME);
  131. // open the audio device
  132. m_audioDevice = open(deviceName, O_RDONLY);
  133. if (m_audioDevice < 0) {
  134. error_message("Failed to open %s", deviceName);
  135. return false;
  136. }
  137. int format = AFMT_S16_LE;
  138. rc = ioctl(m_audioDevice, SNDCTL_DSP_SETFMT, &format);
  139. if (rc < 0 || format != AFMT_S16_LE) {
  140. error_message("Couldn't set format for %s", deviceName);
  141. return false;
  142. }
  143. u_int32_t channels = 
  144. m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS);
  145. rc = ioctl(m_audioDevice, SNDCTL_DSP_CHANNELS, &channels);
  146. if (rc < 0 
  147.   || channels != m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS)) {
  148. error_message("Couldn't set audio channels for %s", deviceName);
  149. return false;
  150. }
  151. u_int32_t samplingRate = 
  152. m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE);
  153. u_int32_t targetSamplingRate = samplingRate;
  154. rc = ioctl(m_audioDevice, SNDCTL_DSP_SPEED, &samplingRate);
  155. if (rc < 0 || abs(samplingRate - targetSamplingRate) > 1) {
  156. error_message("Couldn't set sampling rate for %s", deviceName);
  157. return false;
  158. }
  159. return true;
  160. }
  161. void COSSAudioSource::ProcessAudio(void)
  162. {
  163. // for efficiency, process 1 second before returning to check for commands
  164. for (int pass = 0; pass < m_maxPasses; pass++) {
  165. // read a frame's worth of raw PCM data
  166. u_int32_t bytesRead = 
  167. read(m_audioDevice, m_pcmFrameBuffer, m_pcmFrameSize); 
  168. if (bytesRead < m_pcmFrameSize) {
  169. debug_message("bad audio read");
  170. continue;
  171. }
  172. Timestamp frameTimestamp;
  173. if (m_audioSrcFrameNumber == 0) {
  174. // timestamp needs to reflect the first pcm sample
  175. frameTimestamp = m_audioStartTimestamp =
  176. GetTimestamp() - SrcSamplesToTicks(m_audioSrcSamplesPerFrame);
  177. } else {
  178. frameTimestamp = m_audioStartTimestamp +
  179. SrcSamplesToTicks(m_audioSrcSampleNumber);
  180. }
  181. ProcessAudioFrame(
  182. m_pcmFrameBuffer,
  183. m_pcmFrameSize,
  184. frameTimestamp,
  185. false);
  186. }
  187. }
  188. bool CAudioCapabilities::ProbeDevice()
  189. {
  190. int rc;
  191. // open the audio device
  192. int audioDevice = open(m_deviceName, O_RDONLY);
  193. if (audioDevice < 0) {
  194. return false;
  195. }
  196. m_canOpen = true;
  197. // union of valid sampling rates for MP3 and AAC
  198. static const u_int32_t allSamplingRates[] = {
  199. 7350, 8000, 11025, 12000, 16000, 22050, 
  200. 24000, 32000, 44100, 48000, 64000, 88200, 96000
  201. };
  202. static const u_int8_t numAllSamplingRates =
  203. sizeof(allSamplingRates) / sizeof(u_int32_t);
  204. // for all possible sampling rates
  205. u_int8_t i;
  206. for (i = 0; i < numAllSamplingRates; i++) {
  207. u_int32_t targetRate = allSamplingRates[i];
  208. u_int32_t samplingRate = targetRate;
  209. // attempt to set sound card to this sampling rate
  210. rc = ioctl(audioDevice, SNDCTL_DSP_SPEED, &samplingRate);
  211. // invalid sampling rate, allow deviation of 1 sample/sec
  212. if (rc < 0 || abs(samplingRate - targetRate) > 1) {
  213. debug_message("audio device %s doesn't support sampling rate %u",
  214. m_deviceName, targetRate);
  215. continue;
  216. }
  217. // valid sampling rate
  218. m_samplingRates[m_numSamplingRates++] = targetRate;
  219. }
  220. // zero out remaining sampling rate entries
  221. for (i = m_numSamplingRates; i < numAllSamplingRates; i++) {
  222. m_samplingRates[i] = 0;
  223. }
  224. close(audioDevice);
  225. return true;
  226. }