52#include <condition_variable>
61#include <unordered_map>
77 for (
auto && ssrc_map :
frames) {
78 for (
auto &&
frame : ssrc_map.second) {
94 map<uint32_t, list<struct video_frame *> >
frames;
95 unordered_map<uint32_t, chrono::system_clock::time_point>
disabled_ssrc;
98 condition_variable
cv;
105 shared_ptr<struct state_blend_common>
common;
113 char fmt[2 +
sizeof(
void *) * 2 + 1] =
"";
117 "blend",
fmt, 0, NULL, &out);
118 if (rc == 0)
return out;
else return NULL;
125 char *fmt_copy = NULL;
126 const char *requested_display =
"";
127 const char *cfg =
"";
130 if (
fmt ==
nullptr || strlen(
fmt) == 0 ||
"help"s ==
fmt) {
131 cout <<
"blend is a helper display to combine (blend) multiple incoming streams.\n"
132 "Please do not use directly, intended for internal purposes!\n";
138 if (isdigit(
fmt[0]) != 0) {
140 sscanf(
fmt,
"%p", &orig);
144 fmt_copy = strdup(
fmt);
145 requested_display = fmt_copy;
146 char *delim = strchr(fmt_copy,
':');
147 if (delim !=
nullptr) {
153 assert(ret == 0 &&
"Unable to initialize real display for blend");
158 s->common->parent =
parent;
168 fprintf(stderr,
"RECONFIGURED\n");
176 bool prefill =
false;
182 unique_lock<mutex> lg(s->lock);
183 s->cv.wait(lg, [s]{
return s->incoming_queue.size() > 0;});
184 frame = s->incoming_queue.front();
185 s->incoming_queue.pop();
186 s->in_queue_decremented_cv.notify_one();
194 chrono::system_clock::time_point now = chrono::system_clock::now();
195 auto it = s->disabled_ssrc.find(
frame->
ssrc);
196 if (it != s->disabled_ssrc.end()) {
202 it = s->disabled_ssrc.begin();
203 while (it != s->disabled_ssrc.end()) {
204 if (chrono::duration_cast<chrono::milliseconds>(now - it->second) >
SOURCE_TIMEOUT) {
205 verbose_msg(
"Source 0x%08" PRIx32
" timeout. Deleting from blend display.\n", it->first);
206 s->disabled_ssrc.erase(it++);
214 s->old_ssrc = s->current_ssrc;
226 if (s->frames[s->current_ssrc].size() >=
BUFFER_LEN) {
236 if (s->old_ssrc != 0) {
238 auto & ssrc_list = s->frames[s->old_ssrc];
239 if (ssrc_list.empty()) {
240 fprintf(stderr,
"SMOLIK1!\n");
242 frame = ssrc_list.front();
243 ssrc_list.pop_front();
250 real_display_frame->
ssrc = s->current_ssrc;
254 auto & old_list = s->frames[s->old_ssrc];
255 auto & new_list = s->frames[s->current_ssrc];
259 if (old_list.empty() || new_list.empty()) {
260 fprintf(stderr,
"SMOLIK2!\n");
266 old_frame = old_list.front();
267 old_list.pop_front();
268 new_frame = new_list.front();
269 new_list.pop_front();
279 for (
unsigned int i = 0; i < new_frame->
tiles[0].
data_len; ++i) {
280 int old_val = ((
unsigned char *) old_frame->
tiles[0].
data)[i];
281 int new_val = ((
unsigned char *) new_frame->
tiles[0].
data)[i];
282 ((
unsigned char *) real_display_frame->
tiles[0].
data)[i] =
287 fprintf(stderr,
"SMOLIK4!\n");
292 real_display_frame->
ssrc = s->current_ssrc;
298 if (s->frames[s->current_ssrc].empty()) {
300 fprintf(stderr,
"SMOLIK3!\n");
302 frame = s->frames[s->current_ssrc].front();
303 s->frames[s->current_ssrc].pop_front();
310 real_display_frame->
ssrc = s->current_ssrc;
317 for (
auto &&
frame : s->frames[s->old_ssrc]) {
321 s->frames.erase(s->old_ssrc);
323 s->disabled_ssrc[s->old_ssrc] = chrono::system_clock::now();
352 unique_lock<mutex> lg(s->lock);
354 fprintf(stderr,
"blend: queue full!\n");
361 s->incoming_queue.push(
frame);
410 *available_cards =
nullptr;
struct video_frame * frame
const char unsigned int flags
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
static bool display_blend_get_property(void *state, int property, void *val, size_t *len)
static constexpr unsigned int IN_QUEUE_MAX_BUFFER_LEN
static constexpr int BUFFER_LEN
static struct display * display_blend_fork(void *state)
static constexpr chrono::milliseconds SOURCE_TIMEOUT(500)
static void display_blend_done(void *state)
static bool display_blend_putf(void *state, struct video_frame *frame, long long flags)
static void display_blend_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
static bool display_blend_reconfigure(void *state, struct video_desc desc)
static void check_reconf(struct state_blend_common *s, struct video_desc desc)
static constexpr int TRANSITION_COUNT
static constexpr int SKIP_FIRST_N_FRAMES_IN_STREAM
static bool display_blend_reconfigure_audio(void *state, int quant_samples, int channels, int sample_rate)
static void display_blend_run(void *state)
static void display_blend_put_audio_frame(void *state, const struct audio_frame *frame)
static void * display_blend_init(struct module *parent, const char *fmt, unsigned int flags)
static struct video_frame * display_blend_getf(void *state)
static const struct video_display_info display_blend_info
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.
bool display_ctl_property(struct display *d, int property, void *val, size_t *len)
Gets property from video display.
void display_run_new_thread(struct display *d)
#define VIDEO_DISPLAY_ABI_VERSION
#define DISPLAY_NO_GENERIC_FPS_INDICATOR
void display_done(struct display *d)
This function performs cleanup after done.
void display_join(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.
struct video_frame * display_get_frame(struct display *d)
Returns video framebuffer which will be written to.
@ DISPLAY_PROPERTY_SUPPORTS_MULTI_SOURCES
@ LIBRARY_CLASS_VIDEO_DISPLAY
#define REGISTER_HIDDEN_MODULE(name, info, lclass, abi)
struct used to comunicate with audio capture/playback device
This struct represents initialized video display state.
struct display *(* fork_display)(void *state)
map< uint32_t, list< struct video_frame * > > frames
struct display * real_display
condition_variable in_queue_decremented_cv
unordered_map< uint32_t, chrono::system_clock::time_point > disabled_ssrc
queue< struct video_frame * > incoming_queue
struct video_desc display_desc
shared_ptr< struct state_blend_common > common
char * data
Raw tile data. Pointer must be at least 4B aligned.
unsigned int data_len
length of the data
Struct video_frame represents a video frame and contains video description.
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
@ VIDEO_NORMAL
normal video (one tile)
This is an umbrella header for video functions.
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.