fixed (hopefully) all latency bugs

fixed BMediaRoster::MakeTimeSourceFor()


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3397 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-06-01 22:09:26 +00:00
parent 4d48a4d093
commit 4295907bd1
12 changed files with 114 additions and 159 deletions
+3
View File
@@ -34,6 +34,9 @@
#define ROUND_UP_TO_PAGE(size) (((size) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1)) #define ROUND_UP_TO_PAGE(size) (((size) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1))
#define MEDIA_SERVER_PORT_NAME "__media_server_port"
#define MEDIA_ADDON_SERVER_PORT_NAME "__media_addon_server_port"
namespace BPrivate { namespace media { namespace BPrivate { namespace media {
extern team_id team; extern team_id team;
} } // BPrivate::media } } // BPrivate::media
@@ -529,12 +529,6 @@ AudioMixer::BufferReceived(BBuffer *buffer)
return; return;
} }
bigtime_t now = system_time(); // XXX debugging
bigtime_t send = buffer->Header()->file_pos; // XXX debugging
// printf("buffer received at %10Ld, was send at %10Ld, delta %7Ld # ", now, send, now - send);
// printf("2) should arrive at %20Ld, now %20Ld\n", buffer->Header()->start_time, TimeSource()->Now());
// printf("buffer received at %12Ld, should arrive at %12Ld, delta %12Ld\n", TimeSource()->Now(), buffer->Header()->start_time, TimeSource()->Now() - buffer->Header()->start_time); // printf("buffer received at %12Ld, should arrive at %12Ld, delta %12Ld\n", TimeSource()->Now(), buffer->Header()->start_time, TimeSource()->Now() - buffer->Header()->start_time);
// to receive the buffer at the right time, // to receive the buffer at the right time,
@@ -544,9 +538,6 @@ AudioMixer::BufferReceived(BBuffer *buffer)
buffer, buffer,
BTimedEventQueue::B_RECYCLE_BUFFER); BTimedEventQueue::B_RECYCLE_BUFFER);
EventQueue()->AddEvent(event); EventQueue()->AddEvent(event);
uint32 dummy;
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
} }
@@ -557,12 +548,6 @@ AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
// printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), buffer->Header()->start_time, TimeSource()->Now(), lateness); // printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), buffer->Header()->start_time, TimeSource()->Now(), lateness);
// printf("3) should arrive at %20Ld, now %20Ld\n", buffer->Header()->start_time, TimeSource()->Now());
// bigtime_t now = TimeSource()->Now();
// bigtime_t perf_time = hdr->start_time;
// bigtime_t how_late = now - perf_time - fLatency;
// check input // check input
int inputcount = fMixerInputs.CountItems(); int inputcount = fMixerInputs.CountItems();
@@ -574,10 +559,10 @@ AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
continue; continue;
if (lateness > 5000) { if (lateness > 5000) {
printf("Received buffer with lateness %Ld\n", lateness); printf("Received buffer with way to high lateness %Ld\n", lateness);
if (RunMode() != B_OFFLINE && RunMode() != B_RECORDING) { if (RunMode() != B_DROP_DATA) {
// printf("sending notify\n"); printf("sending notify\n");
// NotifyLateProducer(channel->fInput.source, lateness, TimeSource()->Now()); NotifyLateProducer(channel->fInput.source, lateness / 2, TimeSource()->Now());
} else if (RunMode() == B_DROP_DATA) { } else if (RunMode() == B_DROP_DATA) {
printf("dropping buffer\n"); printf("dropping buffer\n");
return; return;
@@ -595,7 +580,8 @@ AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
*/ */
if (channel->fDataSize == 0) if (channel->fDataSize == 0)
break; break;
// XXX this is probably broken now
size_t total_offset = int(channel->fEventOffset + channel->fInput.format.u.raw_audio.buffer_size) % int(channel->fDataSize); size_t total_offset = int(channel->fEventOffset + channel->fInput.format.u.raw_audio.buffer_size) % int(channel->fDataSize);
char *indata = (char *)buffer->Data(); char *indata = (char *)buffer->Data();
@@ -620,14 +606,16 @@ AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
void void
AudioMixer::SendNewBuffer(bigtime_t event_time) AudioMixer::SendNewBuffer(bigtime_t event_time)
{ {
// XXX All of this should be handled in a different thread to avoid blocking the control loop
bigtime_t start = system_time(); bigtime_t start = system_time();
BBuffer *outbuffer = fBufferGroup->RequestBuffer(fOutput.format.u.raw_audio.buffer_size, BufferDuration() / 4); BBuffer *outbuffer = fBufferGroup->RequestBuffer(fOutput.format.u.raw_audio.buffer_size, BufferDuration() / 2);
bigtime_t delta = system_time() - start; bigtime_t delta = system_time() - start;
if (delta > 200) if (delta > 1000)
printf("RequestBuffer took %Ld usec\n", delta); printf("AudioMixer::SendNewBuffer: RequestBuffer took %Ld usec\n", delta);
if (!outbuffer) { if (!outbuffer) {
printf("AudioMixer: Could not allocate buffer\n"); printf("AudioMixer::SendNewBuffer: Could not allocate buffer\n");
return; return;
} }
@@ -645,8 +633,8 @@ AudioMixer::SendNewBuffer(bigtime_t event_time)
outbuffer->Recycle(); outbuffer->Recycle();
} }
bigtime_t delta2 = system_time() - start2; bigtime_t delta2 = system_time() - start2;
if (delta2 > 200) if (delta2 > 1000)
printf("SendBuffer took %Ld usec\n", delta2); printf("AudioMixer::SendNewBuffer: SendBuffer took %Ld usec\n", delta2);
} }
@@ -660,8 +648,6 @@ AudioMixer::ProducerDataStatus( const media_destination &for_whom,
media_timed_event event(at_performance_time, BTimedEventQueue::B_DATA_STATUS, media_timed_event event(at_performance_time, BTimedEventQueue::B_DATA_STATUS,
(void *)(&for_whom), BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL); (void *)(&for_whom), BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
EventQueue()->AddEvent(event); EventQueue()->AddEvent(event);
uint32 dummy;
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
// FIX_THIS // FIX_THIS
// the for_whom destination is not being sent correctly - verify in HandleEvent loop // the for_whom destination is not being sent correctly - verify in HandleEvent loop
@@ -1090,7 +1076,6 @@ AudioMixer::Connect( status_t error, const media_source &source, const media_des
media_node_id id; media_node_id id;
FindLatencyFor(fOutput.destination, &fLatency, &id); FindLatencyFor(fOutput.destination, &fLatency, &id);
printf("Downstream Latency is %Ld usecs\n", fLatency); printf("Downstream Latency is %Ld usecs\n", fLatency);
fLatency += 6000;
// we need at least the length of a full output buffer's latency (I think?) // we need at least the length of a full output buffer's latency (I think?)
@@ -1109,6 +1094,11 @@ AudioMixer::Connect( status_t error, const media_source &source, const media_des
fInternalLatency = latency_end - latency_start; fInternalLatency = latency_end - latency_start;
printf("Internal latency is %Ld usecs\n", fInternalLatency); printf("Internal latency is %Ld usecs\n", fInternalLatency);
// use a higher internal latency to be able to process buffers that arrive late
// XXX does this make sense?
if (fInternalLatency < 5000)
fInternalLatency = 5000;
delete mouse; delete mouse;
// might need to tweak the latency // might need to tweak the latency
@@ -1163,8 +1153,8 @@ AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much, big
if (RunMode() == B_INCREASE_LATENCY) { if (RunMode() == B_INCREASE_LATENCY) {
fInternalLatency += how_much; fInternalLatency += how_much;
// if (fInternalLatency > 50000) if (fInternalLatency > 50000)
// fInternalLatency = 50000; fInternalLatency = 50000;
printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency); printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
SetEventLatency(fLatency + fInternalLatency); SetEventLatency(fLatency + fInternalLatency);
@@ -1245,7 +1235,7 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
case SEND_NEW_BUFFER_EVENT: case SEND_NEW_BUFFER_EVENT:
{ {
// if the output is connected and enabled, send a bufffer
if (fOutputEnabled && fOutput.destination != media_destination::null) if (fOutputEnabled && fOutput.destination != media_destination::null)
SendNewBuffer(event->event_time); SendNewBuffer(event->event_time);
@@ -1265,8 +1255,6 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
bigtime_t nextevent = TimeSource()->PerformanceTimeFor(bigtime_t(fStartTime + double(fFramesSent / fOutput.format.u.raw_audio.frame_rate) * 1000000.0)); bigtime_t nextevent = TimeSource()->PerformanceTimeFor(bigtime_t(fStartTime + double(fFramesSent / fOutput.format.u.raw_audio.frame_rate) * 1000000.0));
media_timed_event nextBufferEvent(nextevent, SEND_NEW_BUFFER_EVENT); media_timed_event nextBufferEvent(nextevent, SEND_NEW_BUFFER_EVENT);
EventQueue()->AddEvent(nextBufferEvent); EventQueue()->AddEvent(nextBufferEvent);
uint32 dummy;
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
break; break;
} }
@@ -1289,8 +1277,6 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
// this->HandleEvent(&firstBufferEvent, 0, false); // this->HandleEvent(&firstBufferEvent, 0, false);
// //
EventQueue()->AddEvent(firstBufferEvent); EventQueue()->AddEvent(firstBufferEvent);
uint32 dummy;
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
// fStartTime = event->event_time; // fStartTime = event->event_time;
+2 -2
View File
@@ -52,7 +52,7 @@ initit _initit;
void find_media_server_port() void find_media_server_port()
{ {
MediaServerPort = find_port("media_server port"); MediaServerPort = find_port(MEDIA_SERVER_PORT_NAME);
if (MediaServerPort < 0) { if (MediaServerPort < 0) {
FATAL("couldn't find MediaServerPort\n"); FATAL("couldn't find MediaServerPort\n");
MediaServerPort = BAD_MEDIA_SERVER_PORT; // make this a unique number MediaServerPort = BAD_MEDIA_SERVER_PORT; // make this a unique number
@@ -61,7 +61,7 @@ void find_media_server_port()
void find_media_addon_server_port() void find_media_addon_server_port()
{ {
MediaAddonServerPort = find_port("media_addon_server port"); MediaAddonServerPort = find_port(MEDIA_ADDON_SERVER_PORT_NAME);
if (MediaAddonServerPort < 0) { if (MediaAddonServerPort < 0) {
FATAL("couldn't find MediaAddonServerPort\n"); FATAL("couldn't find MediaAddonServerPort\n");
MediaAddonServerPort = BAD_MEDIA_ADDON_SERVER_PORT; // make this a unique number MediaAddonServerPort = BAD_MEDIA_ADDON_SERVER_PORT; // make this a unique number
+4 -3
View File
@@ -55,6 +55,7 @@ static char __copyright[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@O
#include <MediaAddOn.h> #include <MediaAddOn.h>
#include "debug.h" #include "debug.h"
#include "PortPool.h" #include "PortPool.h"
#include "MediaMisc.h"
#include "ServerInterface.h" #include "ServerInterface.h"
#include "DataExchange.h" #include "DataExchange.h"
#include "DormantNodeManager.h" #include "DormantNodeManager.h"
@@ -215,7 +216,7 @@ DormantNodeManager::RegisterAddon(const char *path)
return 0; return 0;
} }
msg.ref = tempref; msg.ref = tempref;
port = find_port("media_server port"); port = find_port(MEDIA_SERVER_PORT_NAME);
if (port <= B_OK) { if (port <= B_OK) {
FATAL("DormantNodeManager::RegisterAddon failed, couldn't find media server\n"); FATAL("DormantNodeManager::RegisterAddon failed, couldn't find media server\n");
return 0; return 0;
@@ -249,7 +250,7 @@ DormantNodeManager::UnregisterAddon(media_addon_id id)
TRACE("DormantNodeManager::UnregisterAddon id %ld\n",id); TRACE("DormantNodeManager::UnregisterAddon id %ld\n",id);
port_id port; port_id port;
port = find_port("media_server port"); port = find_port(MEDIA_SERVER_PORT_NAME);
if (port <= B_OK) if (port <= B_OK)
return; return;
msg.addonid = id; msg.addonid = id;
@@ -266,7 +267,7 @@ DormantNodeManager::FindAddonPath(BPath *path, media_addon_id id)
entry_ref tempref; entry_ref tempref;
status_t rv; status_t rv;
int32 code; int32 code;
port = find_port("media_server port"); port = find_port(MEDIA_SERVER_PORT_NAME);
if (port <= B_OK) if (port <= B_OK)
return B_ERROR; return B_ERROR;
msg.addonid = id; msg.addonid = id;
+7 -13
View File
@@ -209,8 +209,8 @@ BMediaNode::Node() const
{ {
CALLED(); CALLED();
media_node temp; media_node temp;
temp.node = fNodeID; temp.node = ID();
temp.port = fControlPort; temp.port = ControlPort(); // we *must* call ControlPort(), some derived nodes use it to start the port read thread!
temp.kind = Kinds(); temp.kind = Kinds();
return temp; return temp;
} }
@@ -233,7 +233,7 @@ BMediaNode::TimeSource() const
if (fTimeSource != 0) if (fTimeSource != 0)
return fTimeSource; return fTimeSource;
printf("BMediaNode::TimeSource node %ld enter\n", ID()); TRACE("BMediaNode::TimeSource node %ld enter\n", ID());
// If the node doesn't have a time source object, we need to create one. // If the node doesn't have a time source object, we need to create one.
// If the node is still unregistered, we can't call MakeTimeSourceFor(), // If the node is still unregistered, we can't call MakeTimeSourceFor(),
@@ -255,7 +255,7 @@ BMediaNode::TimeSource() const
fTimeSource->AddMe(self); fTimeSource->AddMe(self);
} }
printf("BMediaNode::TimeSource node %ld leave\n", ID()); TRACE("BMediaNode::TimeSource node %ld leave\n", ID());
return fTimeSource; return fTimeSource;
} }
@@ -355,18 +355,13 @@ BMediaNode::WaitForMessage(bigtime_t waitUntil,
int32 message; int32 message;
ssize_t size; ssize_t size;
size = read_port_etc(fControlPort, &message, data, sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil); size = read_port_etc(ControlPort(), &message, data, sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil);
if (size <= 0) { if (size <= 0) {
if (size != B_TIMED_OUT) if (size != B_TIMED_OUT)
FATAL("BMediaNode::WaitForMessage: read_port_etc error 0x%08lx\n",size); FATAL("BMediaNode::WaitForMessage: read_port_etc error 0x%08lx\n",size);
return size; // returns the error code return size; // returns the error code
} }
if (message == -1) {
//printf("BMediaNode::WaitForMessage dummy received\n");
return B_OK;
}
TRACE("BMediaNode::WaitForMessage %#lx, node %ld, this %p\n", message, fNodeID, this); TRACE("BMediaNode::WaitForMessage %#lx, node %ld, this %p\n", message, fNodeID, this);
if (message > NODE_MESSAGE_START && message < NODE_MESSAGE_END) { if (message > NODE_MESSAGE_START && message < NODE_MESSAGE_END) {
@@ -595,9 +590,8 @@ BMediaNode::HandleMessage(int32 message,
case NODE_SET_TIMESOURCE: case NODE_SET_TIMESOURCE:
{ {
const node_set_timesource_command *command = static_cast<const node_set_timesource_command *>(data); const node_set_timesource_command *command = static_cast<const node_set_timesource_command *>(data);
TRACE("NODE_SET_TIMESOURCE, node %ld, timesource %ld\n", fNodeID, command->timesource_id);
printf("NODE_SET_TIMESOURCE, node %ld, timesource %ld enter\n", fNodeID, command->timesource_id); TRACE("NODE_SET_TIMESOURCE, node %ld, timesource %ld enter\n", fNodeID, command->timesource_id);
fTimeSourceID = command->timesource_id; fTimeSourceID = command->timesource_id;
@@ -617,7 +611,7 @@ BMediaNode::HandleMessage(int32 message,
// any derived class // any derived class
SetTimeSource(fTimeSource); SetTimeSource(fTimeSource);
printf("NODE_SET_TIMESOURCE, node %ld, timesource %ld leave\n", fNodeID, command->timesource_id); TRACE("NODE_SET_TIMESOURCE, node %ld, timesource %ld leave\n", fNodeID, command->timesource_id);
return B_OK; return B_OK;
} }
+14 -2
View File
@@ -1567,6 +1567,8 @@ BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 fl
FATAL("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv); FATAL("BMediaRoster::RegisterNode: failed to register node %s (error %#lx)\n", node->Name(), rv);
return rv; return rv;
} }
TRACE("BMediaRoster::RegisterNode: QueryServer SERVER_REGISTER_NODE finished\n");
// we are a friend class of BMediaNode and initialize this member variable // we are a friend class of BMediaNode and initialize this member variable
node->fNodeID = reply.nodeid; node->fNodeID = reply.nodeid;
@@ -1575,6 +1577,8 @@ BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 fl
// call the callback // call the callback
node->NodeRegistered(); node->NodeRegistered();
TRACE("BMediaRoster::RegisterNode: NodeRegistered callback finished\n");
// if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate() // if the BMediaNode also inherits from BTimeSource, we need to call BTimeSource::FinishCreate()
if (node->Kinds() & B_TIME_SOURCE) { if (node->Kinds() & B_TIME_SOURCE) {
@@ -1584,9 +1588,12 @@ BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 fl
ts->FinishCreate(); ts->FinishCreate();
} }
TRACE("BMediaRoster::RegisterNode: publishing inputs/outputs\n");
// register existing inputs and outputs with the // register existing inputs and outputs with the
// media_server, this allows GetLiveNodes() to work // media_server, this allows GetLiveNodes() to work
// with created, but unconnected nodes. // with created, but unconnected nodes.
if (node->Kinds() & B_BUFFER_PRODUCER) { if (node->Kinds() & B_BUFFER_PRODUCER) {
List<media_output> list; List<media_output> list;
if (B_OK == GetAllOutputs(node->Node(), &list)) if (B_OK == GetAllOutputs(node->Node(), &list))
@@ -1598,7 +1605,12 @@ BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 fl
PublishInputs(node->Node(), &list); PublishInputs(node->Node(), &list);
} }
TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n");
BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1);
TRACE("BMediaRoster::RegisterNode: finished\n");
/* /*
TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id); TRACE("BMediaRoster::RegisterNode: registered node name '%s', id %ld, addon %ld, flavor %ld\n", node->Name(), node->ID(), addon_id, addon_flavor_id);
TRACE("BMediaRoster::RegisterNode: node this %p\n", node); TRACE("BMediaRoster::RegisterNode: node this %p\n", node);
@@ -1851,7 +1863,7 @@ BMediaRoster::GetDormantNodes(dormant_node_info * out_info,
port_id port; port_id port;
status_t rv; status_t rv;
port = find_port("media_server port"); port = find_port(MEDIA_SERVER_PORT_NAME);
if (port <= B_OK) if (port <= B_OK)
return B_ERROR; return B_ERROR;
@@ -2152,7 +2164,7 @@ BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonid,
status_t rv; status_t rv;
int32 code; int32 code;
port = find_port("media_server port"); port = find_port(MEDIA_SERVER_PORT_NAME);
if (port <= B_OK) if (port <= B_OK)
return B_ERROR; return B_ERROR;
+31 -83
View File
@@ -79,8 +79,7 @@ _SoundPlayNode::Format() const
// implementation of BMediaNode // implementation of BMediaNode
// -------------------------------------------------------- // // -------------------------------------------------------- //
BMediaAddOn * _SoundPlayNode::AddOn( BMediaAddOn * _SoundPlayNode::AddOn(int32 * internal_id) const
int32 * internal_id) const
{ {
CALLED(); CALLED();
// BeBook says this only gets called if we were in an add-on. // BeBook says this only gets called if we were in an add-on.
@@ -94,10 +93,7 @@ void _SoundPlayNode::Preroll(void)
BMediaNode::Preroll(); BMediaNode::Preroll();
} }
status_t _SoundPlayNode::HandleMessage( status_t _SoundPlayNode::HandleMessage(int32 message, const void * data, size_t size)
int32 message,
const void * data,
size_t size)
{ {
CALLED(); CALLED();
return B_ERROR; return B_ERROR;
@@ -156,23 +152,13 @@ _SoundPlayNode::FormatSuggestionRequested(media_type type, int32 /*quality*/, me
// preferred data format is, given a suggestion by the caller. // preferred data format is, given a suggestion by the caller.
CALLED(); CALLED();
if (!format) // a wildcard type is okay; but we only support raw audio
{ if (type != B_MEDIA_RAW_AUDIO && type != B_MEDIA_UNKNOWN_TYPE)
fprintf(stderr, "\tERROR - NULL format pointer passed in!\n"); return B_MEDIA_BAD_FORMAT;
return B_BAD_VALUE;
}
// this is the format we'll be returning (our preferred format) // this is the format we'll be returning (our preferred format)
*format = mFormat; *format = mFormat;
// a wildcard type is okay; we can specialize it
if (type == B_MEDIA_UNKNOWN_TYPE)
type = B_MEDIA_RAW_AUDIO;
// we only support raw audio
if (type != B_MEDIA_RAW_AUDIO)
return B_MEDIA_BAD_FORMAT;
return B_OK; return B_OK;
} }
@@ -182,9 +168,9 @@ _SoundPlayNode::FormatProposal(const media_source& output, media_format* format)
// FormatProposal() is the first stage in the BMediaRoster::Connect() process. We hand // FormatProposal() is the first stage in the BMediaRoster::Connect() process. We hand
// out a suggested format, with wildcards for any variations we support. // out a suggested format, with wildcards for any variations we support.
CALLED(); CALLED();
// is this a proposal for our one output? // is this a proposal for our one output?
if (output != mOutput.source) if (output != mOutput.source) {
{
fprintf(stderr, "_SoundPlayNode::FormatProposal returning B_MEDIA_BAD_SOURCE\n"); fprintf(stderr, "_SoundPlayNode::FormatProposal returning B_MEDIA_BAD_SOURCE\n");
return B_MEDIA_BAD_SOURCE; return B_MEDIA_BAD_SOURCE;
} }
@@ -193,12 +179,12 @@ _SoundPlayNode::FormatProposal(const media_source& output, media_format* format)
// supply an error code depending on whether we found the proposal acceptable. // supply an error code depending on whether we found the proposal acceptable.
media_type requestedType = format->type; media_type requestedType = format->type;
*format = mFormat; *format = mFormat;
if ((requestedType != B_MEDIA_UNKNOWN_TYPE) && (requestedType != B_MEDIA_RAW_AUDIO)) if ((requestedType != B_MEDIA_UNKNOWN_TYPE) && (requestedType != B_MEDIA_RAW_AUDIO)) {
{
fprintf(stderr, "_SoundPlayNode::FormatProposal returning B_MEDIA_BAD_FORMAT\n"); fprintf(stderr, "_SoundPlayNode::FormatProposal returning B_MEDIA_BAD_FORMAT\n");
return B_MEDIA_BAD_FORMAT; return B_MEDIA_BAD_FORMAT;
} }
else return B_OK; // raw audio or wildcard type, either is okay by us else
return B_OK; // raw audio or wildcard type, either is okay by us
} }
status_t status_t
@@ -237,8 +223,7 @@ _SoundPlayNode::SetBufferGroup(const media_source& for_source, BBufferGroup* new
CALLED(); CALLED();
// is this our output? // is this our output?
if (for_source != mOutput.source) if (for_source != mOutput.source) {
{
fprintf(stderr, "_SoundPlayNode::SetBufferGroup returning B_MEDIA_BAD_SOURCE\n"); fprintf(stderr, "_SoundPlayNode::SetBufferGroup returning B_MEDIA_BAD_SOURCE\n");
return B_MEDIA_BAD_SOURCE; return B_MEDIA_BAD_SOURCE;
} }
@@ -265,6 +250,8 @@ _SoundPlayNode::SetBufferGroup(const media_source& for_source, BBufferGroup* new
// our own buffer group to use from now on // our own buffer group to use from now on
size_t size = mOutput.format.u.raw_audio.buffer_size; size_t size = mOutput.format.u.raw_audio.buffer_size;
int32 count = int32(mLatency / BufferDuration() + 1 + 1); int32 count = int32(mLatency / BufferDuration() + 1 + 1);
if (count < 3)
count = 3;
mBufferGroup = new BBufferGroup(size, count); mBufferGroup = new BBufferGroup(size, count);
} }
@@ -372,7 +359,7 @@ _SoundPlayNode::Connect(status_t error, const media_source& source, const media_
FindLatencyFor(mOutput.destination, &mLatency, &id); FindLatencyFor(mOutput.destination, &mLatency, &id);
fprintf(stderr, "\tdownstream latency = %Ld\n", mLatency); fprintf(stderr, "\tdownstream latency = %Ld\n", mLatency);
mInternalLatency = 1000LL; mInternalLatency = 10000LL;
fprintf(stderr, "\tbuffer-filling took %Ld usec on this machine\n", mInternalLatency); fprintf(stderr, "\tbuffer-filling took %Ld usec on this machine\n", mInternalLatency);
SetEventLatency(mLatency + mInternalLatency); SetEventLatency(mLatency + mInternalLatency);
@@ -433,18 +420,6 @@ _SoundPlayNode::LateNoticeReceived(const media_source& what, bigtime_t how_much,
return; return;
} }
// If we're late, we need to catch up. Respond in a manner appropriate to our
// current run mode.
/*
if (RunMode() == B_RECORDING)
{
// A hardware capture node can't adjust; it simply emits buffers at
// appropriate points. We (partially) simulate this by not adjusting
// our behavior upon receiving late notices -- after all, the hardware
// can't choose to capture "sooner"....
}
else if (RunMode() == B_INCREASE_LATENCY)
*/
if (RunMode() != B_DROP_DATA) if (RunMode() != B_DROP_DATA)
{ {
// We're late, and our run mode dictates that we try to produce buffers // We're late, and our run mode dictates that we try to produce buffers
@@ -453,23 +428,25 @@ _SoundPlayNode::LateNoticeReceived(const media_source& what, bigtime_t how_much,
// that at the moment, so we try to start producing buffers earlier to // that at the moment, so we try to start producing buffers earlier to
// compensate. // compensate.
mInternalLatency += how_much;
// mInternalLatency += how_much;
// if (mInternalLatency > 50000) if (mInternalLatency > 30000) // avoid getting a too high latency
// mInternalLatency = 50000; mInternalLatency = 30000;
// SetEventLatency(mLatency + mInternalLatency); SetEventLatency(mLatency + mInternalLatency);
fprintf(stderr, "\tincreasing latency to %Ld\n", mLatency + mInternalLatency);
// fprintf(stderr, "\tincreasing latency to %Ld\n", mLatency + mInternalLatency);
} }
else else
{ {
// The other run modes dictate various strategies for sacrificing data quality // The other run modes dictate various strategies for sacrificing data quality
// in the interests of timely data delivery. The way *we* do this is to skip // in the interests of timely data delivery. The way *we* do this is to skip
// a buffer, which catches us up in time by one buffer duration. // a buffer, which catches us up in time by one buffer duration.
/*size_t nSamples = mOutput.format.u.raw_audio.buffer_size / sizeof(float);
mSamplesSent += nSamples;*/ size_t nFrames = mOutput.format.u.raw_audio.buffer_size
/ ((mOutput.format.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK)
* mOutput.format.u.raw_audio.channel_count);
mFramesSent += nFrames;
fprintf(stderr, "\tskipping a buffer to try to catch up\n"); fprintf(stderr, "\tskipping a buffer to try to catch up\n");
} }
@@ -570,16 +547,11 @@ void _SoundPlayNode::HandleEvent(
// how should we handle late buffers? drop them? // how should we handle late buffers? drop them?
// notify the producer? // notify the producer?
status_t status_t
_SoundPlayNode::SendNewBuffer( _SoundPlayNode::SendNewBuffer(const media_timed_event *event, bigtime_t lateness, bool realTimeEvent)
const media_timed_event *event,
bigtime_t lateness,
bool realTimeEvent)
{ {
CALLED(); CALLED();
// printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), event->event_time, TimeSource()->Now(), lateness); // printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), event->event_time, TimeSource()->Now(), lateness);
// printf("1) should arrive at %20Ld, now %20Ld\n", event->event_time, TimeSource()->Now());
// 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))
return B_OK; return B_OK;
@@ -587,13 +559,10 @@ _SoundPlayNode::SendNewBuffer(
// The event->event_time is the time at which the buffer we are preparing here should // The event->event_time is the time at which the buffer we are preparing here should
// arrive at it's destination. The MediaEventLooper should have scheduled us early enough // arrive at it's destination. The MediaEventLooper should have scheduled us early enough
// (based on EventLatency() and the SchedulingLatency()) to make this possible. // (based on EventLatency() and the SchedulingLatency()) to make this possible.
// lateness is independent of EventLatency()!
// bigtime_t scheduling_latency = SchedulingLatency(); if (lateness > 1000) {
printf("_SoundPlayNode::SendNewBuffer, event scheduled much too late, lateness is %Ld\n", lateness);
if (lateness > 5000) {
printf("_SoundPlayNode::SendNewBuffer, event sheduled too late, lateness is %Ld\n", lateness);
// mInternalLatency += 1000;
// SetEventLatency(mLatency + mInternalLatency);
} }
// skip buffer creation if output not enabled // skip buffer creation if output not enabled
@@ -622,17 +591,12 @@ _SoundPlayNode::SendNewBuffer(
} }
*/ */
// send the buffer downstream if and only if output is enabled // send the buffer downstream if and only if output is enabled
bigtime_t start = system_time();
buffer->Header()->file_pos = (off_t)start; // XXX debugging
if (B_OK != SendBuffer(buffer, mOutput.destination)) { if (B_OK != SendBuffer(buffer, mOutput.destination)) {
// 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("Buffer sending failed\n"); printf("Buffer sending failed\n");
buffer->Recycle(); buffer->Recycle();
} }
bigtime_t delta = system_time() - start;
if (delta > 200)
printf("SendBuffer took %Ld usec\n", delta);
} }
} }
@@ -646,10 +610,7 @@ _SoundPlayNode::SendNewBuffer(
// nextEvent is the time at which the buffer should arrive at it's destination // nextEvent is the time at which the buffer should arrive at it's destination
bigtime_t nextEvent = TimeSource()->PerformanceTimeFor(mStartTime + bigtime_t((1000000LL * mFramesSent) / mOutput.format.u.raw_audio.frame_rate)); bigtime_t nextEvent = TimeSource()->PerformanceTimeFor(mStartTime + bigtime_t((1000000LL * mFramesSent) / mOutput.format.u.raw_audio.frame_rate));
media_timed_event nextBufferEvent(nextEvent, SEND_NEW_BUFFER_EVENT); media_timed_event nextBufferEvent(nextEvent, SEND_NEW_BUFFER_EVENT);
// printf("0) should arrive at %20Ld, now %20Ld\n", nextEvent, TimeSource()->Now());
EventQueue()->AddEvent(nextBufferEvent); EventQueue()->AddEvent(nextBufferEvent);
uint32 dummy;
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
return B_OK; return B_OK;
} }
@@ -698,8 +659,6 @@ _SoundPlayNode::HandleStart(
// this->HandleEvent(&firstBufferEvent, 0, false); // this->HandleEvent(&firstBufferEvent, 0, false);
// //
EventQueue()->AddEvent(firstBufferEvent); EventQueue()->AddEvent(firstBufferEvent);
uint32 dummy;
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
} }
return B_OK; return B_OK;
} }
@@ -772,16 +731,11 @@ _SoundPlayNode::FillNextBuffer(bigtime_t event_time)
CALLED(); CALLED();
// get a buffer from our buffer group // get a buffer from our buffer group
bigtime_t start = system_time(); BBuffer* buf = mBufferGroup->RequestBuffer(mOutput.format.u.raw_audio.buffer_size, BufferDuration() / 2);
BBuffer* buf = mBufferGroup->RequestBuffer(mOutput.format.u.raw_audio.buffer_size, BufferDuration() / 4);
bigtime_t delta = system_time() - start;
if (delta > 200)
printf("RequestBuffer took %Ld usec\n", delta);
// if we fail to get a buffer (for example, if the request times out), we skip this // if we fail to get a buffer (for example, if the request times out), we skip this
// buffer and go on to the next, to avoid locking up the control thread // buffer and go on to the next, to avoid locking up the control thread
if (!buf) if (!buf) {
{
printf("RequestBuffer failed\n"); printf("RequestBuffer failed\n");
return NULL; return NULL;
} }
@@ -798,11 +752,5 @@ _SoundPlayNode::FillNextBuffer(bigtime_t event_time)
hdr->size_used = mOutput.format.u.raw_audio.buffer_size; hdr->size_used = mOutput.format.u.raw_audio.buffer_size;
hdr->time_source = TimeSource()->ID(); hdr->time_source = TimeSource()->ID();
hdr->start_time = event_time; hdr->start_time = event_time;
/*
DPRINTF("TimeSource()->Now() : %li\n", TimeSource()->Now());
DPRINTF("hdr->start_time : %li\n", hdr->start_time);
DPRINTF("mFramesSent : %li\n", mFramesSent);
DPRINTF("mOutput.format.u.raw_audio.frame_rate : %f\n", mOutput.format.u.raw_audio.frame_rate);
*/
return buf; return buf;
} }
+10 -10
View File
@@ -18,7 +18,7 @@ TimeSourceObject::TimeSourceObject(const media_node &node)
: BMediaNode("some timesource object", node.node, node.kind), : BMediaNode("some timesource object", node.node, node.kind),
BTimeSource(node.node) BTimeSource(node.node)
{ {
printf("TimeSourceObject::TimeSourceObject enter, id = %ld\n", node.node); TRACE("TimeSourceObject::TimeSourceObject enter, id = %ld\n", node.node);
if (fControlPort > 0) if (fControlPort > 0)
delete_port(fControlPort); delete_port(fControlPort);
fControlPort = node.port; fControlPort = node.port;
@@ -26,22 +26,22 @@ TimeSourceObject::TimeSourceObject(const media_node &node)
ASSERT(fKinds == node.kind); ASSERT(fKinds == node.kind);
if (node.node == NODE_SYSTEM_TIMESOURCE_ID) { if (node.node == NODE_SYSTEM_TIMESOURCE_ID) {
strcpy(fName, "System Clock"); strcpy(fName, "System Clock");
} else {
live_node_info lni;
if (B_OK == BMediaRoster::Roster()->GetLiveNodeInfo(node, &lni)) {
strcpy(fName, lni.name);
} else { } else {
sprintf(fName, "timesource %ld", node.node); live_node_info lni;
if (B_OK == BMediaRoster::Roster()->GetLiveNodeInfo(node, &lni)) {
strcpy(fName, lni.name);
} else {
sprintf(fName, "timesource %ld", node.node);
}
} }
}
AddNodeKind(NODE_KIND_SHADOW_TIMESOURCE); AddNodeKind(NODE_KIND_SHADOW_TIMESOURCE);
AddNodeKind(NODE_KIND_NO_REFCOUNTING); AddNodeKind(NODE_KIND_NO_REFCOUNTING);
fControlPort = SHADOW_TIMESOURCE_CONTROL_PORT; // XXX if we don't do this, we get a infinite loop somewhere. This needs to be debugged fControlPort = SHADOW_TIMESOURCE_CONTROL_PORT; // XXX if we don't do this, we get a infinite loop somewhere. This needs to be debugged
printf("TimeSourceObject::TimeSourceObject leave, node id %ld\n", fNodeID); TRACE("TimeSourceObject::TimeSourceObject leave, node id %ld\n", fNodeID);
} }
/* virtual */ status_t /* virtual */ status_t
+4 -2
View File
@@ -53,12 +53,13 @@ TimeSourceObjectManager::~TimeSourceObjectManager()
void void
TimeSourceObjectManager::InitSystemTimeSource() TimeSourceObjectManager::InitSystemTimeSource()
{ {
CALLED();
BAutolock lock(fLock); BAutolock lock(fLock);
if (fSystemTimeSource != 0) if (fSystemTimeSource != 0)
return; return;
printf("TimeSourceObjectManager::InitSystemTimeSource enter\n"); TRACE("TimeSourceObjectManager::InitSystemTimeSource enter\n");
media_node node; media_node node;
node.node = NODE_SYSTEM_TIMESOURCE_ID; node.node = NODE_SYSTEM_TIMESOURCE_ID;
@@ -67,13 +68,14 @@ TimeSourceObjectManager::InitSystemTimeSource()
fSystemTimeSource = new SystemTimeSourceObject(node); fSystemTimeSource = new SystemTimeSourceObject(node);
printf("TimeSourceObjectManager::InitSystemTimeSource leave\n"); TRACE("TimeSourceObjectManager::InitSystemTimeSource leave\n");
} }
BTimeSource * BTimeSource *
TimeSourceObjectManager::GetSystemTimeSource() TimeSourceObjectManager::GetSystemTimeSource()
{ {
CALLED();
BAutolock lock(fLock); BAutolock lock(fLock);
if (fSystemTimeSource == 0) if (fSystemTimeSource == 0)
+6
View File
@@ -252,6 +252,8 @@ DefaultManager::FindPhysicalAudioOut()
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (0 == strcmp(info[i].name, "None Out")) // skip the Null audio driver if (0 == strcmp(info[i].name, "None Out")) // skip the Null audio driver
continue; continue;
if (0 == strcmp(info[i].name, "DV Output")) // skip the Firewire audio driver
continue;
printf("Default physical audio output \"%s\" created!\n", info[i].name); printf("Default physical audio output \"%s\" created!\n", info[i].name);
fPhysicalAudioOut = info[i].node.node; fPhysicalAudioOut = info[i].node.node;
return; return;
@@ -280,6 +282,8 @@ DefaultManager::FindPhysicalAudioIn()
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (0 == strcmp(info[i].name, "None In")) // skip the Null audio driver if (0 == strcmp(info[i].name, "None In")) // skip the Null audio driver
continue; continue;
if (0 == strcmp(info[i].name, "DV Input")) // skip the Firewire audio driver
continue;
printf("Default physical audio input \"%s\" created!\n", info[i].name); printf("Default physical audio input \"%s\" created!\n", info[i].name);
fPhysicalAudioIn = info[i].node.node; fPhysicalAudioIn = info[i].node.node;
return; return;
@@ -327,6 +331,8 @@ DefaultManager::FindTimeSource()
// The BeOS R5 None Out node pretend to be a physical time source, that is pretty dumb // The BeOS R5 None Out node pretend to be a physical time source, that is pretty dumb
if (0 == strcmp(info[i].name, "None Out")) // skip the Null audio driver if (0 == strcmp(info[i].name, "None Out")) // skip the Null audio driver
continue; continue;
if (0 == strcmp(info[i].name, "DV Output")) // skip the Firewire audio driver
continue;
printf("Default DAC timesource \"%s\" created!\n", info[i].name); printf("Default DAC timesource \"%s\" created!\n", info[i].name);
fTimeSource = info[i].node.node; fTimeSource = info[i].node.node;
return; return;
+9 -6
View File
@@ -119,7 +119,7 @@ ServerApp::ServerApp()
gAppManager = new AppManager; gAppManager = new AppManager;
gNodeManager = new NodeManager; gNodeManager = new NodeManager;
control_port = create_port(64,"media_server port"); control_port = create_port(64, MEDIA_SERVER_PORT_NAME);
control_thread = spawn_thread(controlthread, "media_server control", 105, this); control_thread = spawn_thread(controlthread, "media_server control", 105, this);
resume_thread(control_thread); resume_thread(control_thread);
@@ -174,10 +174,10 @@ ServerApp::QuitRequested()
void void
ServerApp::StartSystemTimeSource() ServerApp::StartSystemTimeSource()
{ {
printf("StartSystemTimeSource enter\n"); TRACE("StartSystemTimeSource enter\n");
status_t rv; status_t rv;
printf("StartSystemTimeSource creating object\n"); TRACE("StartSystemTimeSource creating object\n");
// register a dummy node // register a dummy node
media_node node; media_node node;
@@ -186,19 +186,19 @@ ServerApp::StartSystemTimeSource()
ASSERT(node.node == NODE_SYSTEM_TIMESOURCE_ID); ASSERT(node.node == NODE_SYSTEM_TIMESOURCE_ID);
printf("StartSystemTimeSource setting as default\n"); TRACE("StartSystemTimeSource setting as default\n");
rv = gNodeManager->SetDefaultNode(SYSTEM_TIME_SOURCE, &node, NULL, NULL); rv = gNodeManager->SetDefaultNode(SYSTEM_TIME_SOURCE, &node, NULL, NULL);
ASSERT(rv == B_OK); ASSERT(rv == B_OK);
printf("StartSystemTimeSource leave\n"); TRACE("StartSystemTimeSource leave\n");
} }
void void
ServerApp::HandleMessage(int32 code, void *data, size_t size) ServerApp::HandleMessage(int32 code, void *data, size_t size)
{ {
status_t rv; status_t rv;
INFO("ServerApp::HandleMessage %#lx\n", code); TRACE("ServerApp::HandleMessage %#lx enter\n", code);
switch (code) { switch (code) {
case SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT: case SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT:
{ {
@@ -556,6 +556,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size)
default: default:
printf("media_server: received unknown message code %#08lx\n",code); printf("media_server: received unknown message code %#08lx\n",code);
} }
TRACE("ServerApp::HandleMessage %#lx leave\n", code);
} }
int32 int32
@@ -575,6 +576,7 @@ ServerApp::controlthread(void *arg)
void ServerApp::MessageReceived(BMessage *msg) void ServerApp::MessageReceived(BMessage *msg)
{ {
TRACE("ServerApp::MessageReceived %x enter\n", msg->what);
switch (msg->what) { switch (msg->what) {
case MEDIA_SERVER_REQUEST_NOTIFICATIONS: gNotificationManager->EnqueueMessage(msg); break; case MEDIA_SERVER_REQUEST_NOTIFICATIONS: gNotificationManager->EnqueueMessage(msg); break;
case MEDIA_SERVER_CANCEL_NOTIFICATIONS: gNotificationManager->EnqueueMessage(msg); break; case MEDIA_SERVER_CANCEL_NOTIFICATIONS: gNotificationManager->EnqueueMessage(msg); break;
@@ -583,6 +585,7 @@ void ServerApp::MessageReceived(BMessage *msg)
printf("\nnew media server: unknown message received\n"); printf("\nnew media server: unknown message received\n");
msg->PrintToStream(); msg->PrintToStream();
} }
TRACE("ServerApp::MessageReceived %x leave\n", msg->what);
} }
int main() int main()
+2 -2
View File
@@ -105,7 +105,7 @@ MediaAddonServer::MediaAddonServer(const char *sig) :
mediaroster = BMediaRoster::Roster(); mediaroster = BMediaRoster::Roster();
filemap = new Map<ino_t, media_addon_id>; filemap = new Map<ino_t, media_addon_id>;
infomap = new Map<media_addon_id, AddOnInfo>; infomap = new Map<media_addon_id, AddOnInfo>;
control_port = create_port(64, "media_addon_server port"); control_port = create_port(64, MEDIA_ADDON_SERVER_PORT_NAME);
control_thread = spawn_thread(controlthread, "media_addon_server control", 12, this); control_thread = spawn_thread(controlthread, "media_addon_server control", 12, this);
resume_thread(control_thread); resume_thread(control_thread);
} }
@@ -252,7 +252,7 @@ MediaAddonServer::ScanAddOnFlavors(BMediaAddOn *addon)
TRACE("MediaAddonServer::ScanAddOnFlavors: id %ld\n",addon->AddonID()); TRACE("MediaAddonServer::ScanAddOnFlavors: id %ld\n",addon->AddonID());
port = find_port("media_server port"); port = find_port(MEDIA_SERVER_PORT_NAME);
if (port <= B_OK) { if (port <= B_OK) {
FATAL("couldn't find media_server port\n"); FATAL("couldn't find media_server port\n");
return; return;