예제 #1
0
// how should we handle late buffers?  drop them?
// notify the producer?
status_t ESDSinkNode::HandleBuffer(
				const media_timed_event *event,
				bigtime_t lateness,
				bool realTimeEvent)
{
	CALLED();
	BBuffer * buffer = const_cast<BBuffer*>((BBuffer*)event->pointer);
	if (buffer == 0) {
		fprintf(stderr,"<- B_BAD_VALUE\n");
		return B_BAD_VALUE;
	}
	
	if(fInput.destination.id != buffer->Header()->destination) {
		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
		return B_MEDIA_BAD_DESTINATION;
	}
	
	media_header* hdr = buffer->Header();
	bigtime_t now = TimeSource()->Now();
	bigtime_t perf_time = hdr->start_time;
	
	// the how_early calculate here doesn't include scheduling latency because
	// we've already been scheduled to handle the buffer
	bigtime_t how_early = perf_time - EventLatency() - now;
	
	// if the buffer is late, we ignore it and report the fact to the producer
	// who sent it to us
	if ((RunMode() != B_OFFLINE) &&				// lateness doesn't matter in offline mode...
		(RunMode() != B_RECORDING) &&		// ...or in recording mode
		(how_early < 0LL))
	{
		//mLateBuffers++;
		NotifyLateProducer(fInput.source, -how_early, perf_time);
		fprintf(stderr,"	<- LATE BUFFER : %lli\n", how_early);
		buffer->Recycle();
	} else {
		if (fDevice->CanSend())
			fDevice->Write(buffer->Data(), buffer->SizeUsed());
	}
	return B_OK;
}
예제 #2
0
BBuffer*
AudioProducer::_FillNextBuffer(bigtime_t eventTime)
{
	BBuffer* buffer = fBufferGroup->RequestBuffer(
		fOutput.format.u.raw_audio.buffer_size, BufferDuration());

	if (!buffer) {
		ERROR("AudioProducer::_FillNextBuffer() - no buffer\n");
		return NULL;
	}

	size_t sampleSize = fOutput.format.u.raw_audio.format
		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
	size_t numSamples = fOutput.format.u.raw_audio.buffer_size / sampleSize;
		// number of sample in the buffer

	// fill in the buffer header
	media_header* header = buffer->Header();
	header->type = B_MEDIA_RAW_AUDIO;
	header->time_source = TimeSource()->ID();
	buffer->SetSizeUsed(fOutput.format.u.raw_audio.buffer_size);

	bigtime_t performanceTime = bigtime_t(double(fFramesSent)
		* 1000000.0 / double(fOutput.format.u.raw_audio.frame_rate));

	// fill in data from audio supplier
	int64 frameCount = numSamples / fOutput.format.u.raw_audio.channel_count;
	bigtime_t startTime = performanceTime;
	bigtime_t endTime = bigtime_t(double(fFramesSent + frameCount)
		* 1000000.0 / fOutput.format.u.raw_audio.frame_rate);

	if (!fSupplier || fSupplier->InitCheck() != B_OK
		|| fSupplier->GetFrames(buffer->Data(), frameCount, startTime,
			endTime) != B_OK) {
		ERROR("AudioProducer::_FillNextBuffer() - supplier error -> silence\n");
		memset(buffer->Data(), 0, buffer->SizeUsed());
	}

	// stamp buffer
	if (RunMode() == B_RECORDING) {
		header->start_time = eventTime;
	} else {
		header->start_time = fStartTime + performanceTime;
	}

#if DEBUG_TO_FILE
	BMediaTrack* track;
	if (BMediaFile* file = init_media_file(fOutput.format, &track)) {
		track->WriteFrames(buffer->Data(), frameCount);
	}
#endif // DEBUG_TO_FILE

	if (fPeakListener
		&& fOutput.format.u.raw_audio.format
			== media_raw_audio_format::B_AUDIO_FLOAT) {
		// TODO: extend the peak notifier for other sample formats
		int32 channels = fOutput.format.u.raw_audio.channel_count;
		float max[channels];
		float min[channels];
		for (int32 i = 0; i < channels; i++) {
			max[i] = -1.0;
			min[i] = 1.0;
		}
		float* sample = (float*)buffer->Data();
		for (uint32 i = 0; i < frameCount; i++) {
			for (int32 k = 0; k < channels; k++) {
				if (*sample < min[k])
					min[k] = *sample;
				if (*sample > max[k])
					max[k] = *sample;
				sample++;
			}
		}
		BMessage message(MSG_PEAK_NOTIFICATION);
		for (int32 i = 0; i < channels; i++) {
			float maxAbs = max_c(fabs(min[i]), fabs(max[i]));
			message.AddFloat("max", maxAbs);
		}
		bigtime_t realTime = TimeSource()->RealTimeFor(
			fStartTime + performanceTime, 0);
		MessageEvent* event = new (std::nothrow) MessageEvent(realTime,
			fPeakListener, message);
		if (event != NULL)
			EventQueue::Default().AddEvent(event);
	}

	return buffer;
}
예제 #3
0
void MediaReader::Connect(
				status_t error, 
				const media_source & source,
				const media_destination & destination,
				const media_format & format,
				char * io_name)
{
	CALLED();

	if (error != B_OK) {
		PRINT("\t<- error already\n");
		output.destination = media_destination::null;
		GetFormat(&output.format);
		return;
	}
	if (output.source != source) {
		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
		output.destination = media_destination::null;
		GetFormat(&output.format);
		return;
	}	
	
	// record the agreed upon values
	output.destination = destination;
	output.format = format;
	strncpy(io_name,output.name,B_MEDIA_NAME_LENGTH-1);
	io_name[B_MEDIA_NAME_LENGTH-1] = '\0';

	// determine our downstream latency
	media_node_id id;
	FindLatencyFor(output.destination, &fDownstreamLatency, &id);

	// compute the buffer period (must be done before setbuffergroup)
	fBufferPeriod = bigtime_t(1000 * 8000000 / 1024
	                     * output.format.u.multistream.max_chunk_size
			             / output.format.u.multistream.max_bit_rate);

	PRINT("\tmax chunk size = %ld, max bit rate = %f, buffer period = %lld\n",
			output.format.u.multistream.max_chunk_size,
			output.format.u.multistream.max_bit_rate,fBufferPeriod);

	// setup the buffers if they aren't setup yet
	if (fBufferGroup == 0) {
		status_t status = SetBufferGroup(output.source,0);
		if (status != B_OK) {
			PRINT("\t<- SetBufferGroup failed\n");
			output.destination = media_destination::null;
			GetFormat(&output.format);
			return;
		}
	}

	SetBufferDuration(fBufferPeriod);

	if (GetCurrentFile() != 0) {
		bigtime_t start, end;
		// buffer group buffer size
		uint8 * data = new uint8[output.format.u.multistream.max_chunk_size];
		BBuffer * buffer = 0;
		ssize_t bytesRead = 0;
		{ // timed section
			start = TimeSource()->RealTime();
			// first we try to use a real BBuffer
			buffer = fBufferGroup->RequestBuffer(
					output.format.u.multistream.max_chunk_size,fBufferPeriod);
			if (buffer != 0) {
				FillFileBuffer(buffer);
			} else {
				// didn't get a real BBuffer, try simulation by just a read from the disk
				bytesRead = GetCurrentFile()->Read(
						data, output.format.u.multistream.max_chunk_size);
			}
			end = TimeSource()->RealTime();
		}
		bytesRead = buffer->SizeUsed();
		delete data;
		if (buffer != 0) {
			buffer->Recycle();
		}
		GetCurrentFile()->Seek(-bytesRead,SEEK_CUR); // put it back where we found it
	
		fInternalLatency = end - start;
		
		PRINT("\tinternal latency from disk read = %lld\n", fInternalLatency);
	} else {
		fInternalLatency = 100; // just guess
		PRINT("\tinternal latency guessed = %lld\n", fInternalLatency);
	}
	
	SetEventLatency(fDownstreamLatency + fInternalLatency);
	
	// XXX: do anything else?
}
예제 #4
0
파일: BufferTest.cpp 프로젝트: mariuz/haiku
int main()
{
	// app_server connection (no need to run it)
	BApplication app("application/x-vnd-test"); 
	
	BBufferGroup * group;
	status_t s;
	int32 count;
	BBuffer *buffer;

/*
	printf("using default constructor:\n");
	group = new BBufferGroup();


	s = group->InitCheck();
	printf("InitCheck: status = %ld\n",s);
	
	s = group->CountBuffers(&count);
	printf("CountBuffers: count = %ld, status = %ld\n",count,s);
	
	delete group;
*/
	printf("\n");
	printf("using size = 1234 constructor:\n");
	group = new BBufferGroup(1234);

	s = group->InitCheck();
	printf("InitCheck: status = %ld\n",s);
	
	s = group->CountBuffers(&count);
	printf("CountBuffers: count = %ld, status = %ld\n",count,s);

	s = group->GetBufferList(1,&buffer);
	printf("GetBufferList: status = %ld\n",s);

	printf("Buffer->Data:  = %08x\n",(int)buffer->Data());

	printf("Buffer->ID:  = %d\n",(int)buffer->ID());

	printf("Buffer->Size:  = %ld\n",buffer->Size());

	printf("Buffer->SizeAvailable:  = %ld\n",buffer->SizeAvailable());

	printf("Buffer->SizeUsed:  = %ld\n",buffer->SizeUsed());

	printf("\n");

	media_buffer_id id = buffer->ID();
	BBufferGroup * group2 = new BBufferGroup(1,&id);
	printf("creating second group with a buffer from first group:\n");

	s = group2->InitCheck();
	printf("InitCheck: status = %ld\n",s);

	s = group2->CountBuffers(&count);
	printf("CountBuffers: count = %ld, status = %ld\n",count,s);

	buffer = 0;
	s = group2->GetBufferList(1,&buffer);
	printf("GetBufferList: status = %ld\n",s);

	printf("Buffer->Data:  = %08x\n",(int)buffer->Data());

	printf("Buffer->ID:  = %d\n",(int)buffer->ID());

	printf("Buffer->Size:  = %ld\n",buffer->Size());

	printf("Buffer->SizeAvailable:  = %ld\n",buffer->SizeAvailable());

	printf("Buffer->SizeUsed:  = %ld\n",buffer->SizeUsed());

	delete group;
	delete group2;

	printf("\n");
/*
	printf("creating a BSmallBuffer:\n");
	BSmallBuffer * sb = new BSmallBuffer;

	printf("sb->Data:  = %08x\n",(int)sb->Data());

	printf("sb->ID:  = %d\n",(int)sb->ID());

	printf("sb->Size:  = %ld\n",sb->Size());

	printf("sb->SizeAvailable:  = %ld\n",sb->SizeAvailable());

	printf("sb->SizeUsed:  = %ld\n",sb->SizeUsed());

	printf("sb->SmallBufferSizeLimit:  = %ld\n",sb->SmallBufferSizeLimit());

	delete sb;
*/
	return 0;
}