Skip to content

Commit d11e0f5

Browse files
committed
feat: only mix frames in channels which have a consumer attached
If there are no consumers, the mixed frames go nowhere. This does not impact routes, as they take the frames before mixing has occurred, and the producers will still push their frames to the gpu as before. This reduces the cost of using channels as a pre-comp
1 parent 267674c commit d11e0f5

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

src/core/consumer/output.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,16 @@ struct output::impl
8181

8282
bool remove(const spl::shared_ptr<frame_consumer>& consumer) { return remove(consumer->index()); }
8383

84+
size_t consumer_count()
85+
{
86+
std::lock_guard<std::mutex> lock(consumers_mutex_);
87+
return consumers_.size();
88+
}
89+
8490
void operator()(const const_frame& input_frame1,
8591
const const_frame& input_frame2,
8692
const core::video_format_desc& format_desc)
8793
{
88-
if (!input_frame1) {
89-
return;
90-
}
91-
9294
auto time = std::move(time_);
9395

9496
if (format_desc_ != format_desc) {
@@ -107,6 +109,18 @@ struct output::impl
107109
return;
108110
}
109111

112+
// If no frame is provided, this should only happen when the channel has no consumers.
113+
// Take a shortcut and perform the sleep to let the channel tick correctly.
114+
if (!input_frame1) {
115+
if (!time) {
116+
time = std::chrono::high_resolution_clock::now();
117+
} else {
118+
std::this_thread::sleep_until(*time);
119+
}
120+
time_ = *time + std::chrono::microseconds(static_cast<int>(1e6 / format_desc_.hz));
121+
return;
122+
}
123+
110124
const auto bytesPerComponent1 =
111125
input_frame1.pixel_format_desc().planes.at(0).depth == common::bit_depth::bit8 ? 1 : 2;
112126
if (input_frame1.size() != format_desc_.size * bytesPerComponent1) {
@@ -204,11 +218,12 @@ output::output(const spl::shared_ptr<diagnostics::graph>& graph,
204218
{
205219
}
206220
output::~output() {}
207-
void output::add(int index, const spl::shared_ptr<frame_consumer>& consumer) { impl_->add(index, consumer); }
208-
void output::add(const spl::shared_ptr<frame_consumer>& consumer) { impl_->add(consumer); }
209-
bool output::remove(int index) { return impl_->remove(index); }
210-
bool output::remove(const spl::shared_ptr<frame_consumer>& consumer) { return impl_->remove(consumer); }
211-
void output::operator()(const const_frame& frame, const const_frame& frame2, const video_format_desc& format_desc)
221+
void output::add(int index, const spl::shared_ptr<frame_consumer>& consumer) { impl_->add(index, consumer); }
222+
void output::add(const spl::shared_ptr<frame_consumer>& consumer) { impl_->add(consumer); }
223+
bool output::remove(int index) { return impl_->remove(index); }
224+
bool output::remove(const spl::shared_ptr<frame_consumer>& consumer) { return impl_->remove(consumer); }
225+
size_t output::consumer_count() const { return impl_->consumer_count(); }
226+
void output::operator()(const const_frame& frame, const const_frame& frame2, const video_format_desc& format_desc)
212227
{
213228
return (*impl_)(frame, frame2, format_desc);
214229
}

src/core/consumer/output.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class output final
5252
bool remove(const spl::shared_ptr<frame_consumer>& consumer);
5353
bool remove(int index);
5454

55+
size_t consumer_count() const;
56+
5557
core::monitor::state state() const;
5658

5759
private:

src/core/video_channel.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,16 @@ struct video_channel::impl final
152152
auto stage_frames = (*stage_)(frame_counter_, background_routes, routesCb);
153153
graph_->set_value("produce-time", produce_timer.elapsed() * format_desc.hz * 0.5);
154154

155+
// This is a little race prone, but at worst a new consumer will start with a frame of black
156+
bool has_consumers = output_.consumer_count() > 0;
157+
155158
// Mix
156159
caspar::timer mix_timer;
157-
auto mixed_frame = mixer_(stage_frames.frames, stage_frames.format_desc, stage_frames.nb_samples);
160+
auto mixed_frame =
161+
has_consumers ? mixer_(stage_frames.frames, stage_frames.format_desc, stage_frames.nb_samples)
162+
: const_frame{};
158163
auto mixed_frame2 =
159-
stage_frames.format_desc.field_count == 2
164+
has_consumers && stage_frames.format_desc.field_count == 2
160165
? mixer_(stage_frames.frames2, stage_frames.format_desc, stage_frames.nb_samples)
161166
: const_frame{};
162167
graph_->set_value("mix-time", mix_timer.elapsed() * format_desc.hz * 0.5);

0 commit comments

Comments
 (0)