Пример #1
0
// "This hook function is called when a BBufferConsumer that's receiving data
//  from you determines that its latency has changed. It will call its
//  BBufferConsumer::SendLatencyChange() function, and in response, the Media
//  Server will call your LatencyChanged() function.  The source argument
//  indicates your output that's involved in the connection, and destination
//  specifies the input on the consumer to which the connection is linked.
//  newLatency is the consumer's new latency. The flags are currently unused."
void AudioFilterNode::LatencyChanged(
	const media_source&					source,
	const media_destination&		destination,
	bigtime_t										newLatency,
	uint32											flags) {

	PRINT(("AudioFilterNode::LatencyChanged()\n"));
	
	if(source != m_output.source) {
		PRINT(("\tBad source.\n"));
		return;
	}
	if(destination != m_output.destination) {
		PRINT(("\tBad destination.\n"));
		return;
	}
	
	m_downstreamLatency = newLatency;
	SetEventLatency(m_downstreamLatency + m_processingLatency);
	
	if(m_input.source != media_source::null) {
		// pass new latency upstream
		status_t err = SendLatencyChange(
			m_input.source,
			m_input.destination,
			EventLatency() + SchedulingLatency());
		if(err < B_OK)
			PRINT(("\t!!! SendLatencyChange(): %s\n", strerror(err)));
	}
}
Пример #2
0
status_t
GameProducer::GetLatency(bigtime_t* _latency)
{
	// report our *total* latency:  internal plus downstream plus scheduling
	*_latency = EventLatency() + SchedulingLatency();
	return B_OK;
}
Пример #3
0
status_t
ClientNode::GetLatency(bigtime_t *outLatency)
{
    printf("ClientNode::GetLatency\n");
    *outLatency = EventLatency() + SchedulingLatency();
    return B_OK;
}
Пример #4
0
status_t OffsetFilter::GetLatency(bigtime_t* poLatency)
{	
	PRINT(("OffsetFilter::GetLatency()\n"));
	*poLatency = EventLatency() + SchedulingLatency();
	PRINT(("\treturning %Ld\n", *poLatency));
	
	return B_OK;
}
Пример #5
0
status_t 
FireWireDVNode::GetLatency(bigtime_t* out_latency)
{
	CALLED();
	
	*out_latency = EventLatency() + SchedulingLatency();
	return B_OK;
}
status_t FlipTransition::GetLatency(bigtime_t* poLatency)
{	
	PRINT(("FlipTransition::GetLatency()\n"));
	*poLatency = EventLatency() + SchedulingLatency();
	PRINT(("\treturning %Ld\n", *poLatency));
	
	return B_OK;
}
status_t StepMotionBlurFilter::GetLatency(bigtime_t* poLatency)
{	
	PRINT(("StepMotionBlurFilter::GetLatency()\n"));
	*poLatency = EventLatency() + SchedulingLatency();
	PRINT(("\treturning %Ld\n", *poLatency));
	
	return B_OK;
}
Пример #8
0
status_t MediaReader::GetLatency(
				bigtime_t * out_latency)
{
	CALLED();

	*out_latency = EventLatency() + SchedulingLatency();
	return B_OK;
}
Пример #9
0
status_t FlangerNode::GetLatency(
	bigtime_t* poLatency) {

	PRINT(("FlangerNode::GetLatency()\n"));
	*poLatency = EventLatency() + SchedulingLatency();
	PRINT(("\treturning %" B_PRIdBIGTIME "\n", *poLatency));

	return B_OK;
}
Пример #10
0
status_t
AudioProducer::GetLatency(bigtime_t* _latency)
{
	TRACE("%p->AudioProducer::GetLatency()\n", this);

	// report our *total* latency:  internal plus downstream plus scheduling
	*_latency = EventLatency() + SchedulingLatency();
	return B_OK;
}
Пример #11
0
status_t
ToneProducer::GetLatency(bigtime_t* out_latency)
{
	FPRINTF(stderr, "ToneProducer::GetLatency\n");

	// report our *total* latency:  internal plus downstream plus scheduling
	*out_latency = EventLatency() + SchedulingLatency();
	return B_OK;
}
Пример #12
0
status_t AudioFilterNode::GetLatency(
	bigtime_t*									outLatency) {
	
	PRINT(("AudioFilterNode::GetLatency()\n"));
	*outLatency = EventLatency() + SchedulingLatency();
	PRINT(("\treturning %Ld\n", *outLatency));
	
	return B_OK;
}
Пример #13
0
status_t
SoundPlayNode::GetLatency(bigtime_t* _latency)
{
	CALLED();

	// report our *total* latency:  internal plus downstream plus scheduling
	*_latency = EventLatency() + SchedulingLatency();
	return B_OK;
}
Пример #14
0
void FlangerNode::Connect(
	status_t status,
	const media_source& source,
	const media_destination& destination,
	const media_format& format,
	char* pioName) {

	PRINT(("FlangerNode::Connect()\n"));
	status_t err;

	// connection failed?
	if(status < B_OK) {
		PRINT(("\tStatus: %s\n", strerror(status)));
		// 'unreserve' the output
		m_output.destination = media_destination::null;
		return;
	}

	// connection established:
	strncpy(pioName, m_output.name, B_MEDIA_NAME_LENGTH);
	m_output.destination = destination;
	m_format = format;

	// figure downstream latency
	media_node_id timeSource;
	err = FindLatencyFor(m_output.destination, &m_downstreamLatency, &timeSource);
	if(err < B_OK) {
		PRINT(("\t!!! FindLatencyFor(): %s\n", strerror(err)));
	}
	PRINT(("\tdownstream latency = %Ld\n", m_downstreamLatency));

	// prepare the filter
	initFilter();

	// figure processing time
	m_processingLatency = calcProcessingLatency();
	PRINT(("\tprocessing latency = %Ld\n", m_processingLatency));

	// store summed latency
	SetEventLatency(m_downstreamLatency + m_processingLatency);

	if(m_input.source != media_source::null) {
		// pass new latency upstream
		err = SendLatencyChange(
			m_input.source,
			m_input.destination,
			EventLatency() + SchedulingLatency());
		if(err < B_OK)
			PRINT(("\t!!! SendLatencyChange(): %s\n", strerror(err)));
	}

	// cache buffer duration
	SetBufferDuration(
		buffer_duration(
			m_format.u.raw_audio));
}
Пример #15
0
status_t
VideoProducer::GetLatency(bigtime_t* _latency)
{
	if (!_latency)
		return B_BAD_VALUE;

	*_latency = EventLatency() + SchedulingLatency();

	return B_OK;
}
Пример #16
0
void
EqualizerNode::LatencyChanged(const media_source &src,
                              const media_destination &dst, bigtime_t latency, uint32 flags)
{
    if (src != fOutputMedia.source || dst != fOutputMedia.destination)
        return;

    fDownstreamLatency = latency;
    SetEventLatency(fDownstreamLatency + fProcessLatency);

    if (fInputMedia.source != media_source::null) {
        SendLatencyChange(fInputMedia.source,
                          fInputMedia.destination,EventLatency() + SchedulingLatency());
    }
}
Пример #17
0
// [re-]initialize operation if necessary
void AudioFilterNode::updateOperation() {

	if(m_input.source == media_source::null ||
		m_output.destination == media_destination::null)
		// not fully connected; nothing to do
		return;
	
	// ask the factory for an operation
	ASSERT(m_opFactory);
	IAudioOp* op = m_opFactory->createOp(
		this,
		m_input.format.u.raw_audio,
		m_output.format.u.raw_audio);
	if(!op) {
		PRINT((
			"!!! AudioFilterNode::updateOperation(): no operation created!\n"));
			
		// clean up existing operation
		delete m_op;
		m_op = 0;
		return;
	}
	
	// install new operation
	op->replace(m_op);
	m_op = op;
	
	// do performance tests (what if I'm running? +++++)

	m_processingLatency = calcProcessingLatency();
	PRINT(("\tprocessing latency = %Ld\n", m_processingLatency));
	
	// store summed latency
	SetEventLatency(m_downstreamLatency + m_processingLatency);
	
	// pass new latency upstream
	status_t err = SendLatencyChange(
		m_input.source,
		m_input.destination,
		EventLatency() + SchedulingLatency());
	if(err < B_OK)
		PRINT(("\t!!! SendLatencyChange(): %s\n", strerror(err)));
}
Пример #18
0
void
EqualizerNode::Connect(status_t status, const media_source &src,
                       const media_destination &dst, const media_format &format, char* name)
{
    if (status < B_OK) {
        fOutputMedia.destination = media_destination::null;
        return;
    }

    strncpy(name, fOutputMedia.name, B_MEDIA_NAME_LENGTH);
    fOutputMedia.destination = dst;
    fFormat = format;

    media_node_id timeSource;
    FindLatencyFor(fOutputMedia.destination, &fDownstreamLatency, &timeSource);

    InitFilter();

    fProcessLatency = GetFilterLatency();
    SetEventLatency(fDownstreamLatency + fProcessLatency);

    if (fInputMedia.source != media_source::null) {
        SendLatencyChange(fInputMedia.source, fInputMedia.destination,
                          EventLatency() + SchedulingLatency());
    }

    bigtime_t duration = 0;

    int sample_size = (fFormat.u.raw_audio.format & 0xf)
                      * fFormat.u.raw_audio.channel_count;

    if (fFormat.u.raw_audio.buffer_size > 0
            && fFormat.u.raw_audio.frame_rate > 0 && sample_size > 0) {
        duration = (bigtime_t)(((fFormat.u.raw_audio.buffer_size / sample_size)
                                / fFormat.u.raw_audio.frame_rate) * 1000000.0);
    }

    SetBufferDuration(duration);
}
Пример #19
0
void 
LoggingConsumer::BufferReceived(BBuffer* buffer)
{
	bigtime_t bufferStart = buffer->Header()->start_time;
	bigtime_t now = TimeSource()->Now();
	bigtime_t how_early = bufferStart - EventLatency() - SchedulingLatency() - now;

	log_message logMsg;
	logMsg.now = now;
	logMsg.buffer_data.start_time = bufferStart;
	logMsg.buffer_data.offset = how_early;
	mLogger->Log(LOG_BUFFER_RECEIVED, logMsg);

	// There's a special case here with handling B_MEDIA_PARAMETERS buffers.
	// These contain sets of parameter value changes, with their own performance
	// times embedded in the buffers.  So, we want to dispatch those parameter
	// changes as their own events rather than pushing this buffer on the queue to
	// be handled later.
	if (B_MEDIA_PARAMETERS == buffer->Header()->type)
	{
		ApplyParameterData(buffer->Data(), buffer->SizeUsed());
		buffer->Recycle();
	}
	else		// ahh, it's a regular media buffer, so push it on the event queue
	{
		status_t err;
		media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
			buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
		err = EventQueue()->AddEvent(event);

		// HandleEvent() will recycle the buffer.  However, if we incurred an error trying to
		// put the event into the queue, we have to recycle it ourselves, since HandleEvent()
		// will never see the buffer in that case.
		if (err) buffer->Recycle();
	}
}
Пример #20
0
status_t
EqualizerNode::GetLatency(bigtime_t* latency)
{
    *latency = EventLatency() + SchedulingLatency();
    return B_OK;
}
Пример #21
0
void 
LoggingConsumer::HandleEvent(const media_timed_event *event, bigtime_t /* lateness */, bool /* realTimeEvent */)
{
	log_message logMsg;
	logMsg.now = TimeSource()->Now();
	mLogger->Log(LOG_HANDLE_EVENT, logMsg);

	switch (event->type)
	{
	case BTimedEventQueue::B_HANDLE_BUFFER:
		{
			BBuffer* buffer = const_cast<BBuffer*>((BBuffer*) event->pointer);
			if (buffer)
			{
				media_header* hdr = buffer->Header();
				if (hdr->destination == mInput.destination.id)
				{
					bigtime_t now = TimeSource()->Now();
					bigtime_t perf_time = hdr->start_time;

					// the how_early calculated here doesn't include scheduling latency because
					// we've already been scheduled to handle the buffer
					bigtime_t how_early = perf_time - mLatency - now;

					// logMsg.now is already set
					logMsg.buffer_data.start_time = perf_time;
					logMsg.buffer_data.offset = how_early;
					mLogger->Log(LOG_BUFFER_HANDLED, logMsg);

					// if the buffer is late, we ignore it and report the fact to the producer
					// who sent it to us
					if (how_early < 0)
					{
						mLateBuffers++;
						NotifyLateProducer(mInput.source, -how_early, perf_time);
					}
					else
					{
						// burn some percentage of our stated latency in CPU time (controlled by
						// a BParameter).  this simulates a user-configurable amount of CPU cost
						// associated with the consumer.
						bigtime_t spin_start = ::system_time();
						bigtime_t spin_now = spin_start;
						bigtime_t usecToSpin = bigtime_t(mSpinPercentage / 100.0 * mLatency);
						while (spin_now - spin_start < usecToSpin)
						{
							for (long k = 0; k < 1000000; k++) { /* intentionally blank */ }
							spin_now = ::system_time();
						}
					}

					// we're done "processing the buffer;" now we recycle it and return to the loop
					buffer->Recycle();
				}
				else
				{
					//fprintf(stderr, "* Woah!  Got a buffer for a different destination!\n");
				}
			}
		}
		break;

	// !!! change to B_PARAMETER as soon as it's available
	
	// +++++ e.moon [16jun99]
	// !!! this can't be right: the parameter value is accessed by the pointer
	//     originally passed to SetParameterValue().  there's no guarantee that
	//     value's still valid, is there?
	
	case BTimedEventQueue::B_USER_EVENT:
		{
			size_t dataSize = size_t(event->data);
			int32 param = int32(event->bigdata);
			logMsg.param.id = param;

			// handle the message if there's sufficient data provided.  we only check against
			// sizeof(float) because all of our parameters happen to be 4 bytes.  if various
			// parameters took different amounts of data, we'd check the size on a per-parameter
			// basis.
			if (dataSize >= sizeof(float)) switch (param)
			{
			case LATENCY_PARAM:
				{
					float value = *((float*) event->pointer);
					mLatency = bigtime_t(value* 1000);
					mLastLatencyChange = logMsg.now;

					// my latency just changed, so reconfigure the BMediaEventLooper
					// to give me my events at the proper time
					SetEventLatency(mLatency);

					// tell the producer that my latency changed, and broadcast a message
					// about the parameter change to any applications that may be looking
					// for it through the BMediaRoster::StartWatching() mechanism.
					//
					// if we had more than one input, we'd need to tell *all* producers about
					// the change in our latency.
					SendLatencyChange(mInput.source, mInput.destination, EventLatency() + SchedulingLatency());
					BroadcastNewParameterValue(logMsg.now, param, &value, sizeof(value));

					// log the new latency value, for recordkeeping
					logMsg.param.value = value;
					mLogger->Log(LOG_SET_PARAM_HANDLED, logMsg);
				}
				break;

			case CPU_SPIN_PARAM:
				{
					float value = *((float*) event->pointer);
					mSpinPercentage = value;
					mLastSpinChange = logMsg.now;
					BroadcastNewParameterValue(logMsg.now, param, &value, sizeof(value));
					logMsg.param.value = value;
					mLogger->Log(LOG_SET_PARAM_HANDLED, logMsg);
				}
				break;

			case PRIORITY_PARAM:
				{
					mPriority = *((int32*) event->pointer);
					// DO NOT use ::set_thead_priority() to directly alter the node's control
					// thread priority.  BMediaEventLooper tracks the priority itself and recalculates
					// the node's scheduling latency whenever SetPriority() is called.  This is VERY
					// important for correct functioning of a node chain.  You should *only* alter a
					// BMediaEventLooper's priority by calling its SetPriority() method.
					SetPriority(mPriority);

					mLastPrioChange = logMsg.now;
					BroadcastNewParameterValue(logMsg.now, param, &mPriority, sizeof(mPriority));
					logMsg.param.value = (float) mPriority;
					mLogger->Log(LOG_SET_PARAM_HANDLED, logMsg);
				}
				break;

			// log the fact that we "handled" a "set parameter" event for a
			// nonexistent parameter
			default:
				mLogger->Log(LOG_INVALID_PARAM_HANDLED, logMsg);
				break;
			}
		}
		break;

	case BTimedEventQueue::B_START:
		// okay, let's go!
		mLogger->Log(LOG_START_HANDLED, logMsg);
		break;

	case BTimedEventQueue::B_STOP:
		mLogger->Log(LOG_STOP_HANDLED, logMsg);
		// stopping implies not handling any more buffers.  So, we flush all pending
		// buffers out of the event queue before returning to the event loop.
		EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
		break;

	case BTimedEventQueue::B_SEEK:
		// seeking the log doesn't make any sense, so we just log that we handled the seek
		// and return without doing anything else
		mLogger->Log(LOG_SEEK_HANDLED, logMsg);
		break;

	case BTimedEventQueue::B_WARP:
		// similarly, time warps aren't meaningful to the logger, so just record it and return
		mLogger->Log(LOG_WARP_HANDLED, logMsg);
		break;

	case BTimedEventQueue::B_DATA_STATUS:
		// we really don't care about the producer's data status, but this is where
		// we'd do something about it if we did.
		logMsg.data_status.status = event->data;
		mLogger->Log(LOG_DATA_STATUS_HANDLED, logMsg);
		break;

	default:
		// hmm, someone enqueued a message that we don't understand.  log and ignore it.
		logMsg.unknown.what = event->type;
		mLogger->Log(LOG_HANDLE_UNKNOWN, logMsg);
		break;
	}
}
Пример #22
0
void
VideoConsumer::_HandleBuffer(BBuffer* buffer)
{
	if (RunState() != B_STARTED || !fConnectionActive) {
		TRACE("RunState() != B_STARTED\n");
		buffer->Recycle();
		return;
	}

	// See if this is one of our BBitmap buffers
	uint32 index = 0;
	fOurBuffers = true;
	while (index < kBufferCount) {
		if (buffer->ID() == fBufferMap[index]->ID())
			break;
		else
			index++;
	}
	if (index == kBufferCount) {
		// Buffers belong to consumer
		// NOTE: We maintain this in a member variable, since we still need
		// to recycle this buffer later on, in case it was the last buffer
		// received before shutting down.
		fOurBuffers = false;
		index = (fLastBufferIndex + 1) % kBufferCount;
	}

	bool recycle = true;
	bigtime_t now = TimeSource()->Now();
	if (RunMode() == B_OFFLINE
		|| now < buffer->Header()->start_time + kMaxBufferLateness) {
		// Only display the buffer if it's not too late, or if we are
		// in B_OFFLINE run-mode.
		if (!fOurBuffers) {
			memcpy(fBitmap[index]->Bits(), buffer->Data(),
				fBitmap[index]->BitsLength());
		}
		bigtime_t tooEarly = buffer->Header()->start_time - now;
		if (tooEarly > 3000)
			snooze(tooEarly);

		fTargetLock.Lock();
		if (fTarget) {
			fTarget->SetBitmap(fBitmap[index]);
			if (fOurBuffers) {
				// recycle the previous but not the current buffer
				if (fLastBufferIndex >= 0)
					fBufferMap[fLastBufferIndex]->Recycle();
				recycle = false;
			}
			fLastBufferIndex = index;
		}
		fTargetLock.Unlock();
	} else {
		// Drop the buffer if it's too late.
		if (fManager->LockWithTimeout(10000) == B_OK) {
			fManager->FrameDropped();
			fManager->Unlock();
		}
		PROGRESS("VideoConsumer::HandleEvent - DROPPED FRAME\n"
			"   start_time: %lld, current: %lld, latency: %lld\n",
			buffer->Header()->start_time, TimeSource()->Now(),
			SchedulingLatency());
	}
	if (recycle)
		buffer->Recycle();
}
Пример #23
0
// GetLatency
status_t 
VideoProducer::GetLatency(bigtime_t* out_latency)
{
	*out_latency = EventLatency() + SchedulingLatency();
	return B_OK;
}
Пример #24
0
status_t EMBeOutputNode::GetLatency(bigtime_t* out_latency)
{
	// report our *total* latency:  internal plus downstream plus scheduling
	(*out_latency) = EventLatency() + SchedulingLatency();
	return B_OK;
}