diff --git a/src/libs/avPlayer.cpp b/src/libs/avPlayer.cpp index 81a01955..e4e1d1c2 100644 --- a/src/libs/avPlayer.cpp +++ b/src/libs/avPlayer.cpp @@ -552,6 +552,7 @@ private: struct ReadyFrame { std::unique_ptr buffer; AvPlayerFrameInfoEx info {}; + uint64_t timestamp_offset = 0; }; class FileStreamer { @@ -933,6 +934,7 @@ public: } current_video = std::move(*frame); *out = current_video->info; + RecordLoopBoundary(*current_video); if (deliver_seek_frame) { seek_video_frame_pending = false; } @@ -963,11 +965,25 @@ public: std::memcpy(out->details.audio.language_code, current_audio->info.details.audio.language_code, 4); last_audio_ts = out->time_stamp; + RecordLoopBoundary(*current_audio); return true; } - std::optional TakeWarning() { return warnings.TryPop(); } + std::optional TakeWarning() { + std::lock_guard lock(mutex); + if (pending_loop_warnings == 0) { + return std::nullopt; + } + --pending_loop_warnings; + return AVPLAYER_WARNING_LOOPING_BACK; + } private: + void RecordLoopBoundary(const ReadyFrame& frame) { + if (frame.timestamp_offset > last_output_loop_offset) { + last_output_loop_offset = frame.timestamp_offset; + ++pending_loop_warnings; + } + } void Close() { Stop(); if (fmt != nullptr) { @@ -1014,6 +1030,8 @@ private: audio_done = true; seek_video_frame_pending = false; last_audio_ts = 0; + last_output_loop_offset = 0; + pending_loop_warnings = 0; current_video = std::move(delivered_video); current_audio = std::move(delivered_audio); retired_video = std::move(in_flight_video); @@ -1220,7 +1238,6 @@ private: if (avformat_seek_file(fmt, stream, INT64_MIN, 0, INT64_MAX, 0) < 0) { break; } - warnings.Push(AVPLAYER_WARNING_LOOPING_BACK); continue; } if (result != AVERROR_EOF && !worker_stop) { @@ -1340,6 +1357,7 @@ private: return false; } ready.info.time_stamp += timestamp_offset; + ready.timestamp_offset = timestamp_offset; frames.Push(std::move(ready)); av_frame_free(&frame); } @@ -1603,7 +1621,6 @@ private: std::optional current_video; std::optional current_audio; std::deque> retired_video; - WorkQueue warnings; LibKernel::Pthread demux_thread = nullptr; LibKernel::Pthread video_thread = nullptr; LibKernel::Pthread audio_thread = nullptr; @@ -1623,6 +1640,8 @@ private: uint32_t sync_mode = 0; uint64_t start_time_ms = 0; uint64_t last_audio_ts = 0; + uint64_t last_output_loop_offset = 0; + uint32_t pending_loop_warnings = 0; std::chrono::steady_clock::time_point clock_start {}; std::chrono::steady_clock::time_point pause_time {}; std::chrono::steady_clock::duration paused_extra {}; @@ -1951,6 +1970,7 @@ Bool KYTY_SYSV_ABI AvPlayerGetVideoData(AvPlayerInternal* h, AvPlayerFrameInfo* video_info->details.video.height = ex.details.video.height; video_info->details.video.aspect_ratio = ex.details.video.aspect_ratio; std::memcpy(video_info->details.video.language_code, ex.details.video.language_code, 4); + pump_warnings(h); return 1; } Bool KYTY_SYSV_ABI AvPlayerGetVideoDataEx(AvPlayerInternal* h, AvPlayerFrameInfoEx* video_info) {