a couple of fixes regarding latency calculation

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2996 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper 2003-03-23 01:08:27 +00:00
parent 5c080a95ca
commit 60f15390cd
4 changed files with 152 additions and 42 deletions

View File

@ -4,6 +4,7 @@
* DESCR:
***********************************************************************/
#include <BufferProducer.h>
#include <BufferConsumer.h>
#include <BufferGroup.h>
#include <Buffer.h>
#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<BBufferConsumer *>(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<const producer_set_run_mode_delay_command *>(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<const producer_video_clipping_changed_command *>(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));
}

View File

@ -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;
}
/*************************************************************

View File

@ -570,6 +570,7 @@ BMediaNode::HandleMessage(int32 message,
case NODE_SET_RUN_MODE:
{
const node_set_run_mode_command *command = static_cast<const node_set_run_mode_command *>(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);
}

View File

@ -11,6 +11,7 @@
#include <OS.h>
#include <String.h>
#include <TimeSource.h>
#include <ParameterWeb.h>
#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;