feat: retain streaming media and add opt-in automatic quality

This commit is contained in:
2026-10-11 11:17:41 +02:00
parent 041d2b0644
commit 13554a1574
12 changed files with 921 additions and 164 deletions
+15 -4
View File
@@ -182,6 +182,7 @@ struct Player {
// Decoders, timeline and output are worker-owned; network readers exclusively own demux I/O.
AVFormatContext *format = nullptr;
playback::StreamCacheBudget cacheBudget;
std::array<std::unique_ptr<playback::NetworkInput>, 2> inputs;
bool network = false;
bool canSeek = false;
@@ -337,8 +338,17 @@ struct Player {
(videoFinished ? audioEnd : std::min(audioEnd, videoEnd));
}
end = std::min(end, duration);
if (!std::isfinite(end) || end <= position) return;
state.buffered_start = position;
if (!std::isfinite(end) || end < position) return;
double start = 0;
for (int slot = 0; slot < 2; ++slot) {
const auto &track = tracks[slot];
if (!track.codec) continue;
double cached = track.input ? track.input->bufferedStart(slot) : NAN;
if (!std::isfinite(cached) && slot == 0 && audioDrained()) cached = this->audioEnd();
start = std::max(start, std::isfinite(cached) ? std::clamp(cached, 0.0, position) : position);
}
if (end <= start) return;
state.buffered_start = start;
state.buffered_end = end;
}
@@ -359,6 +369,7 @@ struct Player {
return (command.action == Action::Seek || command.action == Action::Step) &&
command.epoch == activeEpoch;
});
for (auto &input : inputs) if (input) input->updatePosition(position);
publishBufferedRange();
state.video_aspect_ratio = 0;
if (const auto *video = tracks[1].codec; video && video->width > 0 && video->height > 0) {
@@ -475,7 +486,7 @@ struct Player {
}
playback::NetworkInput *openNetworkInput(int slot, const std::string &url, const std::string &headers) {
inputs[slot] = std::make_unique<playback::NetworkInput>(stopping, requestedEpoch, activeEpoch, wake);
inputs[slot] = std::make_unique<playback::NetworkInput>(stopping, requestedEpoch, activeEpoch, wake, cacheBudget);
auto &input = *inputs[slot];
input.format = avformat_alloc_context();
if (!input.format) throw std::bad_alloc();
@@ -608,7 +619,7 @@ struct Player {
std::array<int, 2> indices{-1, -1};
for (int slot = 0; slot < 2; ++slot)
if (tracks[slot].input == input.get()) indices[slot] = tracks[slot].index;
input->start(indices, origin);
input->start(indices, origin, canSeek);
}
}
status = PLAYER_PAUSED;