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

📄 soundconsumer.cxx

📁 mgcp协议源代码。支持多种编码:g711
💻 CXX
📖 第 1 页 / 共 2 页
字号:
	}#if !ACCEPT_ANY_FORMAT_CHANGE	//	If we're already connected, and this format doesn't go with the	//	format in effect, we dont' accept this new format.	if (!format_is_compatible(*format, m_input.format)) {		*format = m_input.format;		return B_MEDIA_BAD_FORMAT;	}#endif	//	I guess we're OK by now, because we have no particular needs as	//	far as frame rate, sample format, etc go.	return B_OK;}status_t SoundConsumer::GetNextInput(	int32 * cookie,	media_input * out_input){	NODE(stderr, "SoundConsumer: GetNextInput()\n");	//	The "next" is kind of misleading, since it's also used for	//	getting the first (and only) input.	if (!*cookie) {		if (m_input.source == media_source::null) {			//	If there's no current connection, make sure we return a			//	reasonable format telling the world we accept any raw audio.			m_input.format.type = B_MEDIA_RAW_AUDIO;			m_input.format.u.raw_audio = media_raw_audio_format::wildcard;			m_input.node = Node();			m_input.destination.port = ControlPort();			m_input.destination.id = 1;		}		*out_input = m_input;		*cookie = 1;		return B_OK;	}	//	There's only one input.	return B_BAD_INDEX;}void SoundConsumer::DisposeInputCookie(	int32 /* cookie */){	//	We didn't allocate any memory or set any state in GetNextInput()	//	so this function is a no-op.}void SoundConsumer::BufferReceived(	BBuffer * buffer){	NODE(stderr, "SoundConsumer::BufferReceived()\n");	//	Whee, a buffer! Update the seek info, if necessary.	if (m_seeking && buffer->Header()->start_time >= m_tpSeekAt) {		m_delta = m_tpSeekAt - m_tmSeekTo;		m_seeking = false;	}	//	If there is a record hook, let the interested party have at it!	if (m_recordHook) {		(*m_recordHook)(m_cookie, buffer->Header()->start_time-m_delta, buffer->Data(), buffer->Header()->size_used, m_input.format.u.raw_audio);	}	else {		Record(buffer->Header()->start_time-m_delta, buffer->Data(), buffer->Header()->size_used, m_input.format.u.raw_audio);	}	//	Buffers should ALWAYS be recycled, else whomever is producing them	//	will starve.	buffer->Recycle();}void SoundConsumer::ProducerDataStatus(	const media_destination & for_whom,	int32 status,	bigtime_t at_media_time){	if (for_whom == m_input.destination) {		//	Tell whomever is interested that the upstream producer will or won't		//	send more data in the immediate future.		if (m_notifyHook) {			(*m_notifyHook)(m_cookie, B_PRODUCER_DATA_STATUS, status, at_media_time);		}		else {			Notify(B_PRODUCER_DATA_STATUS, status, at_media_time);		}	}}status_t SoundConsumer::GetLatencyFor(	const media_destination & for_whom,	bigtime_t * out_latency,	media_node_id * out_timesource){	//	We only accept requests for the one-and-only input of our Node.	if (for_whom != m_input.destination) {		return B_MEDIA_BAD_DESTINATION;	}	//	Tell the world about our latency information (overridable by user).	*out_latency = TotalLatency();	*out_timesource = TimeSource()->Node().node;	return B_OK;}status_t SoundConsumer::Connected(	const media_source & producer,	const media_destination & where,	const media_format & with_format,	media_input * out_input){	NODE(stderr, "SoundConsumer::Connected()\n");	//	Only accept connection requests when we're not already connected.	if (m_input.source != media_source::null) {		return B_MEDIA_BAD_DESTINATION;	}	//	Only accept connection requests on the one-and-only available input.	if (where != m_input.destination) {		return B_MEDIA_BAD_DESTINATION;	}	//	Other than that, we accept pretty much anything. The format has been	//	pre-cleared through AcceptFormat(), and we accept any format anyway.	m_input.source = producer;	m_input.format = with_format;	//	Tell whomever is interested that there's now a connection.	if (m_notifyHook) {		(*m_notifyHook)(m_cookie, B_CONNECTED, m_input.name);	}	else {		Notify(B_CONNECTED, m_input.name);	}	//	This is the most important line -- return our connection information	//	to the world so it can use it!	*out_input = m_input;	return B_OK;}void SoundConsumer::Disconnected(	const media_source & producer,	const media_destination & where){	//	We can't disconnect something which isn't us.	if (where != m_input.destination) {		return;	}	//	We can't disconnect from someone who isn't connected to us.	if (producer != m_input.source) {		return;	}	//	Tell the interested party that it's time to leave.	if (m_notifyHook) {		(*m_notifyHook)(m_cookie, B_DISCONNECTED);	}	else {		Notify(B_DISCONNECTED);	}	//	Mark ourselves as not-connected.	m_input.source = media_source::null;}status_t SoundConsumer::FormatChanged(	const media_source & producer,	const media_destination & consumer, 	int32 from_change_count,	const media_format & format){	NODE(stderr, "SoundConsumer::Connected()\n");	//	The up-stream guy feels like changing the format. If we can accept	//	arbitrary format changes, we just say "OK". If, however, we're recording	//	to a file, that's not such a good idea; we only accept format changes	//	that are compatible with the format we're already using. You set this	//	behaviour at compile time by defining ACCEPT_ANY_FORMAT_CHANGE to 1 or 0.	status_t err = B_OK;#if ACCEPT_ANY_FORMAT_CHANGE	media_format fmt(format);	err = AcceptFormat(m_input.destination, &fmt);#else	if (m_input.source != media_source::null) {		err = format_is_compatible(format, m_input.format) ? B_OK : B_MEDIA_BAD_FORMAT;	}#endif	if (err >= B_OK) {		m_input.format = format;		if (m_notifyHook) {			(*m_notifyHook)(m_cookie, B_FORMAT_CHANGED, &m_input.format.u.raw_audio);		}		else {			Notify(B_FORMAT_CHANGED, &m_input.format.u.raw_audio);		}	}	return err;}voidSoundConsumer::DoHookChange(	void * msg){	//	Tell the old guy we're changing the hooks ...	if (m_notifyHook) {		(*m_notifyHook)(m_cookie, B_HOOKS_CHANGED);	}	else {		Notify(B_HOOKS_CHANGED);	}	//	... and then do it.	set_hooks_q * ptr = (set_hooks_q *)msg;	m_recordHook = ptr->process;	m_notifyHook = ptr->notify;	m_cookie = ptr->cookie;}status_tSoundConsumer::ThreadEntry(	void * obj){	((SoundConsumer *)obj)->ServiceThread();	return 0;}voidSoundConsumer::ServiceThread(){	//	The Big Bad ServiceThread receives messages aimed at this	//	Node and dispatches them (typically to HandleMessage()).	//	If we were a Producer, we might have to do finicky timing and	//	queued Start()/Stop() processing in here. But we ain't.	//	A media kit message will never be bigger than B_MEDIA_MESSAGE_SIZE.	//	Avoid wasing stack space by dynamically allocating at start.	char * msg = new char[B_MEDIA_MESSAGE_SIZE];	//	Make sure we clean up this data when we exit the function.	array_delete<char> msg_delete(msg);	int bad = 0;	while (true) {		//	Call read_port_etc() with a timeout derived from a virtual function,		//	to allow clients to do special processing if necessary.		bigtime_t timeout = Timeout();		int32 code = 0;		status_t err = read_port_etc(m_port, &code, msg, B_MEDIA_MESSAGE_SIZE,			B_TIMEOUT, timeout);		MESSAGE(stderr, "SoundConsumer::ServiceThread() port %ld message %#010lx\n", m_port, code);		//	If we received a message, err will be the size of the message (including 0).		if (err >= 0) {			//	Real messages reset the timeout time.			m_trTimeout = 0;			bad = 0;			//	Check for our private stop message.			if (code == MSG_QUIT_NOW) {				if (m_notifyHook) {					(*m_notifyHook)(m_cookie, B_NODE_DIES, 0);				}				else {					Notify(B_NODE_DIES, 0);				}				break;			}			//	Else check for our private change-hooks message.			else if (code == MSG_CHANGE_HOOKS) {				DoHookChange(msg);				//	Write acknowledge to waiting thread.				write_port(((set_hooks_q *)msg)->reply, 0, 0, 0);			}			//	Else it has to be a regular media kit message; go ahead and			//	dispatch it.			else {				HandleMessage(code, msg, err);			}		}		//	Timing out means that there was no buffer. Tell the interested party.		else if (err == B_TIMED_OUT) {			if (m_notifyHook) {				(*m_notifyHook)(m_cookie, B_OP_TIMED_OUT, timeout);			}			else {				Notify(B_OP_TIMED_OUT, timeout);			}		}		//	Other errors are bad.		else {			FPRINTF(stderr, "SoundConsumer: error %#010lx\n", err);			bad++;			//	If we receive three bad reads with no good messages inbetween,			//	things are probably not going to improve (like the port disappeared			//	or something) so we call it a day.			if (bad > 3) {				if (m_notifyHook) {					(*m_notifyHook)(m_cookie, B_NODE_DIES, bad, err, code, msg);				}				else {					Notify(B_NODE_DIES, bad, err, code, msg);				}				break;			}		}	}}bigtime_tSoundConsumer::Timeout(){	//	Timeout() is called for each call to read_port_etc() in the service	//	thread to figure out a reasonable time-out value. The default behaviour	//	we've picked is to exponentially back off from one second and upwards.	//	While it's true that 44 back-offs will run us out of precision in a	//	bigtime_t, the time to actually reach 44 consecutive back-offs is longer	//	than the expected market longevity of just about any piece of real estate.	//	Is that the sound of an impending year-fifteen-million software problem? :-)	m_trTimeout = (m_trTimeout < 1000000) ? 1000000 : m_trTimeout*2;	return m_trTimeout;}bigtime_tSoundConsumer::ProcessingLatency(){	//	We're saying it takes us 500 us to process each buffer. If all we do is	//	copy the data, it probably takes much less than that, but it doesn't	//	hurt to be slightly conservative. 	return 500LL;}bigtime_tSoundConsumer::TotalLatency(){	//	Had we been a producer that passes buffers on, we'd have to	//	include downstream latency in this value. But we are not.	return ProcessingLatency();}voidSoundConsumer::Record(	bigtime_t /* time */,	const void * /* data */,	size_t /* size */,	const media_raw_audio_format & /* format */){	//	If there is no record hook installed, we instead call this function	//	for received buffers.}voidSoundConsumer::Notify(	int32 /* cause */,	...){	//	If there is no notification hook installed, we instead call this function	//	for giving notification of various events.}

⌨️ 快捷键说明

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