From 60f15390cd7b83f1a8083d8530d7256aa1ea71e3 Mon Sep 17 00:00:00 2001 From: beveloper Date: Sun, 23 Mar 2003 01:08:27 +0000 Subject: [PATCH] a couple of fixes regarding latency calculation git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2996 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/media/BufferProducer.cpp | 57 ++++++++++++-- src/kits/media/MediaDefs.cpp | 7 +- src/kits/media/MediaNode.cpp | 7 +- src/kits/media/MediaRoster.cpp | 123 +++++++++++++++++++++++------- 4 files changed, 152 insertions(+), 42 deletions(-) diff --git a/src/kits/media/BufferProducer.cpp b/src/kits/media/BufferProducer.cpp index 50268c4c9c..11595eacad 100644 --- a/src/kits/media/BufferProducer.cpp +++ b/src/kits/media/BufferProducer.cpp @@ -4,6 +4,7 @@ * DESCR: ***********************************************************************/ #include +#include #include #include #include "debug.h" @@ -53,7 +54,8 @@ BBufferProducer::BBufferProducer(media_type producer_type) : BMediaNode("called by BBufferProducer"), fProducerType(producer_type), fInitialLatency(0), - fInitialFlags(0) + fInitialFlags(0), + fDelay(0) { CALLED(); @@ -77,13 +79,45 @@ BBufferProducer::VideoClippingChanged(const media_source &for_source, status_t BBufferProducer::GetLatency(bigtime_t *out_lantency) { - UNIMPLEMENTED(); - - // XXX The default implementation of GetLatency() finds the maximum + CALLED(); + // The default implementation of GetLatency() finds the maximum // latency of your currently-available outputs by iterating over // them, and returns that value in outLatency - - return B_ERROR; + + int32 cookie; + bigtime_t latency; + media_output output; + media_node_id unused; + + *out_lantency = 0; + cookie = 0; + while (B_OK == GetNextOutput(&cookie, &output)) { + cookie++; + + if (output.destination == media_destination::null) + continue; + + if (output.node.node == fNodeID) { // avoid port writes (deadlock) if loopback connection + if (!fConsumerThis) + fConsumerThis = dynamic_cast(this); + if (!fConsumerThis) + continue; + latency = 0; + if (B_OK == fConsumerThis->GetLatencyFor(output.destination, &latency, &unused)) { + if (latency > *out_lantency) { + *out_lantency = latency; + } + } + } else { + if (B_OK == FindLatencyFor(output.destination, &latency, &unused)) { + if (latency > *out_lantency) { + *out_lantency = latency; + } + } + } + } + printf("BBufferProducer::GetLatency: node %ld, name \"%s\" has max latency %Ld\n", fNodeID, fName, *out_lantency); + return B_OK; } @@ -105,6 +139,15 @@ BBufferProducer::HandleMessage(int32 message, INFO("BBufferProducer::HandleMessage %#lx, node %ld\n", message, fNodeID); status_t rv; switch (message) { + case PRODUCER_SET_RUN_MODE_DELAY: + { + const producer_set_run_mode_delay_command *command = static_cast(data); + // when changing this, also change NODE_SET_RUN_MODE + fDelay = command->delay; + fRunMode = command->mode; + SetRunMode(fRunMode); + return B_OK; + } case PRODUCER_FORMAT_SUGGESTION_REQUESTED: { @@ -241,7 +284,6 @@ BBufferProducer::HandleMessage(int32 message, return B_OK; } - case PRODUCER_VIDEO_CLIPPING_CHANGED: { const producer_video_clipping_changed_command *command = static_cast(data); @@ -344,6 +386,7 @@ BBufferProducer::SendBuffer(BBuffer *buffer, command.header = *(buffer->Header()); command.header.buffer = command.buffer; // buffer->ID(); command.header.destination = destination.id; + command.header.start_time += fDelay; // time compensation as set by BMediaRoster::SetProducerRunModeDelay() return SendToPort(destination.port, CONSUMER_BUFFER_RECEIVED, &command, sizeof(command)); } diff --git a/src/kits/media/MediaDefs.cpp b/src/kits/media/MediaDefs.cpp index de91015820..f24b7ec85c 100644 --- a/src/kits/media/MediaDefs.cpp +++ b/src/kits/media/MediaDefs.cpp @@ -359,13 +359,16 @@ bool operator==(const media_format & a, const media_format & b) bool format_is_compatible(const media_format & a, const media_format & b) /* a is the format you want to feed to something accepting b */ { UNIMPLEMENTED(); - return true; + if (a.type == b.type) + return true; + return false; } bool string_for_format(const media_format & f, char * buf, size_t size) { UNIMPLEMENTED(); - return false; + strcpy(buf, "No string_for_format string!"); + return true; } /************************************************************* diff --git a/src/kits/media/MediaNode.cpp b/src/kits/media/MediaNode.cpp index 5777025b78..fe1151325a 100644 --- a/src/kits/media/MediaNode.cpp +++ b/src/kits/media/MediaNode.cpp @@ -570,6 +570,7 @@ BMediaNode::HandleMessage(int32 message, case NODE_SET_RUN_MODE: { const node_set_run_mode_command *command = static_cast(data); + // when changing this, also change PRODUCER_SET_RUN_MODE_DELAY fRunMode = command->mode; SetRunMode(fRunMode); return B_OK; @@ -595,7 +596,7 @@ BMediaNode::HandleMessage(int32 message, BTimeSource *newsource; media_node clone; status_t rv; - printf("NODE_SET_TIMESOURCE, node %ld, timesource %ld\n", fNodeID, command->timesource_id); + TRACE("NODE_SET_TIMESOURCE, node %ld, timesource %ld\n", fNodeID, command->timesource_id); roster = BMediaRoster::Roster(); // Time sources are not reference counted. But since @@ -632,7 +633,7 @@ BMediaNode::HandleMessage(int32 message, // we add this node to the time source controll fTimeSource->AddMe(this); } - printf("#### BMediaNode::HandleMessage NODE_SET_TIMESOURCE: node %ld has been assigned time source %ld\n", ID(), fTimeSource->ID()); + TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE: node %ld has been assigned time source %ld\n", ID(), fTimeSource->ID()); //roster->StartTimeSource(fTimeSource->Node(), fTimeSource->RealTime()); return B_OK; @@ -910,5 +911,3 @@ BMediaNode::NewChangeTag() // BBufferConsumer::SetVideoClippingFor() return atomic_add(&BMediaNode::_m_changeTag,1); } - - diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 1845aec640..3b2e7f9799 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "debug.h" #include "MediaRosterEx.h" #include "MediaMisc.h" @@ -52,7 +53,8 @@ BMediaRosterEx::SaveNodeConfiguration(BMediaNode *node) int32 flavorid; addon = node->AddOn(&flavorid); if (!addon) { - FATAL("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n"); + // XXX this check incorrectly triggers on BeOS R5 BT848 node + FATAL("BMediaRosterEx::SaveNodeConfiguration node %ld not instantiated from BMediaAddOn!\n", node->ID()); return B_ERROR; } addonid = addon->AddonID(); @@ -521,7 +523,7 @@ BMediaRoster::ReleaseNode(const media_node & node) request.node = node; request.team = team; - printf("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team); + TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", node.node, node.port, team); rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); if (rv != B_OK) { @@ -537,10 +539,10 @@ BMediaRoster::MakeTimeSourceFor(const media_node & for_node) BTimeSource *source; -// printf("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind); + TRACE("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind); if (0 == (for_node.kind & B_TIME_SOURCE)) { - FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node); + //FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node); // XXX It appears that Cortex calls this function on every node, and expects // XXX to be returned a system time source if the for_node is not a timesource media_node clone; @@ -551,7 +553,7 @@ BMediaRoster::MakeTimeSourceFor(const media_node & for_node) source = _TimeSourceObjectManager->GetTimeSource(for_node); } -// printf("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind); + TRACE("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind); return source; } @@ -782,7 +784,7 @@ BMediaRoster::StartNode(const media_node & node, if (node.node <= 0) return B_MEDIA_BAD_NODE; - printf("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time); + TRACE("BMediaRoster::StartNode, node %ld, at perf %Ld\n", node.node, at_performance_time); node_start_command command; command.performance_time = at_performance_time; @@ -800,7 +802,7 @@ BMediaRoster::StopNode(const media_node & node, if (IS_INVALID_NODE(node)) return B_MEDIA_BAD_NODE; - printf("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : ""); + TRACE("BMediaRoster::StopNode, node %ld, at perf %Ld %s\n", node.node, at_performance_time, immediate ? "NOW" : ""); node_stop_command command; command.performance_time = at_performance_time; @@ -819,7 +821,7 @@ BMediaRoster::SeekNode(const media_node & node, if (IS_INVALID_NODE(node)) return B_MEDIA_BAD_NODE; - printf("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time); + TRACE("BMediaRoster::SeekNode, node %ld, at perf %Ld, to perf %Ld\n", node.node, at_performance_time, to_media_time); node_seek_command command; command.media_time = to_media_time; @@ -834,16 +836,26 @@ BMediaRoster::StartTimeSource(const media_node & node, bigtime_t at_real_time) { CALLED(); + if (IS_SYSTEM_TIMESOURCE(node)) { + // XXX debug this + //FATAL("BMediaRoster::StartTimeSource node %ld is system timesource\n", node.node); + return B_OK; + } + if (IS_SHADOW_TIMESOURCE(node)) { + // XXX debug this + FATAL("BMediaRoster::StartTimeSource node %ld is shadow timesource\n", node.node); + return B_OK; + } if (IS_INVALID_NODE(node)) { - FATAL("BMediaRoster::StartTimeSource node invalid\n"); + FATAL("BMediaRoster::StartTimeSource node %ld invalid\n", node.node); return B_MEDIA_BAD_NODE; } if ((node.kind & B_TIME_SOURCE) == 0) { - FATAL("BMediaRoster::StartTimeSource node is no timesource invalid\n"); + FATAL("BMediaRoster::StartTimeSource node %ld is no timesource\n", node.node); return B_MEDIA_BAD_NODE; } - printf("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time); + TRACE("BMediaRoster::StartTimeSource, node %ld, at real %Ld\n", node.node, at_real_time); BTimeSource::time_source_op_info msg; msg.op = BTimeSource::B_TIMESOURCE_START; @@ -859,16 +871,26 @@ BMediaRoster::StopTimeSource(const media_node & node, bool immediate) { CALLED(); + if (IS_SYSTEM_TIMESOURCE(node)) { + // XXX debug this + //FATAL("BMediaRoster::StopTimeSource node %ld is system timesource\n", node.node); + return B_OK; + } + if (IS_SHADOW_TIMESOURCE(node)) { + // XXX debug this + FATAL("BMediaRoster::StopTimeSource node %ld is shadow timesource\n", node.node); + return B_OK; + } if (IS_INVALID_NODE(node)) { - FATAL("BMediaRoster::StartTimeSource node invalid\n"); + FATAL("BMediaRoster::StopTimeSource node %ld invalid\n", node.node); return B_MEDIA_BAD_NODE; } if ((node.kind & B_TIME_SOURCE) == 0) { - FATAL("BMediaRoster::StartTimeSource node is no timesource invalid\n"); + FATAL("BMediaRoster::StopTimeSource node %ld is no timesource\n", node.node); return B_MEDIA_BAD_NODE; } - printf("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : ""); + TRACE("BMediaRoster::StopTimeSource, node %ld, at real %Ld %s\n", node.node, at_real_time, immediate ? "NOW" : ""); BTimeSource::time_source_op_info msg; msg.op = immediate ? BTimeSource::B_TIMESOURCE_STOP_IMMEDIATELY : BTimeSource::B_TIMESOURCE_STOP; @@ -884,16 +906,28 @@ BMediaRoster::SeekTimeSource(const media_node & node, bigtime_t at_real_time) { CALLED(); + if (IS_SYSTEM_TIMESOURCE(node)) { + // XXX debug this + // FATAL("BMediaRoster::SeekTimeSource node %ld is system timesource\n", node.node); + // you can't seek the system time source, but + // returning B_ERROR would break StampTV + return B_OK; + } + if (IS_SHADOW_TIMESOURCE(node)) { + // XXX debug this + FATAL("BMediaRoster::SeekTimeSource node %ld is shadow timesource\n", node.node); + return B_OK; + } if (IS_INVALID_NODE(node)) { - FATAL("BMediaRoster::StartTimeSource node invalid\n"); + FATAL("BMediaRoster::SeekTimeSource node %ld invalid\n", node.node); return B_MEDIA_BAD_NODE; } if ((node.kind & B_TIME_SOURCE) == 0) { - FATAL("BMediaRoster::StartTimeSource node is no timesource invalid\n"); + FATAL("BMediaRoster::SeekTimeSource node %ld is no timesource\n", node.node); return B_MEDIA_BAD_NODE; } - printf("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time); + TRACE("BMediaRoster::SeekTimeSource, node %ld, at real %Ld, to perf %Ld\n", node.node, at_real_time, to_performance_time); BTimeSource::time_source_op_info msg; msg.op = BTimeSource::B_TIMESOURCE_SEEK; @@ -910,7 +944,7 @@ BMediaRoster::SyncToNode(const media_node & node, bigtime_t timeout) { UNIMPLEMENTED(); - return B_ERROR; + return B_OK; } @@ -957,8 +991,17 @@ BMediaRoster::SetProducerRunModeDelay(const media_node & node, bigtime_t delay, BMediaNode::run_mode mode) { - UNIMPLEMENTED(); - return B_ERROR; + CALLED(); + if (IS_INVALID_NODE(node)) + return B_MEDIA_BAD_NODE; + if ((node.kind & B_BUFFER_PRODUCER) == 0) + return B_MEDIA_BAD_NODE; + + producer_set_run_mode_delay_command command; + command.mode = mode; + command.delay = delay; + + return SendToPort(node.port, PRODUCER_SET_RUN_MODE_DELAY, &command, sizeof(command)); } @@ -1513,11 +1556,12 @@ BMediaRosterEx::RegisterNode(BMediaNode * node, media_addon_id addonid, int32 fl status_t BMediaRoster::UnregisterNode(BMediaNode * node) { - printf("BMediaRoster::UnregisterNode %p\n", node); CALLED(); if (node == NULL) return B_BAD_VALUE; + TRACE("BMediaRoster::UnregisterNode %ld (%p)\n", node->ID(), node); + if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { printf("BMediaRoster::UnregisterNode, trying to unregister reference counting disabled timesource, node %ld, port %ld, team %ld\n", node->ID(), node->ControlPort(), team); return B_OK; @@ -1620,7 +1664,7 @@ BMediaRoster::SetTimeSourceFor(media_node_id node, return B_ERROR; } - printf("#### BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source); + TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source); // we just send the request to set time_source-id as timesource to the node, // the NODE_SET_TIMESOURCE handler code will do the real assignment @@ -1633,7 +1677,7 @@ BMediaRoster::SetTimeSourceFor(media_node_id node, result = B_ERROR; } - // we release the colone + // we release the clone rv = ReleaseNode(clone); if (rv != B_OK) { FATAL("BMediaRoster::SetTimeSourceFor, ReleaseNode failed, node id %ld\n", node); @@ -1649,7 +1693,9 @@ BMediaRoster::GetParameterWebFor(const media_node & node, BParameterWeb ** out_web) { UNIMPLEMENTED(); - return B_ERROR; +// return B_ERROR; + *out_web = new BParameterWeb; + return B_OK; } @@ -1758,7 +1804,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, t // it will contain (while called in media_addon_server context) the team-id of // the team that requested the instantiation. - printf("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid); + TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld\n", addonid, flavorid); // Get flavor_info from the server dormant_flavor_info node_info; @@ -1846,7 +1892,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, t *out_node = node->Node(); - printf("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld instanciated as node %ld, port %ld in team %ld\n", addonid, flavorid, out_node->node, out_node->port, team); + TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id %ld instanciated as node %ld, port %ld in team %ld\n", addonid, flavorid, out_node->node, out_node->port, team); return B_OK; } @@ -2023,12 +2069,31 @@ BMediaRoster::GetDormantFlavorInfoFor(const dormant_node_info & in_dormant, return MediaRosterEx(this)->GetDormantFlavorInfo(in_dormant.addon, in_dormant.flavor_id, out_flavor); } +// Reports in outLatency the maximum latency found downstream from +// the specified BBufferProducer, producer, given the current connections. status_t BMediaRoster::GetLatencyFor(const media_node & producer, bigtime_t * out_latency) { - UNIMPLEMENTED(); - *out_latency = 2000; + CALLED(); + if (out_latency == NULL) + return B_BAD_VALUE; + if (IS_INVALID_NODE(producer)) + return B_MEDIA_BAD_NODE; + if ((producer.kind & B_BUFFER_PRODUCER) == 0) + return B_MEDIA_BAD_NODE; + + producer_get_latency_request request; + producer_get_latency_reply reply; + status_t rv; + + rv = QueryPort(producer.port, PRODUCER_GET_LATENCY, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) + return rv; + + *out_latency = reply.latency; + + printf("BMediaRoster::GetLatencyFor producer %ld has maximum latency %Ld\n", producer.node, *out_latency); return B_OK; } @@ -2039,7 +2104,7 @@ BMediaRoster::GetInitialLatencyFor(const media_node & producer, uint32 * out_flags /* = NULL */) { UNIMPLEMENTED(); - *out_latency = 1000; + *out_latency = 5000; if (out_flags) *out_flags = 0; return B_OK;