⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio_oss_source.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 CPP
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000-2002.  All Rights Reserved. *  * Contributor(s):  *		Dave Mackie		dmackie@cisco.com *		Bill May 		wmay@cisco.com */#include "mp4live.h"#include "audio_oss_source.h"COSSAudioSource::COSSAudioSource(CLiveConfig *pConfig) : CMediaSource() {  SetConfig(pConfig);  m_audioDevice = -1;  m_pcmFrameBuffer = NULL;  // NOTE: This used to be CAVMediaFlow::SetAudioInput();  // if mixer is specified, then user takes responsibility for  // configuring mixer to set the appropriate input sources  // this allows multiple inputs to be used, for example  if (!strcasecmp(m_pConfig->GetStringValue(CONFIG_AUDIO_INPUT_NAME),		  "mix")) {    return;  }  // else set the mixer input source to the one specified  static char* inputNames[] = SOUND_DEVICE_NAMES;  char* mixerName =     m_pConfig->GetStringValue(CONFIG_AUDIO_MIXER_NAME);  int mixer = open(mixerName, O_RDONLY);  if (mixer < 0) {    error_message("Couldn't open mixer %s", mixerName);    return;  }  u_int8_t i;  int recmask = 0;  for (i = 0; i < sizeof(inputNames) / sizeof(char*); i++) {    if (!strcasecmp(m_pConfig->GetStringValue(CONFIG_AUDIO_INPUT_NAME),		    inputNames[i])) {      recmask |= (1 << i);      ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &recmask);      break;    }  }  close(mixer);}int COSSAudioSource::ThreadMain(void) {	while (true) {		int rc;		if (m_source) {			rc = SDL_SemTryWait(m_myMsgQueueSemaphore);		} else {			rc = SDL_SemWait(m_myMsgQueueSemaphore);		}		// semaphore error		if (rc == -1) {			break;		} 		// message pending		if (rc == 0) {			CMsg* pMsg = m_myMsgQueue.get_message();					if (pMsg != NULL) {				switch (pMsg->get_value()) {				case MSG_NODE_STOP_THREAD:					DoStopCapture();	// ensure things get cleaned up					delete pMsg;					return 0;				case MSG_NODE_START:				case MSG_SOURCE_START_AUDIO:					DoStartCapture();					break;				case MSG_NODE_STOP:					DoStopCapture();					break;				}				delete pMsg;			}		}		if (m_source) {			try {				ProcessAudio();			}			catch (...) {				DoStopCapture();					break;			}		}	}	return -1;}void COSSAudioSource::DoStartCapture(){	if (m_source) {		return;	}	if (!Init()) {		return;	}	m_source = true;}void COSSAudioSource::DoStopCapture(){	if (!m_source) {		return;	}	CMediaSource::DoStopAudio();	close(m_audioDevice);	m_audioDevice = -1;	free(m_pcmFrameBuffer);	m_pcmFrameBuffer = NULL;	m_source = false;}bool COSSAudioSource::Init(void){	bool rc = InitAudio(		true);	if (!rc) {		return false;	}	rc = SetAudioSrc(		PCMAUDIOFRAME,		m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS),		m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE));	if (!rc) {		return false;	}	if (!InitDevice()) {		return false;	}	// for live capture we can match the source to the destination	m_audioSrcSamplesPerFrame = m_audioDstSamplesPerFrame;	m_pcmFrameSize = 		m_audioSrcSamplesPerFrame * m_audioSrcChannels * sizeof(u_int16_t);	m_pcmFrameBuffer = (u_int8_t*)malloc(m_pcmFrameSize);	if (!m_pcmFrameBuffer) {		goto init_failure;	}	// maximum number of passes in ProcessAudio, approx 1 sec.	m_maxPasses = 		m_audioSrcSampleRate / m_audioSrcSamplesPerFrame;	return true;init_failure:	debug_message("audio initialization failed");	free(m_pcmFrameBuffer);	m_pcmFrameBuffer = NULL;	close(m_audioDevice);	m_audioDevice = -1;	return false;}bool COSSAudioSource::InitDevice(void){	int rc;	char* deviceName = m_pConfig->GetStringValue(CONFIG_AUDIO_SOURCE_NAME);	// open the audio device	m_audioDevice = open(deviceName, O_RDONLY);	if (m_audioDevice < 0) {		error_message("Failed to open %s", deviceName);		return false;	}	int enablebits;	// Disable the audio input until we can start it below	ioctl(m_audioDevice, SNDCTL_DSP_GETTRIGGER, &enablebits);	enablebits &= ~PCM_ENABLE_INPUT;	ioctl(m_audioDevice, SNDCTL_DSP_SETTRIGGER, &enablebits);#ifdef WORDS_BIGENDIAN#define OUR_FORMAT AFMT_S16_BE#else#define OUR_FORMAT AFMT_S16_LE#endif	int format = OUR_FORMAT;	rc = ioctl(m_audioDevice, SNDCTL_DSP_SETFMT, &format);	if (rc < 0 || format != OUR_FORMAT) {		error_message("Couldn't set format for %s", deviceName);		return false;	}	u_int32_t channels = 		m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS);	rc = ioctl(m_audioDevice, SNDCTL_DSP_CHANNELS, &channels);	if (rc < 0 	  || channels != m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS)) {		error_message("Couldn't set audio channels for %s", deviceName);		return false;	}	u_int32_t samplingRate = 		m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE);	u_int32_t targetSamplingRate = samplingRate;	rc = ioctl(m_audioDevice, SNDCTL_DSP_SPEED, &samplingRate);	if (rc < 0 || abs(samplingRate - targetSamplingRate) > 1) {		error_message("Couldn't set sampling rate for %s", deviceName);		return false;	}	return true;}void COSSAudioSource::ProcessAudio(void){	// for efficiency, process 1 second before returning to check for commands  int enablebits;#ifdef SNDCTL_DSP_GETERROR  audio_errinfo errinfo;  if (m_audioSrcFrameNumber == 0) {    ioctl(m_audioDevice, SNDCTL_DSP_GETERROR, &errinfo);  } else {    ioctl(m_audioDevice, SNDCTL_DSP_GETERROR, &errinfo);    if (errinfo.rec_overruns > 0) {      debug_message("overrun error found in audio - adding %llu samples",		    SrcBytesToSamples(errinfo.rec_ptradjust));      close(m_audioDevice);      InitDevice();      m_audioSrcSampleNumber = 0;    }  }#endif	for (int pass = 0; pass < m_maxPasses; pass++) {		// read a frame's worth of raw PCM data	  if (m_audioSrcSampleNumber == 0) {	    m_audioCaptureStartTimestamp = GetTimestamp();	    // Now - pull the trigger, and start the audio input	    ioctl(m_audioDevice, SNDCTL_DSP_GETTRIGGER, &enablebits);	    enablebits |= PCM_ENABLE_INPUT;	    ioctl(m_audioDevice, SNDCTL_DSP_SETTRIGGER, &enablebits);	  }		u_int32_t bytesRead = 			read(m_audioDevice, m_pcmFrameBuffer, m_pcmFrameSize); 		if (bytesRead < m_pcmFrameSize) {			debug_message("bad audio read");			continue;		}		Timestamp frameTimestamp;		frameTimestamp = m_audioCaptureStartTimestamp + SrcSamplesToTicks(m_audioSrcSampleNumber);		ProcessAudioFrame(			m_pcmFrameBuffer,			m_pcmFrameSize,			frameTimestamp,			false);	}}bool CAudioCapabilities::ProbeDevice(){	int rc;	// open the audio device	int audioDevice = open(m_deviceName, O_RDONLY);	if (audioDevice < 0) {		return false;	}	m_canOpen = true;	// union of valid sampling rates for MP3 and AAC	static const u_int32_t allSamplingRates[] = {		7350, 8000, 11025, 12000, 16000, 22050, 		24000, 32000, 44100, 48000, 64000, 88200, 96000	};	static const u_int8_t numAllSamplingRates =		sizeof(allSamplingRates) / sizeof(u_int32_t);	// for all possible sampling rates	u_int8_t i;	for (i = 0; i < numAllSamplingRates; i++) {		u_int32_t targetRate = allSamplingRates[i];		u_int32_t samplingRate = targetRate;		// attempt to set sound card to this sampling rate		rc = ioctl(audioDevice, SNDCTL_DSP_SPEED, &samplingRate);		// invalid sampling rate, allow deviation of 1 sample/sec		if (rc < 0 || abs(samplingRate - targetRate) > 1) {			debug_message("audio device %s doesn't support sampling rate %u",				m_deviceName, targetRate);			continue;		}		// valid sampling rate		m_samplingRates[m_numSamplingRates++] = targetRate;	}	// zero out remaining sampling rate entries	for (i = m_numSamplingRates; i < numAllSamplingRates; i++) {		m_samplingRates[i] = 0;	}	close(audioDevice);	return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -