UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
hd-rum-decompress.cpp
Go to the documentation of this file.
1
7/*
8 * Copyright (c) 2013-2024 CESNET
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, is permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * 3. Neither the name of CESNET nor the names of its contributors may be
23 * used to endorse or promote products derived from this software without
24 * specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
28 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
30 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
37 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#include <condition_variable>
41#include <iostream>
42#include <map>
43#include <memory>
44#include <mutex>
45#include <queue>
46#include <thread>
47
50
51#include "audio/types.h"
52#include "capture_filter.h"
53#include "debug.h"
54#include "host.h"
55#include "rtp/rtp.h"
56#include "tv.h"
57#include "video.h"
58#include "video_display.h"
60#include "video_rxtx.hpp" // for param_u, video_rxtx
62
64
65static constexpr int MAX_QUEUE_SIZE = 2;
66
67using std::condition_variable;
68using std::condition_variable;
69using std::map;
70using std::mutex;
71using std::string;
72using std::thread;
73using std::unique_lock;
74
78
80
81 std::queue<std::shared_ptr<video_frame>> received_frame;
82
83 mutex lock;
84 condition_variable have_frame_cv;
85 condition_variable frame_consumed_cv;
87
91
92 void frame_arrived(struct video_frame *f, struct audio_frame *a);
93
95 void worker();
96
98
100};
101
103{
105 if (a) {
106 LOG(LOG_LEVEL_WARNING) << "Unexpectedly receiving audio!\n";
108 }
109 auto deleter = vf_free;
110 // apply capture filter
111 if (f) {
113 }
114 if (f && f->callbacks.dispose) {
116 }
117 if (!f) {
118 return;
119 }
120
121 unique_lock<mutex> l(lock);
122 if (received_frame.size() >= MAX_QUEUE_SIZE) {
123 fprintf(stderr, "Hd-rum-decompress max queue size (%d) reached!\n", MAX_QUEUE_SIZE);
124 }
125 frame_consumed_cv.wait(l, [this]{ return received_frame.size() < MAX_QUEUE_SIZE; });
126 received_frame.emplace(f, deleter);
127 l.unlock();
128 have_frame_cv.notify_one();
129}
130} // end of hd-rum-decompress namespace
131
132using namespace hd_rum_decompress;
133
134ssize_t hd_rum_decompress_write(void *state, void *buf, size_t count)
135{
137
139 (char *) buf, count);
140}
141
143{
145 bool should_exit = false;
146 while (!should_exit) {
147 unique_lock<mutex> l(lock);
148 PROFILE_DETAIL("wait for received frame");
149 have_frame_cv.wait(l, [this]{return !received_frame.empty();});
150
151 auto frame = std::move(received_frame.front());
152 l.unlock();
153 PROFILE_DETAIL("");
154
155 if(!frame){
156 should_exit = true;
157 } else {
159 }
160
161 // we are removing from queue now because special messages are "accepted" when queue is empty
162 l.lock();
163 received_frame.pop();
164 l.unlock();
165 frame_consumed_cv.notify_one();
166 }
167}
168
169void *hd_rum_decompress_init(struct module *parent, struct hd_rum_output_conf conf, const char *capture_filter, struct state_recompress *recompress)
170{
171 if (conf.mode == CONFERENCE && strcmp(conf.arg, "help") == 0) {
172 struct display *display = nullptr;
173 const int ret = initialize_video_display(
174 parent, "conference", "reflhelp", 0, nullptr, &display);
175 assert(ret == 1);
176 return nullptr;
177 }
178
180 int force_ip_version = 0;
181
183
184 s->recompress = recompress;
185 s->common.force_ip_version = force_ip_version;
187
188 char cfg[128] = "";
189 int ret;
190
191 switch(conf.mode){
192 case NORMAL:
193 snprintf(cfg, sizeof cfg, "%p", s);
194 ret = initialize_video_display(parent, "pipe", cfg, 0, NULL, &s->display);
195 break;
196 case BLEND:
197 snprintf(cfg, sizeof cfg, "pipe:%p", s);
198 ret = initialize_video_display(parent, "blend", cfg, 0, NULL, &s->display);
199 break;
200 case CONFERENCE:
201 snprintf(cfg, sizeof cfg, "pipe:%p#%s", s, conf.arg);
202 ret = initialize_video_display(parent, "conference", cfg, 0, NULL, &s->display);
203 break;
204 }
205
206 assert(ret == 0 && "Unable to initialize auxiliary display");
207
208 map<string, param_u> params;
209
210 // common
211 s->common.parent = parent;
212 params["exporter"].ptr = NULL;
213 params["compression"].str = "none";
214 params["rxtx_mode"].i = MODE_RECEIVER;
215
216 //RTP
217 // should be localhost and RX TX ports the same (here dynamic) in order to work like a pipe
218 params["receiver"].str = "localhost";
219 params["rx_port"].i = 0;
220 params["tx_port"].i = 0;
221 params["common"].ptr = &s->common;
222 params["fec"].str = "none";
223 params["bitrate"].ll = 0;
224 params["video_delay"].vptr = 0;
225
226 // UltraGrid RTP
227 params["decoder_mode"].l = VIDEO_NORMAL;
228 params["display_device"].ptr = s->display;
229
230 try {
231 s->video_rxtx = dynamic_cast<ultragrid_rtp_video_rxtx *>(video_rxtx::create("ultragrid_rtp", params));
232 assert (s->video_rxtx);
233
237
239 log_msg(LOG_LEVEL_ERROR, "Unable to initialize capture filter!\n");
240 return nullptr;
241 }
242 } catch (string const &s) {
243 LOG(LOG_LEVEL_ERROR) << s << "\n";
244 return nullptr;
245 }
246
247 return (void *) s;
248}
249
252
253 s->receiver_thread.join();
254
255 {
256 unique_lock<mutex> l(s->lock);
257 s->received_frame.push({});
258 l.unlock();
259 s->have_frame_cv.notify_one();
260 }
261
262 s->worker_thread.join();
263
264 display_put_frame(s->display, NULL, 0);
265 s->video_rxtx->join();
266
267 delete s->video_rxtx;
268
272
273 delete s;
274}
void ** state
struct video_frame * frame
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
This file contains definition of some common audio types.
#define AUDIO_FRAME_DISPOSE(frame)
Definition types.h:117
void capture_filter_destroy(struct capture_filter *state)
struct video_frame * capture_filter(struct capture_filter *state, struct video_frame *frame)
int capture_filter_init(struct module *parent, const char *cfg, struct capture_filter **state)
struct rtp * m_network_device
Definition rtp.hpp:71
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
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_run_new_thread(struct display *d)
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 * hd_rum_decompress_init(struct module *parent, struct hd_rum_output_conf conf, const char *capture_filter, struct state_recompress *recompress)
ssize_t hd_rum_decompress_write(void *state, void *buf, size_t count)
void hd_rum_decompress_done(void *state)
static constexpr int MAX_QUEUE_SIZE
@ NORMAL
@ BLEND
@ CONFERENCE
void recompress_process_async(state_recompress *s, std::shared_ptr< video_frame > frame)
int count
Definition hd-rum.c:44
static struct @19 params[100]
#define MODE_RECEIVER
Definition host.h:103
#define COMMON_OPTS_INIT
Definition host.h:179
#define PROFILE_FUNC
#define PROFILE_DETAIL(name)
int rtp_send_raw_rtp_data(struct rtp *session, char *buffer, int buffer_len)
Definition rtp.c:1518
const char * parent
Definition settings.cpp:198
struct used to comunicate with audio capture/playback device
Definition types.h:99
struct module * parent
Definition host.h:171
time_ns_t start_time
Definition host.h:178
int force_ip_version
Definition host.h:176
This struct represents initialized video display state.
void frame_arrived(struct video_frame *f, struct audio_frame *a)
std::queue< std::shared_ptr< video_frame > > received_frame
enum hd_rum_mode_t mode
void(* dispose)(struct video_frame *)
Definition types.h:245
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
struct video_frame_callbacks callbacks
Definition types.h:324
static video_rxtx * create(std::string const &name, std::map< std::string, param_u > const &)
static void * receiver_thread(void *arg)
static time_ns_t get_time_in_ns()
Definition tv.h:101
@ VIDEO_NORMAL
normal video (one tile)
Definition types.h:356
This is an umbrella header for video functions.
#define MAX_QUEUE_SIZE