|
|
|
@ -182,6 +182,7 @@ void StreamPlayerWindow::decode() { |
|
|
|
bool waitKey = true, opened = false; |
|
|
|
bool waitKey = true, opened = false; |
|
|
|
int64_t deadline = nowUs() + 10000000, reportAt = nowUs(), expectedAudio = -1; |
|
|
|
int64_t deadline = nowUs() + 10000000, reportAt = nowUs(), expectedAudio = -1; |
|
|
|
uint64_t decoded = 0, discarded = 0, late = 0, pressureDropped = 0, previousPressure = 0, previousDecoded = 0, previousShown = 0; |
|
|
|
uint64_t decoded = 0, discarded = 0, late = 0, pressureDropped = 0, previousPressure = 0, previousDecoded = 0, previousShown = 0; |
|
|
|
|
|
|
|
uint64_t prerollSamples = 0; |
|
|
|
uint32_t videoRevision = 0; |
|
|
|
uint32_t videoRevision = 0; |
|
|
|
auto reset = [&] { |
|
|
|
auto reset = [&] { |
|
|
|
avcodec_free_context(&decoder); |
|
|
|
avcodec_free_context(&decoder); |
|
|
|
@ -232,8 +233,10 @@ void StreamPlayerWindow::decode() { |
|
|
|
i == missing ? record.data.size() : 0, audio.pcm.data(), 960); |
|
|
|
i == missing ? record.data.size() : 0, audio.pcm.data(), 960); |
|
|
|
if (count != 960) { fail(text("Stream audio decoder failed")); failed = true; break; } |
|
|
|
if (count != 960) { fail(text("Stream audio decoder failed")); failed = true; break; } |
|
|
|
std::lock_guard<std::mutex> guard(p.lock); |
|
|
|
std::lock_guard<std::mutex> guard(p.lock); |
|
|
|
if (!p.prefillUntil) p.prefillUntil = nowUs() + 150000; |
|
|
|
if (p.audios.size() >= 25) { |
|
|
|
if (p.audios.size() >= 25) { pressure = true; break; } |
|
|
|
if (p.videoBase >= 0) { pressure = true; break; } |
|
|
|
|
|
|
|
prerollSamples += 960; p.audios.pop_front(); |
|
|
|
|
|
|
|
} |
|
|
|
p.audios.push_back(std::move(audio)); |
|
|
|
p.audios.push_back(std::move(audio)); |
|
|
|
} |
|
|
|
} |
|
|
|
if (failed) break; |
|
|
|
if (failed) break; |
|
|
|
@ -278,8 +281,19 @@ void StreamPlayerWindow::decode() { |
|
|
|
int64_t pts = frame->best_effort_timestamp == AV_NOPTS_VALUE ? static_cast<int64_t>(record.pts) : frame->best_effort_timestamp; |
|
|
|
int64_t pts = frame->best_effort_timestamp == AV_NOPTS_VALUE ? static_cast<int64_t>(record.pts) : frame->best_effort_timestamp; |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::lock_guard<std::mutex> guard(p.lock); |
|
|
|
std::lock_guard<std::mutex> guard(p.lock); |
|
|
|
if (!p.prefillUntil) p.prefillUntil = nowUs() + 150000; |
|
|
|
if (p.videoBase < 0) { |
|
|
|
if (p.videoBase < 0) { p.videoBase = pts; p.videoAt = p.prefillUntil; } |
|
|
|
while (!p.audios.empty() && p.audios.front().pts + 20000 <= pts) { |
|
|
|
|
|
|
|
prerollSamples += 960; p.audios.pop_front(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!p.audios.empty() && p.audios.front().pts < pts) { |
|
|
|
|
|
|
|
p.audios.front().offset = static_cast<unsigned>((pts - p.audios.front().pts) * 48000 + 999999) / 1000000; |
|
|
|
|
|
|
|
prerollSamples += p.audios.front().offset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
p.prefillUntil = nowUs() + 150000; p.videoBase = pts; p.videoAt = p.prefillUntil; |
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop playback start id=%llu pts=%lld prefill_ms=150 preroll_frames=%llu audioQ=%zu", |
|
|
|
|
|
|
|
(unsigned long long)p.id, (long long)pts, (unsigned long long)prerollSamples, p.audios.size()); |
|
|
|
|
|
|
|
prerollSamples = 0; |
|
|
|
|
|
|
|
} |
|
|
|
if (pts < p.clock(nowUs()) - 100000) { discarded++; late++; continue; } |
|
|
|
if (pts < p.clock(nowUs()) - 100000) { discarded++; late++; continue; } |
|
|
|
} |
|
|
|
} |
|
|
|
converter = sws_getCachedContext(converter, frame->width, frame->height, static_cast<AVPixelFormat>(frame->format), |
|
|
|
converter = sws_getCachedContext(converter, frame->width, frame->height, static_cast<AVPixelFormat>(frame->format), |
|
|
|
|