From 373eada6ff187bf59e33c2d3b8e33c2ca1581f30 Mon Sep 17 00:00:00 2001
From: Lawrence Rust <lvr@softsystem.co.uk>
Date: Fri, 3 Jun 2011 15:08:57 +0200
Subject: [PATCH 42/42] RingBuffer: CalcReadAheadThresh mods for low bit rate (radio) streams
The existing readahead block size is too large for 64/128 kBps audio streams
and can cause audio underruns.
Make WaitFailAvail return the bytes available if less than that requested
for low bit rate streams (where fill_min is < 32kB).
Signed-off-by: Lawrence Rust <lvr@softsystem.co.uk>
---
mythtv/libs/libmythtv/RingBuffer.cpp | 54 ++++++++++++++++++++++-----------
1 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/mythtv/libs/libmythtv/RingBuffer.cpp b/mythtv/libs/libmythtv/RingBuffer.cpp
index 95fb96b..eda425a 100644
a
|
b
|
void RingBuffer::OpenFile(const QString &lfilename, uint retry_ms) |
540 | 540 | commserror = false; |
541 | 541 | numfailures = 0; |
542 | 542 | |
543 | | rawbitrate = 8000; |
| 543 | rawbitrate = 2500; |
544 | 544 | CalcReadAheadThresh(); |
545 | 545 | |
546 | 546 | rwlock.unlock(); |
… |
… |
void RingBuffer::CalcReadAheadThresh(void) |
806 | 806 | // loop without sleeping if the buffered data is less than this |
807 | 807 | fill_threshold = kBufferSize / 8; |
808 | 808 | |
809 | | const uint KB32 = 32*1024; |
810 | | const uint KB64 = 64*1024; |
811 | | const uint KB128 = 128*1024; |
812 | | const uint KB256 = 256*1024; |
813 | | const uint KB512 = 512*1024; |
| 809 | const int KB1 = 1024; |
| 810 | const int KB2 = 2*1024; |
| 811 | const int KB4 = 4*1024; |
| 812 | const int KB8 = 8*1024; |
| 813 | const int KB16 = 16*1024; |
| 814 | const int KB32 = 32*KB1; |
| 815 | const int KB64 = 64*KB1; |
| 816 | const int KB128 = 128*KB1; |
| 817 | const int KB256 = 256*KB1; |
| 818 | const int KB512 = 512*KB1; |
814 | 819 | |
815 | 820 | estbitrate = (uint) max(abs(rawbitrate * playspeed), |
816 | 821 | 0.5f * rawbitrate); |
817 | 822 | estbitrate = min(rawbitrate * 3, estbitrate); |
818 | | int rbs = (estbitrate > 2500) ? KB64 : KB32; |
819 | | rbs = (estbitrate > 5000) ? KB128 : rbs; |
820 | | rbs = (estbitrate > 9000) ? KB256 : rbs; |
821 | | rbs = (estbitrate > 18000) ? KB512 : rbs; |
822 | | readblocksize = max(rbs,readblocksize); |
| 823 | |
| 824 | int const rbs = estbitrate > 18000 ? KB512 : |
| 825 | estbitrate > 9000 ? KB256 : |
| 826 | estbitrate > 5000 ? KB128 : |
| 827 | estbitrate > 2500 ? KB64 : |
| 828 | estbitrate > 1000 ? KB32 : |
| 829 | estbitrate > 500 ? KB16 : |
| 830 | estbitrate > 250 ? KB8 : |
| 831 | estbitrate > 125 ? KB4 : |
| 832 | KB2; |
| 833 | if (rbs < CHUNK) |
| 834 | readblocksize = rbs; |
| 835 | else |
| 836 | readblocksize = max(rbs,readblocksize); |
823 | 837 | |
824 | 838 | // minumum seconds of buffering before allowing read |
825 | | float secs_min = 0.25; |
| 839 | float const secs_min = 0.25f; |
826 | 840 | // set the minimum buffering before allowing ffmpeg read |
827 | | fill_min = (uint) ((estbitrate * secs_min) * 0.125f); |
| 841 | fill_min = (uint) (estbitrate * ((KB1 / 8) * secs_min)); |
828 | 842 | // make this a multiple of ffmpeg block size.. |
829 | | fill_min = ((fill_min / KB32) + 1) * KB32; |
| 843 | if (fill_min > CHUNK) |
| 844 | fill_min = (fill_min / CHUNK) * CHUNK; |
830 | 845 | |
831 | 846 | VERBOSE(VB_FILE, LOC + |
832 | 847 | QString("CalcReadAheadThresh(%1 Kb)\n\t\t\t -> " |
833 | 848 | "threshhold(%2 KB) min read(%3 KB) blk size(%4 KB)") |
834 | | .arg(estbitrate).arg(fill_threshold/1024) |
835 | | .arg(fill_min/1024).arg(readblocksize/1024)); |
| 849 | .arg(estbitrate).arg(fill_threshold/KB1) |
| 850 | .arg(fill_min/KB1).arg(readblocksize/KB1)); |
836 | 851 | } |
837 | 852 | |
838 | 853 | bool RingBuffer::IsNearEnd(double fps, uint vvf) const |
… |
… |
void RingBuffer::run(void) |
1182 | 1197 | (now.tv_usec - lastread.tv_usec) / 1000; |
1183 | 1198 | readtimeavg = (readtimeavg * 9 + readinterval) / 10; |
1184 | 1199 | |
1185 | | if (readtimeavg < 150 && (uint)readblocksize < (kBufferSize>>2)) |
| 1200 | if (readtimeavg < 150 && (uint)readblocksize < (kBufferSize>>2) && readblocksize >= CHUNK) |
1186 | 1201 | { |
1187 | 1202 | int old_block_size = readblocksize; |
1188 | 1203 | readblocksize = 3 * readblocksize / 2; |
… |
… |
bool RingBuffer::WaitForAvail(int count) |
1431 | 1446 | if (avail < count) |
1432 | 1447 | { |
1433 | 1448 | int elapsed = t.elapsed(); |
1434 | | if (((elapsed > 250) && (elapsed < 500)) || |
| 1449 | // Return avail for low bitrate audio streams to avoid underrun |
| 1450 | if (elapsed >= 500 && fill_min < CHUNK && avail >= fill_min) |
| 1451 | count = avail; |
| 1452 | else if (((elapsed > 250) && (elapsed < 500)) || |
1435 | 1453 | ((elapsed > 500) && (elapsed < 750)) || |
1436 | 1454 | ((elapsed > 1000) && (elapsed < 1250)) || |
1437 | 1455 | ((elapsed > 2000) && (elapsed < 2250)) || |