* 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. // NOTE: Use this function to pass on the buffer on to the BBufferConsumer.
status_t SendBuffer(BBuffer* buffer, status_t SendBuffer(BBuffer* buffer,
const media_source& source,
const media_destination& destination); const media_destination& destination);
status_t SendDataStatus(int32 status, status_t SendDataStatus(int32 status,
@@ -205,6 +206,10 @@ private:
virtual status_t _Reserved_BufferProducer_14(void*); virtual status_t _Reserved_BufferProducer_14(void*);
virtual status_t _Reserved_BufferProducer_15(void*); virtual status_t _Reserved_BufferProducer_15(void*);
// deprecated calls
status_t SendBuffer(BBuffer* buffer,
const media_destination& destination);
private: private:
friend class BBufferConsumer; friend class BBufferConsumer;
friend class BMediaNode; friend class BMediaNode;
+2 -1
View File
@@ -671,7 +671,8 @@ struct media_header {
}; };
type_code user_data_type; type_code user_data_type;
uchar user_data[64]; // user_data_type indicates what this is 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 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 size_t orig_size; // and how big it was. if unused, zero out
@@ -22,6 +22,7 @@
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include <fcntl.h> #include <fcntl.h>
#include <malloc.h> #include <malloc.h>
#include <math.h> #include <math.h>
@@ -1670,7 +1671,8 @@ DVBMediaNode::raw_audio_thread()
hdr->time_source = TimeSource()->ID(); // set time source id hdr->time_source = TimeSource()->ID(); // set time source id
hdr->start_time = start_time; // set start time hdr->start_time = start_time; // set start time
lock.Lock(); lock.Lock();
if (B_OK != SendBuffer(buf, fOutputRawAudio.destination)) { if (SendBuffer(buf, fOutputRawAudio.source, fOutputRawAudio.destination)
!= B_OK) {
TRACE("audio: sending buffer failed\n"); TRACE("audio: sending buffer failed\n");
buf->Recycle(); buf->Recycle();
} }
@@ -1866,7 +1868,8 @@ DVBMediaNode::raw_video_thread()
hdr->time_source = TimeSource()->ID(); // set time source id hdr->time_source = TimeSource()->ID(); // set time source id
hdr->start_time = start_time; // set start time hdr->start_time = start_time; // set start time
lock.Lock(); lock.Lock();
if (B_OK != SendBuffer(buf, fOutputRawVideo.destination)) { if (SendBuffer(buf, fOutputRawVideo.source, fOutputRawVideo.destination)
!= B_OK) {
TRACE("video: sending buffer failed\n"); TRACE("video: sending buffer failed\n");
buf->Recycle(); buf->Recycle();
} }
@@ -8,6 +8,7 @@
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de> * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*/ */
#include "FireWireDVNode.h" #include "FireWireDVNode.h"
#include <fcntl.h> #include <fcntl.h>
@@ -602,7 +603,8 @@ FireWireDVNode::card_reader_thread()
hdr->start_time = TimeSource()->PerformanceTimeFor(system_time()); hdr->start_time = TimeSource()->PerformanceTimeFor(system_time());
fLock.Lock(); fLock.Lock();
if (B_OK != SendBuffer(buf, fOutputEncVideo.destination)) { if (SendBuffer(buf, fOutputEncVideo.source,
fOutputEncVideo.destination) != B_OK) {
TRACE("OutVideo: sending buffer failed\n"); TRACE("OutVideo: sending buffer failed\n");
buf->Recycle(); buf->Recycle();
} }
@@ -100,7 +100,8 @@ AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer)
fBufferGroup(0), fBufferGroup(0),
fDownstreamLatency(1), fDownstreamLatency(1),
fInternalLatency(1), fInternalLatency(1),
fDisableStop(false) fDisableStop(false),
fLastLateNotification(0)
{ {
BMediaNode::AddNodeKind(B_SYSTEM_MIXER); 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); //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, // to receive the buffer at the right time,
// push it through the event looper // push it through the event looper
media_timed_event event(buffer->Header()->start_time, media_timed_event event(buffer->Header()->start_time,
@@ -313,35 +307,31 @@ AudioMixer::BufferReceived(BBuffer *buffer)
void void
AudioMixer::HandleInputBuffer(BBuffer* buffer, bigtime_t lateness) AudioMixer::HandleInputBuffer(BBuffer* buffer, bigtime_t lateness)
{ {
// Note: The following code is outcommented on purpose if (lateness > 0) {
// and is about to be modified at a later point debug_printf("Received buffer %Ld usec late\n", lateness);
/* if (RunMode() == B_DROP_DATA || RunMode() == B_DECREASE_PRECISION
if (lateness > 5000) { || RunMode() == B_INCREASE_LATENCY) {
printf("Received buffer with way to high lateness %Ld\n", lateness); debug_printf("sending notify\n");
if (RunMode() != B_DROP_DATA) {
printf("sending notify\n"); // Build a media_source out of the header data
NotifyLateProducer(channel->fInput.source, lateness / 2, TimeSource()->Now()); media_source source = media_source::null;
} else if (RunMode() == B_DROP_DATA) { source.port = buffer->Header()->source_port;
printf("dropping buffer\n"); source.id = buffer->Header()->source;
NotifyLateProducer(source, lateness, TimeSource()->Now());
if (RunMode() == B_DROP_DATA) {
debug_printf("dropping buffer\n");
return; return;
} }
} }
*/ }
// printf("Received buffer with lateness %Ld\n", lateness); // printf("Received buffer with lateness %Ld\n", lateness);
fCore->Lock(); fCore->Lock();
fCore->BufferReceived(buffer, lateness); fCore->BufferReceived(buffer, lateness);
fCore->Unlock(); 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; return;
} }
/* Switch our prefered format to have the same // Switch our prefered format to have the same
* frame_rate and channel count as the output. // frame_rate and channel count as the output.
*/
fDefaultFormat.u.raw_audio.frame_rate = format.u.raw_audio.frame_rate; fDefaultFormat.u.raw_audio.frame_rate = format.u.raw_audio.frame_rate;
fDefaultFormat.u.raw_audio.channel_count = format.u.raw_audio.channel_count; 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(); UpdateParameterWeb();
} }
void void
AudioMixer::Disconnect(const media_source &what, const media_destination &where) 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 void
AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much, AudioMixer::LateNoticeReceived(const media_source& what, bigtime_t howMuch,
bigtime_t performance_time) bigtime_t performanceTime)
{ {
// We've produced some late buffers... Increase Latency // We've produced some late buffers... Increase Latency
// is the only runmode in which we can do anything about this // 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, ERROR("AudioMixer::LateNoticeReceived, %Ld too late at %Ld\n", howMuch,
performance_time); performanceTime);
// 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;
if (fInternalLatency > 50000) if (what == fCore->Output()->MediaOutput().source
fInternalLatency = 50000; && 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); fInternalLatency += howMuch;
fLastLateNotification = TimeSource()->Now();
debug_printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
SetEventLatency(fDownstreamLatency + fInternalLatency); SetEventLatency(fDownstreamLatency + fInternalLatency);
PublishEventLatencyChange(); PublishEventLatencyChange();
} }
} }
*/
}
void void
AudioMixer::EnableOutput(const media_source& what, bool enabled, AudioMixer::EnableOutput(const media_source& what, bool enabled,
int32 *_deprecated_) int32 */*deprecated*/)
{ {
// we only have one output // we only have one output
if (what.id != 0 || what.port != ControlPort()) if (what.id != 0 || what.port != ControlPort())
@@ -1046,12 +1036,12 @@ AudioMixer::NodeRegistered()
void void
AudioMixer::SetTimeSource(BTimeSource * time_source) AudioMixer::SetTimeSource(BTimeSource* timeSource)
{ {
TRACE("AudioMixer::SetTimeSource: timesource is now %ld\n", TRACE("AudioMixer::SetTimeSource: timesource is now %ld\n",
time_source->ID()); timeSource->ID());
fCore->Lock(); fCore->Lock();
fCore->SetTimingInfo(time_source, fDownstreamLatency); fCore->SetTimingInfo(timeSource, fDownstreamLatency);
fCore->Unlock(); 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 float
AudioMixer::dB_to_Gain(float db) 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 status_t
@@ -1,11 +1,11 @@
/* /*
* Copyright 2002 David Shipman, * Copyright 2002 David Shipman,
* Copyright 2003-2007 Marcus Overhagen * 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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _AUDIOMIXER_H #ifndef AUDIO_MIXER_H
#define _AUDIOMIXER_H #define AUDIO_MIXER_H
#include <BufferConsumer.h> #include <BufferConsumer.h>
@@ -17,13 +17,15 @@
class MixerCore; class MixerCore;
class MixerOutput;
class AudioMixer : public BBufferConsumer, public BBufferProducer, class AudioMixer : public BBufferConsumer, public BBufferProducer,
public BControllable, public BMediaEventLooper { public BControllable, public BMediaEventLooper {
public: public:
AudioMixer(BMediaAddOn *addOn, bool isSystemMixer); AudioMixer(BMediaAddOn* addOn,
~AudioMixer(); bool isSystemMixer);
virtual ~AudioMixer();
void DisableNodeStop(); void DisableNodeStop();
@@ -33,109 +35,108 @@ public:
void PublishEventLatencyChange(); void PublishEventLatencyChange();
void UpdateParameterWeb(); void UpdateParameterWeb();
void HandleInputBuffer(BBuffer *buffer, bigtime_t lateness); void HandleInputBuffer(BBuffer* buffer,
bigtime_t lateness);
BBufferGroup* CreateBufferGroup(); BBufferGroup* CreateBufferGroup();
status_t SendBuffer(BBuffer* buffer,
MixerOutput* output);
float dB_to_Gain(float db); float dB_to_Gain(float db);
float Gain_to_dB(float gain); float Gain_to_dB(float gain);
// BMediaNode methods // BMediaNode methods
BMediaAddOn * AddOn(int32 *internal_id) const; virtual BMediaAddOn* AddOn(int32* _internalID) const;
void NodeRegistered(); virtual void NodeRegistered();
void Stop(bigtime_t performance_time, bool immediate); virtual void Stop(bigtime_t performanceTime, bool immediate);
void SetTimeSource(BTimeSource * time_source); virtual void SetTimeSource(BTimeSource* timeSource);
using BBufferProducer::SendBuffer;
protected: protected:
// BControllable methods // BControllable methods
status_t GetParameterValue(int32 id, virtual status_t GetParameterValue(int32 id,
bigtime_t *last_change, bigtime_t* _lastChange, void* _value,
void *value, size_t* _size);
size_t *ioSize); 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 // BBufferConsumer methods
status_t HandleMessage(int32 message, const void* data, virtual status_t HandleMessage(int32 message, const void* data,
size_t size); size_t size);
status_t AcceptFormat(const media_destination &dest, virtual status_t AcceptFormat(const media_destination& dest,
media_format* format); media_format* format);
status_t GetNextInput(int32 *cookie, virtual status_t GetNextInput(int32* cookie,
media_input *out_input); media_input* _input);
void DisposeInputCookie(int32 cookie); virtual void DisposeInputCookie(int32 cookie);
void BufferReceived(BBuffer *buffer); virtual void BufferReceived(BBuffer *buffer);
void ProducerDataStatus(const media_destination &for_whom, virtual void ProducerDataStatus(
int32 status, const media_destination& forWhom,
bigtime_t at_performance_time); int32 status, bigtime_t atPerformanceTime);
status_t GetLatencyFor(const media_destination &for_whom, virtual status_t GetLatencyFor(const media_destination& forWhom,
bigtime_t *out_latency, bigtime_t* _latency,
media_node_id *out_timesource); media_node_id* _timesource);
status_t Connected(const media_source &producer, virtual status_t Connected(const media_source& producer,
const media_destination& where, const media_destination& where,
const media_format &with_format, const media_format& withFormat,
media_input *out_input); media_input* _input);
void Disconnected(const media_source &producer, virtual void Disconnected(const media_source& producer,
const media_destination& where); const media_destination& where);
status_t FormatChanged(const media_source &producer, virtual status_t FormatChanged(const media_source& producer,
const media_destination& consumer, const media_destination& consumer,
int32 change_tag, int32 changeTag,
const media_format& format); const media_format& format);
// BBufferProducer methods // BBufferProducer methods
status_t FormatSuggestionRequested(media_type type, virtual status_t FormatSuggestionRequested(media_type type,
int32 quality, int32 quality, media_format* format);
virtual status_t FormatProposal(const media_source& output,
media_format* format); media_format* format);
status_t FormatProposal(const media_source &output, virtual status_t FormatChangeRequested(
media_format *format);
status_t FormatChangeRequested(
const media_source& source, const media_source& source,
const media_destination &destination, 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_format* format,
media_source *out_source, int32* /*deprecated*/);
char *out_name); virtual status_t GetNextOutput(int32* cookie,
void Connect(status_t error, 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_source& source,
const media_destination& destination, const media_destination& destination,
const media_format &format, const media_format& format, char *_name);
char *io_name); virtual void Disconnect(const media_source& what,
void Disconnect(const media_source &what,
const media_destination& where); const media_destination& where);
void LateNoticeReceived(const media_source &what, virtual void LateNoticeReceived(const media_source& what,
bigtime_t how_much, bigtime_t howMuch,
bigtime_t performance_time); bigtime_t performanceTime);
void EnableOutput(const media_source &what, virtual void EnableOutput(const media_source& what,
bool enabled, bool enabled, int32* /*_deprecated_*/);
int32 *_deprecated_); virtual void LatencyChanged(const media_source& source,
void LatencyChanged(const media_source &source,
const media_destination& destination, const media_destination& destination,
bigtime_t new_latency, uint32 flags); bigtime_t newLatency, uint32 flags);
// BMediaEventLooper methods // BMediaEventLooper methods
void HandleEvent(const media_timed_event *event, virtual void HandleEvent(const media_timed_event* event,
bigtime_t lateness, bigtime_t lateness,
bool realTimeEvent = false); bool realTimeEvent = false);
private: private:
BMediaAddOn* fAddOn; BMediaAddOn* fAddOn;
MixerCore* fCore; MixerCore* fCore;
BParameterWeb *fWeb; // local pointer to parameterweb BParameterWeb* fWeb;
BBufferGroup* fBufferGroup; BBufferGroup* fBufferGroup;
bigtime_t fDownstreamLatency; bigtime_t fDownstreamLatency;
bigtime_t fInternalLatency; bigtime_t fInternalLatency;
bool fDisableStop; bool fDisableStop;
media_format fDefaultFormat; 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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -530,8 +530,7 @@ MixerCore::MixThread()
hdr->size_used = size; hdr->size_used = size;
hdr->time_source = fTimeSource->ID(); hdr->time_source = fTimeSource->ID();
hdr->start_time = event_time; hdr->start_time = event_time;
if (fNode->SendBuffer(buf, fOutput->MediaOutput().destination) if (fNode->SendBuffer(buf, fOutput) != B_OK) {
!= B_OK) {
#if DEBUG #if DEBUG
ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", ERROR("MixerCore: SendBuffer failed for buffer %Ld\n",
buffer_num); buffer_num);
@@ -664,8 +663,7 @@ MixerCore::MixThread()
fOutput->AdjustByteOrder(buf); fOutput->AdjustByteOrder(buf);
// send the buffer // send the buffer
status_t res = fNode->SendBuffer(buf, status_t res = fNode->SendBuffer(buf, fOutput);
fOutput->MediaOutput().destination);
if (res != B_OK) { if (res != B_OK) {
#if DEBUG #if DEBUG
ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", ERROR("MixerCore: SendBuffer failed for buffer %Ld\n",
@@ -1764,7 +1764,7 @@ MultiAudioNode::_RunThread()
// enabled // enabled
status_t err = B_ERROR; status_t err = B_ERROR;
if (output->fOutputEnabled) { if (output->fOutputEnabled) {
err = SendBuffer(buffer, err = SendBuffer(buffer, output->fOutput.source,
output->fOutput.destination); output->fOutput.destination);
} }
if (err) { if (err) {
@@ -5,6 +5,8 @@
* Copyright (c) 2002, 2003 Jerome Duval (jerome.duval@free.fr) * Copyright (c) 2002, 2003 Jerome Duval (jerome.duval@free.fr)
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "OpenSoundNode.h" #include "OpenSoundNode.h"
#include <Autolock.h> #include <Autolock.h>
@@ -2356,8 +2358,10 @@ OpenSoundNode::_RecThread(NodeOutput* output)
if (buffer) { if (buffer) {
// send the buffer downstream if and only if output is enabled // send the buffer downstream if and only if output is enabled
status_t err = B_ERROR; status_t err = B_ERROR;
if (output->fOutputEnabled) if (output->fOutputEnabled) {
err = SendBuffer(buffer, output->fOutput.destination); err = SendBuffer(buffer, output->fOutput.source,
output->fOutput.destination);
}
// TRACE("OpenSoundNode::_RunThread: I avail: %d, OE %d, %s\n", // TRACE("OpenSoundNode::_RunThread: I avail: %d, OE %d, %s\n",
// avail, output->fOutputEnabled, strerror(err)); // avail, output->fOutputEnabled, strerror(err));
if (err != B_OK) { if (err != B_OK) {
@@ -797,17 +797,18 @@ ToneProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
case BTimedEventQueue::B_HANDLE_BUFFER: case BTimedEventQueue::B_HANDLE_BUFFER:
{ {
// make sure we're both started *and* connected before delivering a 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 // Get the next buffer of data
BBuffer* buffer = FillNextBuffer(event->event_time); BBuffer* buffer = FillNextBuffer(event->event_time);
if (buffer) if (buffer) {
{
// send the buffer downstream if and only if output is enabled // send the buffer downstream if and only if output is enabled
status_t err = B_ERROR; status_t err = B_ERROR;
if (mOutputEnabled) err = SendBuffer(buffer, mOutput.destination); if (mOutputEnabled) {
if (err) err = SendBuffer(buffer, mOutput.source,
{ mOutput.destination);
}
if (err) {
// we need to recycle the buffer ourselves if output is disabled or // we need to recycle the buffer ourselves if output is disabled or
// if the call to SendBuffer() fails // if the call to SendBuffer() fails
buffer->Recycle(); buffer->Recycle();
@@ -820,8 +821,10 @@ ToneProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
mFramesSent += nFrames; mFramesSent += nFrames;
// The buffer is on its way; now schedule the next one to go // 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); bigtime_t nextEvent = mStartTime + bigtime_t(double(mFramesSent)
media_timed_event nextBufferEvent(nextEvent, BTimedEventQueue::B_HANDLE_BUFFER); / double(mOutput.format.u.raw_audio.frame_rate) * 1000000.0);
media_timed_event nextBufferEvent(nextEvent,
BTimedEventQueue::B_HANDLE_BUFFER);
EventQueue()->AddEvent(nextBufferEvent); EventQueue()->AddEvent(nextBufferEvent);
} }
} }
@@ -968,7 +968,7 @@ PRINT(("PS: %Ld\n", fProcessingLatency));
PRINTF(1, ("FrameGenerator: SendBuffer...\n")); PRINTF(1, ("FrameGenerator: SendBuffer...\n"));
/* Send the buffer on down to the consumer */ /* 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")); PRINTF(-1, ("FrameGenerator: Error sending buffer\n"));
/* If there is a problem sending the buffer, return it to its /* If there is a problem sending the buffer, return it to its
* buffer group. */ * buffer group. */
@@ -2,6 +2,8 @@
Copyright 1999, Be Incorporated. All Rights Reserved. Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
*/ */
#include <fcntl.h> #include <fcntl.h>
#include <malloc.h> #include <malloc.h>
#include <math.h> #include <math.h>
@@ -717,7 +719,7 @@ VideoProducer::FrameGenerator()
*(p++) = ((((x+y)^0^x)+fFrame) & 0xff) * (0x01010101 & fColor); *(p++) = ((((x+y)^0^x)+fFrame) & 0xff) * (0x01010101 & fColor);
/* Send the buffer on down to the consumer */ /* 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")); PRINTF(-1, ("FrameGenerator: Error sending buffer\n"));
/* If there is a problem sending the buffer, return it to its /* If there is a problem sending the buffer, return it to its
* buffer group. */ * buffer group. */
@@ -296,7 +296,7 @@ void FlangerNode::BufferReceived(
// process and retransmit buffer // process and retransmit buffer
filterBuffer(pBuffer); filterBuffer(pBuffer);
status_t err = SendBuffer(pBuffer, m_output.destination); status_t err = SendBuffer(pBuffer, m_output.source, m_output.destination);
if (err < B_OK) { if (err < B_OK) {
PRINT(("FlangerNode::BufferReceived():\n" PRINT(("FlangerNode::BufferReceived():\n"
"\tSendBuffer() failed: %s\n", strerror(err))); "\tSendBuffer() failed: %s\n", strerror(err)));
@@ -309,12 +309,11 @@ void FlangerNode::BufferReceived(
// pFormat; as of R4.5 the Media Kit passes poInput->format to // pFormat; as of R4.5 the Media Kit passes poInput->format to
// the producer in BBufferProducer::Connect(). // the producer in BBufferProducer::Connect().
status_t FlangerNode::Connected( status_t
const media_source& source, FlangerNode::Connected(const media_source& source,
const media_destination& destination, const media_destination& destination, const media_format& format,
const media_format& format, media_input* poInput)
media_input* poInput) { {
PRINT(("FlangerNode::Connected()\n" PRINT(("FlangerNode::Connected()\n"
"\tto source %ld\n", source.id)); "\tto source %ld\n", source.id));
@@ -523,7 +523,7 @@ void AudioFilterNode::BufferReceived(
// process and retransmit buffer // process and retransmit buffer
processBuffer(buffer, outBuffer); processBuffer(buffer, outBuffer);
status_t err = SendBuffer(outBuffer, m_output.destination); status_t err = SendBuffer(outBuffer, m_output.source, m_output.destination);
if (err < B_OK) { if (err < B_OK) {
PRINT(("AudioFilterNode::BufferReceived():\n" PRINT(("AudioFilterNode::BufferReceived():\n"
"\tSendBuffer() failed: %s\n", strerror(err))); "\tSendBuffer() failed: %s\n", strerror(err)));
@@ -7,6 +7,7 @@
* All Rights Reserved. Distributed under the terms of the MIT license. * All Rights Reserved. Distributed under the terms of the MIT license.
*/ */
#include "AudioProducer.h" #include "AudioProducer.h"
#include <math.h> #include <math.h>
@@ -465,7 +466,7 @@ AudioProducer::Disconnect(const media_source& what,
TRACE("%p->AudioProducer::Disconnect()\n", this); TRACE("%p->AudioProducer::Disconnect()\n", this);
// Make sure that our connection is the one being disconnected // 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.destination = media_destination::null;
fOutput.format = fPreferredFormat; fOutput.format = fPreferredFormat;
TRACE("AudioProducer: deleting buffer group...\n"); TRACE("AudioProducer: deleting buffer group...\n");
@@ -547,7 +548,7 @@ AudioProducer::LatencyChanged(const media_source& source,
{ {
TRACE("%p->AudioProducer::LatencyChanged(%lld)\n", this, newLatency); TRACE("%p->AudioProducer::LatencyChanged(%lld)\n", this, newLatency);
if ((source == fOutput.source) && (destination == fOutput.destination)) { if (source == fOutput.source && destination == fOutput.destination) {
fLatency = newLatency; fLatency = newLatency;
SetEventLatency(fLatency + fInternalLatency); SetEventLatency(fLatency + fInternalLatency);
} }
@@ -610,20 +611,22 @@ printf("B_START: start time: %lld\n", fStartTime);
TRACE("AudioProducer::HandleEvent(B_STOP) done\n"); TRACE("AudioProducer::HandleEvent(B_STOP) done\n");
break; break;
case BTimedEventQueue::B_HANDLE_BUFFER: { case BTimedEventQueue::B_HANDLE_BUFFER:
{
TRACE_BUFFER("AudioProducer::HandleEvent(B_HANDLE_BUFFER)\n"); TRACE_BUFFER("AudioProducer::HandleEvent(B_HANDLE_BUFFER)\n");
if ((RunState() == BMediaEventLooper::B_STARTED) if (RunState() == BMediaEventLooper::B_STARTED
&& (fOutput.destination != media_destination::null)) { && fOutput.destination != media_destination::null) {
BBuffer* buffer = _FillNextBuffer(event->event_time); BBuffer* buffer = _FillNextBuffer(event->event_time);
if (buffer) { if (buffer) {
status_t err = B_ERROR; status_t err = B_ERROR;
if (fOutputEnabled) if (fOutputEnabled) {
err = SendBuffer(buffer, fOutput.destination); err = SendBuffer(buffer, fOutput.source,
fOutput.destination);
}
if (err) if (err)
buffer->Recycle(); buffer->Recycle();
} }
size_t sampleSize size_t sampleSize = fOutput.format.u.raw_audio.format
= fOutput.format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK; & media_raw_audio_format::B_AUDIO_SIZE_MASK;
size_t nFrames = fOutput.format.u.raw_audio.buffer_size size_t nFrames = fOutput.format.u.raw_audio.buffer_size
@@ -5,6 +5,8 @@
* Copyright (c) 2000-2008, Stephan Aßmus <superstippi@gmx.de>, * Copyright (c) 2000-2008, Stephan Aßmus <superstippi@gmx.de>,
* All Rights Reserved. Distributed under the terms of the MIT license. * All Rights Reserved. Distributed under the terms of the MIT license.
*/ */
#include "VideoProducer.h" #include "VideoProducer.h"
#include <stdio.h> #include <stdio.h>
@@ -812,7 +814,8 @@ h->start_time = 0;
err = B_OK; err = B_OK;
} }
// Send the buffer on down to the consumer // 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 " ERROR("_FrameGeneratorThread: Error "
"sending buffer\n"); "sending buffer\n");
// If there is a problem sending the buffer, // If there is a problem sending the buffer,
+25 -43
View File
@@ -1,57 +1,35 @@
/*****************************************************************************/ /*
// GameProdcure.h * Copyright 2002-2010 Haiku Inc. All rights reserved.
// * Distributed under the terms of the MIT License.
// This produce creates audio buffer on behalf of the GameKit. *
// * Authors:
// Copyright (c) 2001 OpenBeOS Project * Christopher ML Zumwalt May (zummy@users.sf.net)
// */
// 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 /*! A MediaKit producer node which mixes sound from the GameKit
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and sends them to the audio mixer
// 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
/*****************************************************************************/
// Standard Includes -----------------------------------------------------------
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
// System Includes -------------------------------------------------------------
#include <ByteOrder.h>
#include <BufferGroup.h>
#include <Buffer.h> #include <Buffer.h>
#include <BufferGroup.h>
#include <ByteOrder.h>
#include <List.h> #include <List.h>
#include <TimeSource.h>
#include <MediaDefs.h> #include <MediaDefs.h>
#include <TimeSource.h>
// Project Includes ------------------------------------------------------------
#include "GameSoundBuffer.h" #include "GameSoundBuffer.h"
#include "GameSoundDevice.h" #include "GameSoundDevice.h"
#include "GSUtility.h" #include "GSUtility.h"
// Local Includes --------------------------------------------------------------
#include "GameProducer.h" #include "GameProducer.h"
// Local Defines ---------------------------------------------------------------
struct _gs_play struct _gs_play {
{
gs_id sound; gs_id sound;
bool* hook; bool* hook;
@@ -59,9 +37,11 @@ struct _gs_play
_gs_play* previous; _gs_play* previous;
}; };
GameProducer::GameProducer(GameSoundBuffer* object, GameProducer::GameProducer(GameSoundBuffer* object,
const gs_audio_format* format) const gs_audio_format* format)
: BMediaNode("GameProducer.h"), :
BMediaNode("GameProducer.h"),
BBufferProducer(B_MEDIA_RAW_AUDIO), BBufferProducer(B_MEDIA_RAW_AUDIO),
BMediaEventLooper(), BMediaEventLooper(),
fBufferGroup(NULL), fBufferGroup(NULL),
@@ -468,8 +448,10 @@ GameProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, bo
if (buffer) { if (buffer) {
// send the buffer downstream if and only if output is enabled // send the buffer downstream if and only if output is enabled
status_t err = B_ERROR; status_t err = B_ERROR;
if (fOutputEnabled) if (fOutputEnabled) {
err = SendBuffer(buffer, fOutput.destination); err = SendBuffer(buffer, fOutput.source,
fOutput.destination);
}
if (err) { if (err) {
// we need to recycle the buffer ourselves if output is disabled or // we need to recycle the buffer ourselves if output is disabled or
// if the call to SendBuffer() fails // if the call to SendBuffer() fails
+231 -200
View File
@@ -1,57 +1,37 @@
/* /*
* Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de> * Copyright 2002-2010, Haiku.
* * Distributed under the terms of the MIT License.
* 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.
* *
* Authors:
* Marcus Overhagen, <Marcus@Overhagen.de>
* Axel Dörfler, axeld@pinc-software.de.
*/ */
#include <BufferProducer.h>
#include <Buffer.h>
#include <BufferConsumer.h> #include <BufferConsumer.h>
#include <BufferGroup.h> #include <BufferGroup.h>
#include <Buffer.h> #include <BufferProducer.h>
#include "debug.h"
#include "MediaMisc.h" #include "debug.h"
#include "DataExchange.h" #include "DataExchange.h"
#include "MediaMisc.h"
// #pragma mark - protected BBufferProducer
/*************************************************************
* protected BBufferProducer
*************************************************************/
BBufferProducer::~BBufferProducer() BBufferProducer::~BBufferProducer()
{ {
CALLED(); CALLED();
} }
/*************************************************************
* public BBufferProducer // #pragma mark - public BBufferProducer
*************************************************************/
/*static*/ status_t /*static*/ status_t
BBufferProducer::ClipDataToRegion(int32 format, BBufferProducer::ClipDataToRegion(int32 format, int32 size, const void* data,
int32 size,
const void *data,
BRegion* region) BRegion* region)
{ {
CALLED(); CALLED();
@@ -59,9 +39,11 @@ BBufferProducer::ClipDataToRegion(int32 format,
if (format != B_CLIP_SHORT_RUNS) if (format != B_CLIP_SHORT_RUNS)
return B_MEDIA_BAD_CLIP_FORMAT; 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 media_type
BBufferProducer::ProducerType() BBufferProducer::ProducerType()
{ {
@@ -69,12 +51,12 @@ BBufferProducer::ProducerType()
return fProducerType; return fProducerType;
} }
/*************************************************************
* protected BBufferProducer
*************************************************************/
/* explicit */ // #pragma mark - protected BBufferProducer
BBufferProducer::BBufferProducer(media_type producer_type) :
BBufferProducer::BBufferProducer(media_type producer_type)
:
BMediaNode("called by BBufferProducer"), BMediaNode("called by BBufferProducer"),
fProducerType(producer_type), fProducerType(producer_type),
fInitialLatency(0), fInitialLatency(0),
@@ -88,11 +70,9 @@ BBufferProducer::BBufferProducer(media_type producer_type) :
status_t status_t
BBufferProducer::VideoClippingChanged(const media_source &for_source, BBufferProducer::VideoClippingChanged(const media_source& source,
int16 num_shorts, int16 numShorts, int16* clipData, const media_video_display_info& display,
int16 *clip_data, int32* /*_deprecated_*/)
const media_video_display_info &display,
int32 *_deprecated_)
{ {
CALLED(); CALLED();
// may be implemented by derived classes // may be implemented by derived classes
@@ -101,7 +81,7 @@ BBufferProducer::VideoClippingChanged(const media_source &for_source,
status_t status_t
BBufferProducer::GetLatency(bigtime_t *out_lantency) BBufferProducer::GetLatency(bigtime_t* _latency)
{ {
CALLED(); CALLED();
// The default implementation of GetLatency() finds the maximum // The default implementation of GetLatency() finds the maximum
@@ -113,40 +93,36 @@ BBufferProducer::GetLatency(bigtime_t *out_lantency)
media_output output; media_output output;
media_node_id unused; media_node_id unused;
*out_lantency = 0; *_latency = 0;
cookie = 0; cookie = 0;
while (B_OK == GetNextOutput(&cookie, &output)) { while (GetNextOutput(&cookie, &output) == B_OK) {
if (output.destination == media_destination::null) if (output.destination == media_destination::null)
continue; continue;
if (output.node.node == fNodeID) { // avoid port writes (deadlock) if loopback connection if (output.node.node == fNodeID) {
if (!fConsumerThis) // avoid port writes (deadlock) if loopback connection
if (fConsumerThis == NULL)
fConsumerThis = dynamic_cast<BBufferConsumer*>(this); fConsumerThis = dynamic_cast<BBufferConsumer*>(this);
if (!fConsumerThis) if (fConsumerThis == NULL)
continue; continue;
latency = 0; latency = 0;
if (B_OK == fConsumerThis->GetLatencyFor(output.destination, &latency, &unused)) { if (fConsumerThis->GetLatencyFor(output.destination, &latency,
if (latency > *out_lantency) { &unused) == B_OK && latency > *_latency) {
*out_lantency = latency; *_latency = latency;
}
} else if (FindLatencyFor(output.destination, &latency, &unused)
== B_OK && latency > *_latency) {
*_latency = latency;
} }
} }
} else { printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *_latency);
if (B_OK == FindLatencyFor(output.destination, &latency, &unused)) {
if (latency > *out_lantency) {
*out_lantency = latency;
}
}
}
}
printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *out_lantency);
return B_OK; return B_OK;
} }
status_t status_t
BBufferProducer::SetPlayRate(int32 numer, BBufferProducer::SetPlayRate(int32 numer, int32 denom)
int32 denom)
{ {
CALLED(); CALLED();
// may be implemented by derived classes // may be implemented by derived classes
@@ -155,16 +131,16 @@ BBufferProducer::SetPlayRate(int32 numer,
status_t status_t
BBufferProducer::HandleMessage(int32 message, BBufferProducer::HandleMessage(int32 message, const void* data, size_t size)
const void *data,
size_t size)
{ {
PRINT(4, "BBufferProducer::HandleMessage %#lx, node %ld\n", message, fNodeID); PRINT(4, "BBufferProducer::HandleMessage %#lx, node %ld\n", message,
status_t rv; fNodeID);
switch (message) { switch (message) {
case PRODUCER_SET_RUN_MODE_DELAY: 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 // when changing this, also change NODE_SET_RUN_MODE
fDelay = command->delay; fDelay = command->delay;
fRunMode = command->mode; fRunMode = command->mode;
@@ -175,48 +151,58 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_FORMAT_SUGGESTION_REQUESTED: 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; producer_format_suggestion_requested_reply reply;
rv = FormatSuggestionRequested(request->type, request->quality, &reply.format); status_t status = FormatSuggestionRequested(request->type,
request->SendReply(rv, &reply, sizeof(reply)); request->quality, &reply.format);
request->SendReply(status, &reply, sizeof(reply));
return B_OK; return B_OK;
} }
case PRODUCER_FORMAT_PROPOSAL: 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; producer_format_proposal_reply reply;
reply.format = request->format; reply.format = request->format;
rv = FormatProposal(request->output, &reply.format); status_t status = FormatProposal(request->output, &reply.format);
request->SendReply(rv, &reply, sizeof(reply)); request->SendReply(status, &reply, sizeof(reply));
return B_OK; return B_OK;
} }
case PRODUCER_PREPARE_TO_CONNECT: 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; producer_prepare_to_connect_reply reply;
reply.format = request->format; reply.format = request->format;
reply.out_source = request->source; reply.out_source = request->source;
memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH); memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH);
rv = PrepareToConnect(request->source, request->destination, &reply.format, &reply.out_source, reply.name); status_t status = PrepareToConnect(request->source,
request->SendReply(rv, &reply, sizeof(reply)); request->destination, &reply.format, &reply.out_source,
reply.name);
request->SendReply(status, &reply, sizeof(reply));
return B_OK; return B_OK;
} }
case PRODUCER_CONNECT: 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; producer_connect_reply reply;
memcpy(reply.name, request->name, B_MEDIA_NAME_LENGTH); 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)); request->SendReply(B_OK, &reply, sizeof(reply));
return B_OK; return B_OK;
} }
case PRODUCER_DISCONNECT: 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; producer_disconnect_reply reply;
Disconnect(request->source, request->destination); Disconnect(request->source, request->destination);
request->SendReply(B_OK, &reply, sizeof(reply)); request->SendReply(B_OK, &reply, sizeof(reply));
@@ -225,7 +211,9 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_GET_INITIAL_LATENCY: 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; producer_get_initial_latency_reply reply;
reply.initial_latency = fInitialLatency; reply.initial_latency = fInitialLatency;
reply.flags = fInitialFlags; reply.flags = fInitialFlags;
@@ -235,35 +223,40 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_SET_PLAY_RATE: 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; producer_set_play_rate_reply reply;
rv = SetPlayRate(request->numer, request->denom); status_t status = SetPlayRate(request->numer, request->denom);
request->SendReply(rv, &reply, sizeof(reply)); request->SendReply(status, &reply, sizeof(reply));
return B_OK; return B_OK;
} }
case PRODUCER_GET_LATENCY: 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; producer_get_latency_reply reply;
rv = GetLatency(&reply.latency); status_t status = GetLatency(&reply.latency);
request->SendReply(rv, &reply, sizeof(reply)); request->SendReply(status, &reply, sizeof(reply));
return B_OK; return B_OK;
} }
case PRODUCER_GET_NEXT_OUTPUT: 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; producer_get_next_output_reply reply;
reply.cookie = request->cookie; reply.cookie = request->cookie;
rv = GetNextOutput(&reply.cookie, &reply.output); status_t status = GetNextOutput(&reply.cookie, &reply.output);
request->SendReply(rv, &reply, sizeof(reply)); request->SendReply(status, &reply, sizeof(reply));
return B_OK; return B_OK;
} }
case PRODUCER_DISPOSE_OUTPUT_COOKIE: 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; producer_dispose_output_cookie_reply reply;
DisposeOutputCookie(request->cookie); DisposeOutputCookie(request->cookie);
request->SendReply(B_OK, &reply, sizeof(reply)); request->SendReply(B_OK, &reply, sizeof(reply));
@@ -272,91 +265,118 @@ BBufferProducer::HandleMessage(int32 message,
case PRODUCER_SET_BUFFER_GROUP: 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; node_request_completed_command replycommand;
BBufferGroup *group; BBufferGroup *group;
group = command->buffer_count != 0 ? new BBufferGroup(command->buffer_count, command->buffers) : NULL; group = command->buffer_count != 0
rv = SetBufferGroup(command->source, group); ? new BBufferGroup(command->buffer_count, command->buffers)
: NULL;
status_t status = SetBufferGroup(command->source, group);
if (command->destination == media_destination::null) if (command->destination == media_destination::null)
return B_OK; 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.change_tag = command->change_tag;
replycommand.info.status = rv; replycommand.info.status = status;
replycommand.info.cookie = (int32)group; replycommand.info.cookie = (int32)group;
replycommand.info.user_data = command->user_data; replycommand.info.user_data = command->user_data;
replycommand.info.source = command->source; replycommand.info.source = command->source;
replycommand.info.destination = command->destination; 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; return B_OK;
} }
case PRODUCER_FORMAT_CHANGE_REQUESTED: 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; node_request_completed_command replycommand;
replycommand.info.format = command->format; 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) if (command->destination == media_destination::null)
return B_OK; 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.change_tag = command->change_tag;
replycommand.info.status = rv; replycommand.info.status = status;
//replycommand.info.cookie //replycommand.info.cookie
replycommand.info.user_data = command->user_data; replycommand.info.user_data = command->user_data;
replycommand.info.source = command->source; replycommand.info.source = command->source;
replycommand.info.destination = command->destination; 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; return B_OK;
} }
case PRODUCER_VIDEO_CLIPPING_CHANGED: 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; 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) if (command->destination == media_destination::null)
return B_OK; 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.change_tag = command->change_tag;
replycommand.info.status = rv; replycommand.info.status = status;
//replycommand.info.cookie //replycommand.info.cookie
replycommand.info.user_data = command->user_data; replycommand.info.user_data = command->user_data;
replycommand.info.source = command->source; replycommand.info.source = command->source;
replycommand.info.destination = command->destination; replycommand.info.destination = command->destination;
replycommand.info.format.type = B_MEDIA_RAW_VIDEO; replycommand.info.format.type = B_MEDIA_RAW_VIDEO;
replycommand.info.format.u.raw_video.display = command->display; 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; return B_OK;
} }
case PRODUCER_ADDITIONAL_BUFFER_REQUESTED: case PRODUCER_ADDITIONAL_BUFFER_REQUESTED:
{ {
const producer_additional_buffer_requested_command *command = static_cast<const producer_additional_buffer_requested_command *>(data); const producer_additional_buffer_requested_command* command
AdditionalBufferRequested(command->source, command->prev_buffer, command->prev_time, command->has_seek_tag ? &command->prev_tag : NULL); = 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; return B_OK;
} }
case PRODUCER_LATENCY_CHANGED: case PRODUCER_LATENCY_CHANGED:
{ {
const producer_latency_changed_command *command = static_cast<const producer_latency_changed_command *>(data); const producer_latency_changed_command* command
LatencyChanged(command->source, command->destination, command->latency, command->flags); = static_cast<const producer_latency_changed_command*>(data);
LatencyChanged(command->source, command->destination,
command->latency, command->flags);
return B_OK; return B_OK;
} }
case PRODUCER_LATE_NOTICE_RECEIVED: case PRODUCER_LATE_NOTICE_RECEIVED:
{ {
const producer_late_notice_received_command *command = static_cast<const producer_late_notice_received_command *>(data); const producer_late_notice_received_command* command
LateNoticeReceived(command->source, command->how_much, command->performance_time); = static_cast<
const producer_late_notice_received_command*>(data);
LateNoticeReceived(command->source, command->how_much,
command->performance_time);
return B_OK; return B_OK;
} }
case PRODUCER_ENABLE_OUTPUT: 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; node_request_completed_command replycommand;
EnableOutput(command->source, command->enabled, NULL); EnableOutput(command->source, command->enabled, NULL);
if (command->destination == media_destination::null) if (command->destination == media_destination::null)
return B_OK; return B_OK;
replycommand.info.what = media_request_info::B_SET_OUTPUT_ENABLED; replycommand.info.what = media_request_info::B_SET_OUTPUT_ENABLED;
replycommand.info.change_tag = command->change_tag; replycommand.info.change_tag = command->change_tag;
replycommand.info.status = B_OK; replycommand.info.status = B_OK;
@@ -365,20 +385,20 @@ BBufferProducer::HandleMessage(int32 message,
replycommand.info.source = command->source; replycommand.info.source = command->source;
replycommand.info.destination = command->destination; replycommand.info.destination = command->destination;
//replycommand.info.format //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_OK;
} }
}
};
return B_ERROR; return B_ERROR;
} }
void void
BBufferProducer::AdditionalBufferRequested(const media_source& source, BBufferProducer::AdditionalBufferRequested(const media_source& source,
media_buffer_id prev_buffer, media_buffer_id previousBuffer, bigtime_t previousTime,
bigtime_t prev_time, const media_seek_tag* previousTag)
const media_seek_tag *prev_tag)
{ {
CALLED(); CALLED();
// may be implemented by derived classes // may be implemented by derived classes
@@ -387,9 +407,7 @@ BBufferProducer::AdditionalBufferRequested(const media_source &source,
void void
BBufferProducer::LatencyChanged(const media_source& source, BBufferProducer::LatencyChanged(const media_source& source,
const media_destination &destination, const media_destination& destination, bigtime_t newLatency, uint32 flags)
bigtime_t new_latency,
uint32 flags)
{ {
CALLED(); CALLED();
// may be implemented by derived classes // may be implemented by derived classes
@@ -397,33 +415,38 @@ BBufferProducer::LatencyChanged(const media_source &source,
status_t status_t
BBufferProducer::SendBuffer(BBuffer *buffer, BBufferProducer::SendBuffer(BBuffer* buffer, const media_source& source,
const media_destination& destination) const media_destination& destination)
{ {
CALLED(); CALLED();
if (destination == media_destination::null) if (destination == media_destination::null)
return B_MEDIA_BAD_DESTINATION; return B_MEDIA_BAD_DESTINATION;
if (source == media_source::null)
return B_MEDIA_BAD_SOURCE;
if (buffer == NULL) if (buffer == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
consumer_buffer_received_command command; consumer_buffer_received_command command;
command.buffer = buffer->ID(); command.buffer = buffer->ID();
command.header = *(buffer->Header()); command.header = *buffer->Header();
command.header.buffer = command.buffer; // buffer->ID(); command.header.buffer = command.buffer;
command.header.source_port = source.port;
command.header.source = source.id;
command.header.destination = destination.id; command.header.destination = destination.id;
command.header.owner = 0; // XXX fill with "buffer owner info area" 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); //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 status_t
BBufferProducer::SendDataStatus(int32 status, BBufferProducer::SendDataStatus(int32 status,
const media_destination &destination, const media_destination& destination, bigtime_t atTime)
bigtime_t at_time)
{ {
CALLED(); CALLED();
if (IS_INVALID_DESTINATION(destination)) if (IS_INVALID_DESTINATION(destination))
@@ -432,29 +455,30 @@ BBufferProducer::SendDataStatus(int32 status,
consumer_producer_data_status_command command; consumer_producer_data_status_command command;
command.for_whom = destination; command.for_whom = destination;
command.status = status; 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 status_t
BBufferProducer::ProposeFormatChange(media_format* format, BBufferProducer::ProposeFormatChange(media_format* format,
const media_destination &for_destination) const media_destination& destination)
{ {
CALLED(); CALLED();
if (IS_INVALID_DESTINATION(for_destination)) if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION; return B_MEDIA_BAD_DESTINATION;
consumer_accept_format_request request; consumer_accept_format_request request;
consumer_accept_format_reply reply; consumer_accept_format_reply reply;
status_t rv;
request.dest = for_destination; request.dest = destination;
request.format = *format; request.format = *format;
rv = QueryPort(for_destination.port, CONSUMER_ACCEPT_FORMAT, &request, sizeof(request), &reply, sizeof(reply)); status_t status = QueryPort(destination.port, CONSUMER_ACCEPT_FORMAT,
if (rv != B_OK) &request, sizeof(request), &reply, sizeof(reply));
return rv; if (status != B_OK)
return status;
*format = reply.format; *format = reply.format;
return B_OK; return B_OK;
@@ -462,95 +486,90 @@ BBufferProducer::ProposeFormatChange(media_format *format,
status_t status_t
BBufferProducer::ChangeFormat(const media_source &for_source, BBufferProducer::ChangeFormat(const media_source& source,
const media_destination &for_destination, const media_destination& destination, media_format* format)
media_format *format)
{ {
CALLED(); CALLED();
if (IS_INVALID_SOURCE(for_source)) if (IS_INVALID_SOURCE(source))
return B_MEDIA_BAD_SOURCE; return B_MEDIA_BAD_SOURCE;
if (IS_INVALID_DESTINATION(for_destination)) if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION; return B_MEDIA_BAD_DESTINATION;
consumer_format_changed_request request; consumer_format_changed_request request;
consumer_format_changed_reply reply; consumer_format_changed_reply reply;
request.producer = for_source; request.producer = source;
request.consumer = for_destination; request.consumer = destination;
request.format = *format; request.format = *format;
// we use a request/reply to make this synchronous // 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 status_t
BBufferProducer::FindLatencyFor(const media_destination &for_destination, BBufferProducer::FindLatencyFor(const media_destination& destination,
bigtime_t *out_latency, bigtime_t* _latency, media_node_id* _timesource)
media_node_id *out_timesource)
{ {
CALLED(); CALLED();
if (IS_INVALID_DESTINATION(for_destination)) if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION; return B_MEDIA_BAD_DESTINATION;
status_t rv;
consumer_get_latency_for_request request; consumer_get_latency_for_request request;
consumer_get_latency_for_reply reply; consumer_get_latency_for_reply reply;
request.for_whom = for_destination; request.for_whom = destination;
rv = QueryPort(for_destination.port, CONSUMER_GET_LATENCY_FOR, &request, sizeof(request), &reply, sizeof(reply)); status_t status = QueryPort(destination.port, CONSUMER_GET_LATENCY_FOR,
if (rv != B_OK) &request, sizeof(request), &reply, sizeof(reply));
return rv; if (status != B_OK)
return status;
*out_latency = reply.latency; *_latency = reply.latency;
*out_timesource = reply.timesource; *_timesource = reply.timesource;
return rv; return B_OK;
} }
status_t status_t
BBufferProducer::FindSeekTag(const media_destination &for_destination, BBufferProducer::FindSeekTag(const media_destination& destination,
bigtime_t in_target_time, bigtime_t targetTime, media_seek_tag* _tag, bigtime_t* _tagged_time,
media_seek_tag *out_tag, uint32* _flags, uint32 flags)
bigtime_t *out_tagged_time,
uint32 *out_flags,
uint32 in_flags)
{ {
CALLED(); CALLED();
if (IS_INVALID_DESTINATION(for_destination)) if (IS_INVALID_DESTINATION(destination))
return B_MEDIA_BAD_DESTINATION; return B_MEDIA_BAD_DESTINATION;
status_t rv;
consumer_seek_tag_requested_request request; consumer_seek_tag_requested_request request;
consumer_seek_tag_requested_reply reply; consumer_seek_tag_requested_reply reply;
request.destination = for_destination; request.destination = destination;
request.target_time = in_target_time; request.target_time = targetTime;
request.flags = in_flags; request.flags = flags;
rv = QueryPort(for_destination.port, CONSUMER_SEEK_TAG_REQUESTED, &request, sizeof(request), &reply, sizeof(reply)); status_t status = QueryPort(destination.port, CONSUMER_SEEK_TAG_REQUESTED,
if (rv != B_OK) &request, sizeof(request), &reply, sizeof(reply));
return rv; if (status != B_OK)
return status;
*out_tag = reply.seek_tag; *_tag = reply.seek_tag;
*out_tagged_time = reply.tagged_time; *_tagged_time = reply.tagged_time;
*out_flags = reply.flags; *_flags = reply.flags;
return rv; return B_OK;
} }
void void
BBufferProducer::SetInitialLatency(bigtime_t inInitialLatency, BBufferProducer::SetInitialLatency(bigtime_t initialLatency, uint32 flags)
uint32 flags)
{ {
fInitialLatency = inInitialLatency; fInitialLatency = initialLatency;
fInitialFlags = flags; fInitialFlags = flags;
} }
/*************************************************************
* private BBufferProducer // #pragma mark - private BBufferProducer
*************************************************************/
/* /*
private unimplemented private unimplemented
@@ -577,25 +596,37 @@ 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_15(void*) { return B_ERROR; }
//! Deprecated.
status_t status_t
BBufferProducer::clip_shorts_to_region(const int16 *data, BBufferProducer::SendBuffer(BBuffer* buffer,
int count, 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) BRegion* output)
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
return B_ERROR; return B_ERROR;
} }
status_t status_t
BBufferProducer::clip_region_to_shorts(const BRegion *input, BBufferProducer::clip_region_to_shorts(const BRegion* input, int16* data,
int16 *data, int maxCount, int* _count)
int max_count,
int *out_count)
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
return B_ERROR; 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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -664,7 +664,8 @@ SoundPlayNode::SendNewBuffer(const media_timed_event* event,
} }
*/ */
// send the buffer downstream if and only if output is enabled // 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 // we need to recycle the buffer
// if the call to SendBuffer() fails // if the call to SendBuffer() fails
printf("SoundPlayNode::SendNewBuffer: Buffer sending " printf("SoundPlayNode::SendNewBuffer: Buffer sending "