Fixed the input buffer looping bug that existed if an input wouldn't receive new buffers. Now kips inputs that have no available data.

When no input is connected, use a fast path for sending an empty buffer.
No more debugging output when DEUBG < 1


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3763 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-06-30 15:45:37 +00:00
parent 4a87eedfcc
commit af8d0a4d4e
5 changed files with 58 additions and 15 deletions
@@ -435,13 +435,36 @@ MixerCore::MixThread()
if (!LockWithTimeout(10000)) if (!LockWithTimeout(10000))
continue; continue;
// no inputs, skip further processing and just send an empty buffer
if (fInputs->IsEmpty()) {
int size = fOutput->MediaOutput().format.u.raw_audio.buffer_size;
BBuffer* buf = fBufferGroup->RequestBuffer(size, 5000);
if (buf) {
memset(buf->Data(), 0, size);
// fill in the buffer header
media_header* hdr = buf->Header();
hdr->type = B_MEDIA_RAW_AUDIO;
hdr->size_used = size;
hdr->time_source = fTimeSource->ID();
hdr->start_time = event_time;
if (B_OK != fNode->SendBuffer(buf, fOutput->MediaOutput().destination)) {
ERROR("MixerCore: SendBuffer failed\n");
buf->Recycle();
}
} else {
ERROR("MixerCore: RequestBuffer failed\n");
}
goto schedule_next_event;
}
int64 cur_framepos;
cur_framepos = frame_base + frame_pos;
// mix all data from all inputs into the mix buffer // mix all data from all inputs into the mix buffer
ASSERT((frame_base + frame_pos) % fMixBufferFrameCount == 0); ASSERT(cur_framepos % fMixBufferFrameCount == 0);
PRINT(4, "create new buffer event at %Ld, reading input frames at %Ld\n", event_time, frame_base + frame_pos); PRINT(4, "create new buffer event at %Ld, reading input frames at %Ld\n", event_time, cur_framepos);
int64 cur_framepos = frame_base + frame_pos;
MixerInput *input; MixerInput *input;
for (int i = 0; (input = Input(i)) != 0; i++) { for (int i = 0; (input = Input(i)) != 0; i++) {
@@ -451,7 +474,8 @@ MixerCore::MixThread()
const float *base; const float *base;
uint32 sample_offset; uint32 sample_offset;
float gain; float gain;
input->GetMixerChannelInfo(chan, cur_framepos, &base, &sample_offset, &type, &gain); if (!input->GetMixerChannelInfo(chan, cur_framepos, event_time, &base, &sample_offset, &type, &gain))
continue;
if (type < 0 || type >= MAX_TYPES) if (type < 0 || type >= MAX_TYPES)
continue; continue;
chan_info *info = InputChanInfos[type].Create(); chan_info *info = InputChanInfos[type].Create();
@@ -480,7 +504,8 @@ MixerCore::MixThread()
} }
} }
uint32 dst_sample_offset = fMixBufferChannelCount * sizeof(float); uint32 dst_sample_offset;
dst_sample_offset = fMixBufferChannelCount * sizeof(float);
memset(fMixBuffer, 0, fMixBufferChannelCount * fMixBufferFrameCount * sizeof(float)); memset(fMixBuffer, 0, fMixBufferChannelCount * fMixBufferFrameCount * sizeof(float));
for (int chan = 0; chan < fMixBufferChannelCount; chan++) { for (int chan = 0; chan < fMixBufferChannelCount; chan++) {
@@ -499,8 +524,8 @@ MixerCore::MixThread()
} }
// request a buffer // request a buffer
BBuffer* buf = fBufferGroup->RequestBuffer(fOutput->MediaOutput().format.u.raw_audio.buffer_size, 5000); BBuffer *buf;
buf = fBufferGroup->RequestBuffer(fOutput->MediaOutput().format.u.raw_audio.buffer_size, 5000);
if (buf) { if (buf) {
// copy data from mix buffer into output buffer // copy data from mix buffer into output buffer
@@ -539,7 +564,8 @@ MixerCore::MixThread()
InputChanInfos[i].MakeEmpty(); InputChanInfos[i].MakeEmpty();
for (int i = 0; i < fOutput->GetOutputChannelCount(); i++) for (int i = 0; i < fOutput->GetOutputChannelCount(); i++)
MixChanInfos[i].MakeEmpty(); MixChanInfos[i].MakeEmpty();
schedule_next_event:
// schedule next event // schedule next event
frame_pos += fMixBufferFrameCount; frame_pos += fMixBufferFrameCount;
event_time = time_base + bigtime_t((1000000LL * frame_pos) / fMixBufferFrameRate); event_time = time_base + bigtime_t((1000000LL * frame_pos) / fMixBufferFrameRate);
@@ -24,6 +24,7 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame
fMixBuffer(0), fMixBuffer(0),
fMixBufferFrameRate(0), fMixBufferFrameRate(0),
fMixBufferFrameCount(0), fMixBufferFrameCount(0),
fLastDataAvailableTime(-1),
fResampler(0), fResampler(0),
fRtmPool(0), fRtmPool(0),
fUserOverridesChannelDesignations(false) fUserOverridesChannelDesignations(false)
@@ -107,6 +108,8 @@ MixerInput::BufferReceived(BBuffer *buffer)
ERROR("MixerInput::BufferReceived: buffer with negative start time of %Ld dropped\n", start); ERROR("MixerInput::BufferReceived: buffer with negative start time of %Ld dropped\n", start);
return; return;
} }
fLastDataAvailableTime = start + buffer_duration(fInput.format.u.raw_audio);
// swap the byte order of this buffer, if necessary // swap the byte order of this buffer, if necessary
if (fInputByteSwap) if (fInputByteSwap)
@@ -32,7 +32,7 @@ public:
float GetInputChannelGain(int channel); float GetInputChannelGain(int channel);
// only for use by MixerCore // only for use by MixerCore
void GetMixerChannelInfo(int channel, int64 framepos, const float **buffer, uint32 *sample_offset, int *type, float *gain); bool GetMixerChannelInfo(int channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain);
int GetMixerChannelType(int channel); int GetMixerChannelType(int channel);
protected: protected:
@@ -72,6 +72,8 @@ private:
int32 fMixBufferFrameRate; int32 fMixBufferFrameRate;
uint32 fMixBufferFrameCount; uint32 fMixBufferFrameCount;
bigtime_t fLastDataAvailableTime;
Resampler **fResampler; // array Resampler **fResampler; // array
rtm_pool *fRtmPool; rtm_pool *fRtmPool;
@@ -80,17 +82,21 @@ private:
int32 debugMixBufferFrames; int32 debugMixBufferFrames;
}; };
inline void inline bool
MixerInput::GetMixerChannelInfo(int channel, int64 framepos, const float **buffer, uint32 *sample_offset, int *type, float *gain) MixerInput::GetMixerChannelInfo(int channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain)
{ {
ASSERT(fMixBuffer); // this function should not be called if we don't have a mix buffer! ASSERT(fMixBuffer); // this function should not be called if we don't have a mix buffer!
ASSERT(channel >= 0 && channel < fMixerChannelCount); ASSERT(channel >= 0 && channel < fMixerChannelCount);
if (time > fLastDataAvailableTime)
return false;
int32 offset = framepos % fMixBufferFrameCount; int32 offset = framepos % fMixBufferFrameCount;
if (channel == 0) PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset, offset + debugMixBufferFrames - 1); if (channel == 0) PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset, offset + debugMixBufferFrames - 1);
*buffer = reinterpret_cast<float *>(reinterpret_cast<char *>(fMixerChannelInfo[channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount)); *buffer = reinterpret_cast<float *>(reinterpret_cast<char *>(fMixerChannelInfo[channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount));
*sample_offset = sizeof(float) * fInputChannelCount; *sample_offset = sizeof(float) * fInputChannelCount;
*type = fMixerChannelInfo[channel].type; *type = fMixerChannelInfo[channel].type;
*gain = fMixerChannelInfo[channel].gain; *gain = fMixerChannelInfo[channel].gain;
return true;
} }
inline int inline int
@@ -114,7 +114,7 @@ fix_multiaudio_format(media_multi_audio_format *format)
&& int(format->frame_rate + 0.5) == 11025 && int(format->frame_rate + 0.5) == 11025
&& format->byte_order == B_MEDIA_BIG_ENDIAN && format->byte_order == B_MEDIA_BIG_ENDIAN
&& format->buffer_size == 548) { && format->buffer_size == 548) {
printf("### quicktime extractor bug workaround activated, changing buffer size from 548 into 4096\n"); ERROR("Mixer: quicktime extractor bug workaround activated, changing buffer size from 548 into 4096\n");
format->buffer_size = 4096; format->buffer_size = 4096;
} }
} }
@@ -1,11 +1,17 @@
#ifndef _MIXER_UTILS_H
#define _MIXER_UTILS_H
#if DEBUG > 0
#define PRINT_CHANNEL_MASK(fmt) do { char s[200]; string_for_channel_mask(s, (fmt).u.raw_audio.channel_mask); printf(" channel_mask 0x%08X %s\n", (fmt).u.raw_audio.channel_mask, s); } while (0)
#else
#define PRINT_CHANNEL_MASK(fmt) ((void)0)
#endif
void string_for_channel_mask(char *str, uint32 mask); void string_for_channel_mask(char *str, uint32 mask);
void fix_multiaudio_format(media_multi_audio_format *format); void fix_multiaudio_format(media_multi_audio_format *format);
int count_nonzero_bits(uint32 value); int count_nonzero_bits(uint32 value);
#define PRINT_CHANNEL_MASK(fmt) do { char s[200]; string_for_channel_mask(s, (fmt).u.raw_audio.channel_mask); printf(" channel_mask 0x%08X %s\n", (fmt).u.raw_audio.channel_mask, s); } while (0)
uint32 GetChannelMask(int channel, uint32 all_channel_masks); uint32 GetChannelMask(int channel, uint32 all_channel_masks);
bool HasKawamba(); bool HasKawamba();
@@ -27,3 +33,5 @@ uint32 ChannelTypeToChannelMask(int type);
double us_to_s(bigtime_t usecs); double us_to_s(bigtime_t usecs);
bigtime_t s_to_us(double secs); bigtime_t s_to_us(double secs);
#endif //_MIXER_UTILS_H