Exemple #1
0
void
BMediaEventLooper::Run()
{
	CALLED();

	if (fControlThread != -1)
		return; // thread already running

	// until now, the run state is B_UNREGISTERED, but we need to start in B_STOPPED state.
	SetRunState(B_STOPPED);

	char threadName[32];
	sprintf(threadName, "%.20s control", Name());
	fControlThread = spawn_thread(_ControlThreadStart, threadName, fCurrentPriority, this);
	resume_thread(fControlThread);

	// get latency information
	fSchedulingLatency = estimate_max_scheduling_latency(fControlThread);
}
Exemple #2
0
/* virtual */ void
BMediaEventLooper::SetRunMode(run_mode mode)
{
	CALLED();
	// The SetRunMode() hook function is called when someone requests that your node's run mode be changed.

	// bump or reduce priority when switching from/to offline run mode
	int32 priority;
	priority = (mode == B_OFFLINE) ? min_c(B_NORMAL_PRIORITY, fSetPriority) : fSetPriority;
	if (priority != fCurrentPriority) {
		fCurrentPriority = priority;
		if (fControlThread > 0) {
			set_thread_priority(fControlThread, fCurrentPriority);
			fSchedulingLatency = estimate_max_scheduling_latency(fControlThread);
			printf("BMediaEventLooper: SchedulingLatency is %" B_PRId64 "\n",
				fSchedulingLatency);
		}
	}

	BMediaNode::SetRunMode(mode);
}
Exemple #3
0
status_t
BMediaEventLooper::SetPriority(int32 priority)
{
	CALLED();

	// clamp to a valid value
	if (priority < 5)
		priority = 5;

	if (priority > 120)
		priority = 120;

	fSetPriority = priority;
	fCurrentPriority = (RunMode() == B_OFFLINE) ? min_c(B_NORMAL_PRIORITY, fSetPriority) : fSetPriority;

	if (fControlThread > 0) {
		set_thread_priority(fControlThread, fCurrentPriority);
		fSchedulingLatency = estimate_max_scheduling_latency(fControlThread);
		printf("BMediaEventLooper: SchedulingLatency is %" B_PRId64 "\n",
			fSchedulingLatency);
	}

	return B_OK;
}
Exemple #4
0
status_t
CodyCam::_SetUpNodes()
{
	status_t status = B_OK;

	/* find the media roster */
	fMediaRoster = BMediaRoster::Roster(&status);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot find the media roster"),
			status);
		return status;
	}

	/* find the time source */
	status = fMediaRoster->GetTimeSource(&fTimeSourceNode);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot get a time source"), status);
		return status;
	}

	/* find a video producer node */
	INFO("CodyCam acquiring VideoInput node\n");
	status = fMediaRoster->GetVideoInput(&fProducerNode);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot find a video source. You need "
			"a webcam to use CodyCam."), status);
		return status;
	}

	/* create the video consumer node */
	fVideoConsumer = new VideoConsumer("CodyCam",
		((VideoWindow*)fWindow)->VideoView(),
		((VideoWindow*)fWindow)->StatusLine(), NULL, 0);
	if (!fVideoConsumer) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot create a video window"),
			B_ERROR);
		return B_ERROR;
	}

	/* register the node */
	status = fMediaRoster->RegisterNode(fVideoConsumer);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot register the video window"),
			status);
		return status;
	}
	fPort = fVideoConsumer->ControlPort();

	/* find free producer output */
	int32 cnt = 0;
	status = fMediaRoster->GetFreeOutputsFor(fProducerNode, &fProducerOut, 1,
		&cnt, B_MEDIA_RAW_VIDEO);
	if (status != B_OK || cnt < 1) {
		status = B_RESOURCE_UNAVAILABLE;
		fWindow->ErrorAlert(B_TRANSLATE("Cannot find an available video stream"),
			status);
		return status;
	}

	/* find free consumer input */
	cnt = 0;
	status = fMediaRoster->GetFreeInputsFor(fVideoConsumer->Node(),
		&fConsumerIn, 1, &cnt, B_MEDIA_RAW_VIDEO);
	if (status != B_OK || cnt < 1) {
		status = B_RESOURCE_UNAVAILABLE;
		fWindow->ErrorAlert(B_TRANSLATE("Can't find an available connection to "
			"the video window"), status);
		return status;
	}

	/* Connect The Nodes!!! */
	media_format format;
	format.type = B_MEDIA_RAW_VIDEO;
	media_raw_video_format vid_format = {0, 1, 0, 239, B_VIDEO_TOP_LEFT_RIGHT,
		1, 1, {B_RGB32, VIDEO_SIZE_X, VIDEO_SIZE_Y, VIDEO_SIZE_X * 4, 0, 0}};
	format.u.raw_video = vid_format;

	/* connect producer to consumer */
	status = fMediaRoster->Connect(fProducerOut.source,
		fConsumerIn.destination, &format, &fProducerOut, &fConsumerIn);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot connect the video source to "
			"the video window"), status);
		return status;
	}


	/* set time sources */
	status = fMediaRoster->SetTimeSourceFor(fProducerNode.node,
		fTimeSourceNode.node);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot set the time source for the "
			"video source"), status);
		return status;
	}

	status = fMediaRoster->SetTimeSourceFor(fVideoConsumer->ID(),
		fTimeSourceNode.node);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot set the time source for the "
			"video window"), status);
		return status;
	}

	/* figure out what recording delay to use */
	bigtime_t latency = 0;
	status = fMediaRoster->GetLatencyFor(fProducerNode, &latency);
	status = fMediaRoster->SetProducerRunModeDelay(fProducerNode, latency);

	/* start the nodes */
	bigtime_t initLatency = 0;
	status = fMediaRoster->GetInitialLatencyFor(fProducerNode, &initLatency);
	if (status < B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Error getting initial latency for the "
			"capture node"), status);
		return status;
	}

	initLatency += estimate_max_scheduling_latency();

	BTimeSource* timeSource = fMediaRoster->MakeTimeSourceFor(fProducerNode);
	bool running = timeSource->IsRunning();

	/* workaround for people without sound cards */
	/* because the system time source won't be running */
	bigtime_t real = BTimeSource::RealTime();
	if (!running) {
		status = fMediaRoster->StartTimeSource(fTimeSourceNode, real);
		if (status != B_OK) {
			timeSource->Release();
			fWindow->ErrorAlert(B_TRANSLATE("Cannot start time source!"),
				status);
			return status;
		}
		status = fMediaRoster->SeekTimeSource(fTimeSourceNode, 0, real);
		if (status != B_OK) {
			timeSource->Release();
			fWindow->ErrorAlert(B_TRANSLATE("Cannot seek time source!"),
				status);
			return status;
		}
	}

	bigtime_t perf = timeSource->PerformanceTimeFor(real + latency
		+ initLatency);
	timeSource->Release();

	/* start the nodes */
	status = fMediaRoster->StartNode(fProducerNode, perf);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot start the video source"),
			status);
		return status;
	}
	status = fMediaRoster->StartNode(fVideoConsumer->Node(), perf);
	if (status != B_OK) {
		fWindow->ErrorAlert(B_TRANSLATE("Cannot start the video window"),
			status);
		return status;
	}

	return status;
}
Exemple #5
0
status_t
NodeManager::_StartNodes()
{
	status_t status = B_NO_INIT;
	if (!fMediaRoster)
		return status;

	bigtime_t latency = 0;
	bigtime_t initLatency = 0;
	if (fVideoProducer && fVideoConsumer) {
		// figure out what recording delay to use
		status = fMediaRoster->GetLatencyFor(fVideoConnection.producer,
			&latency);
		if (status < B_OK) {
			print_error("error getting latency for video producer",
				status);
		} else
			TRACE("video latency: %Ld\n", latency);
		status = fMediaRoster->SetProducerRunModeDelay(
			fVideoConnection.producer, latency);
		if (status < B_OK) {
			print_error("error settings run mode delay for video producer",
				status);
		}

		// start the nodes
		status = fMediaRoster->GetInitialLatencyFor(
			fVideoConnection.producer, &initLatency);
		if (status < B_OK) {
			print_error("error getting initial latency for video producer",
				status);
		}
	}
	initLatency += estimate_max_scheduling_latency();

	if (fAudioProducer) {
		// TODO: was this supposed to be added to initLatency?!?
		bigtime_t audioLatency = 0;
		status = fMediaRoster->GetLatencyFor(fAudioConnection.producer,
			&audioLatency);
		TRACE("audio latency: %Ld\n", audioLatency);
	}

	BTimeSource* timeSource;
	if (fVideoProducer) {
		timeSource = fMediaRoster->MakeTimeSourceFor(
			fVideoConnection.producer);
	} else {
		timeSource = fMediaRoster->MakeTimeSourceFor(
			fAudioConnection.producer);
	}
	bool running = timeSource->IsRunning();

	// workaround for people without sound cards
	// because the system time source won't be running
	bigtime_t real = BTimeSource::RealTime();
	if (!running) {
		status = fMediaRoster->StartTimeSource(fTimeSource, real);
		if (status != B_OK) {
			timeSource->Release();
			print_error("cannot start time source!", status);
			return status;
		}
		status = fMediaRoster->SeekTimeSource(fTimeSource, 0, real);
		if (status != B_OK) {
			timeSource->Release();
			print_error("cannot seek time source!", status);
			return status;
		}
	}

	bigtime_t perf = timeSource->PerformanceTimeFor(real + latency
		+ initLatency);

	timeSource->Release();

	// start the nodes
	if (fVideoProducer && fVideoConsumer) {
		status = fMediaRoster->StartNode(fVideoConnection.consumer, perf);
		if (status != B_OK) {
			print_error("Can't start the video consumer", status);
			return status;
		}
		status = fMediaRoster->StartNode(fVideoConnection.producer, perf);
		if (status != B_OK) {
			print_error("Can't start the video producer", status);
			return status;
		}
	}

	if (fAudioProducer) {
		status = fMediaRoster->StartNode(fAudioConnection.producer, perf);
		if (status != B_OK) {
			print_error("Can't start the audio producer", status);
			return status;
		}
	}

	fPerformanceTimeBase = perf;

	return status;
}
Exemple #6
0
/* virtual */ void
BMediaEventLooper::ControlLoop()
{
	CALLED();

	status_t err = B_OK;
	bigtime_t waitUntil = B_INFINITE_TIMEOUT;
	bool hasRealtime = false;
	bool hasEvent = false;

	// While there are no events or it is not time for the earliest event,
	// process messages using WaitForMessages. Whenever this funtion times out,
	// we need to handle the next event

	fSchedulingLatency = estimate_max_scheduling_latency(fControlThread);
	while (RunState() != B_QUITTING) {
		if (err == B_TIMED_OUT
				|| err == B_WOULD_BLOCK) {
			// NOTE: The reference for doing the lateness calculus this way can
			// be found in the BeBook article "A BMediaEventLooper Example".
			// The value which we are going to calculate, is referred there as
			// 'lateness'.
			media_timed_event event;
			if (hasEvent)
				err = fEventQueue.RemoveFirstEvent(&event);
			else if (hasRealtime)
				err = fRealTimeQueue.RemoveFirstEvent(&event);

			if (err == B_OK) {
				// The general idea of lateness is to allow
				// the client code to detect when the buffer
				// is handled late or early.
				bigtime_t lateness = TimeSource()->RealTime() - waitUntil;

				DispatchEvent(&event, lateness, hasRealtime);
			}
		} else if (err != B_OK)
			return;

		// BMediaEventLooper compensates your performance time by adding
		// the event latency (see SetEventLatency()) and the scheduling
		// latency (or, for real-time events, only the scheduling latency).

		hasRealtime = fRealTimeQueue.HasEvents();
		hasEvent = fEventQueue.HasEvents();

		if (hasEvent) {
			waitUntil = TimeSource()->RealTimeFor(
				fEventQueue.FirstEventTime(),
				fEventLatency + fSchedulingLatency);
		} else if (!hasRealtime)
			waitUntil = B_INFINITE_TIMEOUT;

		if (hasRealtime) {
			bigtime_t realtimeWait = fRealTimeQueue.FirstEventTime()
				- fSchedulingLatency;

			if (!hasEvent || realtimeWait <= waitUntil) {
				waitUntil = realtimeWait;
				hasEvent = false;
			} else
				hasRealtime = false;
		}

		if (waitUntil != B_INFINITE_TIMEOUT
				&& TimeSource()->RealTime() >= waitUntil) {
			err = WaitForMessage(0);
		} else
			err = WaitForMessage(waitUntil);
	}
}