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

📄 soundconsumer.cxx

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 CXX
📖 第 1 页 / 共 2 页
字号:
//// (c) Yuri Kiryanov, openh323@kiryanov.com// for www.Openh323.org by Equivalence//// Portions: 1998-1999, Be Incorporated//#include <stdio.h>#include <OS.h>#include <scheduler.h>#include <Buffer.h>#include <TimeSource.h>#include "SoundPrivate.h"#include "SoundConsumer.h"template<class C> class array_delete {	C * & m_ptr;public:	//	auto_ptr<> uses delete, not delete[], so we have to write our own.	//	I like hanging on to a reference, because if we manually delete the	//	array and set the pointer to NULL (or otherwise change the pointer)	//	it will still work. Others like the more elaborate implementation	//	of auto_ptr<>. Your Mileage May Vary.	array_delete(C * & ptr) : m_ptr(ptr) {}	~array_delete() { delete[] m_ptr; }};//	If we don't mind the format changing to another format while//	running, we can define this to 1. Look for the symbol down in the source.#define ACCEPT_ANY_FORMAT_CHANGE 0//	Compiling with NDEBUG means "release" -- it also turns off assert() and//	other such debugging aids. By contrast, DEBUG turns on extra debugging//	in some programs.#if !NDEBUG#define FPRINTF fprintf#else#define FPRINTF (void)#endif//	Comment out the FPRINTF part of these lines to reduce verbiage.//	Enabling MESSAGE will kill performance on slower machines, because it//	prints for each message received (including each buffer).#define NODE  //FPRINTF#define MESSAGE  //FPRINTFSoundConsumer::SoundConsumer(	const char * name,	SoundProcessFunc recordFunc,	SoundNotifyFunc notifyFunc,	void * cookie) :	BMediaNode(name ? name : "SoundConsumer"),	BBufferConsumer(B_MEDIA_RAW_AUDIO){	NODE(stderr, "SoundConsumer::SoundConsumer(%p, %p, %p, %p)\n",		name, recordFunc, notifyFunc, cookie);	if (!name) name = "SoundConsumer";	//	Set up the hook functions.	m_recordHook = recordFunc;	m_notifyHook = notifyFunc;	m_cookie = cookie;	//	Create the port that we publish as our Control Port.	char pname[32];	sprintf(pname, "%.20s Control", name);	m_port = create_port(10, pname);	// Initialize our single media_input. Make sure it knows	// the Control Port associated with the destination, and	// the index of the destination (since we only have one,	// that's trivial).	m_input.destination.port = m_port;	m_input.destination.id = 1;	sprintf(m_input.name, "%.20s Input", name);	// Set up the timing variables that we'll be using.	m_trTimeout = 0LL;	m_tpSeekAt = 0;	m_tmSeekTo = 0;	m_delta = 0;	m_seeking = false;	//	Create, and run, the thread that we use to service	// the Control Port.	sprintf(pname, "%.20s Service", name);	m_thread = spawn_thread(ThreadEntry, pname, 110, this);	resume_thread(m_thread);}SoundConsumer::~SoundConsumer(){	NODE(stderr, "SoundConsumer::~SoundConsumer()\n");	//	Signal to our thread that it's time to go home.	write_port(m_port, MSG_QUIT_NOW, 0, 0);	status_t s;	while (wait_for_thread(m_thread, &s) == B_INTERRUPTED)		NODE(stderr, "wait_for_thread() B_INTERRUPTED\n");	delete_port(m_port);}status_tSoundConsumer::SetHooks(	SoundProcessFunc recordFunc,	SoundNotifyFunc notifyFunc,	void * cookie){	//	SetHooks needs to be synchronized with the service thread, else we may	//	call the wrong hook function with the wrong cookie, which would be bad.	//	Rather than do locking, which is expensive, we streamline the process	//	by sending our service thread a request to change the hooks, and waiting	//	for the acknowledge.	status_t err = B_OK;	set_hooks_q cmd;	cmd.process = recordFunc;	cmd.notify = notifyFunc;	cmd.cookie = cookie;	//	If we're not in the service thread, we need to round-trip a message.	if (find_thread(0) != m_thread) {		cmd.reply = create_port(1, "SetHooks reply");		//	Send the private message to our service thread.		err = write_port(ControlPort(), MSG_CHANGE_HOOKS, &cmd, sizeof(cmd));		if (err >= 0) {			int32 code;			//	Wait for acknowledge from the service thread.			err = read_port_etc(cmd.reply, &code, 0, 0, B_TIMEOUT, 6000000LL);			if (err > 0) err = 0;			NODE(stderr, "SoundConsumer::SetHooks read reply: %#010lx\n", err);		}		//	Clean up.		delete_port(cmd.reply);	}	else {		//	Within the service thread, it's OK to just go ahead and do the change.		DoHookChange(&cmd);	}	return err;}////////////////////////////////////////////////////////////////////////////////////	BMediaNode-derived methods//////////////////////////////////////////////////////////////////////////////////port_id SoundConsumer::ControlPort() const{	return m_port;}BMediaAddOn* SoundConsumer::AddOn(	int32 * internal_id) const{	//	This object is instantiated inside an application.	//	Therefore, it has no add-on.	if (internal_id) *internal_id = 0;	return 0;}void SoundConsumer::Start(	bigtime_t performance_time){	//	Since we are a consumer and just blindly accept buffers that are	//	thrown at us, we don't need to do anything special in Start()/Stop().	//	If we were (also) a producer, we'd have to be more elaborate.	//	The only thing we do is immediately perform any queued Seek based on	//	the start time, which is the right thing to do (seeing as we were	//	Seek()-ed when we weren't started).	if (m_seeking) {		m_delta = performance_time - m_tmSeekTo;		m_seeking = false;	}	if (m_notifyHook) {		(*m_notifyHook)(m_cookie, B_WILL_START, performance_time);	}	else {		Notify(B_WILL_START, performance_time);	}}void SoundConsumer::Stop(	bigtime_t performance_time,	bool immediate){	//	Since we are a consumer and just blindly accept buffers that are	//	thrown at us, we don't need to do anything special in Start()/Stop().	//	If we were (also) a producer, we'd have to be more elaborate.	//	Note that this is not strictly in conformance with The Rules,	//	but since this is not an add-on Node for use with any application;	//	it's a Node over which we have complete control, we can live with	//	treating buffers received before the start time or after the stop	//	time as any other buffer.	if (m_notifyHook) {		(*m_notifyHook)(m_cookie, B_WILL_STOP, performance_time, immediate);	}	else {		Notify(B_WILL_STOP, performance_time, immediate);	}}void SoundConsumer::Seek(	bigtime_t media_time,	bigtime_t performance_time){	//	Seek() on a consumer just serves to offset the time stamp	//	of received buffers passed to our Record hook function.	//	In the hook function, you may wish to save those time stamps	//	to disk or otherwise store them. You may also want to	//	synchronize this node's media time with an upstream	//	producer's media time to make this offset meaningful.	if (m_notifyHook) {		(*m_notifyHook)(m_cookie, B_WILL_SEEK, performance_time, media_time);	}	else {		Notify(B_WILL_SEEK, performance_time, media_time);	}	m_tpSeekAt = performance_time;	m_tmSeekTo = media_time;	m_seeking = true;}void SoundConsumer::SetRunMode(	run_mode mode){	if (mode == BMediaNode::B_OFFLINE) {		// BMediaNode::B_OFFLINE means we don't need to run in		// real time. So, we shouldn't run as a real time		// thread.		int32 new_prio = suggest_thread_priority(B_OFFLINE_PROCESSING);		set_thread_priority(m_thread, new_prio);	}	else {		//	We're running in real time, so we'd better have		//	a big enough thread priority to handle it!		//	Here's where those magic scheduler values		//	come from:		//		//	* In the worst case, we process one buffer per		//	  reschedule (we get rescheduled when we go to		//	  look for a message on our Control Port), so		//	  in order to keep up with the incoming buffers,		//	  the duration of one buffer becomes our		//	  scheduling period. If we don't know anything		//	  about the buffers, we pick a reasonable		//	  default.		//	* We're a simple consumer, so we don't have to		//	  be too picky about the jitter. Half a period		//	  of jitter means that we'd have to get two		//	  consecutive worst-case reschedules before		//	  we'd fall behind.		//	* The amount of time we spend processing is		//	  our ProcessingLatency().		bigtime_t period = 10000;		if (buffer_duration(m_input.format.u.raw_audio) > 0) {			period = buffer_duration(m_input.format.u.raw_audio);		}		//	assuming we're running for 500 us or less per buffer		int32 new_prio = suggest_thread_priority(B_AUDIO_RECORDING,			period, period/2, ProcessingLatency());		set_thread_priority(m_thread, new_prio);	}}void SoundConsumer::TimeWarp(	bigtime_t at_real_time,	bigtime_t to_performance_time){	//	Since buffers will come pre-time-stamped, we only need to look	//	at them, so we can ignore the time warp as a consumer.	if (m_notifyHook) {		(*m_notifyHook)(m_cookie, B_WILL_TIMEWARP, at_real_time, to_performance_time);	}	else {		Notify(B_WILL_TIMEWARP, at_real_time, to_performance_time);	}}void SoundConsumer::Preroll(){	//	There is nothing for us to do in Preroll()}void SoundConsumer::SetTimeSource(	BTimeSource * /* time_source */){	//	We don't need to do anything special to take note of the	//	fact that the time source changed, because we get our timing	//	information from the buffers we receive.}status_t SoundConsumer::HandleMessage(	int32 message,	const void * data,	size_t size){	// Check with each of our superclasses to see if they	// understand the message. If none of them do, call	// BMediaNode::HandleBadMessage().	if ((BBufferConsumer::HandleMessage(message, data, size) < 0)		&& (BMediaNode::HandleMessage(message, data, size) < 0))	{		HandleBadMessage(message, data, size);		return B_ERROR;	}	return B_OK;}////////////////////////////////////////////////////////////////////////////////////	BBufferConsumer-derived methods//////////////////////////////////////////////////////////////////////////////////status_t SoundConsumer::AcceptFormat(	const media_destination & dest,	media_format * format){	//	We only accept formats aimed at our single input.	if (dest != m_input.destination) {		return B_MEDIA_BAD_DESTINATION;	}	//	If no format is specified, we say we want raw audio.	if (format->type <= 0) {		format->type = B_MEDIA_RAW_AUDIO;		format->u.raw_audio = media_raw_audio_format::wildcard;	}	//	If a non-raw-audio format is specified, we tell the world what	//	we want, and that the specified format was unacceptable to us.	else if (format->type != B_MEDIA_RAW_AUDIO) {		format->type = B_MEDIA_RAW_AUDIO;		format->u.raw_audio = media_raw_audio_format::wildcard;		return B_MEDIA_BAD_FORMAT;

⌨️ 快捷键说明

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