fix: share buffered Cast HLS input and select streams
This commit is contained in:
@@ -125,7 +125,9 @@ public:
|
||||
for (int slot = 0; slot < 2; ++slot) trim(slot);
|
||||
budget.changed.notify_all();
|
||||
}
|
||||
void seek(int streamIndex, int64_t timestamp) {
|
||||
// Optional audio target gives fresh segment encoders their AAC preroll without
|
||||
// moving the video cursor away from its own keyframe. Omission preserves player seeks.
|
||||
void seek(int streamIndex, int64_t timestamp, double audioTarget = NAN) {
|
||||
std::lock_guard lock(budget.mutex);
|
||||
const double target = (streamIndex < 0 ? static_cast<double>(timestamp) / AV_TIME_BASE :
|
||||
static_cast<double>(timestamp) * av_q2d(format->streams[streamIndex]->time_base)) - origin;
|
||||
@@ -138,7 +140,7 @@ public:
|
||||
// track can resume without restoring its I/O position through a real seek.
|
||||
if (halted && !ended && !(std::isfinite(lane.mediaEnd) &&
|
||||
lane.frontierEnd + lane.tick >= lane.mediaEnd)) cached = false;
|
||||
else cached = cachedCursor(slot, target, cursors[slot]);
|
||||
else cached = cachedCursor(slot, slot == 0 && std::isfinite(audioTarget) ? audioTarget : target, cursors[slot]);
|
||||
}
|
||||
position = std::max(0.0, target);
|
||||
if (cached) {
|
||||
@@ -156,6 +158,11 @@ public:
|
||||
failure = 0;
|
||||
seekIndex = streamIndex;
|
||||
seekTimestamp = timestamp;
|
||||
if (lanes[0].index >= 0 && !skipAudio && std::isfinite(audioTarget)) {
|
||||
const double earliest = std::min(target, std::max(0.0, audioTarget - lanes[0].preroll));
|
||||
seekIndex = -1;
|
||||
seekTimestamp = static_cast<int64_t>((earliest + origin) * AV_TIME_BASE);
|
||||
}
|
||||
seeking = true;
|
||||
serial.fetch_add(1, std::memory_order_release);
|
||||
budget.changed.notify_all();
|
||||
@@ -187,6 +194,20 @@ public:
|
||||
std::lock_guard lock(budget.mutex);
|
||||
return failure;
|
||||
}
|
||||
// Whether an existing bounded forward fetch can supply a seek's missing packets.
|
||||
// Past history and targets outside the current ahead window require normal seek handling.
|
||||
bool readAheadPending(double target, double audioTarget = NAN) const {
|
||||
std::lock_guard lock(budget.mutex);
|
||||
if (failure || seeking || ended || halted || waitingForRoom ||
|
||||
target < position || target > position + aheadSeconds) return false;
|
||||
for (int slot = 0; slot < 2; ++slot) {
|
||||
const auto &lane = lanes[slot];
|
||||
if (lane.index < 0 || (slot == 0 && skipAudio) || trackEnded(lane)) continue;
|
||||
const double laneTarget = slot == 0 && std::isfinite(audioTarget) ? audioTarget : target;
|
||||
if (laneTarget > lane.frontierEnd + lane.tick) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
double bufferedStart(int slot) const {
|
||||
std::lock_guard lock(budget.mutex);
|
||||
if (!cacheSeeking || failure || seeking || (slot == 0 && skipAudio)) return NAN;
|
||||
@@ -253,6 +274,7 @@ private:
|
||||
std::atomic<int64_t> deadline{std::numeric_limits<int64_t>::max()};
|
||||
bool seeking = false, ended = false, halted = false, skipAudio = false;
|
||||
bool cacheSeeking = false, started = false, audioDropped = false;
|
||||
bool waitingForRoom = false;
|
||||
int seekIndex = -1, failure = 0;
|
||||
int64_t seekTimestamp = 0;
|
||||
double origin = 0, position = 0;
|
||||
@@ -464,10 +486,15 @@ private:
|
||||
}
|
||||
// The demuxer's single in-flight packet is not retained until it fits.
|
||||
// Byte pressure shortens consumed history, never drops unread packets.
|
||||
budget.changed.wait(lock, [&] {
|
||||
return stoppingNow() || serial.load(std::memory_order_acquire) != current ||
|
||||
(slot == 0 && skipAudio) || makeRoom(lane, bytes);
|
||||
});
|
||||
if (!makeRoom(lane, bytes)) {
|
||||
waitingForRoom = true;
|
||||
playerWake.notify_one();
|
||||
budget.changed.wait(lock, [&] {
|
||||
return stoppingNow() || serial.load(std::memory_order_acquire) != current ||
|
||||
(slot == 0 && skipAudio) || makeRoom(lane, bytes);
|
||||
});
|
||||
waitingForRoom = false;
|
||||
}
|
||||
if (stoppingNow()) return;
|
||||
if (serial.load(std::memory_order_acquire) != current || (slot == 0 && skipAudio)) {
|
||||
if (slot == 0 && skipAudio) audioDropped = true;
|
||||
|
||||
Reference in New Issue
Block a user