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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user