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:
parent
4a87eedfcc
commit
af8d0a4d4e
@ -435,13 +435,36 @@ MixerCore::MixThread()
|
||||
|
||||
if (!LockWithTimeout(10000))
|
||||
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
|
||||
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);
|
||||
|
||||
int64 cur_framepos = frame_base + frame_pos;
|
||||
PRINT(4, "create new buffer event at %Ld, reading input frames at %Ld\n", event_time, cur_framepos);
|
||||
|
||||
MixerInput *input;
|
||||
for (int i = 0; (input = Input(i)) != 0; i++) {
|
||||
@ -451,7 +474,8 @@ MixerCore::MixThread()
|
||||
const float *base;
|
||||
uint32 sample_offset;
|
||||
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)
|
||||
continue;
|
||||
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));
|
||||
for (int chan = 0; chan < fMixBufferChannelCount; chan++) {
|
||||
@ -499,8 +524,8 @@ MixerCore::MixThread()
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
// copy data from mix buffer into output buffer
|
||||
@ -539,7 +564,8 @@ MixerCore::MixThread()
|
||||
InputChanInfos[i].MakeEmpty();
|
||||
for (int i = 0; i < fOutput->GetOutputChannelCount(); i++)
|
||||
MixChanInfos[i].MakeEmpty();
|
||||
|
||||
|
||||
schedule_next_event:
|
||||
// schedule next event
|
||||
frame_pos += fMixBufferFrameCount;
|
||||
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),
|
||||
fMixBufferFrameRate(0),
|
||||
fMixBufferFrameCount(0),
|
||||
fLastDataAvailableTime(-1),
|
||||
fResampler(0),
|
||||
fRtmPool(0),
|
||||
fUserOverridesChannelDesignations(false)
|
||||
@ -107,6 +108,8 @@ MixerInput::BufferReceived(BBuffer *buffer)
|
||||
ERROR("MixerInput::BufferReceived: buffer with negative start time of %Ld dropped\n", start);
|
||||
return;
|
||||
}
|
||||
|
||||
fLastDataAvailableTime = start + buffer_duration(fInput.format.u.raw_audio);
|
||||
|
||||
// swap the byte order of this buffer, if necessary
|
||||
if (fInputByteSwap)
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
float GetInputChannelGain(int channel);
|
||||
|
||||
// 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);
|
||||
|
||||
protected:
|
||||
@ -72,6 +72,8 @@ private:
|
||||
int32 fMixBufferFrameRate;
|
||||
uint32 fMixBufferFrameCount;
|
||||
|
||||
bigtime_t fLastDataAvailableTime;
|
||||
|
||||
Resampler **fResampler; // array
|
||||
rtm_pool *fRtmPool;
|
||||
|
||||
@ -80,17 +82,21 @@ private:
|
||||
int32 debugMixBufferFrames;
|
||||
};
|
||||
|
||||
inline void
|
||||
MixerInput::GetMixerChannelInfo(int channel, int64 framepos, const float **buffer, uint32 *sample_offset, int *type, float *gain)
|
||||
inline bool
|
||||
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(channel >= 0 && channel < fMixerChannelCount);
|
||||
if (time > fLastDataAvailableTime)
|
||||
return false;
|
||||
|
||||
int32 offset = framepos % fMixBufferFrameCount;
|
||||
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));
|
||||
*sample_offset = sizeof(float) * fInputChannelCount;
|
||||
*type = fMixerChannelInfo[channel].type;
|
||||
*gain = fMixerChannelInfo[channel].gain;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int
|
||||
|
@ -114,7 +114,7 @@ fix_multiaudio_format(media_multi_audio_format *format)
|
||||
&& int(format->frame_rate + 0.5) == 11025
|
||||
&& format->byte_order == B_MEDIA_BIG_ENDIAN
|
||||
&& 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;
|
||||
}
|
||||
}
|
||||
|
@ -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 fix_multiaudio_format(media_multi_audio_format *format);
|
||||
|
||||
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);
|
||||
|
||||
bool HasKawamba();
|
||||
@ -27,3 +33,5 @@ uint32 ChannelTypeToChannelMask(int type);
|
||||
|
||||
double us_to_s(bigtime_t usecs);
|
||||
bigtime_t s_to_us(double secs);
|
||||
|
||||
#endif //_MIXER_UTILS_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user