UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
multiplier.cpp File Reference
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#include "debug.h"
#include "host.h"
#include "lib_common.h"
#include "video.h"
#include "video_display.h"
#include "utils/string_view_utils.hpp"
#include <condition_variable>
#include <vector>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
Include dependency graph for multiplier.cpp:

Go to the source code of this file.

Classes

struct  state_multiplier
 

Functions

static void check_reconf (struct state_multiplier *s, struct video_desc *current_desc, struct video_desc desc)
 
static void display_multiplier_done (void *state)
 
static bool display_multiplier_get_property (void *state, int property, void *val, size_t *len)
 
static struct video_frame * display_multiplier_getf (void *state)
 
static void * display_multiplier_init (struct module *parent, const char *fmt, unsigned int flags)
 
static void display_multiplier_probe (struct device_info **available_cards, int *count, void(**deleter)(void *))
 
static void display_multiplier_put_audio_frame (void *state, const struct audio_frame *frame)
 
static bool display_multiplier_putf (void *state, struct video_frame *frame, long long flags)
 
static bool display_multiplier_reconfigure (void *state, struct video_desc desc)
 
static bool display_multiplier_reconfigure_audio (void *state, int quant_samples, int channels, int sample_rate)
 
static void display_multiplier_run (void *state)
 
static void display_multiplier_worker (void *state)
 
 REGISTER_MODULE (multiplier, &display_multiplier_info, LIBRARY_CLASS_VIDEO_DISPLAY, VIDEO_DISPLAY_ABI_VERSION)
 
static void show_help ()
 

Variables

static const struct video_display_info display_multiplier_info
 
static constexpr unsigned int IN_QUEUE_MAX_BUFFER_LEN = 5
 
static constexpr const char * MOD_NAME = "[multiplier] "
 
static constexpr int SKIP_FIRST_N_FRAMES_IN_STREAM = 5
 

Detailed Description

Function Documentation

◆ check_reconf()

static void check_reconf ( struct state_multiplier * s,
struct video_desc * current_desc,
struct video_desc desc )
static

Definition at line 127 of file multiplier.cpp.

129{
130 if (video_desc_eq(desc, *current_desc)) {
131 return;
132 }
133 *current_desc = desc;
134 fprintf(stderr, "RECONFIGURED\n");
135 for (auto &disp : s->displays) {
137 }
138}
struct video_desc desc
std::vector< unique_disp > displays
@ VIDEO_NORMAL
normal video (one tile)
Definition types.h:356
bool display_reconfigure(struct display *d, struct video_desc desc, enum video_mode video_mode)
Reconfigure display to new video format.
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.

References desc, display_reconfigure(), state_multiplier::displays, video_desc_eq(), and VIDEO_NORMAL.

Referenced by display_multiplier_worker().

Here is the call graph for this function:

◆ display_multiplier_done()

static void display_multiplier_done ( void * state)
static

Definition at line 209 of file multiplier.cpp.

210{
211 auto *s = (state_multiplier *) state;
212 delete s;
213}
void ** state

References state.

◆ display_multiplier_get_property()

static bool display_multiplier_get_property ( void * state,
int property,
void * val,
size_t * len )
static

Definition at line 246 of file multiplier.cpp.

247{
248 auto *s = (state_multiplier *) state;
249
250 //TODO Find common properties, for now just return properties of the first display
251 return display_ctl_property(s->displays[0].get(), property, val, len);
252}
int void * val
int void size_t * len
int property
bool display_ctl_property(struct display *d, int property, void *val, size_t *len)
Gets property from video display.

References display_ctl_property(), len, property, state, and val.

Here is the call graph for this function:

◆ display_multiplier_getf()

static struct video_frame * display_multiplier_getf ( void * state)
static

Definition at line 215 of file multiplier.cpp.

216{
217 auto *s = (state_multiplier *) state;
218
219 return vf_alloc_desc_data(s->desc);
220}
struct video_frame * vf_alloc_desc_data(struct video_desc desc)

References state, and vf_alloc_desc_data().

Here is the call graph for this function:

◆ display_multiplier_init()

static void * display_multiplier_init ( struct module * parent,
const char * fmt,
unsigned int flags )
static

Definition at line 88 of file multiplier.cpp.

89{
90 auto s = std::make_unique<state_multiplier>();
91
92 if(!fmt || strlen(fmt) == 0){
93 show_help();
94 return INIT_NOERR;
95 }
96
97 std::string_view fmt_sv = fmt;
98
99 if (fmt_sv == "help") {
100 show_help();
101 return INIT_NOERR;
102 }
103
104 s->parent = parent;
105
106 for(auto tok = tokenize(fmt_sv, '#'); !tok.empty(); tok = tokenize(fmt_sv, '#')){
107 LOG(LOG_LEVEL_VERBOSE) << MOD_NAME << "Initializing display " << tok << "\n";
108 auto display = std::string(tokenize(tok, ':'));
109 auto cfg = std::string(tok);
110
111 struct display *d_ptr;
112 if (initialize_video_display(parent, display.c_str(), cfg.c_str(), flags, NULL, &d_ptr) != 0) {
113 LOG(LOG_LEVEL_FATAL) << "[multiplier] Unable to initialize a display " << display << "!\n";
114 return nullptr;
115 }
116 unique_disp disp(d_ptr);
117 if (display_needs_mainloop(disp.get()) && !s->displays.empty()) {
118 LOG(LOG_LEVEL_ERROR) << "[multiplier] Display " << display << " needs mainloop and should be given first!\n";
119 }
120
121 s->displays.push_back(std::move(disp));
122 }
123
124 return s.release();
125}
const char * fmt
const char unsigned int flags
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_FATAL
errors that prevent UG run
Definition debug.h:58
bool display_needs_mainloop(struct display *d)
int initialize_video_display(struct module *parent, const char *requested_display, const char *fmt, unsigned int flags, const char *postprocess, struct display **out)
Initializes video display.
#define INIT_NOERR
Definition host.h:73
static void show_help()
static constexpr const char * MOD_NAME
const char * parent
Definition settings.cpp:198
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
This struct represents initialized video display state.

References display_needs_mainloop(), flags, fmt, INIT_NOERR, initialize_video_display(), LOG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_VERBOSE, MOD_NAME, parent, show_help(), and tokenize().

Here is the call graph for this function:

◆ display_multiplier_probe()

static void display_multiplier_probe ( struct device_info ** available_cards,
int * count,
void(** deleter )(void *) )
static

Definition at line 282 of file multiplier.cpp.

282 {
284 *available_cards = nullptr;
285 *count = 0;
286}
#define UNUSED(x)
int void(** deleter)(void *))
int count
Definition hd-rum.c:44

References count, deleter, and UNUSED.

◆ display_multiplier_put_audio_frame()

static void display_multiplier_put_audio_frame ( void * state,
const struct audio_frame * frame )
static

Definition at line 267 of file multiplier.cpp.

268{
269 auto *s = static_cast<struct state_multiplier*>(state);
270
271 display_put_audio_frame(s->displays.at(0).get(), frame);
272}
struct video_frame * frame
void display_put_audio_frame(struct display *d, const struct audio_frame *frame)
Puts audio data.

References display_put_audio_frame(), frame, and state.

Here is the call graph for this function:

◆ display_multiplier_putf()

static bool display_multiplier_putf ( void * state,
struct video_frame * frame,
long long flags )
static

Definition at line 222 of file multiplier.cpp.

223{
224 auto *s = (state_multiplier *) state;
225
226 if (flags == PUTF_DISCARD) {
227 vf_free(frame);
228 } else {
229 unique_lock<mutex> lg(s->lock);
230 if (s->incoming_queue.size() >= IN_QUEUE_MAX_BUFFER_LEN) {
231 fprintf(stderr, "Multiplier: queue full!\n");
232 }
233 if (flags != PUTF_BLOCKING && s->incoming_queue.size() >= IN_QUEUE_MAX_BUFFER_LEN) {
234 vf_free(frame);
235 return false;
236 }
237 s->in_queue_decremented_cv.wait(lg, [s]{return s->incoming_queue.size() < IN_QUEUE_MAX_BUFFER_LEN;});
238 s->incoming_queue.push(frame);
239 lg.unlock();
240 s->cv.notify_one();
241 }
242
243 return true;
244}
void vf_free(struct video_frame *buf)
Frees video_frame structure.
#define PUTF_DISCARD
#define PUTF_BLOCKING
static constexpr unsigned int IN_QUEUE_MAX_BUFFER_LEN

References flags, frame, IN_QUEUE_MAX_BUFFER_LEN, PUTF_BLOCKING, PUTF_DISCARD, state, and vf_free().

Here is the call graph for this function:

◆ display_multiplier_reconfigure()

static bool display_multiplier_reconfigure ( void * state,
struct video_desc desc )
static

Definition at line 254 of file multiplier.cpp.

255{
256 auto *s = (state_multiplier *) state;
257
258 s->desc = desc;
259
260 for (auto &disp : s->displays) {
262 }
263
264 return true;
265}

References desc, display_reconfigure(), state, and VIDEO_NORMAL.

Here is the call graph for this function:

◆ display_multiplier_reconfigure_audio()

static bool display_multiplier_reconfigure_audio ( void * state,
int quant_samples,
int channels,
int sample_rate )
static

Definition at line 274 of file multiplier.cpp.

276{
277 auto *s = static_cast<struct state_multiplier *>(state);
278
279 return display_reconfigure_audio(s->displays.at(0).get(), quant_samples, channels, sample_rate);
280}
int int int sample_rate
int int channels
int quant_samples
bool display_reconfigure_audio(struct display *d, int quant_samples, int channels, int sample_rate)

References channels, display_reconfigure_audio(), quant_samples, sample_rate, and state.

Here is the call graph for this function:

◆ display_multiplier_run()

static void display_multiplier_run ( void * state)
static

Multiplier main loop

Runs threads for all slave displays except the first one and an additional one for this display. For the first display given on command-line it then switches to its run-loop. This allows a flawless run on macOS where a GUI worker (GL/SDL) needs to be run in the main thread to work properly.

Definition at line 189 of file multiplier.cpp.

190{
191 auto *s = (state_multiplier *) state;
192
193 assert(!s->displays.empty());
194
195 for (size_t i = 1; i < s->displays.size(); i++) {
196 display_run_new_thread(s->displays[i].get());
197 }
198
199 s->worker_thread = thread(display_multiplier_worker, state);
200
201 display_run_mainloop(s->displays[0].get());
202
203 s->worker_thread.join();
204 for (size_t i = 1; i < s->displays.size(); i++) {
205 display_join(s->displays[i].get());
206 }
207}
void display_run_mainloop(struct display *d)
Display mainloop function.
void display_run_new_thread(struct display *d)
void display_join(struct display *d)
static void display_multiplier_worker(void *state)

References display_join(), display_multiplier_worker(), display_run_mainloop(), display_run_new_thread(), and state.

Here is the call graph for this function:

◆ display_multiplier_worker()

static void display_multiplier_worker ( void * state)
static

Definition at line 140 of file multiplier.cpp.

141{
142 auto *s = (struct state_multiplier *)state;
143 int skipped = 0;
144 struct video_desc display_desc{};
145
146 while (1) {
147 struct video_frame *frame;
148 {
149 unique_lock<mutex> lg(s->lock);
150 s->cv.wait(lg, [s]{return s->incoming_queue.size() > 0;});
151 frame = s->incoming_queue.front();
152 s->incoming_queue.pop();
153 s->in_queue_decremented_cv.notify_one();
154 }
155
156 if (!frame) {
157 for (auto& disp : s->displays) {
158 display_put_frame(disp.get(), NULL, PUTF_BLOCKING);
159 }
160 break;
161 }
162
163 if (skipped < SKIP_FIRST_N_FRAMES_IN_STREAM){
164 skipped++;
165 vf_free(frame);
166 continue;
167 }
168
169 check_reconf(s, &display_desc, video_desc_from_frame(frame));
170
171 for (auto& disp : s->displays) {
172 struct video_frame *real_display_frame = display_get_frame(disp.get());
173 memcpy(real_display_frame->tiles[0].data, frame->tiles[0].data, frame->tiles[0].data_len);
174 display_put_frame(disp.get(), real_display_frame, PUTF_BLOCKING);
175 }
176
177 vf_free(frame);
178 }
179}
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
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.
static constexpr int SKIP_FIRST_N_FRAMES_IN_STREAM
static void check_reconf(struct state_multiplier *s, struct video_desc *current_desc, struct video_desc desc)
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int data_len
length of the data
Definition types.h:288
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345

References check_reconf(), tile::data, tile::data_len, display_get_frame(), display_put_frame(), frame, PUTF_BLOCKING, SKIP_FIRST_N_FRAMES_IN_STREAM, state, video_frame::tiles, vf_free(), and video_desc_from_frame().

Referenced by display_multiplier_run().

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( multiplier ,
& display_multiplier_info,
LIBRARY_CLASS_VIDEO_DISPLAY ,
VIDEO_DISPLAY_ABI_VERSION  )

◆ show_help()

static void show_help ( void )
static

Definition at line 82 of file multiplier.cpp.

82 {
83 printf("Multiplier display\n");
84 printf("Usage:\n");
85 printf("\t-d multiplier:<display1>[:<display_config1>][#<display2>[:<display_config2>]]...\n");
86}

Referenced by display_multiplier_init().

Variable Documentation

◆ display_multiplier_info

const struct video_display_info display_multiplier_info
static
Initial value:
= {
}
#define DISPLAY_NO_GENERIC_FPS_INDICATOR
static void display_multiplier_put_audio_frame(void *state, const struct audio_frame *frame)
static void display_multiplier_done(void *state)
static void * display_multiplier_init(struct module *parent, const char *fmt, unsigned int flags)
static bool display_multiplier_reconfigure_audio(void *state, int quant_samples, int channels, int sample_rate)
static bool display_multiplier_get_property(void *state, int property, void *val, size_t *len)
static bool display_multiplier_reconfigure(void *state, struct video_desc desc)
static void display_multiplier_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
static void display_multiplier_run(void *state)
static bool display_multiplier_putf(void *state, struct video_frame *frame, long long flags)
static struct video_frame * display_multiplier_getf(void *state)

Definition at line 288 of file multiplier.cpp.

◆ IN_QUEUE_MAX_BUFFER_LEN

unsigned int IN_QUEUE_MAX_BUFFER_LEN = 5
staticconstexpr

Definition at line 58 of file multiplier.cpp.

Referenced by display_multiplier_putf().

◆ MOD_NAME

const char* MOD_NAME = "[multiplier] "
staticconstexpr

Definition at line 59 of file multiplier.cpp.

Referenced by display_multiplier_init().

◆ SKIP_FIRST_N_FRAMES_IN_STREAM

int SKIP_FIRST_N_FRAMES_IN_STREAM = 5
staticconstexpr

Definition at line 60 of file multiplier.cpp.

Referenced by display_multiplier_worker().