diff --git a/src/modules/html/producer/html_producer.cpp b/src/modules/html/producer/html_producer.cpp index f5b42bd61b..5fc33621e7 100644 --- a/src/modules/html/producer/html_producer.cpp +++ b/src/modules/html/producer/html_producer.cpp @@ -75,17 +75,13 @@ inline std::int_least64_t now() struct presentation_frame { - std::int_least64_t timestamp = now(); - core::draw_frame frame = core::draw_frame::empty(); - bool has_video = false; - bool has_audio = false; + std::int_least64_t timestamp; + core::draw_frame frame; - explicit presentation_frame(core::draw_frame video = {}) + explicit presentation_frame(core::draw_frame frame = {}, std::int_least64_t ts = now()) noexcept + : timestamp(ts) + , frame(std::move(frame)) { - if (video) { - frame = std::move(video); - has_video = true; - } } presentation_frame(presentation_frame&& other) noexcept @@ -97,7 +93,7 @@ struct presentation_frame presentation_frame(const presentation_frame&) = delete; presentation_frame& operator=(const presentation_frame&) = delete; - presentation_frame& operator=(presentation_frame&& rhs) + presentation_frame& operator=(presentation_frame&& rhs) noexcept { timestamp = rhs.timestamp; frame = std::move(rhs.frame); @@ -105,32 +101,6 @@ struct presentation_frame } ~presentation_frame() {} - - void add_audio(core::mutable_frame audio) - { - if (has_audio) - return; - has_audio = true; - - if (frame) { - frame = core::draw_frame::over(frame, core::draw_frame(std::move(audio))); - } else { - frame = core::draw_frame(std::move(audio)); - } - } - - void add_video(core::draw_frame video) - { - if (has_video) - return; - has_video = true; - - if (frame) { - frame = core::draw_frame::over(frame, std::move(video)); - } else { - frame = std::move(video); - } - } }; class html_client @@ -156,13 +126,15 @@ class html_client tbb::concurrent_queue javascript_before_load_; std::atomic loaded_; std::queue frames_; - core::draw_frame last_generated_frame_; + std::queue audio_frames_; mutable std::mutex frames_mutex_; + mutable std::mutex audio_frames_mutex_; const size_t frames_max_size_ = 4; std::atomic closing_; std::unique_ptr audioResampler_; + core::draw_frame last_video_frame_; core::draw_frame last_frame_; std::int_least64_t last_frame_time_; @@ -219,8 +191,21 @@ class html_client bool try_pop(const core::video_field field) { + bool result = false; std::lock_guard lock(frames_mutex_); + core::draw_frame audio_frame; + uint64_t audio_frame_timestamp = 0; + + { + std::lock_guard audio_lock(audio_frames_mutex_); + if (!audio_frames_.empty()) { + audio_frame_timestamp = audio_frames_.front().timestamp; + audio_frame = core::draw_frame(std::move(audio_frames_.front().frame)); + audio_frames_.pop(); + } + } + if (!frames_.empty()) { /* * CEF in gpu-enabled mode only sends frames when something changes, and interlaced channels @@ -248,15 +233,22 @@ class html_client } last_frame_time_ = frames_.front().timestamp; - last_frame_ = std::move(frames_.front().frame); + last_video_frame_ = std::move(frames_.front().frame); + last_frame_ = last_video_frame_; frames_.pop(); graph_->set_value("buffered-frames", (double)frames_.size() / frames_max_size_); - return true; + result = true; } - return false; + if (audio_frame) { + last_frame_time_ = audio_frame_timestamp; + last_frame_ = core::draw_frame::over(last_video_frame_, audio_frame); + result = true; + } + + return result; } core::draw_frame receive(const core::video_field field) @@ -370,10 +362,9 @@ class html_client std::lock_guard lock(frames_mutex_); core::draw_frame new_frame = core::draw_frame(std::move(frame)); - last_generated_frame_ = new_frame; frames_.push(presentation_frame(std::move(new_frame))); - while (frames_.size() > 4) { + while (frames_.size() > frames_max_size_) { frames_.pop(); graph_->set_tag(diagnostics::tag_severity::WARNING, "dropped-frame"); } @@ -492,21 +483,11 @@ class html_client auto audio_frame = core::mutable_frame(this, {}, std::move(audio), core::pixel_format_desc()); { - std::lock_guard lock(frames_mutex_); - if (frames_.empty()) { - presentation_frame wrapped_frame(last_generated_frame_); - wrapped_frame.add_audio(std::move(audio_frame)); - - frames_.push(std::move(wrapped_frame)); - } else { - if (!frames_.back().has_audio) { - frames_.back().add_audio(std::move(audio_frame)); - } else { - presentation_frame wrapped_frame(last_generated_frame_); - wrapped_frame.add_audio(std::move(audio_frame)); - frames_.push(std::move(wrapped_frame)); - } + std::lock_guard lock(audio_frames_mutex_); + while (audio_frames_.size() >= frames_max_size_) { + audio_frames_.pop(); } + audio_frames_.push(presentation_frame(core::draw_frame(std::move(audio_frame)))); } } void OnAudioStreamStopped(CefRefPtr browser) override { audioResampler_ = nullptr; }