Fix AvPlayer end-of-file handling

This commit is contained in:
nmzik
2026-09-20 14:40:29 +04:00
parent 6b79b7a003
commit fa51da4d76
+8 -26
View File
@@ -829,20 +829,22 @@ public:
} }
int Stop() { int Stop() {
bool was_playing_video = false; bool was_playing_video = false;
AvPlayerEventReplacement stop_event; AvPlayerEventReplacement stop_event {};
{ {
std::scoped_lock lifecycle_lock(lifecycle_mutex); std::scoped_lock lifecycle_lock(lifecycle_mutex);
{ {
std::lock_guard lock(mutex); std::lock_guard lock(mutex);
was_playing_video = state == State::Playing && video_id.has_value(); if (state == State::Playing) {
state = State::Stopped; was_playing_video = video_id.has_value();
stop_event = event;
}
state = State::Stopped;
} }
StopWorkers(); StopWorkers();
{ {
std::lock_guard lock(mutex); std::lock_guard lock(mutex);
ResetNoLock(); ResetNoLock();
} }
stop_event = TakeStopEvent();
} }
if (was_playing_video) { if (was_playing_video) {
::printf("AvPlayer video stopped\n"); ::printf("AvPlayer video stopped\n");
@@ -960,7 +962,6 @@ public:
current_video = std::move(*frame); current_video = std::move(*frame);
*out = current_video->info; *out = current_video->info;
RecordLoopBoundary(*current_video); RecordLoopBoundary(*current_video);
completion_changed.notify_all();
if (deliver_seek_frame) { if (deliver_seek_frame) {
seek_video_frame_pending = false; seek_video_frame_pending = false;
} }
@@ -993,7 +994,6 @@ public:
current_audio->info.details.audio.language_code, 4); current_audio->info.details.audio.language_code, 4);
last_audio_ts = out->time_stamp; last_audio_ts = out->time_stamp;
RecordLoopBoundary(*current_audio); RecordLoopBoundary(*current_audio);
completion_changed.notify_all();
return true; return true;
} }
std::optional<int32_t> TakeWarning() { std::optional<int32_t> TakeWarning() {
@@ -1012,9 +1012,6 @@ private:
return demux_eof && video_done && audio_done && video_frames.Empty() && return demux_eof && video_done && audio_done && video_frames.Empty() &&
audio_frames.Empty(); audio_frames.Empty();
} }
AvPlayerEventReplacement TakeStopEvent() {
return stop_event_sent.exchange(true) ? AvPlayerEventReplacement {} : event;
}
void RecordLoopBoundary(const ReadyFrame& frame) { void RecordLoopBoundary(const ReadyFrame& frame) {
if (frame.timestamp_offset > last_output_loop_offset) { if (frame.timestamp_offset > last_output_loop_offset) {
last_output_loop_offset = frame.timestamp_offset; last_output_loop_offset = frame.timestamp_offset;
@@ -1206,12 +1203,10 @@ private:
StopWorkers(); StopWorkers();
return false; return false;
} }
state = State::Playing; state = State::Playing;
stop_event_sent = false;
return true; return true;
} }
void NotifyWorkers() { void NotifyWorkers() {
completion_changed.notify_all();
video_packets.Notify(); video_packets.Notify();
audio_packets.Notify(); audio_packets.Notify();
video_buffers.Notify(); video_buffers.Notify();
@@ -1298,13 +1293,6 @@ private:
demux_eof = true; demux_eof = true;
video_packets.Notify(); video_packets.Notify();
audio_packets.Notify(); audio_packets.Notify();
std::unique_lock lock(mutex);
completion_changed.wait(lock, [&] { return worker_stop || DrainedNoLock(); });
if (!worker_stop) {
const auto stop_event = TakeStopEvent();
lock.unlock();
emit_event(stop_event, AVPLAYER_EVENT_STATE_STOP);
}
} }
void VideoDecoder() { void VideoDecoder() {
Decoder(video_packets, video_ctx, video_buffers, video_frames, video_done, Decoder(video_packets, video_ctx, video_buffers, video_frames, video_done,
@@ -1352,11 +1340,7 @@ private:
break; break;
} }
} }
{ done = true;
std::lock_guard lock(mutex);
done = true;
}
completion_changed.notify_all();
} }
bool DecodePacket(AVCodecContext* codec, AVPacket* packet, uint64_t timestamp_offset, bool DecodePacket(AVCodecContext* codec, AVPacket* packet, uint64_t timestamp_offset,
WorkQueue<std::unique_ptr<GuestBuffer>>& buffers, WorkQueue<std::unique_ptr<GuestBuffer>>& buffers,
@@ -1681,8 +1665,6 @@ private:
std::atomic_bool demux_eof {true}; std::atomic_bool demux_eof {true};
std::atomic_bool video_done {true}; std::atomic_bool video_done {true};
std::atomic_bool audio_done {true}; std::atomic_bool audio_done {true};
std::atomic_bool stop_event_sent {true};
std::condition_variable completion_changed;
std::mutex lifecycle_mutex; std::mutex lifecycle_mutex;
mutable std::mutex mutex; mutable std::mutex mutex;
State state = State::Ready; State state = State::Ready;