UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
preview.cpp File Reference
#include <vector>
#include <queue>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <thread>
#include <chrono>
#include "capture_filter.h"
#include "debug.h"
#include "lib_common.h"
#include "utils/color_out.h"
#include "utils/fs.h"
#include "utils/misc.h"
#include "utils/macros.h"
#include "utils/string_view_utils.hpp"
#include "video.h"
#include "video_codec.h"
#include "tools/ipc_frame.h"
#include "tools/ipc_frame_unix.h"
#include "tools/ipc_frame_ug.h"
Include dependency graph for preview.cpp:

Go to the source code of this file.

Classes

struct  state_preview_filter
 

Macros

#define DEFAULT_PREVIEW_FILENAME   "ug_preview_cap_unix"
 
#define DEFAULT_SCALE_H   540
 
#define DEFAULT_SCALE_W   960
 
#define MOD_NAME   "[capture filter preview] "
 

Typedefs

using clk = std::chrono::steady_clock
 
using ipc_frame_conv_func_t
 

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 (preview, &capture_filter_preview, LIBRARY_CLASS_CAPTURE_FILTER, CAPTURE_FILTER_ABI_VERSION)
 
static void show_help ()
 
static void worker (struct state_preview_filter *s, std::string path)
 

Variables

static const struct capture_filter_info capture_filter_preview
 

Detailed Description

Author
Martin Piatka piatk.nosp@m.a@ce.nosp@m.snet..nosp@m.cz

Definition in file preview.cpp.

Macro Definition Documentation

◆ DEFAULT_PREVIEW_FILENAME

#define DEFAULT_PREVIEW_FILENAME   "ug_preview_cap_unix"

Definition at line 69 of file preview.cpp.

Referenced by init(), and show_help().

◆ DEFAULT_SCALE_H

#define DEFAULT_SCALE_H   540

Definition at line 72 of file preview.cpp.

Referenced by show_help().

◆ DEFAULT_SCALE_W

#define DEFAULT_SCALE_W   960

Definition at line 71 of file preview.cpp.

Referenced by show_help().

◆ MOD_NAME

#define MOD_NAME   "[capture filter preview] "

Definition at line 67 of file preview.cpp.

Referenced by filter(), and worker().

Typedef Documentation

◆ clk

Definition at line 85 of file preview.cpp.

◆ ipc_frame_conv_func_t

Initial value:
bool (*)(struct Ipc_frame *dst,
const struct video_frame *src,
unsigned scale_factor)
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
codec_t
Definition types.h:65

Definition at line 80 of file preview.cpp.

Function Documentation

◆ done()

static void done ( void * state)
static

Definition at line 202 of file preview.cpp.

202 {
203 auto s = static_cast<state_preview_filter *> (state);
204
205 {
206 std::lock_guard<std::mutex> lock(s->mut);
207 s->frame_queue.push(nullptr);
208 s->should_exit = true;
209 }
210 s->frame_submitted_cv.notify_one();
211 s->worker_thread.join();
212
213 delete s;
214}
void ** state
std::condition_variable frame_submitted_cv
Definition preview.cpp:89

References state_preview_filter::frame_submitted_cv, and state.

◆ filter()

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

Definition at line 216 of file preview.cpp.

216 {
218
219 auto now = clk::now();
220 if(now < s->next_frame)
221 return in;
222
223 Ipc_frame_uniq ipc_frame;
224 {
225 std::lock_guard<std::mutex> lock(s->mut);
226 if(!s->free_frames.empty()){
227 ipc_frame = std::move(s->free_frames.back());
228 s->free_frames.pop_back();
229 }
230 }
231
232 if(!ipc_frame)
233 return in;
234
235 assert(in->tile_count == 1);
236 const tile *tile = &in->tiles[0];
237
240
241 if(s->ipc_conv(ipc_frame.get(), in, RGB, scale)){
242 std::lock_guard<std::mutex> lock(s->mut);
243 s->frame_queue.push(std::move(ipc_frame));
244 s->frame_submitted_cv.notify_one();
245 } else {
246 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Unable to convert\n");
247 }
248
249 s->next_frame = std::max(s->next_frame + s->frame_time, now);
250
251 return in;
252}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
std::unique_ptr< Ipc_frame, Ipc_frame_deleter > Ipc_frame_uniq
Definition ipc_frame.h:40
int ipc_frame_get_scale_factor(int src_w, int src_h, int target_w, int target_h)
#define MOD_NAME
Definition preview.cpp:67
clk::time_point next_frame
Definition preview.cpp:101
std::vector< Ipc_frame_uniq > free_frames
Definition preview.cpp:92
std::queue< Ipc_frame_uniq > frame_queue
Definition preview.cpp:93
ipc_frame_conv_func_t ipc_conv
Definition preview.cpp:98
clk::duration frame_time
Definition preview.cpp:100
Struct tile is an area of video_frame.
Definition types.h:279
unsigned int width
Definition types.h:280
unsigned int height
Definition types.h:281
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
unsigned int tile_count
Definition types.h:344
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80

References state_preview_filter::frame_queue, state_preview_filter::frame_submitted_cv, state_preview_filter::frame_time, state_preview_filter::free_frames, tile::height, state_preview_filter::ipc_conv, ipc_frame_get_scale_factor(), LOG_LEVEL_WARNING, log_msg(), MOD_NAME, state_preview_filter::mut, state_preview_filter::next_frame, RGB, state, state_preview_filter::target_height, state_preview_filter::target_width, video_frame::tile_count, video_frame::tiles, and tile::width.

Here is the call graph for this function:

◆ init()

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

Definition at line 155 of file preview.cpp.

155 {
156 UNUSED(parent);
157 auto s = std::make_unique<state_preview_filter>();
158
159 s->free_frames.emplace_back(ipc_frame_new());
160 s->free_frames.emplace_back(ipc_frame_new());
161
162 std::string socket_path = get_temp_dir();
163 socket_path += DEFAULT_PREVIEW_FILENAME;
164
165 std::string_view cfg_sv = cfg ? cfg : "";
166 while(!cfg_sv.empty()){
167 auto tok = tokenize(cfg_sv, ':', '"');
168 auto key = tokenize(tok, '=');
169 auto val = tokenize(tok, '=');
170
171 if(key == "help"){
172 show_help();
173 return 1;
174 } else if(key == "path"){
175 socket_path = val;
176 } else if(key == "key"){
177 socket_path = get_temp_dir();
178 socket_path += DEFAULT_PREVIEW_FILENAME;
179 socket_path += val;
180 } else if(key == "target_size"){
181 parse_num(tokenize(val, 'x'), s->target_width);
182 parse_num(tokenize(val, 'x'), s->target_height);
183 } else if(key == "hq"){
184 s->ipc_conv = ipc_frame_from_ug_frame_hq;
185 } else if(key == "rate_limit"){
186 double limit = 1;
188 s->frame_time = std::chrono::duration_cast<clk::duration>(std::chrono::duration<double>(1 / limit));
189 } else {
190 log_msg(LOG_LEVEL_ERROR, "Invalid option\n");
191 return -1;
192 }
193 }
194
195 s->worker_thread = std::thread(worker, s.get(), socket_path);
196
197 *state = s.release();
198
199 return 0;
200}
#define UNUSED(x)
int void * val
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
Ipc_frame * ipc_frame_new()
Definition ipc_frame.cpp:48
bool ipc_frame_from_ug_frame_hq(struct Ipc_frame *dst, const struct video_frame *src, codec_t codec, unsigned scale_factor)
Same as ipc_frame_from_ug_frame, but convert pixfmt first and scale later.
static void worker(struct state_preview_filter *s, std::string path)
Definition preview.cpp:106
#define DEFAULT_PREVIEW_FILENAME
Definition preview.cpp:69
static void show_help()
Definition preview.cpp:143
static const char * get_temp_dir(void)
const char * parent
Definition settings.cpp:198
const char * limit
Definition settings.cpp:199
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
bool parse_num(std::string_view sv, T &res, int base=10)
const char * key
Definition cineform.cpp:125

References DEFAULT_PREVIEW_FILENAME, get_temp_dir(), ipc_frame_from_ug_frame_hq(), ipc_frame_new(), key, limit, LOG_LEVEL_ERROR, log_msg(), parent, parse_num(), show_help(), state, tokenize(), UNUSED, val, and worker().

Here is the call graph for this function:

◆ REGISTER_HIDDEN_MODULE()

REGISTER_HIDDEN_MODULE ( preview ,
& capture_filter_preview,
LIBRARY_CLASS_CAPTURE_FILTER ,
CAPTURE_FILTER_ABI_VERSION  )

◆ show_help()

static void show_help ( void )
static

Definition at line 143 of file preview.cpp.

143 {
144 col() << "preview capture filter\n";
145 col() << "usage:\n";
146 col() << TBOLD(TRED("\t--capture-filter preview") "[:path=<path>][:target_size=<w>x<h>]\n\n");
147 col() << "options:\n";
148 col() << TBOLD("\tpath=<path>") << "\tpath to unix socket to connect to. Default is \""
150 col() << TBOLD("\ttarget_size=<w>x<h>")<< "\tScales the video frame so that the total number of pixel is around <w>x<h>. If -1x-1 is passed, no scaling takes place."
151 << " Defaults are " TOSTRING(DEFAULT_SCALE_W) "x" TOSTRING(DEFAULT_SCALE_H) ".\n";
152 col() << TBOLD("\thq") << "\tUse higher quality downscale\n";
153}
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70
#define TOSTRING(A)
Definition macros.h:49
#define DEFAULT_SCALE_H
Definition preview.cpp:72
#define DEFAULT_SCALE_W
Definition preview.cpp:71

References DEFAULT_PREVIEW_FILENAME, DEFAULT_SCALE_H, DEFAULT_SCALE_W, get_temp_dir(), TBOLD, TOSTRING, and TRED.

Referenced by init().

Here is the call graph for this function:

◆ worker()

static void worker ( struct state_preview_filter * s,
std::string path )
static

Definition at line 106 of file preview.cpp.

106 {
109
110 for(;;){
111 if(!writer){
112 if(s->should_exit)
113 break;
114
115 writer.reset(ipc_frame_writer_new(path.c_str()));
116 if(!writer){
117 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Unable to init ipc writer for path %s\n", path.c_str());
118 sleep(1);
119 continue;
120 }
121 }
122
123 {
124 std::unique_lock<std::mutex> lock(s->mut);
125 s->frame_submitted_cv.wait(lock,
126 [=]{ return !s->frame_queue.empty(); });
127 frame = std::move(s->frame_queue.front());
128 s->frame_queue.pop();
129 }
130
131 if(!frame)
132 break;
133
134 if(!ipc_frame_writer_write(writer.get(), frame.get())){;
135 writer.reset();
136 }
137
138 std::lock_guard<std::mutex> lock(s->mut);
139 s->free_frames.push_back(std::move(frame));
140 }
141}
struct video_frame * frame
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
static void * writer(void *arg)
Definition hd-rum.c:129
bool ipc_frame_writer_write(struct Ipc_frame_writer *writer, const struct Ipc_frame *f)
Ipc_frame_writer * ipc_frame_writer_new(const char *path)
std::unique_ptr< Ipc_frame_writer, Ipc_frame_writer_deleter > Ipc_frame_writer_uniq
std::atomic< bool > should_exit
Definition preview.cpp:90

References frame, state_preview_filter::frame_queue, state_preview_filter::frame_submitted_cv, state_preview_filter::free_frames, ipc_frame_writer_new(), ipc_frame_writer_write(), LOG_LEVEL_VERBOSE, log_msg(), MOD_NAME, state_preview_filter::mut, state_preview_filter::should_exit, and writer().

Referenced by init().

Here is the call graph for this function:

Variable Documentation

◆ capture_filter_preview

const struct capture_filter_info capture_filter_preview
static
Initial value:
= {
.init = init,
.done = done,
.filter = filter,
}
static struct video_frame * filter(void *state, struct video_frame *in)
Definition preview.cpp:216
static void done(void *state)
Definition preview.cpp:202
static int init(struct module *parent, const char *cfg, void **state)
Definition preview.cpp:155

Definition at line 255 of file preview.cpp.

255 {
256 .init = init,
257 .done = done,
258 .filter = filter,
259};