Trace stream startup decoding and presentation delays
This commit is contained in:
1 parent
f38aa3b08d
commit
1b036e4ea9
3 files changed
+90
-20
No files matched your search
@@ -49,6 +49,7 @@ struct StreamPlayerWindow::Playback {
|
||||
bool held = false;
|
||||
} audioGap;
|
||||
uint64_t id = ++nextId, group = 0, source = 0, epoch = 0;
|
||||
int64_t createdAt = nowUs(), firstInputAt = 0;
|
||||
std::atomic<bool> running{true}, audioAvailable{false};
|
||||
std::atomic<bool> complete{false}, failed{false};
|
||||
std::atomic<float> volume{1.0f};
|
||||
@@ -90,6 +91,8 @@ struct StreamPlayerWindow::Playback {
|
||||
StreamPlayerWindow::StreamPlayerWindow(uint64_t group, uint64_t source, uint64_t epoch, const QString& name, QWidget* parent, bool embedded)
|
||||
: QWidget(parent), m_playback(std::make_unique<Playback>()) {
|
||||
m_playback->group = group; m_playback->source = source; m_playback->epoch = epoch;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop viewer requested id=%llu source=%llx epoch=%llx",
|
||||
(unsigned long long)m_playback->id, (unsigned long long)source, (unsigned long long)epoch);
|
||||
setWindowTitle(text("Live stream: %1").arg(name)); resize(800, 500);
|
||||
setObjectName(QStringLiteral("streamPlayer_%1").arg(source));
|
||||
auto* layout = new QVBoxLayout(this); auto* title = new QLabel(name, this); layout->addWidget(title);
|
||||
@@ -170,6 +173,7 @@ void StreamPlayerWindow::tick() {
|
||||
auto& p = *m_playback;
|
||||
if (!SoundManager::instance()->outputAvailable()) p.audioAvailable = false;
|
||||
QImage image; bool finished = false, first = false;
|
||||
int64_t shownPts = -1, readyPts = -1, mediaPosition = -1, deviceLead = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(p.lock);
|
||||
int64_t clock = p.clock(nowUs());
|
||||
@@ -177,14 +181,22 @@ void StreamPlayerWindow::tick() {
|
||||
p.videoBytes -= static_cast<size_t>(p.videos.front().image.sizeInBytes());
|
||||
p.lastShownPts = p.videos.front().pts; image = std::move(p.videos.front().image); p.videos.pop_front();
|
||||
}
|
||||
if (!image.isNull()) first = p.shown++ == 0;
|
||||
if (!image.isNull()) {
|
||||
first = p.shown++ == 0;
|
||||
shownPts = p.lastShownPts; readyPts = p.ready; mediaPosition = clock; deviceLead = p.deviceLead;
|
||||
}
|
||||
bool audioDone = !p.activeAudio || !p.audioAvailable || (p.endFrames != UINT64_MAX && p.played(nowUs()) >= p.endFrames);
|
||||
finished = p.ended && p.videoEnded && p.videos.empty() && audioDone;
|
||||
}
|
||||
if (!image.isNull()) {
|
||||
m_render->setFrame(image); m_status->setText(text("Live"));
|
||||
if (first) DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop first frame id=%llu %dx%d RGB_stride=%lld",
|
||||
(unsigned long long)p.id, image.width(), image.height(), (long long)image.bytesPerLine());
|
||||
if (first) DEBUG_INFO(DEBUG_CATEGORY_STREAM,
|
||||
"desktop first frame id=%llu source=%llx epoch=%llx %dx%d RGB_stride=%lld stage=display_submit "
|
||||
"elapsed_us=%lld pts=%lld clock_us=%lld ready_us=%lld ready_ahead_us=%lld av_us=%lld device_lead_us=%lld",
|
||||
(unsigned long long)p.id, (unsigned long long)p.source, (unsigned long long)p.epoch,
|
||||
image.width(), image.height(), (long long)image.bytesPerLine(), (long long)(nowUs() - p.createdAt),
|
||||
(long long)shownPts, (long long)mediaPosition, (long long)readyPts, (long long)(readyPts - shownPts),
|
||||
(long long)(shownPts - mediaPosition), (long long)deviceLead);
|
||||
emit framePresented();
|
||||
}
|
||||
if (finished || p.failed) {
|
||||
@@ -259,8 +271,12 @@ void StreamPlayerWindow::decode() {
|
||||
if (p.activeAudio && !p.sound) { p.running = false; return; }
|
||||
p.position = status.start_us; p.clockAt = nowUs(); p.started = true;
|
||||
stream_playback_clock_reset(&p.adaptation, p.id);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop playback starts id=%llu pts=%lld fixed_prefill=0",
|
||||
(unsigned long long)p.id, (long long)p.position);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM,
|
||||
"desktop playback starts id=%llu pts=%lld fixed_prefill=0 elapsed_us=%lld "
|
||||
"ready_us=%lld video_us=%lld audio_us=%lld initial_reserve_us=%lld audio=%d",
|
||||
(unsigned long long)p.id, (long long)p.position, (long long)(nowUs() - p.createdAt),
|
||||
(long long)status.ready_us, (long long)status.video_us, (long long)status.audio_us,
|
||||
(long long)((p.activeAudio ? status.ready_us : status.video_us) - p.position), p.activeAudio);
|
||||
}
|
||||
p.ready = p.activeAudio ? status.ready_us : status.video_us;
|
||||
};
|
||||
@@ -291,8 +307,10 @@ void StreamPlayerWindow::decode() {
|
||||
pts = frame->best_effort_timestamp == AV_NOPTS_VALUE ? p.lastInputPts : frame->best_effort_timestamp;
|
||||
p.decoderLead = std::max(p.decoderLead, p.lastInputPts - pts); p.lastDecodedPts = pts; p.videoReady = true;
|
||||
if (!p.presenting) { p.presenting = true; p.clockAt = nowUs();
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "desktop first decoded frame id=%llu pts=%lld decoder_lead=%lld",
|
||||
(unsigned long long)p.id, (long long)pts, (long long)p.decoderLead); }
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO,
|
||||
"desktop first decoded frame id=%llu pts=%lld decoder_lead=%lld elapsed_us=%lld decode_us=%lld ready_ahead_us=%lld",
|
||||
(unsigned long long)p.id, (long long)pts, (long long)p.decoderLead, (long long)(nowUs() - p.createdAt),
|
||||
(long long)(p.firstInputAt ? nowUs() - p.firstInputAt : -1), (long long)(p.ready - pts)); }
|
||||
if (pts < p.clock(nowUs()) - 100000) { discarded++; continue; } }
|
||||
converter = sws_getCachedContext(converter, frame->width, frame->height, (AVPixelFormat)frame->format,
|
||||
frame->width, frame->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||
@@ -425,6 +443,7 @@ void StreamPlayerWindow::decode() {
|
||||
}
|
||||
}
|
||||
if (!decoder) {
|
||||
int64_t openingAt = nowUs();
|
||||
AVCodecID codecId = record.format.video_codec == STREAM_MEDIA_H264 ? AV_CODEC_ID_H264
|
||||
: record.format.video_codec == STREAM_MEDIA_H265 ? AV_CODEC_ID_HEVC
|
||||
: record.format.video_codec == STREAM_MEDIA_VP9 ? AV_CODEC_ID_VP9
|
||||
@@ -449,8 +468,12 @@ void StreamPlayerWindow::decode() {
|
||||
record.format.video_codec, codec ? codec->name : "unavailable", configurationSize, openResult);
|
||||
fail(text("Stream video decoder failed")); break;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop decoder codec=%u name=%s config=%zu", record.format.video_codec, codec->name, configurationSize);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM,
|
||||
"desktop decoder id=%llu codec=%u name=%s config=%zu elapsed_us=%lld open_us=%lld key_pts=%llu",
|
||||
(unsigned long long)p.id, record.format.video_codec, codec->name, configurationSize,
|
||||
(long long)(nowUs() - p.createdAt), (long long)(nowUs() - openingAt), (unsigned long long)record.pts);
|
||||
decoder->pkt_timebase = AVRational{1, 1000000}; waitKey = false;
|
||||
p.firstInputAt = nowUs();
|
||||
}
|
||||
av_packet_unref(packet);
|
||||
if (av_new_packet(packet, (int)size) < 0) { fail(text("Stream decoder allocation failed")); break; }
|
||||
@@ -462,11 +485,14 @@ void StreamPlayerWindow::decode() {
|
||||
std::lock_guard<std::mutex> guard(p.lock);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_STREAM,
|
||||
"desktop viewer id=%llu decoded=%llu discarded=%llu shown=%llu showFps=%.1f videoQ=%zu "
|
||||
"clock=%lld reserve_us=%lld minimum_us=%lld tempo=%d lead_us=%lld underruns=%llu",
|
||||
"clock=%lld reserve_us=%lld minimum_us=%lld tempo=%d lead_us=%lld underruns=%llu "
|
||||
"ready_us=%lld shown_pts=%lld display_lag_us=%lld decoder_lead_us=%lld hold=%d",
|
||||
(unsigned long long)p.id, (unsigned long long)decoded, (unsigned long long)discarded,
|
||||
(unsigned long long)p.shown, (p.shown - reportedShown) / seconds, p.videos.size(), (long long)p.position,
|
||||
(long long)p.timing.reserve_us, (long long)p.timing.minimum_us, p.timing.tempo_milli,
|
||||
(long long)p.deviceLead, (unsigned long long)p.underruns);
|
||||
(long long)p.deviceLead, (unsigned long long)p.underruns, (long long)p.ready,
|
||||
(long long)p.lastShownPts, (long long)(p.lastShownPts >= 0 ? p.position - p.lastShownPts : -1),
|
||||
(long long)p.decoderLead, p.holdAudio);
|
||||
reportedShown = p.shown;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user