We initially set next_frame_time to infinity (or a very long time from now) to avoid uselessly outputing the same frame twice in a row if we haven't received any new input, because then any new input would have to wait up to 1 frametime adding needless latency.
548 {
550 Video_mixer mixer(s->desc.width, s->desc.height, s->layout);
551
558 auto next_frame_time = clock::now() + std::chrono::hours(1);
559 auto last_frame_time = clock::time_point::min();
560 for(;;){
564 std::string_view msg_text = msg_univ->
text;
567
570 if (
key ==
"layout") {
571 Video_mixer::Layout new_layout = layout_from_name(
val);
572
573 if(new_layout == Video_mixer::Layout::Invalid){
576 } else {
578 mixer.set_layout(new_layout);
580 }
581
582 }
else if (
key ==
"primary_ssrc"){
583 uint32_t parsed_ssrc = 0;
587 } else {
589 mixer.set_primary_ssrc(parsed_ssrc);
591 }
592
593 }
else if (
key ==
"info"){
594 auto ssrcs = mixer.get_participant_ssrc_list();
597 for(const auto& p : ssrcs){
599 }
601 } else {
603 }
605 }
606
608
609 auto wait_p = [s]{ return !s->incoming_frames.empty(); };
610 std::unique_lock<std::mutex>
lock(s->incoming_frames_lock);
611 bool have_frame = s->new_incoming_frame_cv.wait_until(
lock, next_frame_time, wait_p);
612 if(have_frame){
613 frame = std::move(s->incoming_frames.front());
614 s->incoming_frames.pop();
615 }
617
618 if(have_frame){
619 s->incoming_frame_consumed.notify_one();
622 break;
623 }
624 if(s->req_fps <= 0){
625 s->desc.fps = std::max(s->desc.fps,
frame->
fps);
626 }
627 mixer.process_frame(std::move(
frame));
628 }
629
630 auto now = clock::now();
631 if(next_frame_time <= now){
634
635 mixer.get_mixed(disp_frame);
636
638
639 last_frame_time = next_frame_time;
640 next_frame_time = now + std::chrono::hours(1);
641 } else {
642 if(!have_frame)
644 using namespace std::chrono_literals;
645 next_frame_time = last_frame_time + std::chrono::duration_cast<clock::duration>(1s / s->desc.fps);
646 if(next_frame_time <= now){
647 next_frame_time = now;
648 }
649 }
650 }
651
652 return;
653}
static void check_reconf(struct state_conference_common *s, struct video_desc desc)
#define LOG_LEVEL_NOTICE
information that may be interesting
bool display_put_frame(struct display *d, struct video_frame *frame, long long timeout_ns)
Puts filled video frame. After calling this function, video frame cannot be used.
struct video_frame * display_get_frame(struct display *d)
Returns video framebuffer which will be written to.
void free_message(struct message *msg, struct response *r)
struct response * new_response(int status, const char *text)
struct message * check_message(struct module *mod)
#define RESPONSE_BAD_REQUEST
std::unique_ptr< video_frame, frame_deleter > unique_frame