* A BBuffer does not know where it came from, so

BBufferConsumer::BufferReceived() cannot know whom to send the "buffer is
  late" notification (unless we only have a single input). To solve this, the
  media_header now contains extra fields that can be used to create a
  media_source object.
* Unfortunately, BBufferProducer::SendBuffer() cannot know the output either in
  case there is more than one. Hence, I deprecated the existing SendBuffer()
  call and moved it into "private" - IOW old sources using it won't compile
  anymore under Haiku.
* I introduced a new SendBuffer() variant that also gets the media_source as
  argument.
* Updated all sources (that are part of the image) to use the new variant.
* Removed some purposely commented out code in the audio mixer.
* Implemented late buffer notification, as well as late buffer handling in the
  audio mixer; this is a bit of work in progress, so the debug output is left
  in there.
* Some cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36184 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-04-12 13:15:46 +00:00
parent 5819c3f9ff
commit b289aaf66b
19 changed files with 533 additions and 497 deletions
+5
View File
@@ -138,6 +138,7 @@ protected:
// NOTE: Use this function to pass on the buffer on to the BBufferConsumer.
status_t SendBuffer(BBuffer* buffer,
const media_source& source,
const media_destination& destination);
status_t SendDataStatus(int32 status,
@@ -205,6 +206,10 @@ private:
virtual status_t _Reserved_BufferProducer_14(void*);
virtual status_t _Reserved_BufferProducer_15(void*);
// deprecated calls
status_t SendBuffer(BBuffer* buffer,
const media_destination& destination);
private:
friend class BBufferConsumer;
friend class BMediaNode;
+2 -1
View File
@@ -671,7 +671,8 @@ struct media_header {
};
type_code user_data_type;
uchar user_data[64]; // user_data_type indicates what this is
uint32 _reserved_[2];
int32 source;
port_id source_port;
off_t file_pos; // where in a file this data came from
size_t orig_size; // and how big it was. if unused, zero out
@@ -22,6 +22,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <fcntl.h>
#include <malloc.h>
#include <math.h>
@@ -1670,7 +1671,8 @@ DVBMediaNode::raw_audio_thread()
hdr->time_source = TimeSource()->ID(); // set time source id
hdr->start_time = start_time; // set start time
lock.Lock();
if (B_OK != SendBuffer(buf, fOutputRawAudio.destination)) {
if (SendBuffer(buf, fOutputRawAudio.source, fOutputRawAudio.destination)
!= B_OK) {
TRACE("audio: sending buffer failed\n");
buf->Recycle();
}
@@ -1866,7 +1868,8 @@ DVBMediaNode::raw_video_thread()
hdr->time_source = TimeSource()->ID(); // set time source id
hdr->start_time = start_time; // set start time
lock.Lock();
if (B_OK != SendBuffer(buf, fOutputRawVideo.destination)) {
if (SendBuffer(buf, fOutputRawVideo.source, fOutputRawVideo.destination)
!= B_OK) {
TRACE("video: sending buffer failed\n");
buf->Recycle();
}
@@ -8,6 +8,7 @@
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*/
#include "FireWireDVNode.h"
#include <fcntl.h>
@@ -602,7 +603,8 @@ FireWireDVNode::card_reader_thread()
hdr->start_time = TimeSource()->PerformanceTimeFor(system_time());
fLock.Lock();
if (B_OK != SendBuffer(buf, fOutputEncVideo.destination)) {
if (SendBuffer(buf, fOutputEncVideo.source,
fOutputEncVideo.destination) != B_OK) {
TRACE("OutVideo: sending buffer failed\n");
buf->Recycle();
}
@@ -100,7 +100,8 @@ AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer)
fBufferGroup(0),
fDownstreamLatency(1),
fInternalLatency(1),
fDisableStop(false)
fDisableStop(false),
fLastLateNotification(0)
{
BMediaNode::AddNodeKind(B_SYSTEM_MIXER);
@@ -294,13 +295,6 @@ AudioMixer::BufferReceived(BBuffer *buffer)
//PRINT(4, "buffer received at %12Ld, should arrive at %12Ld, delta %12Ld\n", TimeSource()->Now(), buffer->Header()->start_time, TimeSource()->Now() - buffer->Header()->start_time);
// Note: The following code is outcommented on purpose
// and is about to be modified at a later point
// HandleInputBuffer(buffer, 0);
// buffer->Recycle();
// return;
// to receive the buffer at the right time,
// push it through the event looper
media_timed_event event(buffer->Header()->start_time,
@@ -311,37 +305,33 @@ AudioMixer::BufferReceived(BBuffer *buffer)
void
AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
AudioMixer::HandleInputBuffer(BBuffer* buffer, bigtime_t lateness)
{
// Note: The following code is outcommented on purpose
// and is about to be modified at a later point
/*
if (lateness > 5000) {
printf("Received buffer with way to high lateness %Ld\n", lateness);
if (RunMode() != B_DROP_DATA) {
printf("sending notify\n");
NotifyLateProducer(channel->fInput.source, lateness / 2, TimeSource()->Now());
} else if (RunMode() == B_DROP_DATA) {
printf("dropping buffer\n");
return;
if (lateness > 0) {
debug_printf("Received buffer %Ld usec late\n", lateness);
if (RunMode() == B_DROP_DATA || RunMode() == B_DECREASE_PRECISION
|| RunMode() == B_INCREASE_LATENCY) {
debug_printf("sending notify\n");
// Build a media_source out of the header data
media_source source = media_source::null;
source.port = buffer->Header()->source_port;
source.id = buffer->Header()->source;
NotifyLateProducer(source, lateness, TimeSource()->Now());
if (RunMode() == B_DROP_DATA) {
debug_printf("dropping buffer\n");
return;
}
}
}
*/
// printf("Received buffer with lateness %Ld\n", lateness);
fCore->Lock();
fCore->BufferReceived(buffer, lateness);
fCore->Unlock();
// Note: The following code is outcommented on purpose
// and is about to be modified at a later point
/*
if ((B_OFFLINE == RunMode()) && (B_DATA_AVAILABLE == channel->fProducerDataStatus))
{
RequestAdditionalBuffer(channel->fInput.source, buffer);
}
*/
}
@@ -894,9 +884,8 @@ AudioMixer::Connect(status_t error, const media_source &source,
return;
}
/* Switch our prefered format to have the same
* frame_rate and channel count as the output.
*/
// Switch our prefered format to have the same
// frame_rate and channel count as the output.
fDefaultFormat.u.raw_audio.frame_rate = format.u.raw_audio.frame_rate;
fDefaultFormat.u.raw_audio.channel_count = format.u.raw_audio.channel_count;
@@ -953,6 +942,7 @@ AudioMixer::Connect(status_t error, const media_source &source,
UpdateParameterWeb();
}
void
AudioMixer::Disconnect(const media_source &what, const media_destination &where)
{
@@ -991,37 +981,37 @@ AudioMixer::Disconnect(const media_source &what, const media_destination &where)
void
AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much,
bigtime_t performance_time)
AudioMixer::LateNoticeReceived(const media_source& what, bigtime_t howMuch,
bigtime_t performanceTime)
{
// We've produced some late buffers... Increase Latency
// is the only runmode in which we can do anything about this
// TODO: quality could be decreased, too
ERROR("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", how_much,
performance_time);
// Note: The following code is outcommented on purpose
// and is about to be modified at a later point
/*
if (what == fOutput.source) {
if (RunMode() == B_INCREASE_LATENCY) {
fInternalLatency += how_much;
ERROR("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", howMuch,
performanceTime);
if (fInternalLatency > 50000)
fInternalLatency = 50000;
if (what == fCore->Output()->MediaOutput().source
&& RunMode() == B_INCREASE_LATENCY) {
// We need to ignore subsequent notices whose performance time
// lies before the performance time of the last notification
if (performanceTime < fLastLateNotification)
return;
printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
SetEventLatency(fDownstreamLatency + fInternalLatency);
fInternalLatency += howMuch;
fLastLateNotification = TimeSource()->Now();
PublishEventLatencyChange();
}
debug_printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
SetEventLatency(fDownstreamLatency + fInternalLatency);
PublishEventLatencyChange();
}
*/
}
void
AudioMixer::EnableOutput(const media_source &what, bool enabled,
int32 *_deprecated_)
AudioMixer::EnableOutput(const media_source& what, bool enabled,
int32 */*deprecated*/)
{
// we only have one output
if (what.id != 0 || what.port != ControlPort())
@@ -1046,12 +1036,12 @@ AudioMixer::NodeRegistered()
void
AudioMixer::SetTimeSource(BTimeSource * time_source)
AudioMixer::SetTimeSource(BTimeSource* timeSource)
{
TRACE("AudioMixer::SetTimeSource: timesource is now %ld\n",
time_source->ID());
timeSource->ID());
fCore->Lock();
fCore->SetTimingInfo(time_source, fDownstreamLatency);
fCore->SetTimingInfo(timeSource, fDownstreamLatency);
fCore->Unlock();
}
@@ -1156,6 +1146,14 @@ AudioMixer::CreateBufferGroup()
}
status_t
AudioMixer::SendBuffer(BBuffer* buffer, MixerOutput* output)
{
return BBufferProducer::SendBuffer(buffer, output->MediaOutput().source,
output->MediaOutput().destination);
}
float
AudioMixer::dB_to_Gain(float db)
{
@@ -1200,7 +1198,7 @@ AudioMixer::Gain_to_dB(float gain)
}
// #pragma markß - BControllable methods
// #pragma mark - BControllable methods
status_t
+104 -103
View File
@@ -1,11 +1,11 @@
/*
* Copyright 2002 David Shipman,
* Copyright 2003-2007 Marcus Overhagen
* Copyright 2007 Haiku Inc. All rights reserved.
* Copyright 2007-2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _AUDIOMIXER_H
#define _AUDIOMIXER_H
#ifndef AUDIO_MIXER_H
#define AUDIO_MIXER_H
#include <BufferConsumer.h>
@@ -17,125 +17,126 @@
class MixerCore;
class MixerOutput;
class AudioMixer : public BBufferConsumer, public BBufferProducer,
public BControllable, public BMediaEventLooper {
public:
AudioMixer(BMediaAddOn *addOn, bool isSystemMixer);
~AudioMixer();
AudioMixer(BMediaAddOn* addOn,
bool isSystemMixer);
virtual ~AudioMixer();
void DisableNodeStop();
void DisableNodeStop();
// AudioMixer support
void ApplySettings();
// AudioMixer support
void ApplySettings();
void PublishEventLatencyChange();
void UpdateParameterWeb();
void PublishEventLatencyChange();
void UpdateParameterWeb();
void HandleInputBuffer(BBuffer *buffer, bigtime_t lateness);
void HandleInputBuffer(BBuffer* buffer,
bigtime_t lateness);
BBufferGroup * CreateBufferGroup();
BBufferGroup* CreateBufferGroup();
float dB_to_Gain(float db);
float Gain_to_dB(float gain);
status_t SendBuffer(BBuffer* buffer,
MixerOutput* output);
// BMediaNode methods
BMediaAddOn * AddOn(int32 *internal_id) const;
void NodeRegistered();
void Stop(bigtime_t performance_time, bool immediate);
void SetTimeSource(BTimeSource * time_source);
using BBufferProducer::SendBuffer;
float dB_to_Gain(float db);
float Gain_to_dB(float gain);
// BMediaNode methods
virtual BMediaAddOn* AddOn(int32* _internalID) const;
virtual void NodeRegistered();
virtual void Stop(bigtime_t performanceTime, bool immediate);
virtual void SetTimeSource(BTimeSource* timeSource);
protected:
// BControllable methods
status_t GetParameterValue(int32 id,
bigtime_t *last_change,
void *value,
size_t *ioSize);
// BControllable methods
virtual status_t GetParameterValue(int32 id,
bigtime_t* _lastChange, void* _value,
size_t* _size);
virtual void SetParameterValue(int32 id, bigtime_t when,
const void* value, size_t size);
void SetParameterValue(int32 id, bigtime_t when,
const void *value,
size_t size);
// BBufferConsumer methods
virtual status_t HandleMessage(int32 message, const void* data,
size_t size);
virtual status_t AcceptFormat(const media_destination& dest,
media_format* format);
virtual status_t GetNextInput(int32* cookie,
media_input* _input);
virtual void DisposeInputCookie(int32 cookie);
virtual void BufferReceived(BBuffer *buffer);
virtual void ProducerDataStatus(
const media_destination& forWhom,
int32 status, bigtime_t atPerformanceTime);
virtual status_t GetLatencyFor(const media_destination& forWhom,
bigtime_t* _latency,
media_node_id* _timesource);
virtual status_t Connected(const media_source& producer,
const media_destination& where,
const media_format& withFormat,
media_input* _input);
virtual void Disconnected(const media_source& producer,
const media_destination& where);
virtual status_t FormatChanged(const media_source& producer,
const media_destination& consumer,
int32 changeTag,
const media_format& format);
// BBufferConsumer methods
status_t HandleMessage(int32 message, const void* data,
size_t size);
status_t AcceptFormat(const media_destination &dest,
media_format *format);
status_t GetNextInput(int32 *cookie,
media_input *out_input);
void DisposeInputCookie(int32 cookie);
void BufferReceived(BBuffer *buffer);
void ProducerDataStatus(const media_destination &for_whom,
int32 status,
bigtime_t at_performance_time);
status_t GetLatencyFor(const media_destination &for_whom,
bigtime_t *out_latency,
media_node_id *out_timesource);
status_t Connected(const media_source &producer,
const media_destination &where,
const media_format &with_format,
media_input *out_input);
void Disconnected(const media_source &producer,
const media_destination &where);
status_t FormatChanged(const media_source &producer,
const media_destination &consumer,
int32 change_tag,
const media_format &format);
// BBufferProducer methods
status_t FormatSuggestionRequested(media_type type,
int32 quality,
media_format *format);
status_t FormatProposal(const media_source &output,
media_format *format);
status_t FormatChangeRequested(
const media_source& source,
const media_destination &destination,
media_format *io_format,
int32 *_deprecated_);
status_t GetNextOutput(int32 *cookie,media_output *out_output);
status_t DisposeOutputCookie(int32 cookie);
status_t SetBufferGroup(const media_source &for_source,
BBufferGroup *group);
status_t GetLatency(bigtime_t *out_latency);
status_t PrepareToConnect(const media_source &what,
const media_destination &where,
media_format *format,
media_source *out_source,
char *out_name);
void Connect(status_t error,
const media_source &source,
const media_destination &destination,
const media_format &format,
char *io_name);
void Disconnect(const media_source &what,
const media_destination &where);
void LateNoticeReceived(const media_source &what,
bigtime_t how_much,
bigtime_t performance_time);
void EnableOutput(const media_source &what,
bool enabled,
int32 *_deprecated_);
void LatencyChanged(const media_source &source,
const media_destination &destination,
bigtime_t new_latency, uint32 flags);
// BBufferProducer methods
virtual status_t FormatSuggestionRequested(media_type type,
int32 quality, media_format* format);
virtual status_t FormatProposal(const media_source& output,
media_format* format);
virtual status_t FormatChangeRequested(
const media_source& source,
const media_destination &destination,
media_format* format,
int32* /*deprecated*/);
virtual status_t GetNextOutput(int32* cookie,
media_output* _output);
virtual status_t DisposeOutputCookie(int32 cookie);
virtual status_t SetBufferGroup(const media_source& source,
BBufferGroup* group);
virtual status_t GetLatency(bigtime_t* _latency);
virtual status_t PrepareToConnect(const media_source& what,
const media_destination& where,
media_format* format, media_source* _source,
char* _name);
virtual void Connect(status_t error,
const media_source& source,
const media_destination& destination,
const media_format& format, char *_name);
virtual void Disconnect(const media_source& what,
const media_destination& where);
virtual void LateNoticeReceived(const media_source& what,
bigtime_t howMuch,
bigtime_t performanceTime);
virtual void EnableOutput(const media_source& what,
bool enabled, int32* /*_deprecated_*/);
virtual void LatencyChanged(const media_source& source,
const media_destination& destination,
bigtime_t newLatency, uint32 flags);
// BMediaEventLooper methods
void HandleEvent(const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent = false);
virtual void HandleEvent(const media_timed_event* event,
bigtime_t lateness,
bool realTimeEvent = false);
private:
BMediaAddOn *fAddOn;
MixerCore *fCore;
BParameterWeb *fWeb; // local pointer to parameterweb
BBufferGroup *fBufferGroup;
bigtime_t fDownstreamLatency;
bigtime_t fInternalLatency;
bool fDisableStop;
media_format fDefaultFormat;
BMediaAddOn* fAddOn;
MixerCore* fCore;
BParameterWeb* fWeb;
BBufferGroup* fBufferGroup;
bigtime_t fDownstreamLatency;
bigtime_t fInternalLatency;
bool fDisableStop;
media_format fDefaultFormat;
bigtime_t fLastLateNotification;
};
#endif // _AUDIOMIXER_H
#endif // AUDIO_MIXER_H
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2009 Haiku Inc. All rights reserved.
* Copyright 2003-2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -530,8 +530,7 @@ MixerCore::MixThread()
hdr->size_used = size;
hdr->time_source = fTimeSource->ID();
hdr->start_time = event_time;
if (fNode->SendBuffer(buf, fOutput->MediaOutput().destination)
!= B_OK) {
if (fNode->SendBuffer(buf, fOutput) != B_OK) {
#if DEBUG
ERROR("MixerCore: SendBuffer failed for buffer %Ld\n",
buffer_num);
@@ -664,8 +663,7 @@ MixerCore::MixThread()
fOutput->AdjustByteOrder(buf);
// send the buffer
status_t res = fNode->SendBuffer(buf,
fOutput->MediaOutput().destination);
status_t res = fNode->SendBuffer(buf, fOutput);
if (res != B_OK) {
#if DEBUG
ERROR("MixerCore: SendBuffer failed for buffer %Ld\n",
@@ -1764,7 +1764,7 @@ MultiAudioNode::_RunThread()
// enabled
status_t err = B_ERROR;
if (output->fOutputEnabled) {
err = SendBuffer(buffer,
err = SendBuffer(buffer, output->fOutput.source,
output->fOutput.destination);
}
if (err) {
@@ -5,6 +5,8 @@
* Copyright (c) 2002, 2003 Jerome Duval (jerome.duval@free.fr)
* Distributed under the terms of the MIT License.
*/
#include "OpenSoundNode.h"
#include <Autolock.h>
@@ -2356,8 +2358,10 @@ OpenSoundNode::_RecThread(NodeOutput* output)
if (buffer) {
// send the buffer downstream if and only if output is enabled
status_t err = B_ERROR;
if (output->fOutputEnabled)
err = SendBuffer(buffer, output->fOutput.destination);
if (output->fOutputEnabled) {
err = SendBuffer(buffer, output->fOutput.source,
output->fOutput.destination);
}
// TRACE("OpenSoundNode::_RunThread: I avail: %d, OE %d, %s\n",
// avail, output->fOutputEnabled, strerror(err));
if (err != B_OK) {
@@ -797,17 +797,18 @@ ToneProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
case BTimedEventQueue::B_HANDLE_BUFFER:
{
// make sure we're both started *and* connected before delivering a buffer
if ((RunState() == BMediaEventLooper::B_STARTED) && (mOutput.destination != media_destination::null))
{
if (RunState() == BMediaEventLooper::B_STARTED
&& mOutput.destination != media_destination::null) {
// Get the next buffer of data
BBuffer* buffer = FillNextBuffer(event->event_time);
if (buffer)
{
if (buffer) {
// send the buffer downstream if and only if output is enabled
status_t err = B_ERROR;
if (mOutputEnabled) err = SendBuffer(buffer, mOutput.destination);
if (err)
{
if (mOutputEnabled) {
err = SendBuffer(buffer, mOutput.source,
mOutput.destination);
}
if (err) {
// we need to recycle the buffer ourselves if output is disabled or
// if the call to SendBuffer() fails
buffer->Recycle();
@@ -820,8 +821,10 @@ ToneProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
mFramesSent += nFrames;
// The buffer is on its way; now schedule the next one to go
bigtime_t nextEvent = mStartTime + bigtime_t(double(mFramesSent) / double(mOutput.format.u.raw_audio.frame_rate) * 1000000.0);
media_timed_event nextBufferEvent(nextEvent, BTimedEventQueue::B_HANDLE_BUFFER);
bigtime_t nextEvent = mStartTime + bigtime_t(double(mFramesSent)
/ double(mOutput.format.u.raw_audio.frame_rate) * 1000000.0);
media_timed_event nextBufferEvent(nextEvent,
BTimedEventQueue::B_HANDLE_BUFFER);
EventQueue()->AddEvent(nextBufferEvent);
}
}
@@ -968,7 +968,7 @@ PRINT(("PS: %Ld\n", fProcessingLatency));
PRINTF(1, ("FrameGenerator: SendBuffer...\n"));
/* Send the buffer on down to the consumer */
if (SendBuffer(buffer, fOutput.destination) < B_OK) {
if (SendBuffer(buffer, fOutput.source, fOutput.destination) < B_OK) {
PRINTF(-1, ("FrameGenerator: Error sending buffer\n"));
/* If there is a problem sending the buffer, return it to its
* buffer group. */
@@ -2,6 +2,8 @@
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
#include <fcntl.h>
#include <malloc.h>
#include <math.h>
@@ -717,7 +719,7 @@ VideoProducer::FrameGenerator()
*(p++) = ((((x+y)^0^x)+fFrame) & 0xff) * (0x01010101 & fColor);
/* Send the buffer on down to the consumer */
if (SendBuffer(buffer, fOutput.destination) < B_OK) {
if (SendBuffer(buffer, fOutput.source, fOutput.destination) < B_OK) {
PRINTF(-1, ("FrameGenerator: Error sending buffer\n"));
/* If there is a problem sending the buffer, return it to its
* buffer group. */
@@ -296,8 +296,8 @@ void FlangerNode::BufferReceived(
// process and retransmit buffer
filterBuffer(pBuffer);
status_t err = SendBuffer(pBuffer, m_output.destination);
if(err < B_OK) {
status_t err = SendBuffer(pBuffer, m_output.source, m_output.destination);
if (err < B_OK) {
PRINT(("FlangerNode::BufferReceived():\n"
"\tSendBuffer() failed: %s\n", strerror(err)));
pBuffer->Recycle();
@@ -309,12 +309,11 @@ void FlangerNode::BufferReceived(
// pFormat; as of R4.5 the Media Kit passes poInput->format to
// the producer in BBufferProducer::Connect().
status_t FlangerNode::Connected(
const media_source& source,
const media_destination& destination,
const media_format& format,
media_input* poInput) {
status_t
FlangerNode::Connected(const media_source& source,
const media_destination& destination, const media_format& format,
media_input* poInput)
{
PRINT(("FlangerNode::Connected()\n"
"\tto source %ld\n", source.id));
@@ -523,8 +523,8 @@ void AudioFilterNode::BufferReceived(
// process and retransmit buffer
processBuffer(buffer, outBuffer);
status_t err = SendBuffer(outBuffer, m_output.destination);
if(err < B_OK) {
status_t err = SendBuffer(outBuffer, m_output.source, m_output.destination);
if (err < B_OK) {
PRINT(("AudioFilterNode::BufferReceived():\n"
"\tSendBuffer() failed: %s\n", strerror(err)));
outBuffer->Recycle();
@@ -7,6 +7,7 @@
* All Rights Reserved. Distributed under the terms of the MIT license.
*/
#include "AudioProducer.h"
#include <math.h>
@@ -465,7 +466,7 @@ AudioProducer::Disconnect(const media_source& what,
TRACE("%p->AudioProducer::Disconnect()\n", this);
// Make sure that our connection is the one being disconnected
if ((where == fOutput.destination) && (what == fOutput.source)) {
if (where == fOutput.destination && what == fOutput.source) {
fOutput.destination = media_destination::null;
fOutput.format = fPreferredFormat;
TRACE("AudioProducer: deleting buffer group...\n");
@@ -547,7 +548,7 @@ AudioProducer::LatencyChanged(const media_source& source,
{
TRACE("%p->AudioProducer::LatencyChanged(%lld)\n", this, newLatency);
if ((source == fOutput.source) && (destination == fOutput.destination)) {
if (source == fOutput.source && destination == fOutput.destination) {
fLatency = newLatency;
SetEventLatency(fLatency + fInternalLatency);
}
@@ -610,20 +611,22 @@ printf("B_START: start time: %lld\n", fStartTime);
TRACE("AudioProducer::HandleEvent(B_STOP) done\n");
break;
case BTimedEventQueue::B_HANDLE_BUFFER: {
case BTimedEventQueue::B_HANDLE_BUFFER:
{
TRACE_BUFFER("AudioProducer::HandleEvent(B_HANDLE_BUFFER)\n");
if ((RunState() == BMediaEventLooper::B_STARTED)
&& (fOutput.destination != media_destination::null)) {
if (RunState() == BMediaEventLooper::B_STARTED
&& fOutput.destination != media_destination::null) {
BBuffer* buffer = _FillNextBuffer(event->event_time);
if (buffer) {
status_t err = B_ERROR;
if (fOutputEnabled)
err = SendBuffer(buffer, fOutput.destination);
if (fOutputEnabled) {
err = SendBuffer(buffer, fOutput.source,
fOutput.destination);
}
if (err)
buffer->Recycle();
}
size_t sampleSize
= fOutput.format.u.raw_audio.format
size_t sampleSize = fOutput.format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK;
size_t nFrames = fOutput.format.u.raw_audio.buffer_size
@@ -5,6 +5,8 @@
* Copyright (c) 2000-2008, Stephan Aßmus <superstippi@gmx.de>,
* All Rights Reserved. Distributed under the terms of the MIT license.
*/
#include "VideoProducer.h"
#include <stdio.h>
@@ -812,7 +814,8 @@ h->start_time = 0;
err = B_OK;
}
// Send the buffer on down to the consumer
if (SendBuffer(buffer, fOutput.destination) < B_OK) {
if (SendBuffer(buffer, fOutput.source,
fOutput.destination) < B_OK) {
ERROR("_FrameGeneratorThread: Error "
"sending buffer\n");
// If there is a problem sending the buffer,
+37 -55
View File
@@ -1,73 +1,53 @@
/*****************************************************************************/
// GameProdcure.h
//
// This produce creates audio buffer on behalf of the GameKit.
//
// Copyright (c) 2001 OpenBeOS Project
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: GameProducer.cpp
// Author: Christopher ML Zumwalt May ([email protected])
// Description: A MediaKit producer node which mixes sound from the GameKit
// and sends them to the audio mixer
/*****************************************************************************/
/*
* Copyright 2002-2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Christopher ML Zumwalt May (zummy@users.sf.net)
*/
/*! A MediaKit producer node which mixes sound from the GameKit
and sends them to the audio mixer
*/
// Standard Includes -----------------------------------------------------------
#include <string.h>
#include <stdio.h>
// System Includes -------------------------------------------------------------
#include <ByteOrder.h>
#include <BufferGroup.h>
#include <Buffer.h>
#include <BufferGroup.h>
#include <ByteOrder.h>
#include <List.h>
#include <TimeSource.h>
#include <MediaDefs.h>
#include <TimeSource.h>
// Project Includes ------------------------------------------------------------
#include "GameSoundBuffer.h"
#include "GameSoundDevice.h"
#include "GSUtility.h"
// Local Includes --------------------------------------------------------------
#include "GameProducer.h"
// Local Defines ---------------------------------------------------------------
struct _gs_play
{
gs_id sound;
bool * hook;
struct _gs_play {
gs_id sound;
bool* hook;
_gs_play * next;
_gs_play * previous;
_gs_play* next;
_gs_play* previous;
};
GameProducer::GameProducer(GameSoundBuffer * object,
const gs_audio_format * format)
: BMediaNode("GameProducer.h"),
BBufferProducer(B_MEDIA_RAW_AUDIO),
BMediaEventLooper(),
fBufferGroup(NULL),
fLatency(0),
fInternalLatency(0),
fOutputEnabled(true)
GameProducer::GameProducer(GameSoundBuffer* object,
const gs_audio_format* format)
:
BMediaNode("GameProducer.h"),
BBufferProducer(B_MEDIA_RAW_AUDIO),
BMediaEventLooper(),
fBufferGroup(NULL),
fLatency(0),
fInternalLatency(0),
fOutputEnabled(true)
{
// initialize our preferred format object
fPreferredFormat.type = B_MEDIA_RAW_AUDIO;
@@ -468,8 +448,10 @@ GameProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
if (buffer) {
// send the buffer downstream if and only if output is enabled
status_t err = B_ERROR;
if (fOutputEnabled)
err = SendBuffer(buffer, fOutput.destination);
if (fOutputEnabled) {
err = SendBuffer(buffer, fOutput.source,
fOutput.destination);
}
if (err) {
// we need to recycle the buffer ourselves if output is disabled or
// if the call to SendBuffer() fails
+269 -238
View File
@@ -1,67 +1,49 @@
/*
* Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files or portions
* thereof (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice
* in the binary, as well as this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
* Copyright 2002-2010, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Marcus Overhagen, <Marcus@Overhagen.de>
* Axel Dörfler, axeld@pinc-software.de.
*/
#include <BufferProducer.h>
#include <Buffer.h>
#include <BufferConsumer.h>
#include <BufferGroup.h>
#include <Buffer.h>
#include "debug.h"
#include "MediaMisc.h"
#include "DataExchange.h"
#include <BufferProducer.h>
#include "debug.h"
#include "DataExchange.h"
#include "MediaMisc.h"
// #pragma mark - protected BBufferProducer
/*************************************************************
* protected BBufferProducer
*************************************************************/
BBufferProducer::~BBufferProducer()
{
CALLED();
}
/*************************************************************
* public BBufferProducer
*************************************************************/
/* static */ status_t
BBufferProducer::ClipDataToRegion(int32 format,
int32 size,
const void *data,
BRegion *region)
// #pragma mark - public BBufferProducer
/*static*/ status_t
BBufferProducer::ClipDataToRegion(int32 format, int32 size, const void* data,
BRegion* region)
{
CALLED();
if (format != B_CLIP_SHORT_RUNS)
return B_MEDIA_BAD_CLIP_FORMAT;
return clip_shorts_to_region((const int16 *)data, size / sizeof(int16), region);
return clip_shorts_to_region((const int16*)data, size / sizeof(int16),
region);
}
media_type
BBufferProducer::ProducerType()
{
@@ -69,12 +51,12 @@ BBufferProducer::ProducerType()
return fProducerType;
}
/*************************************************************
* protected BBufferProducer
*************************************************************/
/* explicit */
BBufferProducer::BBufferProducer(media_type producer_type) :
// #pragma mark - protected BBufferProducer
BBufferProducer::BBufferProducer(media_type producer_type)
:
BMediaNode("called by BBufferProducer"),
fProducerType(producer_type),
fInitialLatency(0),
@@ -88,11 +70,9 @@ BBufferProducer::BBufferProducer(media_type producer_type) :
status_t
BBufferProducer::VideoClippingChanged(const media_source &for_source,
int16 num_shorts,
int16 *clip_data,
const media_video_display_info &display,
int32 *_deprecated_)
BBufferProducer::VideoClippingChanged(const media_source& source,
int16 numShorts, int16* clipData, const media_video_display_info& display,
int32* /*_deprecated_*/)
{
CALLED();
// may be implemented by derived classes
@@ -101,70 +81,66 @@ BBufferProducer::VideoClippingChanged(const media_source &for_source,
status_t
BBufferProducer::GetLatency(bigtime_t *out_lantency)
BBufferProducer::GetLatency(bigtime_t* _latency)
{
CALLED();
// The default implementation of GetLatency() finds the maximum
// latency of your currently-available outputs by iterating over
// them, and returns that value in outLatency
int32 cookie;
bigtime_t latency;
media_output output;
media_node_id unused;
*out_lantency = 0;
*_latency = 0;
cookie = 0;
while (B_OK == GetNextOutput(&cookie, &output)) {
while (GetNextOutput(&cookie, &output) == B_OK) {
if (output.destination == media_destination::null)
continue;
if (output.node.node == fNodeID) { // avoid port writes (deadlock) if loopback connection
if (!fConsumerThis)
fConsumerThis = dynamic_cast<BBufferConsumer *>(this);
if (!fConsumerThis)
if (output.node.node == fNodeID) {
// avoid port writes (deadlock) if loopback connection
if (fConsumerThis == NULL)
fConsumerThis = dynamic_cast<BBufferConsumer*>(this);
if (fConsumerThis == NULL)
continue;
latency = 0;
if (B_OK == fConsumerThis->GetLatencyFor(output.destination, &latency, &unused)) {
if (latency > *out_lantency) {
*out_lantency = latency;
}
}
} else {
if (B_OK == FindLatencyFor(output.destination, &latency, &unused)) {
if (latency > *out_lantency) {
*out_lantency = latency;
}
if (fConsumerThis->GetLatencyFor(output.destination, &latency,
&unused) == B_OK && latency > *_latency) {
*_latency = latency;
}
} else if (FindLatencyFor(output.destination, &latency, &unused)
== B_OK && latency > *_latency) {
*_latency = latency;
}
}
printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *out_lantency);
printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *_latency);
return B_OK;
}
status_t
BBufferProducer::SetPlayRate(int32 numer,
int32 denom)
BBufferProducer::SetPlayRate(int32 numer, int32 denom)
{
CALLED();
// may be implemented by derived classes
return B_ERROR;
}
status_t
BBufferProducer::HandleMessage(int32 message,
const void *data,
size_t size)
BBufferProducer::HandleMessage(int32 message, const void* data, size_t size)
{
PRINT(4, "BBufferProducer::HandleMessage %#lx, node %ld\n", message, fNodeID);
status_t rv;
PRINT(4, "BBufferProducer::HandleMessage %#lx, node %ld\n", message,
fNodeID);
switch (message) {
case PRODUCER_SET_RUN_MODE_DELAY:
{
const producer_set_run_mode_delay_command *command = static_cast<const producer_set_run_mode_delay_command *>(data);
const producer_set_run_mode_delay_command* command
= static_cast<const producer_set_run_mode_delay_command*>(data);
// when changing this, also change NODE_SET_RUN_MODE
fDelay = command->delay;
fRunMode = command->mode;
@@ -175,48 +151,58 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_FORMAT_SUGGESTION_REQUESTED:
{
const producer_format_suggestion_requested_request *request = static_cast<const producer_format_suggestion_requested_request *>(data);
const producer_format_suggestion_requested_request* request
= static_cast<
const producer_format_suggestion_requested_request*>(data);
producer_format_suggestion_requested_reply reply;
rv = FormatSuggestionRequested(request->type, request->quality, &reply.format);
request->SendReply(rv, &reply, sizeof(reply));
status_t status = FormatSuggestionRequested(request->type,
request->quality, &reply.format);
request->SendReply(status, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_FORMAT_PROPOSAL:
{
const producer_format_proposal_request *request = static_cast<const producer_format_proposal_request *>(data);
const producer_format_proposal_request* request
= static_cast<const producer_format_proposal_request*>(data);
producer_format_proposal_reply reply;
reply.format = request->format;
rv = FormatProposal(request->output, &reply.format);
request->SendReply(rv, &reply, sizeof(reply));
status_t status = FormatProposal(request->output, &reply.format);
request->SendReply(status, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_PREPARE_TO_CONNECT:
{
const producer_prepare_to_connect_request *request = static_cast<const producer_prepare_to_connect_request *>(data);
const producer_prepare_to_connect_request* request
= static_cast<const producer_prepare_to_connect_request*>(data);
producer_prepare_to_connect_reply reply;
reply.format = request->format;
reply.out_source = request->source;
memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
rv = PrepareToConnect(request->source, request->destination, &reply.format, &reply.out_source, reply.name);
request->SendReply(rv, &reply, sizeof(reply));
status_t status = PrepareToConnect(request->source,
request->destination, &reply.format, &reply.out_source,
reply.name);
request->SendReply(status, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_CONNECT:
{
const producer_connect_request *request = static_cast<const producer_connect_request *>(data);
const producer_connect_request* request
= static_cast<const producer_connect_request*>(data);
producer_connect_reply reply;
memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
Connect(request->error, request->source, request->destination, request->format, reply.name);
Connect(request->error, request->source, request->destination,
request->format, reply.name);
request->SendReply(B_OK, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_DISCONNECT:
{
const producer_disconnect_request *request = static_cast<const producer_disconnect_request *>(data);
const producer_disconnect_request* request
= static_cast<const producer_disconnect_request*>(data);
producer_disconnect_reply reply;
Disconnect(request->source, request->destination);
request->SendReply(B_OK, &reply, sizeof(reply));
@@ -225,7 +211,9 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_GET_INITIAL_LATENCY:
{
const producer_get_initial_latency_request *request = static_cast<const producer_get_initial_latency_request *>(data);
const producer_get_initial_latency_request* request
= static_cast<
const producer_get_initial_latency_request*>(data);
producer_get_initial_latency_reply reply;
reply.initial_latency = fInitialLatency;
reply.flags = fInitialFlags;
@@ -235,35 +223,40 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_SET_PLAY_RATE:
{
const producer_set_play_rate_request *request = static_cast<const producer_set_play_rate_request *>(data);
const producer_set_play_rate_request* request
= static_cast<const producer_set_play_rate_request*>(data);
producer_set_play_rate_reply reply;
rv = SetPlayRate(request->numer, request->denom);
request->SendReply(rv, &reply, sizeof(reply));
status_t status = SetPlayRate(request->numer, request->denom);
request->SendReply(status, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_GET_LATENCY:
{
const producer_get_latency_request *request = static_cast<const producer_get_latency_request *>(data);
const producer_get_latency_request* request
= static_cast<const producer_get_latency_request*>(data);
producer_get_latency_reply reply;
rv = GetLatency(&reply.latency);
request->SendReply(rv, &reply, sizeof(reply));
status_t status = GetLatency(&reply.latency);
request->SendReply(status, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_GET_NEXT_OUTPUT:
{
const producer_get_next_output_request *request = static_cast<const producer_get_next_output_request *>(data);
const producer_get_next_output_request* request
= static_cast<const producer_get_next_output_request*>(data);
producer_get_next_output_reply reply;
reply.cookie = request->cookie;
rv = GetNextOutput(&reply.cookie, &reply.output);
request->SendReply(rv, &reply, sizeof(reply));
status_t status = GetNextOutput(&reply.cookie, &reply.output);
request->SendReply(status, &reply, sizeof(reply));
return B_OK;
}
case PRODUCER_DISPOSE_OUTPUT_COOKIE:
{
const producer_dispose_output_cookie_request *request = static_cast<const producer_dispose_output_cookie_request *>(data);
const producer_dispose_output_cookie_request*request
= static_cast<
const producer_dispose_output_cookie_request*>(data);
producer_dispose_output_cookie_reply reply;
DisposeOutputCookie(request->cookie);
request->SendReply(B_OK, &reply, sizeof(reply));
@@ -272,91 +265,118 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_SET_BUFFER_GROUP:
{
const producer_set_buffer_group_command *command = static_cast<const producer_set_buffer_group_command *>(data);
const producer_set_buffer_group_command* command
= static_cast<const producer_set_buffer_group_command*>(data);
node_request_completed_command replycommand;
BBufferGroup *group;
group = command->buffer_count != 0 ? new BBufferGroup(command->buffer_count, command->buffers) : NULL;
rv = SetBufferGroup(command->source, group);
group = command->buffer_count != 0
? new BBufferGroup(command->buffer_count, command->buffers)
: NULL;
status_t status = SetBufferGroup(command->source, group);
if (command->destination == media_destination::null)
return B_OK;
replycommand.info.what = media_request_info::B_SET_OUTPUT_BUFFERS_FOR;
replycommand.info.what
= media_request_info::B_SET_OUTPUT_BUFFERS_FOR;
replycommand.info.change_tag = command->change_tag;
replycommand.info.status = rv;
replycommand.info.status = status;
replycommand.info.cookie = (int32)group;
replycommand.info.user_data = command->user_data;
replycommand.info.source = command->source;
replycommand.info.destination = command->destination;
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
&replycommand, sizeof(replycommand));
return B_OK;
}
case PRODUCER_FORMAT_CHANGE_REQUESTED:
{
const producer_format_change_requested_command *command = static_cast<const producer_format_change_requested_command *>(data);
const producer_format_change_requested_command* command
= static_cast<
const producer_format_change_requested_command*>(data);
node_request_completed_command replycommand;
replycommand.info.format = command->format;
rv = FormatChangeRequested(command->source, command->destination, &replycommand.info.format, NULL);
status_t status = FormatChangeRequested(command->source,
command->destination, &replycommand.info.format, NULL);
if (command->destination == media_destination::null)
return B_OK;
replycommand.info.what = media_request_info::B_REQUEST_FORMAT_CHANGE;
replycommand.info.what
= media_request_info::B_REQUEST_FORMAT_CHANGE;
replycommand.info.change_tag = command->change_tag;
replycommand.info.status = rv;
replycommand.info.status = status;
//replycommand.info.cookie
replycommand.info.user_data = command->user_data;
replycommand.info.source = command->source;
replycommand.info.destination = command->destination;
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
&replycommand, sizeof(replycommand));
return B_OK;
}
case PRODUCER_VIDEO_CLIPPING_CHANGED:
{
const producer_video_clipping_changed_command *command = static_cast<const producer_video_clipping_changed_command *>(data);
const producer_video_clipping_changed_command* command
= static_cast<
const producer_video_clipping_changed_command*>(data);
node_request_completed_command replycommand;
rv = VideoClippingChanged(command->source, command->short_count, (int16 *)command->shorts, command->display, NULL);
status_t status = VideoClippingChanged(command->source,
command->short_count, (int16 *)command->shorts,
command->display, NULL);
if (command->destination == media_destination::null)
return B_OK;
replycommand.info.what = media_request_info::B_SET_VIDEO_CLIPPING_FOR;
replycommand.info.what
= media_request_info::B_SET_VIDEO_CLIPPING_FOR;
replycommand.info.change_tag = command->change_tag;
replycommand.info.status = rv;
replycommand.info.status = status;
//replycommand.info.cookie
replycommand.info.user_data = command->user_data;
replycommand.info.source = command->source;
replycommand.info.destination = command->destination;
replycommand.info.format.type = B_MEDIA_RAW_VIDEO;
replycommand.info.format.u.raw_video.display = command->display;
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
&replycommand, sizeof(replycommand));
return B_OK;
}
case PRODUCER_ADDITIONAL_BUFFER_REQUESTED:
{
const producer_additional_buffer_requested_command *command = static_cast<const producer_additional_buffer_requested_command *>(data);
AdditionalBufferRequested(command->source, command->prev_buffer, command->prev_time, command->has_seek_tag ? &command->prev_tag : NULL);
const producer_additional_buffer_requested_command* command
= static_cast<
const producer_additional_buffer_requested_command*>(data);
AdditionalBufferRequested(command->source, command->prev_buffer,
command->prev_time, command->has_seek_tag
? &command->prev_tag : NULL);
return B_OK;
}
case PRODUCER_LATENCY_CHANGED:
{
const producer_latency_changed_command *command = static_cast<const producer_latency_changed_command *>(data);
LatencyChanged(command->source, command->destination, command->latency, command->flags);
const producer_latency_changed_command* command
= static_cast<const producer_latency_changed_command*>(data);
LatencyChanged(command->source, command->destination,
command->latency, command->flags);
return B_OK;
}
case PRODUCER_LATE_NOTICE_RECEIVED:
{
const producer_late_notice_received_command *command = static_cast<const producer_late_notice_received_command *>(data);
LateNoticeReceived(command->source, command->how_much, command->performance_time);
const producer_late_notice_received_command* command
= static_cast<
const producer_late_notice_received_command*>(data);
LateNoticeReceived(command->source, command->how_much,
command->performance_time);
return B_OK;
}
case PRODUCER_ENABLE_OUTPUT:
{
const producer_enable_output_command *command = static_cast<const producer_enable_output_command *>(data);
const producer_enable_output_command* command
= static_cast<const producer_enable_output_command*>(data);
node_request_completed_command replycommand;
EnableOutput(command->source, command->enabled, NULL);
if (command->destination == media_destination::null)
return B_OK;
replycommand.info.what = media_request_info::B_SET_OUTPUT_ENABLED;
replycommand.info.change_tag = command->change_tag;
replycommand.info.status = B_OK;
@@ -365,20 +385,20 @@ BBufferProducer::HandleMessage(int32 message,
replycommand.info.source = command->source;
replycommand.info.destination = command->destination;
//replycommand.info.format
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED, &replycommand, sizeof(replycommand));
SendToPort(command->destination.port, NODE_REQUEST_COMPLETED,
&replycommand, sizeof(replycommand));
return B_OK;
}
};
}
return B_ERROR;
}
void
BBufferProducer::AdditionalBufferRequested(const media_source &source,
media_buffer_id prev_buffer,
bigtime_t prev_time,
const media_seek_tag *prev_tag)
BBufferProducer::AdditionalBufferRequested(const media_source& source,
media_buffer_id previousBuffer, bigtime_t previousTime,
const media_seek_tag* previousTag)
{
CALLED();
// may be implemented by derived classes
@@ -386,10 +406,8 @@ BBufferProducer::AdditionalBufferRequested(const media_source &source,
void
BBufferProducer::LatencyChanged(const media_source &source,
const media_destination &destination,
bigtime_t new_latency,
uint32 flags)
BBufferProducer::LatencyChanged(const media_source& source,
const media_destination& destination, bigtime_t newLatency, uint32 flags)
{
CALLED();
// may be implemented by derived classes
@@ -397,64 +415,70 @@ BBufferProducer::LatencyChanged(const media_source &source,
status_t
BBufferProducer::SendBuffer(BBuffer *buffer,
const media_destination &destination)
BBufferProducer::SendBuffer(BBuffer* buffer, const media_source& source,
const media_destination& destination)
{
CALLED();
if (destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION;
if (source == media_source::null)
return B_MEDIA_BAD_SOURCE;
if (buffer == NULL)
return B_BAD_VALUE;
consumer_buffer_received_command command;
command.buffer = buffer->ID();
command.header = *(buffer->Header());
command.header.buffer = command.buffer; // buffer->ID();
command.header = *buffer->Header();
command.header.buffer = command.buffer;
command.header.source_port = source.port;
command.header.source = source.id;
command.header.destination = destination.id;
command.header.owner = 0; // XXX fill with "buffer owner info area"
command.header.start_time += fDelay; // time compensation as set by BMediaRoster::SetProducerRunModeDelay()
command.header.start_time += fDelay;
// time compensation as set by BMediaRoster::SetProducerRunModeDelay()
//printf("BBufferProducer::SendBuffer node %2ld, buffer %2ld, start_time %12Ld with lateness %6Ld\n", ID(), buffer->Header()->buffer, command.header.start_time, TimeSource()->Now() - command.header.start_time);
return SendToPort(destination.port, CONSUMER_BUFFER_RECEIVED, &command, sizeof(command));
return SendToPort(destination.port, CONSUMER_BUFFER_RECEIVED, &command,
sizeof(command));
}
status_t
BBufferProducer::SendDataStatus(int32 status,
const media_destination &destination,
bigtime_t at_time)
const media_destination& destination, bigtime_t atTime)
{
CALLED();
if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION;
consumer_producer_data_status_command command;
command.for_whom = destination;
command.status = status;
command.at_performance_time = at_time;
command.at_performance_time = atTime;
return SendToPort(destination.port, CONSUMER_PRODUCER_DATA_STATUS, &command, sizeof(command));
return SendToPort(destination.port, CONSUMER_PRODUCER_DATA_STATUS, &command,
sizeof(command));
}
status_t
BBufferProducer::ProposeFormatChange(media_format *format,
const media_destination &for_destination)
BBufferProducer::ProposeFormatChange(media_format* format,
const media_destination& destination)
{
CALLED();
if (IS_INVALID_DESTINATION(for_destination))
if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION;
consumer_accept_format_request request;
consumer_accept_format_reply reply;
status_t rv;
request.dest = for_destination;
request.dest = destination;
request.format = *format;
rv = QueryPort(for_destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK)
return rv;
status_t status = QueryPort(destination.port, CONSUMER_ACCEPT_FORMAT,
&request, sizeof(request), &reply, sizeof(reply));
if (status != B_OK)
return status;
*format = reply.format;
return B_OK;
@@ -462,95 +486,90 @@ BBufferProducer::ProposeFormatChange(media_format *format,
status_t
BBufferProducer::ChangeFormat(const media_source &for_source,
const media_destination &for_destination,
media_format *format)
BBufferProducer::ChangeFormat(const media_source& source,
const media_destination& destination, media_format* format)
{
CALLED();
if (IS_INVALID_SOURCE(for_source))
if (IS_INVALID_SOURCE(source))
return B_MEDIA_BAD_SOURCE;
if (IS_INVALID_DESTINATION(for_destination))
if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION;
consumer_format_changed_request request;
consumer_format_changed_reply reply;
request.producer = for_source;
request.consumer = for_destination;
request.producer = source;
request.consumer = destination;
request.format = *format;
// we use a request/reply to make this synchronous
return QueryPort(for_destination.port, CONSUMER_FORMAT_CHANGED, &request, sizeof(request), &reply, sizeof(reply));
return QueryPort(destination.port, CONSUMER_FORMAT_CHANGED, &request,
sizeof(request), &reply, sizeof(reply));
}
status_t
BBufferProducer::FindLatencyFor(const media_destination &for_destination,
bigtime_t *out_latency,
media_node_id *out_timesource)
BBufferProducer::FindLatencyFor(const media_destination& destination,
bigtime_t* _latency, media_node_id* _timesource)
{
CALLED();
if (IS_INVALID_DESTINATION(for_destination))
if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION;
status_t rv;
consumer_get_latency_for_request request;
consumer_get_latency_for_reply reply;
request.for_whom = for_destination;
rv = QueryPort(for_destination.port, CONSUMER_GET_LATENCY_FOR, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK)
return rv;
request.for_whom = destination;
*out_latency = reply.latency;
*out_timesource = reply.timesource;
return rv;
status_t status = QueryPort(destination.port, CONSUMER_GET_LATENCY_FOR,
&request, sizeof(request), &reply, sizeof(reply));
if (status != B_OK)
return status;
*_latency = reply.latency;
*_timesource = reply.timesource;
return B_OK;
}
status_t
BBufferProducer::FindSeekTag(const media_destination &for_destination,
bigtime_t in_target_time,
media_seek_tag *out_tag,
bigtime_t *out_tagged_time,
uint32 *out_flags,
uint32 in_flags)
BBufferProducer::FindSeekTag(const media_destination& destination,
bigtime_t targetTime, media_seek_tag* _tag, bigtime_t* _tagged_time,
uint32* _flags, uint32 flags)
{
CALLED();
if (IS_INVALID_DESTINATION(for_destination))
if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION;
status_t rv;
consumer_seek_tag_requested_request request;
consumer_seek_tag_requested_reply reply;
request.destination = for_destination;
request.target_time = in_target_time;
request.flags = in_flags;
request.destination = destination;
request.target_time = targetTime;
request.flags = flags;
rv = QueryPort(for_destination.port, CONSUMER_SEEK_TAG_REQUESTED, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK)
return rv;
status_t status = QueryPort(destination.port, CONSUMER_SEEK_TAG_REQUESTED,
&request, sizeof(request), &reply, sizeof(reply));
if (status != B_OK)
return status;
*out_tag = reply.seek_tag;
*out_tagged_time = reply.tagged_time;
*out_flags = reply.flags;
return rv;
*_tag = reply.seek_tag;
*_tagged_time = reply.tagged_time;
*_flags = reply.flags;
return B_OK;
}
void
BBufferProducer::SetInitialLatency(bigtime_t inInitialLatency,
uint32 flags)
BBufferProducer::SetInitialLatency(bigtime_t initialLatency, uint32 flags)
{
fInitialLatency = inInitialLatency;
fInitialLatency = initialLatency;
fInitialFlags = flags;
}
/*************************************************************
* private BBufferProducer
*************************************************************/
// #pragma mark - private BBufferProducer
/*
private unimplemented
@@ -559,43 +578,55 @@ BBufferProducer::BBufferProducer(const BBufferProducer &clone)
BBufferProducer & BBufferProducer::operator=(const BBufferProducer &clone)
*/
status_t BBufferProducer::_Reserved_BufferProducer_0(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_1(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_2(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_3(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_4(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_5(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_6(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_7(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_8(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_9(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_10(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_11(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_12(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_13(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_14(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_15(void *) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_0(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_1(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_2(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_3(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_4(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_5(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_6(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_7(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_8(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_9(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_10(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_11(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_12(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_13(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_14(void*) { return B_ERROR; }
status_t BBufferProducer::_Reserved_BufferProducer_15(void*) { return B_ERROR; }
//! Deprecated.
status_t
BBufferProducer::SendBuffer(BBuffer* buffer,
const media_destination& destination)
{
CALLED();
// Try to find the source - this is the best we can do
media_output output;
int32 cookie = 0;
status_t status = GetNextOutput(&cookie, &output);
if (status != B_OK)
return status;
return SendBuffer(buffer, output.source, destination);
}
status_t
BBufferProducer::clip_shorts_to_region(const int16 *data,
int count,
BRegion *output)
BBufferProducer::clip_shorts_to_region(const int16* data, int count,
BRegion* output)
{
UNIMPLEMENTED();
return B_ERROR;
}
status_t
BBufferProducer::clip_region_to_shorts(const BRegion *input,
int16 *data,
int max_count,
int *out_count)
BBufferProducer::clip_region_to_shorts(const BRegion* input, int16* data,
int maxCount, int* _count)
{
UNIMPLEMENTED();
return B_ERROR;
}
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009, Haiku.
* Copyright 2002-2010, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -664,7 +664,8 @@ SoundPlayNode::SendNewBuffer(const media_timed_event* event,
}
*/
// send the buffer downstream if and only if output is enabled
if (B_OK != SendBuffer(buffer, fOutput.destination)) {
if (SendBuffer(buffer, fOutput.source, fOutput.destination)
!= B_OK) {
// we need to recycle the buffer
// if the call to SendBuffer() fails
printf("SoundPlayNode::SendNewBuffer: Buffer sending "