I fixed a timing bug. The mixer was accidentally sending itself
a notification about downstream latency change, when it really should have send that to the connected inputs. This is now done by the PublishEventLatencyChange() function. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4567 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -22,7 +22,7 @@
|
|||||||
#include "MixerUtils.h"
|
#include "MixerUtils.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#define VERSION_STRING "0.1 alpha 2"
|
#define VERSION_STRING "0.1 alpha 3"
|
||||||
#define BUILD_STRING __DATE__ " " __TIME__
|
#define BUILD_STRING __DATE__ " " __TIME__
|
||||||
|
|
||||||
// the range of the gain sliders (in dB)
|
// the range of the gain sliders (in dB)
|
||||||
@@ -313,7 +313,7 @@ AudioMixer::GetLatencyFor(const media_destination &for_whom,
|
|||||||
*out_latency = EventLatency();
|
*out_latency = EventLatency();
|
||||||
*out_timesource = TimeSource()->ID();
|
*out_timesource = TimeSource()->ID();
|
||||||
|
|
||||||
//printf("AudioMixer::GetLatencyFor %Ld, timesource is %ld\n", *out_latency, *out_timesource);
|
printf("AudioMixer::GetLatencyFor %Ld, timesource is %ld\n", *out_latency, *out_timesource);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
@@ -509,13 +509,15 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin
|
|||||||
TRACE("AudioMixer: buffer duration is %Ld usecs\n", BufferDuration());
|
TRACE("AudioMixer: buffer duration is %Ld usecs\n", BufferDuration());
|
||||||
|
|
||||||
// Our internal latency is at least the length of a full output buffer
|
// Our internal latency is at least the length of a full output buffer
|
||||||
fInternalLatency = BufferDuration() + min(4500LL, bigtime_t(0.5 * BufferDuration()));
|
fInternalLatency = BufferDuration() + max(4500LL, bigtime_t(0.5 * BufferDuration()));
|
||||||
TRACE("AudioMixer: Internal latency is %Ld usecs\n", fInternalLatency);
|
TRACE("AudioMixer: Internal latency is %Ld usecs\n", fInternalLatency);
|
||||||
|
|
||||||
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
||||||
|
|
||||||
TRACE("AudioMixer: SendLatencyChange %Ld\n", EventLatency());
|
// we need to inform all connected *inputs* about *our* change in latency
|
||||||
SendLatencyChange(source, destination, EventLatency());
|
PublishEventLatencyChange();
|
||||||
|
|
||||||
|
// XXX we might need to create more buffers, to span a larger downstream latency
|
||||||
|
|
||||||
// apply latency change
|
// apply latency change
|
||||||
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
|
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
|
||||||
@@ -605,23 +607,31 @@ void
|
|||||||
AudioMixer::LatencyChanged(const media_source & source, const media_destination & destination,
|
AudioMixer::LatencyChanged(const media_source & source, const media_destination & destination,
|
||||||
bigtime_t new_latency, uint32 flags)
|
bigtime_t new_latency, uint32 flags)
|
||||||
{
|
{
|
||||||
TRACE("AudioMixer::LatencyChanged: downstream latency changed from %Ld to %Ld\n", fDownstreamLatency, new_latency);
|
if (source.port != ControlPort() || source.id != 0) {
|
||||||
|
ERROR("AudioMixer::LatencyChanged: received but has wrong source %ld/%ld\n", source.port, source.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("AudioMixer::LatencyChanged: downstream latency from %ld/%ld to %ld/%ld changed from %Ld to %Ld\n",
|
||||||
|
source.port, source.id, destination.port, destination.id, fDownstreamLatency, new_latency);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
{
|
||||||
|
media_node_id id;
|
||||||
|
bigtime_t l;
|
||||||
|
FindLatencyFor(destination, &l, &id);
|
||||||
|
TRACE("AudioMixer: Reported downstream Latency is %Ld usecs\n", l);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fDownstreamLatency = new_latency;
|
fDownstreamLatency = new_latency;
|
||||||
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
||||||
|
|
||||||
|
// XXX we might need to create more buffers, to span a larger downstream latency
|
||||||
|
|
||||||
fCore->Lock();
|
fCore->Lock();
|
||||||
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
|
fCore->SetTimingInfo(TimeSource(), fDownstreamLatency);
|
||||||
|
PublishEventLatencyChange();
|
||||||
MixerInput *input;
|
|
||||||
for (int i = 0; (input = fCore->Input(i)) != 0; i++) {
|
|
||||||
TRACE("AudioMixer: SendLatencyChange from %ld/%ld to %ld/%ld event latency is now %Ld\n",
|
|
||||||
input->MediaInput().source.port, input->MediaInput().source.id,
|
|
||||||
input->MediaInput().destination.port, input->MediaInput().destination.id,
|
|
||||||
EventLatency());
|
|
||||||
SendLatencyChange(input->MediaInput().source, input->MediaInput().destination, EventLatency());
|
|
||||||
}
|
|
||||||
|
|
||||||
fCore->Unlock();
|
fCore->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,13 +782,13 @@ AudioMixer::Connect(status_t error, const media_source &source, const media_dest
|
|||||||
TRACE("AudioMixer: buffer duration is %Ld usecs\n", BufferDuration());
|
TRACE("AudioMixer: buffer duration is %Ld usecs\n", BufferDuration());
|
||||||
|
|
||||||
// Our internal latency is at least the length of a full output buffer
|
// Our internal latency is at least the length of a full output buffer
|
||||||
fInternalLatency = BufferDuration() + min(4500LL, bigtime_t(0.5 * BufferDuration()));
|
fInternalLatency = BufferDuration() + max(4500LL, bigtime_t(0.5 * BufferDuration()));
|
||||||
TRACE("AudioMixer: Internal latency is %Ld usecs\n", fInternalLatency);
|
TRACE("AudioMixer: Internal latency is %Ld usecs\n", fInternalLatency);
|
||||||
|
|
||||||
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
||||||
|
|
||||||
TRACE("AudioMixer: SendLatencyChange %Ld\n", EventLatency());
|
// we need to inform all connected *inputs* about *our* change in latency
|
||||||
SendLatencyChange(source, dest, EventLatency());
|
PublishEventLatencyChange();
|
||||||
|
|
||||||
// Set up the buffer group for our connection, as long as nobody handed us a
|
// Set up the buffer group for our connection, as long as nobody handed us a
|
||||||
// buffer group (via SetBufferGroup()) prior to this. That can happen, for example,
|
// buffer group (via SetBufferGroup()) prior to this. That can happen, for example,
|
||||||
@@ -868,9 +878,8 @@ AudioMixer::LateNoticeReceived(const media_source &what, bigtime_t how_much, big
|
|||||||
|
|
||||||
printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
|
printf("AudioMixer: increasing internal latency to %Ld usec\n", fInternalLatency);
|
||||||
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
SetEventLatency(fDownstreamLatency + fInternalLatency);
|
||||||
|
|
||||||
// printf("AudioMixer: SendLatencyChange %Ld (2)\n", EventLatency());
|
PublishEventLatencyChange();
|
||||||
// SendLatencyChange(source, dest, EventLatency());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@@ -962,6 +971,28 @@ AudioMixer::HandleEvent(const media_timed_event *event, bigtime_t lateness, bool
|
|||||||
// AudioMixer methods
|
// AudioMixer methods
|
||||||
//
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioMixer::PublishEventLatencyChange()
|
||||||
|
{
|
||||||
|
// our event (processing + downstream) latency has changed,
|
||||||
|
// and we need tell all inputs about this
|
||||||
|
|
||||||
|
TRACE("AudioMixer::PublishEventLatencyChange\n");
|
||||||
|
|
||||||
|
fCore->Lock();
|
||||||
|
|
||||||
|
MixerInput *input;
|
||||||
|
for (int i = 0; (input = fCore->Input(i)) != 0; i++) {
|
||||||
|
TRACE("AudioMixer::PublishEventLatencyChange: SendLatencyChange, connection %ld/%ld to %ld/%ld event latency is now %Ld\n",
|
||||||
|
input->MediaInput().source.port, input->MediaInput().source.id,
|
||||||
|
input->MediaInput().destination.port, input->MediaInput().destination.id,
|
||||||
|
EventLatency());
|
||||||
|
SendLatencyChange(input->MediaInput().source, input->MediaInput().destination, EventLatency());
|
||||||
|
}
|
||||||
|
|
||||||
|
fCore->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
BBufferGroup *
|
BBufferGroup *
|
||||||
AudioMixer::CreateBufferGroup()
|
AudioMixer::CreateBufferGroup()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class AudioMixer :
|
|||||||
|
|
||||||
void ApplySettings();
|
void ApplySettings();
|
||||||
|
|
||||||
|
void PublishEventLatencyChange();
|
||||||
void UpdateParameterWeb();
|
void UpdateParameterWeb();
|
||||||
|
|
||||||
void HandleInputBuffer(BBuffer *buffer, bigtime_t lateness);
|
void HandleInputBuffer(BBuffer *buffer, bigtime_t lateness);
|
||||||
|
|||||||
@@ -418,12 +418,10 @@ MixerCore::MixThread()
|
|||||||
|
|
||||||
if (!LockFromMixThread())
|
if (!LockFromMixThread())
|
||||||
return;
|
return;
|
||||||
latency = min(3600LL, bigtime_t(0.4 * buffer_duration(fOutput->MediaOutput().format.u.raw_audio)));
|
latency = max(3600LL, bigtime_t(0.4 * buffer_duration(fOutput->MediaOutput().format.u.raw_audio)));
|
||||||
// XXX we might need to add scheduling latency
|
|
||||||
// latency += 0.4 * buffer_duration(fOutput->MediaOutput().format.u.raw_audio);
|
|
||||||
|
|
||||||
// XXX when the format changes while running, everything is wrong!
|
// XXX when the format changes while running, everything is wrong!
|
||||||
buffer_request_timeout = (3 * buffer_duration(fOutput->MediaOutput().format.u.raw_audio)) / 4;
|
buffer_request_timeout = buffer_duration(fOutput->MediaOutput().format.u.raw_audio) / 2;
|
||||||
|
|
||||||
TRACE("MixerCore: starting MixThread at %Ld with latency %Ld and downstream latency %Ld, buffer_request_timeout %Ld\n", start, latency, fDownstreamLatency, buffer_request_timeout);
|
TRACE("MixerCore: starting MixThread at %Ld with latency %Ld and downstream latency %Ld, buffer_request_timeout %Ld\n", start, latency, fDownstreamLatency, buffer_request_timeout);
|
||||||
|
|
||||||
@@ -459,9 +457,11 @@ MixerCore::MixThread()
|
|||||||
continue;
|
continue;
|
||||||
if (rv != B_TIMED_OUT && rv < B_OK)
|
if (rv != B_TIMED_OUT && rv < B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!LockWithTimeout(10000))
|
if (!LockWithTimeout(10000)) {
|
||||||
|
ERROR("MixerCore: LockWithTimeout failed\n");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// no inputs or output muted, skip further processing and just send an empty buffer
|
// no inputs or output muted, skip further processing and just send an empty buffer
|
||||||
if (fInputs->IsEmpty() || fOutput->IsMuted()) {
|
if (fInputs->IsEmpty() || fOutput->IsMuted()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user