UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
display.c File Reference
#include "capture_filter.h"
#include "compat/strings.h"
#include "debug.h"
#include "lib_common.h"
#include "utils/color_out.h"
#include "utils/list.h"
#include "utils/text.h"
#include "video.h"
#include "video_codec.h"
#include "video_display.h"
#include "video_frame.h"
Include dependency graph for display.c:

Go to the source code of this file.

Classes

struct  capture_filter_display
 

Macros

#define MAX_QUEUE_LEN   3
 
#define MOD_NAME   "[display cap. f.] "
 

Functions

static void done (void *state)
 
static struct video_frame * filter (void *state, struct video_frame *in)
 
static int init (struct module *parent, const char *cfg, void **state)
 
 REGISTER_HIDDEN_MODULE (display, &capture_filter_display, LIBRARY_CLASS_CAPTURE_FILTER, CAPTURE_FILTER_ABI_VERSION)
 
static codec_t select_display_codec (codec_t *display_codecs, codec_t recv_codec)
 
static void * worker (void *arg)
 

Variables

static const struct capture_filter_info capture_filter_display
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

Definition in file display.c.

Macro Definition Documentation

◆ MAX_QUEUE_LEN

#define MAX_QUEUE_LEN   3
Todo
  • the data is 2x copied

Definition at line 60 of file display.c.

Referenced by filter().

◆ MOD_NAME

#define MOD_NAME   "[display cap. f.] "

Definition at line 61 of file display.c.

Referenced by filter(), init(), and worker().

Function Documentation

◆ done()

static void done ( void * state)
static

Definition at line 204 of file display.c.

205{
206 struct capture_filter_display *s = state;
207 filter(s, NULL);
208 pthread_join(s->thread_id, NULL);
209 display_join(s->d);
210 display_done(s->d);
211 pthread_mutex_destroy(&s->lock);
212 pthread_cond_destroy(&s->cv);
214 free(s);
215}
void ** state
static struct video_frame * filter(void *state, struct video_frame *in)
Definition display.c:186
void display_done(struct display *d)
This function performs cleanup after done.
void display_join(struct display *d)
void simple_linked_list_destroy(struct simple_linked_list *l)
Definition list.cpp:58
struct display * d
Definition display.c:70
struct simple_linked_list * frame_queue
Definition display.c:72
pthread_mutex_t lock
Definition display.c:74
pthread_t thread_id
Definition display.c:76
pthread_cond_t cv
Definition display.c:75

References capture_filter_display::cv, capture_filter_display::d, display_done(), display_join(), filter(), capture_filter_display::frame_queue, capture_filter_display::lock, simple_linked_list_destroy(), state, and capture_filter_display::thread_id.

Here is the call graph for this function:

◆ filter()

static struct video_frame * filter ( void * state,
struct video_frame * in )
static

Definition at line 186 of file display.c.

187{
188 struct capture_filter_display *s = state;
189 struct video_frame *f = in ? vf_get_copy(in) : NULL;
190 pthread_mutex_lock(&s->lock);
192 pthread_mutex_unlock(&s->lock);
193 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Queue full, frame not displayed.\n");
194 vf_free(f);
195 return in;
196 }
198 pthread_mutex_unlock(&s->lock);
199 pthread_cond_signal(&s->cv);
200
201 return in;
202}
void vf_free(struct video_frame *buf)
Frees video_frame structure.
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define MAX_QUEUE_LEN
Definition display.c:60
#define MOD_NAME
Definition display.c:61
void simple_linked_list_append(struct simple_linked_list *l, void *data)
Definition list.cpp:68
int simple_linked_list_size(struct simple_linked_list *l)
Definition list.cpp:93
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
struct video_frame * vf_get_copy(struct video_frame *original_frame)
Makes deep copy of the video frame.

References capture_filter_display::cv, capture_filter_display::frame_queue, capture_filter_display::lock, LOG_LEVEL_WARNING, log_msg(), MAX_QUEUE_LEN, MOD_NAME, simple_linked_list_append(), simple_linked_list_size(), state, vf_free(), and vf_get_copy().

Referenced by done().

Here is the call graph for this function:

◆ init()

static int init ( struct module * parent,
const char * cfg,
void ** state )
static

Definition at line 145 of file display.c.

146{
147 char warn[] = MOD_NAME "Capture filter \"display\" is experimental and may not "
148 "always work as expected, especially if the same SW display "
149 "type (eg. GL) is given as both preview display and a regular one.";
151
152 if (strlen(cfg) == 0 || strcmp(cfg, "help") == 0) {
153 color_printf("Previews captured frame with specified dispay.\n"
154 "Usage:\n"
155 "\t" TBOLD("--capture-filter display:<display_cfg>") "\n");
156 return 1;
157 }
158
159 char *requested_display = strdupa(cfg);
160 char *delim = strchr(requested_display, ':');
161 const char *fmt = "";
162 if (delim) {
163 *delim = '\0';
164 fmt = delim + 1;
165 }
166 struct display *d;
167 int ret = initialize_video_display(parent, requested_display,
168 fmt, 0, NULL, &d);
169 if (ret != 0) {
170 return ret;
171 }
172
173 struct capture_filter_display *s = calloc(1, sizeof *s);
174 s->d = d;
176 pthread_mutex_init(&s->lock, NULL);
177 pthread_cond_init(&s->cv, NULL);
178
180 pthread_create(&s->thread_id, NULL, worker, s);
181
182 *state = s;
183 return 0;
184}
const char * fmt
int color_printf(const char *format,...)
#define TBOLD(x)
Definition color_out.h:70
static void * worker(void *arg)
Definition display.c:88
void display_run_new_thread(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 simple_linked_list * simple_linked_list_init(void)
Definition list.cpp:53
const char * parent
Definition settings.cpp:198
#define strdupa(s)
Definition strings.h:77
This struct represents initialized video display state.
char * wrap_paragraph(char *text)
Definition text.c:204

References color_printf(), capture_filter_display::cv, capture_filter_display::d, display_run_new_thread(), fmt, capture_filter_display::frame_queue, initialize_video_display(), capture_filter_display::lock, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, parent, simple_linked_list_init(), state, strdupa, TBOLD, capture_filter_display::thread_id, worker(), and wrap_paragraph().

Here is the call graph for this function:

◆ REGISTER_HIDDEN_MODULE()

REGISTER_HIDDEN_MODULE ( display ,
& capture_filter_display,
LIBRARY_CLASS_CAPTURE_FILTER ,
CAPTURE_FILTER_ABI_VERSION  )

◆ select_display_codec()

static codec_t select_display_codec ( codec_t * display_codecs,
codec_t recv_codec )
static

Definition at line 79 of file display.c.

79 {
80 if (codec_is_in_set(recv_codec, display_codecs)) {
81 return recv_codec;
82 }
84 get_best_decoder_from(recv_codec, display_codecs, &out);
85 return out;
86}
decoder_t get_best_decoder_from(codec_t in, const codec_t *out_candidates, codec_t *out)
codec_t
Definition types.h:65
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
bool codec_is_in_set(codec_t codec, const codec_t *set)

References codec_is_in_set(), get_best_decoder_from(), and VIDEO_CODEC_NONE.

Referenced by worker().

Here is the call graph for this function:

◆ worker()

static void * worker ( void * arg)
static

Definition at line 88 of file display.c.

88 {
89 struct capture_filter_display *s = arg;
90 struct video_desc configured_desc = { 0 };
91 codec_t display_codecs[VIDEO_CODEC_COUNT + 1];
92 size_t len = sizeof display_codecs;
93 if (!display_ctl_property(s->d, DISPLAY_PROPERTY_CODECS, display_codecs, &len)) {
94 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot query display supported codecs!\n");
95 exit_uv(1);
96 return NULL;
97 }
98 display_codecs[len / sizeof display_codecs[0]] = VIDEO_CODEC_NONE;
99 int rgb_shift[] = { DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, DEFAULT_B_SHIFT };
100 len = sizeof rgb_shift;
101 if (!display_ctl_property(s->d, DISPLAY_PROPERTY_RGB_SHIFT, rgb_shift, &len)) {
102 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Cannot query display RGB shift!\n");
103 }
104 decoder_t dec = NULL;
105 int src_linesize = 0;
106 int dst_linesize = 0;
107
108 while (1) {
109 pthread_mutex_lock(&s->lock);
110 while (simple_linked_list_size(s->frame_queue) == 0) {
111 pthread_cond_wait(&s->cv, &s->lock);
112 }
114 pthread_mutex_unlock(&s->lock);
115 if (!f) {
116 display_put_frame(s->d, NULL, PUTF_BLOCKING); // pass poison pill
117 break;
118 }
119
120 struct video_desc new_desc = video_desc_from_frame(f);
121 if (!video_desc_eq(configured_desc, new_desc)) {
122 struct video_desc display_desc = new_desc;
123 display_desc.color_spec = select_display_codec(display_codecs, new_desc.color_spec);
124 if (!display_desc.color_spec || !display_reconfigure(s->d, display_desc, VIDEO_NORMAL)) {
125 log_msg(LOG_LEVEL_ERROR, "Unable to reconfigure to %s!\n", video_desc_to_string(display_desc));
126 continue;
127 }
128 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Reconfigured display to %s\n", video_desc_to_string(display_desc));
129 dec = get_decoder_from_to(new_desc.color_spec, display_desc.color_spec);
130 src_linesize = vc_get_linesize(f->tiles[0].width, f->color_spec);
131 dst_linesize = vc_get_linesize(f->tiles[0].width, display_desc.color_spec);
132 configured_desc = new_desc;
133 }
134 struct video_frame *df = display_get_frame(s->d);
135 for (size_t i = 0; i < f->tiles[0].height; ++i) {
136 dec((unsigned char *) df->tiles[0].data + i * dst_linesize, (unsigned char *) f->tiles[0].data + i * src_linesize, dst_linesize, rgb_shift[0], rgb_shift[1], rgb_shift[2]);
137 }
139 vf_free(f);
140 }
141
142 return NULL;
143}
int void size_t * len
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
int vc_get_linesize(unsigned int width, codec_t codec)
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
static codec_t select_display_codec(codec_t *display_codecs, codec_t recv_codec)
Definition display.c:79
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.
#define PUTF_BLOCKING
struct video_frame * display_get_frame(struct display *d)
Returns video framebuffer which will be written to.
@ DISPLAY_PROPERTY_RGB_SHIFT
red,green,blue shift - int[3] (bits)
@ DISPLAY_PROPERTY_CODECS
list of natively supported codecs - codec_t[]
void exit_uv(int status)
Definition host.cpp:625
void * simple_linked_list_pop(struct simple_linked_list *l)
Definition list.cpp:82
decoder_t get_decoder_from_to(codec_t in, codec_t out)
#define DEFAULT_B_SHIFT
Definition pixfmt_conv.h:72
#define DEFAULT_R_SHIFT
Definition pixfmt_conv.h:70
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
#define DEFAULT_G_SHIFT
Definition pixfmt_conv.h:71
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 height
Definition types.h:281
codec_t color_spec
Definition types.h:182
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
codec_t color_spec
Definition types.h:306
@ VIDEO_NORMAL
normal video (one tile)
Definition types.h:356
@ VIDEO_CODEC_COUNT
count of known video codecs (including VIDEO_CODEC_NONE)
Definition types.h:108
const char * video_desc_to_string(struct video_desc d)
Definition video.cpp:241
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 video_desc::color_spec, video_frame::color_spec, capture_filter_display::cv, capture_filter_display::d, tile::data, DEFAULT_B_SHIFT, DEFAULT_G_SHIFT, DEFAULT_R_SHIFT, display_ctl_property(), display_get_frame(), DISPLAY_PROPERTY_CODECS, DISPLAY_PROPERTY_RGB_SHIFT, display_put_frame(), display_reconfigure(), exit_uv(), capture_filter_display::frame_queue, get_decoder_from_to(), tile::height, len, capture_filter_display::lock, LOG_LEVEL_ERROR, LOG_LEVEL_NOTICE, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, PUTF_BLOCKING, select_display_codec(), simple_linked_list_pop(), simple_linked_list_size(), video_frame::tiles, vc_get_linesize(), vf_free(), VIDEO_CODEC_COUNT, VIDEO_CODEC_NONE, video_desc_eq(), video_desc_from_frame(), video_desc_to_string(), VIDEO_NORMAL, and tile::width.

Referenced by init().

Here is the call graph for this function:

Variable Documentation

◆ capture_filter_display

const struct capture_filter_info capture_filter_display
static
Initial value:
= {
.init = init,
.done = done,
.filter = filter,
}
static void done(void *state)
Definition display.c:204
static int init(struct module *parent, const char *cfg, void **state)
Definition display.c:145

Definition at line 217 of file display.c.

217 {
218 .init = init,
219 .done = done,
220 .filter = filter,
221};