Account for thread pauses for audio data

- In the audio I/O code, if there's a pause in the program or its
   threads (especially the audio thread), it'll cause it to sample too
   much data, and increase line->base_timestamp to a potentially higher
   value than the next audio timestamp that may be added to the line.
   This would cause it to crash originally, because it expects audio
   data that is within the designated buffering limit.

   Because that audio data cannot be filled by that data anyway, just
   ignore the audio data until it goes back to the right timing (which
   it will as long as the code that is using the line accounts for its
   current system time)
master
jp9000 2014-01-10 19:03:21 -07:00
parent 2a89306420
commit 4aa4858ac7
1 changed files with 21 additions and 5 deletions

View File

@ -403,7 +403,7 @@ static inline void mul_vol_float(struct audio_line *line, float volume,
vals[i] *= volume; vals[i] *= volume;
} }
static void audio_line_place_data(struct audio_line *line, static void audio_line_place_data_pos(struct audio_line *line,
const struct audio_data *data, size_t position) const struct audio_data *data, size_t position)
{ {
size_t total_num = data->frames * line->audio->channels; size_t total_num = data->frames * line->audio->channels;
@ -432,6 +432,15 @@ static void audio_line_place_data(struct audio_line *line,
total_size); total_size);
} }
static inline void audio_line_place_data(struct audio_line *line,
const struct audio_data *data)
{
uint64_t time_offset = data->timestamp - line->base_timestamp;
size_t pos = convert_to_sample_offset(line->audio, time_offset);
audio_line_place_data_pos(line, data, pos);
}
void audio_line_output(audio_line_t line, const struct audio_data *data) void audio_line_output(audio_line_t line, const struct audio_data *data)
{ {
/* TODO: prevent insertation of data too far away from expected /* TODO: prevent insertation of data too far away from expected
@ -442,12 +451,19 @@ void audio_line_output(audio_line_t line, const struct audio_data *data)
if (!line->buffer.size) { if (!line->buffer.size) {
line->base_timestamp = data->timestamp; line->base_timestamp = data->timestamp;
audio_line_place_data(line, data, 0); audio_line_place_data_pos(line, data, 0);
} else { } else {
uint64_t time_offset = data->timestamp - line->base_timestamp;
size_t pos = convert_to_sample_offset(line->audio, time_offset);
audio_line_place_data(line, data, pos); if (line->base_timestamp <= data->timestamp)
audio_line_place_data(line, data);
else
blog(LOG_DEBUG, "Bad timestamp for audio line '%s', "
"data->timestamp: %llu, "
"line->base_timestamp: %llu. "
"This can sometimes happen when "
"there's a pause in the threads.",
line->name, data->timestamp,
line->base_timestamp);
} }
pthread_mutex_unlock(&line->mutex); pthread_mutex_unlock(&line->mutex);