UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
video_display.c
Go to the documentation of this file.
1
15/*
16 * Copyright (c) 2001-2003 University of Southern California
17 * Copyright (c) 2005-2023 CESNET z.s.p.o.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, is permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 *
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 *
33 * This product includes software developed by the University of Southern
34 * California Information Sciences Institute. This product also includes
35 * software developed by CESNET z.s.p.o.
36 *
37 * 4. Neither the name of the University, Institute, CESNET nor the names of
38 * its contributors may be used to endorse or promote products derived from
39 * this software without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
42 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
43 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
44 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
45 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
46 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
51 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
52 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 *
54 */
62#include "config.h"
63#include "config_unix.h"
64#include "config_win32.h"
65#include "debug.h"
66#include "lib_common.h"
67#include "module.h"
68#include "tv.h"
69#include "types.h"
70#include "utils/color_out.h"
71#include "utils/macros.h"
72#include "utils/thread.h"
73#include "video.h"
74#include "video_display.h"
76#include "vo_postprocess.h"
77
78#define DISPLAY_MAGIC 0x01ba7ef1
79#define MOD_NAME "[display] "
80
99
101{
102 printf("Available display devices:\n");
104 if (!full) {
105 printf("(use \"fullhelp\" to show hidden displays)\n");
106 }
107}
108
109/*
110 * Display initialisation and playout routines...
111 */
112
124int initialize_video_display(struct module *parent, const char *requested_display,
125 const char *fmt, unsigned int flags, const char *postprocess, struct display **out)
126{
127 assert (requested_display != NULL && fmt != NULL && out != NULL);
128
129 if (postprocess && (strcmp(postprocess, "help") == 0 || strcmp(postprocess, "fullhelp") == 0)) {
130 show_vo_postprocess_help(strcmp(postprocess, "fullhelp") == 0);
131 return 1;
132 }
133
134 const struct video_display_info *vdi = (const struct video_display_info *)
136
137 if (!vdi) {
138 log_msg(LOG_LEVEL_ERROR, "WARNING: Selected '%s' display card "
139 "was not found.\n", requested_display);
140 return -1;
141 }
142
143 struct display *d = calloc(1, sizeof(struct display));
144 d->magic = DISPLAY_MAGIC;
145 d->funcs = vdi;
146
150
151 d->state = d->funcs->init(&d->mod, fmt, flags);
152
153 if (d->state == NULL) {
154 debug_msg("Unable to start display %s\n",
155 requested_display);
156 module_done(&d->mod);
157 free(d);
158 return -1;
159 } else if (d->state == INIT_NOERR) {
160 module_done(&d->mod);
161 free(d);
162 return 1;
163 }
164
165 if (postprocess) {
167 if (!d->postprocess) {
168 display_done(d);
169 return 1;
170 }
171 }
172
173 d->t0 = get_time_in_ns();
174 d->display_name = strdup(requested_display);
175
176 *out = d;
177 return 0;
178}
179
184void display_done(struct display *d)
185{
186 assert(d->magic == DISPLAY_MAGIC);
187 d->funcs->done(d->state);
188 module_done(&d->mod);
190 free(d->display_name);
191 free(d);
192}
193
198{
199 assert(d->magic == DISPLAY_MAGIC);
200 return d->funcs->run != NULL;
201}
202
203#define CHECK(cmd) do { \
204 int ret = cmd; \
205 if (ret != 0) { \
206 errno = ret; \
207 perror(#cmd); \
208 abort(); \
209 } \
210} while(0)
211
212static void *display_run_helper(void *args)
213{
214 set_thread_name("display");
215 struct display *d = args;
216 assert(d->magic == DISPLAY_MAGIC);
217 d->funcs->run(d->state);
218 return NULL;
219}
220
233{
234 assert(d->magic == DISPLAY_MAGIC);
235 if (d->funcs->run) {
236 d->funcs->run(d->state);
237 } else if (mainloop) {
239 }
240}
241
254{
255 assert(d->magic == DISPLAY_MAGIC);
256 if (display_needs_mainloop(d)) {
257 log_msg(LOG_LEVEL_WARNING, "Display requires mainloop, but is "
258 "being run in a new thread!\n");
259 }
260 if (d->funcs->run) {
261 CHECK(pthread_create(&d->thread_id, NULL, display_run_helper, d));
262 d->thread_started = 1;
263 }
264}
265
273void display_join(struct display *d)
274{
275 assert(d->magic == DISPLAY_MAGIC);
276 if (d->thread_started) {
277 CHECK(pthread_join(d->thread_id, NULL));
278 }
279}
280
281static struct response *process_message(struct display *d, struct msg_universal *msg)
282{
283 if (strncasecmp(msg->text, "postprocess ", strlen("postprocess ")) != 0) {
284 log_msg(LOG_LEVEL_ERROR, "Unknown command '%s'.\n", msg->text);
286 }
287
288 log_msg(LOG_LEVEL_WARNING, "On fly changing postprocessing is currently "
289 "only an experimental feature! Use with caution!\n");
290 const char *text = msg->text + strlen("postprocess ");
291
292 struct vo_postprocess_state *postprocess_old = d->postprocess;
293
294 if (strcmp(text, "flush") != 0) {
296 if (!d->postprocess) {
297 d->postprocess = postprocess_old;
298 log_msg(LOG_LEVEL_ERROR, "Unable to create postprocess '%s'.\n", text);
300 }
301 } else {
302 d->postprocess = NULL;
303 }
304
305 vo_postprocess_done(postprocess_old);
306
308
309 return new_response(RESPONSE_OK, NULL);
310}
311
322{
323 struct message *msg;
324 while((msg = check_message(&d->mod))) {
325 struct response *r = process_message(d, (struct msg_universal *) msg);
326 free_message(msg, r);
327 }
328
329 assert(d->magic == DISPLAY_MAGIC);
330 if (d->postprocess) {
332 } else {
333 return d->funcs->getf(d->state);
334 }
335}
336
337static bool display_frame_helper(struct display *d, struct video_frame *frame, long long timeout_ns)
338{
339 bool ret = d->funcs->putf(d->state, frame, timeout_ns);
341 return ret;
342 }
343 if (ret) {
344 d->frames++;
345 }
346 // display FPS
348 long long seconds_ns = t - d->t0;
349 if (seconds_ns > 5 * NS_IN_SEC) {
350 log_msg(LOG_LEVEL_INFO, TERM_BOLD TERM_FG_MAGENTA "%s" TERM_RESET "%d frames in %g seconds = " TERM_BOLD "%g FPS" TERM_RESET "\n",
352 d->frames, (double) seconds_ns / NS_IN_SEC,
353 (double) d->frames * NS_IN_SEC / seconds_ns);
354 d->frames = 0;
355 d->t0 = t;
356 }
357 return ret;
358}
359
372bool display_put_frame(struct display *d, struct video_frame *frame, long long timeout_ns)
373{
374 assert(d->magic == DISPLAY_MAGIC);
375
376 if (!frame) {
377 return d->funcs->putf(d->state, frame, timeout_ns);
378 }
379
380 if (!d->postprocess) {
381 return display_frame_helper(d, frame, timeout_ns);
382 }
383
384 bool display_ret = true;
385 for (int i = 0; i < d->pp_output_frames_count; ++i) {
386 struct video_frame *display_frame = d->funcs->getf(d->state);
387 int ret = vo_postprocess(d->postprocess,
388 frame,
390 d->display_pitch);
391 frame = NULL;
392 if (!ret) {
394 return 1;
395 }
396
397 display_ret = display_frame_helper(d, display_frame, timeout_ns);
398 }
399 return display_ret;
400
401}
402
414{
415
416 assert(d->magic == DISPLAY_MAGIC);
417
418 d->saved_desc = desc;
420 bool rc = false;
421 struct video_desc display_desc = desc;
422
423 if (d->postprocess) {
424 bool pp_does_change_tiling_mode = false;
425 size_t len = sizeof(pp_does_change_tiling_mode);
427 &pp_does_change_tiling_mode, &len)) {
428 if(len == 0) {
429 // just for sake of completness since it shouldn't be a case
430 log_msg(LOG_LEVEL_WARNING, "Warning: unable to get pp tiling mode!\n");
431 }
432 }
433 struct video_desc pp_desc = desc;
434
435 if (!pp_does_change_tiling_mode) {
438 pp_desc.tile_count = 1;
439 }
440 if (!vo_postprocess_reconfigure(d->postprocess, pp_desc)) {
441 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to reconfigure video "
442 "postprocess.\n");
443 return false;
444 }
445 int render_mode; // WTF ?
446 vo_postprocess_get_out_desc(d->postprocess, &display_desc, &render_mode, &d->pp_output_frames_count);
447 rc = d->funcs->reconfigure_video(d->state, display_desc);
448 len = sizeof d->display_pitch;
451 &d->display_pitch, &len);
452 if (d->display_pitch == PITCH_DEFAULT) {
453 d->display_pitch = vc_get_linesize(display_desc.width, display_desc.color_spec);
454 }
455 } else {
456 rc = d->funcs->reconfigure_video(d->state, desc);
457 }
458 if (rc) {
459 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Successfully reconfigured display to %s\n",
460 video_desc_to_string(display_desc));
461 } else {
462 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to reconfigure display to %s\n",
463 video_desc_to_string(display_desc));
464 }
465
466 return rc;
467}
468
474static void
476 codec_t *display_codecs, size_t *display_codecs_count,
477 codec_t *pp_codecs, size_t pp_codecs_count)
478{
479 codec_t new_disp_codecs[VC_COUNT];
480 size_t new_disp_codec_count = 0;
481
482 for (unsigned i = 0; i < pp_codecs_count; ++i) {
483 const struct video_desc in_desc = { 1920, 1080,
484 pp_codecs[i], 30,
485 PROGRESSIVE, 1 };
486 vo_postprocess_reconfigure(postprocess, in_desc);
487 int out_display_mode = 0; // unused
488 int out_frames_count = 0; // "
489 struct video_desc out_desc = { 0 };
490 vo_postprocess_get_out_desc(postprocess, &out_desc,
491 &out_display_mode,
492 &out_frames_count);
493 assert(out_desc.color_spec != VC_NONE);
494
495 for (unsigned j = 0; j < *display_codecs_count; ++j) {
496 if (display_codecs[j] == out_desc.color_spec) {
497 new_disp_codecs[new_disp_codec_count++] =
498 in_desc.color_spec;
499 }
500 }
501 }
502 *display_codecs_count = new_disp_codec_count;
503 memcpy(display_codecs, new_disp_codecs,
504 new_disp_codec_count * sizeof(codec_t));
505}
506
515bool display_ctl_property(struct display *d, int property, void *val, size_t *len)
516{
517 assert(d->magic == DISPLAY_MAGIC);
518 if (!d->postprocess){
519 return d->funcs->ctl_property(d->state, property, val, len);
520 }
521
522 switch (property) {
524 *(int *) val = PITCH_DEFAULT;
525 *len = sizeof(int);
526 return true;
528 {
529 codec_t display_codecs[VIDEO_CODEC_COUNT];
530 codec_t pp_codecs[VIDEO_CODEC_COUNT];
531 size_t display_codecs_count, pp_codecs_count;
532 size_t nlen;
533 bool ret;
534 nlen = sizeof display_codecs;
535 ret = d->funcs->ctl_property(d->state, DISPLAY_PROPERTY_CODECS, display_codecs, &nlen);
536 if (!ret) {
537 log_msg(LOG_LEVEL_ERROR, "[Display] Unable to get display supported codecs.\n");
538 return false;
539 }
540 display_codecs_count = nlen / sizeof(codec_t);
541 nlen = sizeof pp_codecs;
543 if (ret) {
544 if (nlen == 0) { // problem detected
545 log_msg(LOG_LEVEL_ERROR, "[Decoder] Unable to get supported codecs.\n");
546 return false;
547
548 }
549 pp_codecs_count = nlen / sizeof(codec_t);
551 d->postprocess, display_codecs,
552 &display_codecs_count, pp_codecs,
553 pp_codecs_count);
554 }
555 nlen = display_codecs_count * sizeof(codec_t);
556 if (nlen <= *len) {
557 *len = nlen;
558 memcpy(val, display_codecs, nlen);
559 return true;
560 }
561 return false;
562 }
563 break;
564 default:
565 return d->funcs->ctl_property(d->state, property, val, len);
566 }
567}
568
574void display_put_audio_frame(struct display *d, const struct audio_frame *frame)
575{
576 assert(d->magic == DISPLAY_MAGIC);
578}
579
591{
592 assert(d->magic == DISPLAY_MAGIC);
593 if (!d->funcs->reconfigure_audio) {
594 log_msg(LOG_LEVEL_FATAL, MOD_NAME "Selected display '%s' doesn't support audio!\n", d->display_name);
596 return FALSE;
597 }
599}
600
605{
606 struct video_desc desc;
607
608 desc.width = 512;
609 desc.height = 512;
612 desc.fps = 1;
613 desc.tile_count = 1;
614
616
617 const char *data = splash_data;
618 memset(frame->tiles[0].data, 0, frame->tiles[0].data_len);
619 for (unsigned int y = 0; y < splash_height; ++y) {
620 char *line = frame->tiles[0].data;
621 line += vc_get_linesize(frame->tiles[0].width,
622 frame->color_spec) *
623 (((frame->tiles[0].height - splash_height) / 2) + y);
624 line += vc_get_linesize(
625 (frame->tiles[0].width - splash_width)/2,
627 for (unsigned int x = 0; x < splash_width; ++x) {
628 HEADER_PIXEL(data,line);
629 line += 4;
630 }
631 }
632 return frame;
633}
634
635const char *
636get_audio_conn_flag_name(int audio_init_flag)
637{
638 switch (audio_init_flag) {
639 case 0:
640 return "(none)";
642 return "embedeed";
644 return "AES/EBU";
646 return "analog";
647 default:
648 UG_ASSERT(0 && "Wrong audio flag!");
649 }
650}
651
652void dev_add_option(struct device_info *dev, const char *name, const char *desc, const char *key, const char *opt_str, bool is_boolean){
653
654 int idx = 0;
655 while(*dev->options[idx].key)
656 idx++;
657
658 strncpy(dev->options[idx].display_name, name, sizeof(dev->options[idx].display_name) - 1);
659 strncpy(dev->options[idx].display_desc, desc, sizeof(dev->options[idx].display_desc) - 1);
660 strncpy(dev->options[idx].key, key, sizeof(dev->options[idx].key) - 1);
661 strncpy(dev->options[idx].opt_str, opt_str, sizeof(dev->options[idx].opt_str) - 1);
662 dev->options[idx].is_boolean = is_boolean;
663}
int void * val
struct video_desc desc
int int int sample_rate
int int channels
struct video_frame * frame
const char * fmt
int void size_t * len
const char unsigned int flags
int property
int quant_samples
int vc_get_linesize(unsigned int width, codec_t codec)
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
#define TERM_BOLD
Definition color_out.h:48
#define TERM_RESET
Definition color_out.h:47
#define TERM_FG_MAGENTA
Definition color_out.h:54
#define FALSE
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
Definition debug.h:92
#define LOG_LEVEL_FATAL
errors that prevent UG run
Definition debug.h:58
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
bool display_reconfigure_audio(struct display *d, int quant_samples, int channels, int sample_rate)
void display_put_audio_frame(struct display *d, const struct audio_frame *frame)
Puts audio data.
#define PITCH_DEFAULT
default pitch, i. e. respective linesize
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.
#define DISPLAY_FLAG_AUDIO_ANALOG
void display_run_mainloop(struct display *d)
Display mainloop function.
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 DISPLAY_FLAG_AUDIO_AESEBU
#define PUTF_DISCARD
#define VIDEO_DISPLAY_ABI_VERSION
const char * get_audio_conn_flag_name(int audio_init_flag)
#define DISPLAY_FLAG_AUDIO_EMBEDDED
bool display_needs_mainloop(struct display *d)
struct video_frame * get_splashscreen()
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.
void list_video_display_devices(bool full)
struct video_frame * display_get_frame(struct display *d)
Returns video framebuffer which will be written to.
@ DISPLAY_PROPERTY_BUF_PITCH
requested framebuffer pitch - int (bytes), may be PITCH_DEFAULT
@ DISPLAY_PROPERTY_CODECS
list of natively supported codecs - codec_t[]
void module_init_default(struct module *module_data)
Definition module.c:48
void module_register(struct module *module_data, struct module *parent)
Definition module.c:82
void module_done(struct module *module_data)
Definition module.c:93
@ MODULE_CLASS_DISPLAY
Definition module.h:94
void exit_uv(int status)
Definition host.cpp:625
void * mainloop_udata
Definition host.cpp:187
mainloop_t mainloop
mainloop to be run if display mainloop isn't run
Definition host.cpp:186
#define INIT_NOERR
Definition host.h:73
#define EXIT_FAIL_USAGE
Definition host.h:61
void list_modules(enum library_class cls, int abi_version, bool full)
const void * load_library(const char *name, enum library_class cls, int abi_version)
@ LIBRARY_CLASS_VIDEO_DISPLAY
Definition lib_common.h:79
#define UG_ASSERT(cond)
unconditional alternative to assert that is not affected by NDEBUG macro
Definition macros.h:78
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_OK
Definition messaging.h:57
#define RESPONSE_BAD_REQUEST
Definition messaging.h:60
struct msghdr msg
static void display_frame(struct state_sdl *s, struct video_frame *frame)
Definition sdl.cpp:219
const char * parent
Definition settings.cpp:198
const char * name
Definition settings.cpp:193
#define HEADER_PIXEL(data, pixel)
Definition splashscreen.h:8
static const char *const splash_data
static const unsigned int splash_width
Definition splashscreen.h:3
static const unsigned int splash_height
Definition splashscreen.h:4
struct used to comunicate with audio capture/playback device
Definition types.h:99
struct device_option options[64]
Definition types.h:398
char display_name[512]
Definition types.h:369
char key[512]
Definition types.h:376
char display_desc[512]
Definition types.h:370
char opt_str[512]
Definition types.h:377
bool is_boolean
Definition types.h:379
This struct represents initialized video display state.
enum video_mode saved_mode
struct module mod
void * state
state of the created video capture driver
struct video_desc saved_desc
_Bool thread_started
const struct video_display_info * funcs
char * display_name
int display_pitch
int pp_output_frames_count
time_ns_t t0
struct vo_postprocess_state * postprocess
pthread_t thread_id
thread ID of the display thread (
uint32_t magic
For debugging. Conatins DISPLAY_MAGIC.
enum module_class cls
Definition module.h:115
char text[]
Definition messaging.cpp:68
unsigned int width
Definition types.h:280
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
unsigned int height
Definition types.h:281
unsigned int tile_count
Definition types.h:185
codec_t color_spec
Definition types.h:182
enum interlacing_t interlacing
Definition types.h:184
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
void(* run)(void *state)
callback to display main event loop; may be NULL
struct video_frame *(* getf)(void *state)
void *(* init)(struct module *parent, const char *fmt, unsigned int flags)
void(* put_audio_frame)(void *state, const struct audio_frame *frame)
may be NULL
bool(* reconfigure_video)(void *state, struct video_desc desc)
bool(* putf)(void *state, struct video_frame *frame, long long timeout_ns)
const char * generic_fps_indicator_prefix
NO_GENERIC_FPS_INDICATOR or pointer to preferred module name.
bool(* reconfigure_audio)(void *state, int quant_samples, int channels, int sample_rate)
bool(* ctl_property)(void *state, int property, void *val, size_t *len)
void(* done)(void *state)
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
codec_t color_spec
Definition types.h:306
void set_thread_name(const char *name)
Definition thread.c:72
long long time_ns_t
Definition tv.h:81
#define NS_IN_SEC
Definition tv.h:92
static time_ns_t get_time_in_ns()
Definition tv.h:101
This file contains some common data types.
video_mode
Definition types.h:354
@ PROGRESSIVE
progressive frame
Definition types.h:164
codec_t
Definition types.h:65
@ VC_NONE
Definition types.h:67
@ VIDEO_CODEC_COUNT
count of known video codecs (including VIDEO_CODEC_NONE)
Definition types.h:108
@ VC_COUNT
Definition types.h:109
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
const char * video_desc_to_string(struct video_desc d)
Definition video.cpp:241
int get_video_mode_tiles_x(enum video_mode video_mode)
Definition video.cpp:108
int get_video_mode_tiles_y(enum video_mode video_mode)
Definition video.cpp:113
This is an umbrella header for video functions.
const char * opt_str
Definition cineform.cpp:127
const char * key
Definition cineform.cpp:125
const bool is_boolean
#define CHECK(cmd)
bool display_reconfigure(struct display *d, struct video_desc desc, enum video_mode video_mode)
Reconfigure display to new video format.
static void restrict_returned_codecs(struct vo_postprocess_state *postprocess, codec_t *display_codecs, size_t *display_codecs_count, codec_t *pp_codecs, size_t pp_codecs_count)
void dev_add_option(struct device_info *dev, const char *name, const char *desc, const char *key, const char *opt_str, bool is_boolean)
static bool display_frame_helper(struct display *d, struct video_frame *frame, long long timeout_ns)
#define MOD_NAME
static void * display_run_helper(void *args)
static struct response * process_message(struct display *d, struct msg_universal *msg)
#define DISPLAY_MAGIC
void show_vo_postprocess_help(bool full)
struct vo_postprocess_state * vo_postprocess_init(const char *config_string)
bool vo_postprocess_get_property(struct vo_postprocess_state *s, int property, void *val, size_t *len)
bool vo_postprocess_reconfigure(struct vo_postprocess_state *s, struct video_desc desc)
void vo_postprocess_get_out_desc(struct vo_postprocess_state *s, struct video_desc *out, int *display_mode, int *out_frames_count)
void vo_postprocess_done(struct vo_postprocess_state *s)
bool vo_postprocess(struct vo_postprocess_state *s, struct video_frame *in, struct video_frame *out, int req_pitch)
struct video_frame * vo_postprocess_getf(struct vo_postprocess_state *s)
#define VO_PP_DOES_CHANGE_TILING_MODE
#define VO_PP_PROPERTY_CODECS