174{
176 bool prefill = false;
177 int skipped = 0;
178
179 while (1) {
181 {
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();
187 }
188
191 break;
192 }
193
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()) {
197 it->second = now;
199 continue;
200 }
201
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++);
207 } else {
208 ++it;
209 }
210 }
211
214 s->old_ssrc = s->current_ssrc;
216 prefill = true;
217 skipped = 0;
218 } else {
219 skipped++;
220 continue;
221 }
222 }
223
225
226 if (s->frames[s->current_ssrc].size() >=
BUFFER_LEN) {
227 prefill = false;
228 }
229
230
231
233 continue;
234 }
235
236 if (s->old_ssrc != 0) {
237 if (prefill) {
238 auto & ssrc_list = s->frames[s->old_ssrc];
239 if (ssrc_list.empty()) {
240 fprintf(stderr, "SMOLIK1!\n");
241 } else {
242 frame = ssrc_list.front();
243 ssrc_list.pop_front();
244
246
250 real_display_frame->
ssrc = s->current_ssrc;
252 }
253 } else {
254 auto & old_list = s->frames[s->old_ssrc];
255 auto & new_list = s->frames[s->current_ssrc];
256
257 s->transition += 1;
258
259 if (old_list.empty() || new_list.empty()) {
260 fprintf(stderr, "SMOLIK2!\n");
261
263 } else {
265
266 old_frame = old_list.front();
267 old_list.pop_front();
268 new_frame = new_list.front();
269 new_list.pop_front();
270
273
275
277
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] =
284 }
285 } else {
286
287 fprintf(stderr, "SMOLIK4!\n");
289 }
292 real_display_frame->
ssrc = s->current_ssrc;
294 }
295 }
296 } else {
297 if (!prefill) {
298 if (s->frames[s->current_ssrc].empty()) {
299
300 fprintf(stderr, "SMOLIK3!\n");
301 } else {
302 frame = s->frames[s->current_ssrc].front();
303 s->frames[s->current_ssrc].pop_front();
304
306
310 real_display_frame->
ssrc = s->current_ssrc;
312 }
313 }
314 }
315
317 for (
auto &&
frame : s->frames[s->old_ssrc]) {
319 }
320
321 s->frames.erase(s->old_ssrc);
322
323 s->disabled_ssrc[s->old_ssrc] = chrono::system_clock::now();
324 s->old_ssrc = 0u;
325 s->transition = 0;
326 }
327 }
328
330}
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
static constexpr int BUFFER_LEN
static constexpr chrono::milliseconds SOURCE_TIMEOUT(500)
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
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.
void display_join(struct display *d)
struct video_frame * display_get_frame(struct display *d)
Returns video framebuffer which will be written to.
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]