10fe9fd36SDavid McPaul/*
20fe9fd36SDavid McPaul* Copyright (C) 2009-2010 David McPaul
30fe9fd36SDavid McPaul*
40fe9fd36SDavid McPaul* All rights reserved. Distributed under the terms of the MIT License.
50fe9fd36SDavid McPaul* VideoMixerNode.cpp
60fe9fd36SDavid McPaul*
70fe9fd36SDavid McPaul* The VideoMixerNode class
80fe9fd36SDavid McPaul* takes in multiple video streams and supplies
90fe9fd36SDavid McPaul* a single stream as the output.
100fe9fd36SDavid McPaul* each stream is converted to the same colourspace
110fe9fd36SDavid McPaul*/
120fe9fd36SDavid McPaul
130fe9fd36SDavid McPaul#include "VideoMixerNode.h"
140fe9fd36SDavid McPaul
15127a93c2SDario Casalinuovo#include <stdio.h>
16127a93c2SDario Casalinuovo#include <string.h>
17127a93c2SDario Casalinuovo
18127a93c2SDario Casalinuovo
190fe9fd36SDavid McPaul// -------------------------------------------------------- //
200fe9fd36SDavid McPaul// implemention of BBufferProducer
210fe9fd36SDavid McPaul// -------------------------------------------------------- //
220fe9fd36SDavid McPaul
230fe9fd36SDavid McPaul// They are asking us to make the first offering.
240fe9fd36SDavid McPaul// So, we get a fresh format and then add requirements
250fe9fd36SDavid McPaulstatus_t VideoMixerNode::FormatSuggestionRequested(
260fe9fd36SDavid McPaul				media_type type,
270fe9fd36SDavid McPaul				int32 quality,
280fe9fd36SDavid McPaul				media_format * format)
290fe9fd36SDavid McPaul{
300fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::FormatSuggestionRequested\n");
310fe9fd36SDavid McPaul
320fe9fd36SDavid McPaul	if (format->type == B_MEDIA_NO_TYPE) {
330fe9fd36SDavid McPaul		format->type = B_MEDIA_RAW_VIDEO;
340fe9fd36SDavid McPaul	}
350fe9fd36SDavid McPaul
360fe9fd36SDavid McPaul	if (format->type != B_MEDIA_RAW_VIDEO) {
370fe9fd36SDavid McPaul		return B_MEDIA_BAD_FORMAT;
380fe9fd36SDavid McPaul	}
390fe9fd36SDavid McPaul
400fe9fd36SDavid McPaul	GetOutputFormat(format);
410fe9fd36SDavid McPaul
420fe9fd36SDavid McPaul	return B_OK;
430fe9fd36SDavid McPaul}
440fe9fd36SDavid McPaul
450fe9fd36SDavid McPaul// They made an offer to us.  We should make sure that the offer is
460fe9fd36SDavid McPaul// acceptable, and then we can add any requirements we have on top of
470fe9fd36SDavid McPaul// that.  We leave wildcards for anything that we don't care about.
480fe9fd36SDavid McPaulstatus_t VideoMixerNode::FormatProposal(
490fe9fd36SDavid McPaul				const media_source &output_source,
500fe9fd36SDavid McPaul				media_format *format)
510fe9fd36SDavid McPaul{
520fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::FormatProposal\n");
530fe9fd36SDavid McPaul
540fe9fd36SDavid McPaul	fOutput.source = output_source;
550fe9fd36SDavid McPaul
560fe9fd36SDavid McPaul	// If we have an input then set our output as the same except for color_space
570fe9fd36SDavid McPaul	if (fConnectedInputs.size() > 0) {
580fe9fd36SDavid McPaul		if (fOutput.format.u.raw_video == media_raw_video_format::wildcard) {
590fe9fd36SDavid McPaul			// First proposal
600fe9fd36SDavid McPaul			fOutput.format = fConnectedInputs[0]->format;
610fe9fd36SDavid McPaul			fOutput.format.u.raw_video.display.format = B_NO_COLOR_SPACE;
620fe9fd36SDavid McPaul		} else {
630fe9fd36SDavid McPaul			// Second proposal
640fe9fd36SDavid McPaul			fOutput.format = fConnectedInputs[0]->format;
650fe9fd36SDavid McPaul			fOutput.format.u.raw_video.display.format = B_RGBA32;
660fe9fd36SDavid McPaul		}
670fe9fd36SDavid McPaul	}
680fe9fd36SDavid McPaul
690fe9fd36SDavid McPaul	*format = fOutput.format;
700fe9fd36SDavid McPaul
710fe9fd36SDavid McPaul	return B_OK;
720fe9fd36SDavid McPaul}
730fe9fd36SDavid McPaul
740fe9fd36SDavid McPaul// Presumably we have already agreed with them that this format is
750fe9fd36SDavid McPaul// okay.  But just in case, we check the offer. (and complain if it
760fe9fd36SDavid McPaul// is invalid)  Then as the last thing we do, we get rid of any
770fe9fd36SDavid McPaul// remaining wilcards.
780fe9fd36SDavid McPaulstatus_t VideoMixerNode::FormatChangeRequested(
790fe9fd36SDavid McPaul				const media_source &source,
800fe9fd36SDavid McPaul				const media_destination &destination,
810fe9fd36SDavid McPaul				media_format *io_format,
820fe9fd36SDavid McPaul				int32 * _deprecated_)
830fe9fd36SDavid McPaul{
840fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::FormatChangeRequested\n");
850fe9fd36SDavid McPaul
860fe9fd36SDavid McPaul	if (fOutput.source != source) {
870fe9fd36SDavid McPaul		// we don't have that output
880fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
890fe9fd36SDavid McPaul		return B_MEDIA_BAD_SOURCE;
900fe9fd36SDavid McPaul	}
910fe9fd36SDavid McPaul
920fe9fd36SDavid McPaul	fOutput.destination = destination;
930fe9fd36SDavid McPaul	fOutput.format = *io_format;
940fe9fd36SDavid McPaul
950fe9fd36SDavid McPaul	return B_OK;
960fe9fd36SDavid McPaul}
970fe9fd36SDavid McPaul
980fe9fd36SDavid McPaulstatus_t VideoMixerNode::GetNextOutput(	/* cookie starts as 0 */
990fe9fd36SDavid McPaul				int32 *cookie,
1000fe9fd36SDavid McPaul				media_output *out_output)
1010fe9fd36SDavid McPaul{
1020fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::GetNextOutput (%ld)\n",*cookie);
1030fe9fd36SDavid McPaul
1040fe9fd36SDavid McPaul	// only 1 output
1050fe9fd36SDavid McPaul	if (*cookie != 0) {
1060fe9fd36SDavid McPaul		fprintf(stderr,"<- B_ERROR (no more outputs)\n");
1070fe9fd36SDavid McPaul		return B_ERROR;
1080fe9fd36SDavid McPaul	}
1090fe9fd36SDavid McPaul
1100fe9fd36SDavid McPaul	*out_output = fOutput;
1110fe9fd36SDavid McPaul	*cookie = 1;
1120fe9fd36SDavid McPaul
1130fe9fd36SDavid McPaul	return B_OK;
1140fe9fd36SDavid McPaul}
1150fe9fd36SDavid McPaul
1160fe9fd36SDavid McPaulstatus_t VideoMixerNode::DisposeOutputCookie(int32 cookie)
1170fe9fd36SDavid McPaul{
1180fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::DisposeOutputCookie\n");
1190fe9fd36SDavid McPaul	// nothing to do since our cookies are part of the vector iterator
120a3d9c49aSDavid McPaul	return B_OK;
1210fe9fd36SDavid McPaul}
1220fe9fd36SDavid McPaul
1230fe9fd36SDavid McPaulstatus_t VideoMixerNode::SetBufferGroup(
1240fe9fd36SDavid McPaul				const media_source & for_source,
1250fe9fd36SDavid McPaul				BBufferGroup * group)
1260fe9fd36SDavid McPaul{
1270fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::SetBufferGroup\n");
1280fe9fd36SDavid McPaul
1290fe9fd36SDavid McPaul	if (fOutput.source != for_source) {
1300fe9fd36SDavid McPaul		// we don't have that output
1310fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
1320fe9fd36SDavid McPaul		return B_MEDIA_BAD_SOURCE;
1330fe9fd36SDavid McPaul	}
1340fe9fd36SDavid McPaul
1350fe9fd36SDavid McPaul	return B_OK;
1360fe9fd36SDavid McPaul}
1370fe9fd36SDavid McPaul
1380fe9fd36SDavid McPaul	/* Format of clipping is (as int16-s): <from line> <npairs> <startclip> <endclip>. */
1390fe9fd36SDavid McPaul	/* Repeat for each line where the clipping is different from the previous line. */
1400fe9fd36SDavid McPaul	/* If <npairs> is negative, use the data from line -<npairs> (there are 0 pairs after */
1410fe9fd36SDavid McPaul	/* a negative <npairs>. Yes, we only support 32k*32k frame buffers for clipping. */
1420fe9fd36SDavid McPaul	/* Any non-0 field of 'display' means that that field changed, and if you don't support */
1430fe9fd36SDavid McPaul	/* that change, you should return an error and ignore the request. Note that the buffer */
1440fe9fd36SDavid McPaul	/* offset values do not have wildcards; 0 (or -1, or whatever) are real values and must */
1450fe9fd36SDavid McPaul	/* be adhered to. */
1460fe9fd36SDavid McPaulstatus_t VideoMixerNode::VideoClippingChanged(
1470fe9fd36SDavid McPaul				const media_source & for_source,
1480fe9fd36SDavid McPaul				int16 num_shorts,
1490fe9fd36SDavid McPaul				int16 * clip_data,
1500fe9fd36SDavid McPaul				const media_video_display_info & display,
1510fe9fd36SDavid McPaul				int32 * _deprecated_)
1520fe9fd36SDavid McPaul{
1530fe9fd36SDavid McPaul	return BBufferProducer::VideoClippingChanged(for_source, num_shorts, clip_data, display, _deprecated_);
1540fe9fd36SDavid McPaul}
1550fe9fd36SDavid McPaul
1560fe9fd36SDavid McPaulstatus_t VideoMixerNode::GetLatency(
1570fe9fd36SDavid McPaul				bigtime_t *out_latency)
1580fe9fd36SDavid McPaul{
1590fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::GetLatency\n");
1600fe9fd36SDavid McPaul	if (out_latency == NULL) {
1610fe9fd36SDavid McPaul		fprintf(stderr,"<- B_BAD_VALUE\n");
1620fe9fd36SDavid McPaul		return B_BAD_VALUE;
1630fe9fd36SDavid McPaul	}
1640fe9fd36SDavid McPaul
1650fe9fd36SDavid McPaul	*out_latency = EventLatency() + SchedulingLatency();
1660fe9fd36SDavid McPaul	return B_OK;
1670fe9fd36SDavid McPaul}
1680fe9fd36SDavid McPaul
1690fe9fd36SDavid McPaulstatus_t VideoMixerNode::PrepareToConnect(
1700fe9fd36SDavid McPaul				const media_source &what,
1710fe9fd36SDavid McPaul				const media_destination &where,
1720fe9fd36SDavid McPaul				media_format *format,
1730fe9fd36SDavid McPaul				media_source *out_source,
1740fe9fd36SDavid McPaul				char *out_name)
1750fe9fd36SDavid McPaul{
1760fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::PrepareToConnect\n");
1770fe9fd36SDavid McPaul
1780fe9fd36SDavid McPaul	if (fOutput.source != what) {
1790fe9fd36SDavid McPaul		// we don't have that output
1800fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
1810fe9fd36SDavid McPaul		return B_MEDIA_BAD_SOURCE;
1820fe9fd36SDavid McPaul	}
1830fe9fd36SDavid McPaul
1840fe9fd36SDavid McPaul	*out_source = fOutput.source;
1850fe9fd36SDavid McPaul	strcpy(out_name, fOutput.name);
1860fe9fd36SDavid McPaul
1870fe9fd36SDavid McPaul	fOutput.destination = where;
1880fe9fd36SDavid McPaul
1890fe9fd36SDavid McPaul	return B_OK;
1900fe9fd36SDavid McPaul}
1910fe9fd36SDavid McPaul
1920fe9fd36SDavid McPaulvoid VideoMixerNode::Connect(
1930fe9fd36SDavid McPaul				status_t error,
1940fe9fd36SDavid McPaul				const media_source &source,
1950fe9fd36SDavid McPaul				const media_destination &destination,
1960fe9fd36SDavid McPaul				const media_format &format,
1970fe9fd36SDavid McPaul				char *io_name)
1980fe9fd36SDavid McPaul{
1990fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::Connect\n");
2000fe9fd36SDavid McPaul
2010fe9fd36SDavid McPaul	if (fOutput.source != source) {
2020fe9fd36SDavid McPaul		// we don't have that output
2030fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
2040fe9fd36SDavid McPaul		return;
2050fe9fd36SDavid McPaul	}
2060fe9fd36SDavid McPaul
2070fe9fd36SDavid McPaul	if (error != B_OK) {
2080fe9fd36SDavid McPaul		fprintf(stderr,"<- error already\n");
2090fe9fd36SDavid McPaul		fOutput.destination = media_destination::null;
2100fe9fd36SDavid McPaul		fOutput.format.u.raw_video = media_raw_video_format::wildcard;
2110fe9fd36SDavid McPaul		return;
2120fe9fd36SDavid McPaul	}
2130fe9fd36SDavid McPaul
2140fe9fd36SDavid McPaul	// calculate the downstream latency
2150fe9fd36SDavid McPaul	// must happen before itr->Connect
2160fe9fd36SDavid McPaul	bigtime_t downstreamLatency;
2170fe9fd36SDavid McPaul	media_node_id id;
2180fe9fd36SDavid McPaul	FindLatencyFor(fOutput.destination, &downstreamLatency, &id);
2190fe9fd36SDavid McPaul
2200fe9fd36SDavid McPaul	// record the agreed upon values
2210fe9fd36SDavid McPaul	fOutput.format = format;
2220fe9fd36SDavid McPaul	fOutput.destination = destination;
2230fe9fd36SDavid McPaul	strcpy(io_name, fOutput.name);
2240fe9fd36SDavid McPaul
2250fe9fd36SDavid McPaul	// compute the internal latency
2260fe9fd36SDavid McPaul	// must happen after itr->Connect
2270fe9fd36SDavid McPaul	if (fInternalLatency == 0) {
2280fe9fd36SDavid McPaul		fInternalLatency = 100; // temporary until we finish computing it
2290fe9fd36SDavid McPaul		ComputeInternalLatency();
2300fe9fd36SDavid McPaul	}
2310fe9fd36SDavid McPaul
2320fe9fd36SDavid McPaul	// If the downstream latency for this output is larger
2330fe9fd36SDavid McPaul	// than our current downstream latency, we have to increase
2340fe9fd36SDavid McPaul	// our current downstream latency to be the larger value.
2350fe9fd36SDavid McPaul	if (downstreamLatency > fDownstreamLatency) {
2360fe9fd36SDavid McPaul		SetEventLatency(fDownstreamLatency + fInternalLatency);
2370fe9fd36SDavid McPaul	}
2380fe9fd36SDavid McPaul}
2390fe9fd36SDavid McPaul
2400fe9fd36SDavid McPaulvoid VideoMixerNode::ComputeInternalLatency() {
2410fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::ComputeInternalLatency\n");
2420fe9fd36SDavid McPaul	fInternalLatency = 100; // just guess
2430fe9fd36SDavid McPaul	fprintf(stderr,"  internal latency guessed = %lld\n",fInternalLatency);
2440fe9fd36SDavid McPaul}
2450fe9fd36SDavid McPaul
2460fe9fd36SDavid McPaulvoid VideoMixerNode::Disconnect(
2470fe9fd36SDavid McPaul				const media_source & what,
2480fe9fd36SDavid McPaul				const media_destination & where)
2490fe9fd36SDavid McPaul{
2500fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::Disconnect\n");
2510fe9fd36SDavid McPaul
2520fe9fd36SDavid McPaul	if (fOutput.source != what) {
2530fe9fd36SDavid McPaul		// we don't have that output
2540fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
2550fe9fd36SDavid McPaul		return;
2560fe9fd36SDavid McPaul	}
2570fe9fd36SDavid McPaul
2580fe9fd36SDavid McPaul	if (fOutput.destination != where) {
2590fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
2600fe9fd36SDavid McPaul		return;
2610fe9fd36SDavid McPaul	}
2620fe9fd36SDavid McPaul
2630fe9fd36SDavid McPaul	fOutput.destination = media_destination::null;
2640fe9fd36SDavid McPaul	GetOutputFormat(&fOutput.format);
2650fe9fd36SDavid McPaul}
2660fe9fd36SDavid McPaul
2670fe9fd36SDavid McPaulvoid VideoMixerNode::LateNoticeReceived(
2680fe9fd36SDavid McPaul				const media_source & what,
2690fe9fd36SDavid McPaul				bigtime_t how_much,
2700fe9fd36SDavid McPaul				bigtime_t performance_time)
2710fe9fd36SDavid McPaul{
2720fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::LateNoticeReceived\n");
2730fe9fd36SDavid McPaul
2740fe9fd36SDavid McPaul	if (fOutput.source != what) {
2750fe9fd36SDavid McPaul		// we don't have that output
2760fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
2770fe9fd36SDavid McPaul		return;
2780fe9fd36SDavid McPaul	}
2790fe9fd36SDavid McPaul
2800fe9fd36SDavid McPaul	switch (RunMode()) {
2810fe9fd36SDavid McPaul		case B_OFFLINE:
2820fe9fd36SDavid McPaul		    // nothing to do
2830fe9fd36SDavid McPaul			break;
2840fe9fd36SDavid McPaul		case B_RECORDING:
2850fe9fd36SDavid McPaul		    // nothing to do
2860fe9fd36SDavid McPaul			break;
2870fe9fd36SDavid McPaul		case B_INCREASE_LATENCY:
2880fe9fd36SDavid McPaul			fInternalLatency += how_much;
2890fe9fd36SDavid McPaul			SetEventLatency(fDownstreamLatency + fInternalLatency);
2900fe9fd36SDavid McPaul			break;
2910fe9fd36SDavid McPaul		case B_DECREASE_PRECISION:
2920fe9fd36SDavid McPaul			// XXX: try to catch up by producing buffers faster
2930fe9fd36SDavid McPaul			break;
2940fe9fd36SDavid McPaul		case B_DROP_DATA:
2950fe9fd36SDavid McPaul			// XXX: should we really drop buffers?  just for that output?
2960fe9fd36SDavid McPaul			break;
2970fe9fd36SDavid McPaul		default:
2980fe9fd36SDavid McPaul			fprintf(stderr,"VideoMixerNode::LateNoticeReceived with unexpected run mode.\n");
2990fe9fd36SDavid McPaul			break;
3000fe9fd36SDavid McPaul	}
3010fe9fd36SDavid McPaul}
3020fe9fd36SDavid McPaul
3030fe9fd36SDavid McPaulvoid VideoMixerNode::EnableOutput(
3040fe9fd36SDavid McPaul				const media_source &what,
3050fe9fd36SDavid McPaul				bool enabled,
3060fe9fd36SDavid McPaul				int32 *_deprecated_)
3070fe9fd36SDavid McPaul{
3080fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::EnableOutput\n");
3090fe9fd36SDavid McPaul
3100fe9fd36SDavid McPaul	if (fOutput.source != what) {
3110fe9fd36SDavid McPaul		// we don't have that output
3120fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
3130fe9fd36SDavid McPaul		return;
3140fe9fd36SDavid McPaul	}
3150fe9fd36SDavid McPaul
3160fe9fd36SDavid McPaul	status_t status = B_OK;
3170fe9fd36SDavid McPaul	if (status != B_OK) {
3180fe9fd36SDavid McPaul		fprintf(stderr,"  error in itr->EnableOutput\n");
3190fe9fd36SDavid McPaul	}
3200fe9fd36SDavid McPaul}
3210fe9fd36SDavid McPaul
3220fe9fd36SDavid McPaulstatus_t VideoMixerNode::SetPlayRate(
3230fe9fd36SDavid McPaul				int32 numer,
3240fe9fd36SDavid McPaul				int32 denom)
3250fe9fd36SDavid McPaul{
3260fe9fd36SDavid McPaul	BBufferProducer::SetPlayRate(numer, denom); // XXX: do something intelligent later
3270fe9fd36SDavid McPaul	return B_OK;
3280fe9fd36SDavid McPaul}
3290fe9fd36SDavid McPaul
3300fe9fd36SDavid McPaulvoid VideoMixerNode::AdditionalBufferRequested(			//	used to be Reserved 0
3310fe9fd36SDavid McPaul				const media_source & source,
3320fe9fd36SDavid McPaul				media_buffer_id prev_buffer,
3330fe9fd36SDavid McPaul				bigtime_t prev_time,
3340fe9fd36SDavid McPaul				const media_seek_tag * prev_tag)
3350fe9fd36SDavid McPaul{
3360fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::AdditionalBufferRequested\n");
3370fe9fd36SDavid McPaul
3380fe9fd36SDavid McPaul	if (fOutput.source != source) {
3390fe9fd36SDavid McPaul		// we don't have that output
3400fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
3410fe9fd36SDavid McPaul		return;
3420fe9fd36SDavid McPaul	}
3430fe9fd36SDavid McPaul
3440fe9fd36SDavid McPaul//	BBuffer * buffer;
3450fe9fd36SDavid McPaul//	status_t status = itr->AdditionalBufferRequested(prev_buffer, prev_time, prev_tag);
3460fe9fd36SDavid McPaul//	if (status != B_OK) {
3470fe9fd36SDavid McPaul//		fprintf(stderr,"  itr->AdditionalBufferRequested returned an error.\n");
3480fe9fd36SDavid McPaul//	}
3490fe9fd36SDavid McPaul}
3500fe9fd36SDavid McPaul
3510fe9fd36SDavid McPaulvoid VideoMixerNode::LatencyChanged(
3520fe9fd36SDavid McPaul				const media_source & source,
3530fe9fd36SDavid McPaul				const media_destination & destination,
3540fe9fd36SDavid McPaul				bigtime_t new_latency,
3550fe9fd36SDavid McPaul				uint32 flags)
3560fe9fd36SDavid McPaul{
3570fe9fd36SDavid McPaul	fprintf(stderr,"VideoMixerNode(BBufferProducer)::LatencyChanged\n");
3580fe9fd36SDavid McPaul
3590fe9fd36SDavid McPaul	if (fOutput.source != source) {
3600fe9fd36SDavid McPaul		// we don't have that output
3610fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
3620fe9fd36SDavid McPaul		return;
3630fe9fd36SDavid McPaul	}
3640fe9fd36SDavid McPaul
3650fe9fd36SDavid McPaul	if (fOutput.destination != destination) {
3660fe9fd36SDavid McPaul		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
3670fe9fd36SDavid McPaul		return;
3680fe9fd36SDavid McPaul	}
3690fe9fd36SDavid McPaul
3700fe9fd36SDavid McPaul	fDownstreamLatency = new_latency;
3710fe9fd36SDavid McPaul	SetEventLatency(fDownstreamLatency + fInternalLatency);
3720fe9fd36SDavid McPaul
3730fe9fd36SDavid McPaul	// XXX: we may have to recompute the number of buffers that we are using
3740fe9fd36SDavid McPaul	// see SetBufferGroup
3750fe9fd36SDavid McPaul}