Skip to content

Commit b0fd636

Browse files
committed
vrxtx: fix C API
+ use it in ug_input
1 parent 2263fe1 commit b0fd636

4 files changed

Lines changed: 97 additions & 65 deletions

File tree

src/utils/list.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @author Martin Pulec <martin.pulec@cesnet.cz>
44
*/
55
/*
6-
* Copyright (c) 2013-2023 CESNET, z. s. p. o.
6+
* Copyright (c) 2013-2026 CESNET, zájmové sdružení právnických osob
77
* All rights reserved.
88
*
99
* Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,8 @@ void simple_linked_list_append(struct simple_linked_list *, void *data);
5252
bool simple_linked_list_append_if_less(struct simple_linked_list *, void *data, int max_size);
5353
void *simple_linked_list_pop(struct simple_linked_list *);
5454
int simple_linked_list_size(struct simple_linked_list *);
55-
void *simple_linked_list_first(struct simple_linked_list *); ///< returns first element of list, UB if empty
55+
/// returns first element of list keeping it in the list (UB if empty)
56+
void *simple_linked_list_first(struct simple_linked_list *);
5657
void *simple_linked_list_last(struct simple_linked_list *); ///< returns last element of list, UB if empty
5758

5859
/** iterator
Lines changed: 73 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @file video_capture/ug_input.cpp
2+
* @file video_capture/ug_input.c
33
* @author Martin Pulec <pulec@cesnet.cz>
44
*/
55
/*
@@ -35,25 +35,23 @@
3535
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3636
*/
3737

38-
#include <cassert> // for assert
39-
#include <cctype> // for isdigit
40-
#include <cstdint> // for uint16_t
41-
#include <cstdio> // for printf, snprintf
42-
#include <cstdlib> // for free
43-
#include <cstring> // for strlen, strchr, strcmp, strdup
44-
#include <memory> // for unique_ptr
45-
#include <mutex> // for mutex, lock_guard
46-
#include <queue> // for queue
47-
#include <string> // for basic_string, stoi, string
48-
#include <utility> // for pair
38+
#include <assert.h> // for assert
39+
#include <ctype.h> // for isdigit
40+
#include <pthread.h> // for pthread_mutex_unlock, pthread_mute...
41+
#include <stdint.h> // for uint16_t
42+
#include <stdio.h> // for printf, snprintf
43+
#include <stdlib.h> // for free
44+
#include <string.h> // for strlen, strchr, strcmp, strdup
4945

5046
#include "audio/audio.h" // for audio_options, AUDIO_OPTIONS_INIT
5147
#include "audio/types.h" // for AUDIO_FRAME_DISPOSE
48+
#include "compat/c23.h" // IWYU pragma: keep
5249
#include "debug.h" // for LOG_LEVEL_ERROR, LOG_LEVEL_WARNING
5350
#include "host.h" // for common_opts, COMMON_OPTS_INIT
5451
#include "lib_common.h" // for REGISTER_MODULE, library_class
5552
#include "types.h" // for VIDEO_CODEC_NONE, codec_t, device_...
5653
#include "utils/color_out.h" // for TBOLD, color_printf, TRED
54+
#include "utils/list.h" // for simple_linked_list
5755
#include "utils/macros.h" // for to_fourcc, IS_KEY_PREFIX, snprintf_ch
5856
#include "video_capture.h" // for VIDCAP_INIT_FAIL, VIDCAP_INIT_NOERR
5957
#include "video_capture_params.h" // for vidcap_params_get_fmt, vidcap_para...
@@ -63,42 +61,47 @@
6361
#include "video_frame.h" // for VIDEO_FRAME_DISPOSE, vf_free
6462
#include "video_rxtx.hpp" // for video_rxtx, vrxtx_params, VRXTX_INIT
6563

64+
struct vidcap_params;
65+
6666
#define MAGIC to_fourcc('V', 'C', 'u', 'i')
6767
#define MOD_NAME "[ug_input] "
68-
static constexpr int MAX_QUEUE_SIZE = 2;
69-
70-
using std::lock_guard;
71-
using std::mutex;
72-
using std::pair;
73-
using std::queue;
74-
using std::stoi;
75-
using std::string;
76-
using std::unique_ptr;
77-
78-
struct ug_input_state final {
79-
uint32_t magic = MAGIC;
80-
mutex lock;
81-
queue<pair<struct video_frame *, struct audio_frame *>> frame_queue;
82-
struct display *display = nullptr;
83-
84-
unique_ptr<struct video_rxtx> video_rxtx;
85-
struct state_audio *audio = nullptr;
68+
static const int MAX_QUEUE_SIZE = 2;
69+
70+
struct av_frame {
71+
struct video_frame *vframe;
72+
struct audio_frame *aframe;
73+
};
74+
75+
struct ug_input_state {
76+
uint32_t magic;
77+
pthread_mutex_t lock;
78+
struct simple_linked_list *list;
79+
struct display *display;
80+
81+
struct video_rxtx *video_rxtx;
82+
struct state_audio *audio;
8683
};
8784

85+
static void vidcap_ug_input_done(void *state);
86+
8887
static void
89-
ug_input_frame_arrived(void *state, struct video_frame *f,
88+
ug_input_frame_arrived(void *state, struct video_frame *v,
9089
struct audio_frame *a)
9190
{
92-
auto *s = (ug_input_state *) state;
91+
struct ug_input_state *s = state;
9392
assert(s->magic == MAGIC);
94-
lock_guard<mutex> lk(s->lock);
95-
if (s->frame_queue.size() < MAX_QUEUE_SIZE) {
96-
s->frame_queue.push({f, a});
93+
pthread_mutex_lock(&s->lock);
94+
if (simple_linked_list_size(s->list) < MAX_QUEUE_SIZE) {
95+
struct av_frame *avf = (struct av_frame *) malloc(sizeof *avf);
96+
avf->aframe = a;
97+
avf->vframe = v;
98+
simple_linked_list_append(s->list, avf);
9799
} else {
98100
MSG(WARNING, "Dropping frame!\n");
99101
AUDIO_FRAME_DISPOSE(a);
100-
VIDEO_FRAME_DISPOSE(f);
102+
VIDEO_FRAME_DISPOSE(v);
101103
}
104+
pthread_mutex_unlock(&s->lock);
102105
}
103106

104107
static void
@@ -123,9 +126,9 @@ parse_fmt(char *fmt, uint16_t *port, codec_t *decode_to)
123126
if (isdigit(tok[0])) {
124127
MSG(WARNING, "port specification without the keyword "
125128
"port= is deprecated\n");
126-
*port = stoi(tok);
129+
*port = atoi(tok);
127130
} else if (IS_KEY_PREFIX(tok, "port")) {
128-
*port = stoi(val);
131+
*port = atoi(val);
129132
} else if (IS_KEY_PREFIX(tok, "codec")) {
130133
*decode_to = get_codec_from_name(val);
131134
if (*decode_to == VIDEO_CODEC_NONE) {
@@ -156,7 +159,10 @@ static int vidcap_ug_input_init(const struct vidcap_params *cap_params, void **s
156159
return VIDCAP_INIT_FAIL;
157160
}
158161

159-
auto *s = new ug_input_state();
162+
struct ug_input_state *s = calloc(1, sizeof *s);
163+
s->magic = MAGIC;
164+
pthread_mutex_init(&s->lock, nullptr);
165+
s->list = simple_linked_list_init();
160166

161167
char cfg[128] = "";
162168

@@ -192,10 +198,8 @@ static int vidcap_ug_input_init(const struct vidcap_params *cap_params, void **s
192198
// params["decoder_mode"].l = VIDEO_NORMAL;
193199
params.display_device = s->display;
194200

195-
struct video_rxtx *rxtx = nullptr;
196-
int rc = vrxtx_init("ultragrid_rtp", &params, &common, &rxtx);
201+
int rc = vrxtx_init("ultragrid_rtp", &params, &common, &s->video_rxtx);
197202
assert(rc == 0);
198-
s->video_rxtx = unique_ptr<video_rxtx>(rxtx);
199203

200204
if (vidcap_params_get_flags(cap_params) & VIDCAP_FLAG_AUDIO_ANY) {
201205
struct audio_options opt = AUDIO_OPTIONS_INIT;
@@ -205,10 +209,10 @@ static int vidcap_ug_input_init(const struct vidcap_params *cap_params, void **s
205209
opt.recv_cfg = "embedded";
206210
opt.proto = "ultragrid_rtp";
207211
opt.display = s->display;
208-
opt.vrxtx = s->video_rxtx.get();
212+
opt.vrxtx = s->video_rxtx;
209213

210214
if (audio_init(&s->audio, &opt, &common) != 0) {
211-
delete s;
215+
vidcap_ug_input_done(s);
212216
return VIDCAP_INIT_FAIL;
213217
}
214218

@@ -223,46 +227,55 @@ static int vidcap_ug_input_init(const struct vidcap_params *cap_params, void **s
223227

224228
static void vidcap_ug_input_done(void *state)
225229
{
226-
auto s = (ug_input_state *) state;
230+
struct ug_input_state *s = state;
227231
assert(s->magic == MAGIC);
228232

229233
audio_join(s->audio);
230-
s->video_rxtx->join();
234+
vrxtx_join(s->video_rxtx);
231235

232236
// display_put_frame(s->display, nullptr, 0); // already done by ultragrid_rtp_video_rxtx::receiver_loop
233237
display_join(s->display);
234238
display_done(s->display);
235239

236-
while (!s->frame_queue.empty()) {
237-
auto item = s->frame_queue.front();
238-
s->frame_queue.pop();
239-
VIDEO_FRAME_DISPOSE(item.first);
240-
AUDIO_FRAME_DISPOSE(item.second);
240+
while (simple_linked_list_size(s->list) == 0) {
241+
struct av_frame *item = simple_linked_list_pop(s->list);
242+
VIDEO_FRAME_DISPOSE(item->vframe);
243+
AUDIO_FRAME_DISPOSE(item->aframe);
244+
free(item);
241245
}
246+
242247
audio_done(s->audio);
248+
vrxtx_destroy(s->video_rxtx);
243249

244-
delete s;
250+
pthread_mutex_destroy(&s->lock);
251+
simple_linked_list_destroy(s->list);
252+
253+
free(s);
245254
}
246255

247256
static struct video_frame *vidcap_ug_input_grab(void *state, struct audio_frame **audio)
248257
{
249-
auto s = (ug_input_state *) state;
258+
struct ug_input_state *s = state;
250259
*audio = nullptr;
251-
lock_guard<mutex> lk(s->lock);
252-
if (s->frame_queue.empty()) {
260+
pthread_mutex_lock(&s->lock);
261+
while (simple_linked_list_size(s->list) == 0) {
262+
pthread_mutex_unlock(&s->lock);
253263
return nullptr;
254264
}
255265

256-
auto item = s->frame_queue.front();
257-
struct video_frame *frame = item.first;
258-
*audio = item.second;
259-
s->frame_queue.pop();
266+
struct av_frame *item = simple_linked_list_pop(s->list);
267+
struct video_frame *frame = item->vframe;
268+
*audio = item->aframe;
269+
free(item);
260270
frame->callbacks.dispose = vf_free;
271+
pthread_mutex_unlock(&s->lock);
261272

262273
return frame;
263274
}
264275

265-
static void vidcap_ug_input_probe(device_info **available_cards, int *count, void (**deleter)(void *))
276+
static void
277+
vidcap_ug_input_probe(struct device_info **available_cards, int *count,
278+
void (**deleter)(void *))
266279
{
267280
*deleter = free;
268281
*count = 0;

src/video_rxtx.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,15 @@ int vrxtx_init(const char *proto_name, const struct vrxtx_params *params,
339339
*state = ret;
340340
return 0;
341341
}
342+
343+
void
344+
vrxtx_join(struct video_rxtx *state)
345+
{
346+
state->join();
347+
}
348+
349+
void
350+
vrxtx_destroy(struct video_rxtx *state)
351+
{
352+
delete state;
353+
}

src/video_rxtx.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@
3838
#ifndef VIDEO_RXTX_H_
3939
#define VIDEO_RXTX_H_
4040

41+
#ifdef __cplusplus
4142
#include <atomic>
4243
#include <memory>
4344
#include <string>
45+
#endif // defined __cplusplus
4446

4547
#include "host.h"
4648
#define WANT_PTHREAD_NULL
@@ -95,6 +97,7 @@ struct vrxtx_params {
9597
.receiver_mod = nullptr, \
9698
}
9799

100+
#ifdef __cplusplus
98101
struct video_rxtx_info {
99102
const char *long_name;
100103
void *(*create)(const struct vrxtx_params *params,
@@ -158,18 +161,21 @@ struct video_rxtx {
158161
video_desc m_video_desc{};
159162
std::atomic<codec_t> m_input_codec{};
160163
};
164+
#endif // defined __cplusplus
161165

162-
#ifndef _cplusplus
166+
#ifdef __cplusplus
163167
extern "C" {
164168
#endif
165169

166170
int vrxtx_init(const char *proto_name, const struct vrxtx_params *params,
167171
const struct common_opts *opts, struct video_rxtx **state);
168172
const char *vrxtx_get_compression(const char *video_protocol,
169173
const char *req_compression);
174+
void vrxtx_join(struct video_rxtx *state);
175+
void vrxtx_destroy(struct video_rxtx *state);
170176

171-
#ifndef _cplusplus
172-
}
177+
#ifdef __cplusplus
178+
} // extern "C"
173179
#endif
174180

175181
#endif // VIDEO_RXTX_H_

0 commit comments

Comments
 (0)