Skip to content

Commit

Permalink
Fix potential deadlocks resulting in "Waited 100ms for video buffers"
Browse files Browse the repository at this point in the history
[backport to fixes/0.24]

When we are waiting for video the video buffers to fill up, if the audio buffer is almost full, reset it.
Collaborative effort between tralph@mythtv.org mkendall@mythtv.org and jyavenard@mythtv.org
  • Loading branch information
jyavenard committed Dec 14, 2010
1 parent 208e2f5 commit 588cc6e
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 31 deletions.
11 changes: 11 additions & 0 deletions mythtv/libs/libmythtv/audioplayer.cpp
Expand Up @@ -351,3 +351,14 @@ bool AudioPlayer::GetBufferStatus(uint &fill, uint &total)
m_audioOutput->GetBufferStatus(fill, total);
return true;
}

bool AudioPlayer::IsBufferAlmostFull(void)
{
uint ofill = 0, ototal = 0, othresh = 0;
if (GetBufferStatus(ofill, ototal))
{
othresh = ((ototal>>1) + (ototal>>2));
return ofill > othresh;
}
return false;
}
1 change: 1 addition & 0 deletions mythtv/libs/libmythtv/audioplayer.h
Expand Up @@ -53,6 +53,7 @@ class MPUBLIC AudioPlayer

void AddAudioData(char *buffer, int len, int64_t timecode);
bool GetBufferStatus(uint &fill, uint &total);
bool IsBufferAlmostFull(void);

private:
MythPlayer *m_parent;
Expand Down
34 changes: 3 additions & 31 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -3929,11 +3929,8 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
avcodeclock->unlock();

uint ofill = 0, ototal = 0, othresh = 0, total_decoded_audio = 0;
if (m_audio->GetBufferStatus(ofill, ototal))
{
othresh = ((ototal>>1) + (ototal>>2));
allowedquit = (!(decodetype & kDecodeAudio)) && (ofill > othresh);
}
allowedquit = (!(decodetype & kDecodeAudio)) &&
m_audio->IsBufferAlmostFull();

if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000);
Expand Down Expand Up @@ -4098,26 +4095,6 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
total_decoded_audio += data_size;

allowedquit |= ringBuffer->InDVDMenuOrStillFrame();
// Audio can expand by a factor of 6 in audiooutputbase's audiobuffer
allowedquit |= !(decodetype & kDecodeVideo) &&
((ofill + total_decoded_audio * 6) > othresh);

// top off audio buffers initially in audio only mode
if (!allowedquit && !(decodetype & kDecodeVideo))
{
uint fill, total;
if (m_audio->GetBufferStatus(fill, total))
{
total /= 6; // Possible expansion in aobase (upmix, float conv)
allowedquit = fill == 0 || fill > total>>1 ||
total - fill < (uint)(data_size) ||
ofill + total_decoded_audio > total>>2 ||
total - fill < (uint)(data_size<<1);
}
else
VERBOSE(VB_IMPORTANT, LOC_ERR + "GetFrame() : Failed to top off "
"buffers in audio only mode");
}

tmp_pkt.data += ret;
tmp_pkt.size -= ret;
Expand Down Expand Up @@ -4156,12 +4133,7 @@ bool AvFormatDecoder::GetFrame(DecodeType decodetype)
skipaudio = false;
}

uint ofill = 0, ototal = 0, othresh = 0;
if (m_audio->GetBufferStatus(ofill, ototal))
{
othresh = ((ototal>>1) + (ototal>>2));
allowedquit = ofill > othresh;
}
allowedquit = m_audio->IsBufferAlmostFull();

if (private_dec && private_dec->HasBufferedFrames() &&
(selectedTrack[kTrackTypeVideo].av_stream_index > -1))
Expand Down
8 changes: 8 additions & 0 deletions mythtv/libs/libmythtv/mythplayer.cpp
Expand Up @@ -1920,6 +1920,14 @@ bool MythPlayer::PrebufferEnoughFrames(bool pause_audio, int min_buffers)
VERBOSE(VB_IMPORTANT, LOC +
QString("Waited 100ms for video buffers %1")
.arg(videoOutput->GetFrameStatus()));
if (audio.IsBufferAlmostFull())
{
// We are likely to enter this condition
// if the audio buffer was too full during GetFrame in AVFD
VERBOSE(VB_AUDIO, LOC +
QString("Resetting audio buffer"));
audio.Reset();
}
}
if ((waited_for > 500) && !videoOutput->EnoughFreeFrames())
{
Expand Down

0 comments on commit 588cc6e

Please sign in to comment.