some workarounds, fMixStartTime is now always 0,

delay mix thread if timesource has negative time,
calculate correct time and frame base for mix thread


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3663 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-06-25 16:21:41 +00:00
parent c8c8057167
commit 16cecbde36
6 changed files with 78 additions and 30 deletions
@@ -31,7 +31,7 @@ AudioMixer::AudioMixer(BMediaAddOn *addOn)
BControllable(),
BMediaEventLooper(),
fAddOn(addOn),
fCore(new MixerCore),
fCore(new MixerCore(this)),
fWeb(0),
fBufferGroup(0),
fDownstreamLatency(1),
@@ -57,6 +57,14 @@ AudioMixer::~AudioMixer()
BMediaEventLooper::Quit();
SetParameterWeb(NULL);
// stop the mixer
fCore->Lock();
fCore->Stop();
fCore->Unlock();
// disconnect all nodes from the mixer
// XXX todo
delete fCore;
delete fBufferGroup;
@@ -715,7 +723,7 @@ AudioMixer::SetTimeSource(BTimeSource * time_source)
}
void
AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, bool realTimeEvent)
AudioMixer::HandleEvent(const media_timed_event *event, bigtime_t lateness, bool realTimeEvent)
{
switch (event->type)
{
@@ -729,6 +737,7 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
case BTimedEventQueue::B_START:
{
printf("AudioMixer::HandleEvent: B_START\n");
if (RunState() != B_STARTED) {
fCore->Lock();
fCore->Start(event->event_time);
@@ -739,6 +748,7 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
case BTimedEventQueue::B_STOP:
{
printf("AudioMixer::HandleEvent: B_STOP\n");
// stopped - don't process any more buffers, flush all buffers from eventqueue
EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
fCore->Lock();
@@ -59,6 +59,8 @@ class AudioMixer :
void NodeRegistered();
void Stop(bigtime_t performance_time, bool immediate);
void SetTimeSource(BTimeSource * time_source);
using BBufferProducer::SendBuffer;
protected:
@@ -1,5 +1,6 @@
#include <RealtimeAlloc.h>
#include <MediaNode.h>
#include <BufferProducer.h>
#include <TimeSource.h>
#include <Buffer.h>
#include <BufferGroup.h>
@@ -7,6 +8,7 @@
#include "MixerInput.h"
#include "MixerOutput.h"
#include "MixerUtils.h"
#include "AudioMixer.h"
#include "Debug.h"
#define DOUBLE_RATE_MIXING 1
@@ -26,7 +28,7 @@
*/
MixerCore::MixerCore()
MixerCore::MixerCore(AudioMixer *node)
: fLocker(new BLocker),
fInputs(new BList),
fOutput(0),
@@ -38,7 +40,8 @@ MixerCore::MixerCore()
fMixBufferChannelTypes(0),
fMixBufferChannelCount(0),
fDoubleRateMixing(DOUBLE_RATE_MIXING),
fLastMixStartTime(0),
fMixStartTime(0),
fNode(node),
fBufferGroup(0),
fTimeSource(0),
fMixThread(-1),
@@ -67,7 +70,7 @@ bool
MixerCore::AddInput(const media_input &input)
{
ASSERT_LOCKED();
fInputs->AddItem(new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount, fLastMixStartTime));
fInputs->AddItem(new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount, fMixStartTime));
return true;
}
@@ -184,7 +187,7 @@ MixerCore::OutputFormatChanged(const media_multi_audio_format &format)
MixerInput *input;
for (int i = 0; (input = Input(i)); i++)
input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount, fLastMixStartTime);
input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount, fMixStartTime);
}
void
@@ -204,11 +207,13 @@ MixerCore::SetTimeSource(BTimeSource *ts)
fTimeSource->Release();
fTimeSource = dynamic_cast<BTimeSource *>(ts->Acquire());
fLastMixStartTime = fTimeSource->Now();
// fMixStartTime = fTimeSource->Now();
MixerInput *input;
for (int i = 0; (input = Input(i)); i++)
input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount, fLastMixStartTime);
printf("MixerCore::SetTimeSource, now = %Ld\n", fTimeSource->Now());
// MixerInput *input;
// for (int i = 0; (input = Input(i)); i++)
// input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount, fMixStartTime);
}
void
@@ -222,6 +227,7 @@ void
MixerCore::Start(bigtime_t time)
{
ASSERT_LOCKED();
printf("MixerCore::Start\n");
if (fRunning)
return;
@@ -235,6 +241,7 @@ void
MixerCore::Stop()
{
ASSERT_LOCKED();
printf("MixerCore::Stop\n");
if (!fRunning)
return;
@@ -277,39 +284,66 @@ void
MixerCore::MixThread()
{
bigtime_t event_time;
bigtime_t base;
bigtime_t time_base;
bigtime_t latency;
int64 pos;
int64 frame_base;
int64 frame_pos;
pos = 0;
latency = 30000;
base = event_time = fTimeSource->Now();
while (fTimeSource->Now() <= 0) {
printf("delay MixThread start, now %Ld\n", (int64)fTimeSource->Now());
snooze(1000);
}
printf("starting MixThread, now %Ld\n", (int64)fTimeSource->Now());
/* We must read from the input buffer at a position (pos) that is always a multiple of fMixBufferFrameCount.
*/
int64 temp = frames_for_duration(fMixBufferFrameRate, fTimeSource->Now() - fMixStartTime);
frame_base = ((temp / fMixBufferFrameCount) + 1) * fMixBufferFrameCount;
time_base = duration_for_frames(fMixBufferFrameRate, frame_base) + fMixStartTime;
printf("starting MixThread, now %Ld, time_base %Ld, fMixStartTime %Ld, frame_base %Ld\n", fTimeSource->Now(), time_base, fMixStartTime, frame_base);
event_time = time_base;
frame_pos = 0;
for (;;) {
status_t rv;
rv = acquire_sem_etc(fMixThreadWaitSem, 1, B_ABSOLUTE_TIMEOUT, fTimeSource->RealTimeFor(event_time, latency));
if (rv == B_INTERRUPTED)
continue;
if (rv < B_OK)
if (rv != B_TIMED_OUT && rv < B_OK)
return;
// mix all data from all inputs into the mix buffer
ASSERT((frame_base + frame_pos) % fMixBufferFrameCount == 0);
printf("create new buffer event at %Ld, reading input frames at %Ld\n", event_time, frame_base + frame_pos);
// request a buffer
BBuffer* buf = fBufferGroup->RequestBuffer(fOutput->MediaOutput().format.u.raw_audio.buffer_size, 10000);
if (buf) {
// copy data from mix buffer into output buffer
// copy data from mix buffer into output buffer
// fill in the buffer header
media_header* hdr = buf->Header();
hdr->type = B_MEDIA_RAW_AUDIO;
hdr->size_used = fOutput->MediaOutput().format.u.raw_audio.buffer_size;
hdr->time_source = fTimeSource->ID();
hdr->start_time = event_time;
// fill in the buffer header
media_header* hdr = buf->Header();
hdr->type = B_MEDIA_RAW_AUDIO;
hdr->size_used = fOutput->MediaOutput().format.u.raw_audio.buffer_size;
hdr->time_source = fTimeSource->ID();
hdr->start_time = event_time;
// send the buffer
// send the buffer
if (B_OK != fNode->SendBuffer(buf, fOutput->MediaOutput().destination)) {
printf("SendBuffer failed\n");
buf->Recycle();
}
}
// shedule next event
pos += fMixBufferFrameCount;
event_time = base + bigtime_t((1000000LL * pos) / fMixBufferFrameRate);
frame_pos += fMixBufferFrameCount;
event_time = time_base + bigtime_t((1000000LL * frame_pos) / fMixBufferFrameRate);
}
}
@@ -3,13 +3,14 @@
#include <Locker.h>
class AudioMixer;
class MixerInput;
class MixerOutput;
class MixerCore
{
public:
MixerCore();
MixerCore(AudioMixer *node);
~MixerCore();
bool AddInput(const media_input &input);
@@ -60,8 +61,9 @@ private:
int32 fMixBufferChannelCount;
int32 *fMixBufferChannelTypes; //array
bool fDoubleRateMixing;
bigtime_t fLastMixStartTime;
bigtime_t fMixStartTime;
AudioMixer *fNode;
BBufferGroup *fBufferGroup;
BTimeSource *fTimeSource;
thread_id fMixThread;
@@ -11,7 +11,7 @@
template<class t> const t & max(const t &t1, const t &t2) { return (t1 > t2) ? t1 : t2; }
MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime)
MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrameRate, int32 mixFrameCount, bigtime_t mixStartTime)
: fCore(core),
fInput(input),
fInputByteSwap(0),
@@ -60,7 +60,7 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampl
// fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels()
SetMixBufferFormat(mixSampleRate, mixFramesCount, mixStartTime);
SetMixBufferFormat(mixFrameRate, mixFrameCount, mixStartTime);
UpdateChannelDesignations();
UpdateMixerChannels();
@@ -8,7 +8,7 @@ class Resampler;
class MixerInput
{
public:
MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime);
MixerInput(MixerCore *core, const media_input &input, float mixFrameRate, int32 mixFrameCount, bigtime_t mixStartTime);
~MixerInput();
int32 ID();