UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
sdi.cpp
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2011-2023 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#include "config_unix.h"
41#include "config_win32.h"
42#endif // HAVE_CONFIG_H
43
44#include "audio/audio_capture.h"
45#include "audio/capture/sdi.h"
46#include "audio/types.h"
47#include "debug.h"
48#include "host.h"
49#include "lib_common.h"
50#include "types.h"
51
52#include <condition_variable>
53#include <chrono>
54#include <mutex>
55#include <string>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59
60#define DEFAULT_BUF_SIZE_MS 100L
61
62#define FRAME_NETWORK 0
63#define FRAME_CAPTURE 1
64#define MOD_NAME "[acap.] "
65
66using std::condition_variable;
67using std::chrono::milliseconds;
68using std::mutex;
69using std::stol;
70using std::unique_lock;
71
74 if (commandline_params.find("audio-buffer-len") != commandline_params.end()) {
75 buf_size_ms = stol(commandline_params.at("audio-buffer-len"));
76 }
77 }
78
81 mutex lock;
82 condition_variable audio_frame_ready_cv;
83};
84
85static void audio_cap_sdi_help(const char *driver_name);
86
87static void audio_cap_sdi_probe_common(struct device_info **available_devices, int *count,
88 const char *dev, const char *name)
89{
90 *available_devices = (struct device_info *) calloc(1, sizeof(struct device_info));
91 strncpy((*available_devices)[0].dev, dev, sizeof (*available_devices)[0].dev - 1);
92 strncpy((*available_devices)[0].name, name, sizeof (*available_devices)[0].name - 1);
93 snprintf((*available_devices)[0].extra, sizeof (*available_devices)[0].extra, "\"isEmbeddedAudio\":\"t\"");
94 *count = 1;
95}
96
97static void audio_cap_sdi_probe_embedded(struct device_info **available_devices, int *count, void (**deleter)(void *))
98{
99 *deleter = free;
100 audio_cap_sdi_probe_common(available_devices, count, "", "Embedded SDI/HDMI audio");
101}
102
103static void audio_cap_sdi_probe_aesebu(struct device_info **available_devices, int *count, void (**deleter)(void *))
104{
105 *deleter = free;
106 audio_cap_sdi_probe_common(available_devices, count, "", "Digital AES/EBU audio");
107}
108
109static void audio_cap_sdi_probe_analog(struct device_info **available_devices, int *count, void (**deleter)(void *))
110{
111 *deleter = free;
112 audio_cap_sdi_probe_common(available_devices, count, "", "Analog audio through capture card");
113}
114
115static void * audio_cap_sdi_init(struct module *parent, const char *cfg)
116{
117 UNUSED(parent);
118 if (strcmp(cfg, "help") == 0) {
119 printf("Available vidcap audio devices:\n");
120 audio_cap_sdi_help("embedded");
121 audio_cap_sdi_help("AESEBU");
122 audio_cap_sdi_help("analog");
123 printf("\t\twhere <index> is index of vidcap device "
124 "to be taken audio from.\n");
125 return INIT_NOERR;
126 }
127
128 return new state_sdi_capture();
129}
130
132{
133 struct state_sdi_capture *s = (struct state_sdi_capture *) state;
134
135 unique_lock<mutex> lk(s->lock);
136 bool rc = s->audio_frame_ready_cv.wait_for(lk, milliseconds(100), [s]{return s->audio_frame[FRAME_CAPTURE].data_len > 0;});
137
138 if (rc == false) {
139 return NULL;
140 }
141
142 // FRAME_NETWORK has been "consumed"
144 // swap
145 struct audio_frame tmp;
146 memcpy(&tmp, &s->audio_frame[FRAME_CAPTURE], sizeof(struct audio_frame));
147 memcpy(&s->audio_frame[FRAME_CAPTURE], &s->audio_frame[FRAME_NETWORK], sizeof(struct audio_frame));
148 memcpy(&s->audio_frame[FRAME_NETWORK], &tmp, sizeof(struct audio_frame));
149
150 return &s->audio_frame[FRAME_NETWORK];
151}
152
153static void audio_cap_sdi_done(void *state)
154{
155 struct state_sdi_capture *s;
156
157 s = (struct state_sdi_capture *) state;
158 for(int i = 0; i < 2; ++i) {
159 free(s->audio_frame[i].data);
160 }
161}
162
163static void audio_cap_sdi_help(const char *driver_name)
164{
165 if(strcmp(driver_name, "embedded") == 0) {
166 printf("\tembedded[:<index>] : SDI audio (if available)\n");
167 } else if(strcmp(driver_name, "AESEBU") == 0) {
168 printf("\tAESEBU[:<index>] : separately connected AES/EBU to a grabbing card (if available)\n");
169 } else if(strcmp(driver_name, "analog") == 0) {
170 printf("\tanalog[:<index>] : analog input of grabbing card (if available)\n");
171 }
172}
173
175{
176 struct state_sdi_capture *s;
177
178 s = (struct state_sdi_capture *) state;
179
180 unique_lock<mutex> lk(s->lock);
181
182 if (s->audio_frame[FRAME_CAPTURE].bps != frame->bps ||
183 s->audio_frame[FRAME_CAPTURE].ch_count != frame->ch_count ||
184 s->audio_frame[FRAME_CAPTURE].sample_rate != frame->sample_rate) {
186 s->audio_frame[FRAME_CAPTURE].ch_count = frame->ch_count;
187 s->audio_frame[FRAME_CAPTURE].sample_rate = frame->sample_rate;
189 s->audio_frame[FRAME_CAPTURE].max_size = frame->bps * frame->ch_count * frame->sample_rate / 1000L * s->buf_size_ms;
190 s->audio_frame[FRAME_CAPTURE].data = static_cast<char *>(malloc(s->audio_frame[FRAME_CAPTURE].max_size));
191 }
192
193 int len = frame->data_len;
195 LOG(LOG_LEVEL_WARNING) << MOD_NAME << "Maximal audio buffer length " << s->buf_size_ms << " ms exceeded! Dropping "
196 << len - (s->audio_frame[FRAME_CAPTURE].max_size - s->audio_frame[FRAME_CAPTURE].data_len) << " samples.\n";
198 }
200 frame->data, len);
201 if (s->audio_frame[FRAME_CAPTURE].data_len == 0 && (frame->flags & TIMESTAMP_VALID) != 0) {
204 }
206
207 lk.unlock();
208 s->audio_frame_ready_cv.notify_one();
209}
210
217
224
231
235
236/* vim: set expandtab sw=8: */
#define UNUSED(x)
void ** state
struct video_frame * frame
int void size_t * len
int void(** deleter)(void *))
This file contains definition of some common audio types.
#define AUDIO_CAPTURE_ABI_VERSION
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
int count
Definition hd-rum.c:44
std::unordered_map< std::string, std::string > commandline_params
Definition host.cpp:184
#define INIT_NOERR
Definition host.h:73
@ LIBRARY_CLASS_AUDIO_CAPTURE
Definition lib_common.h:76
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
void sdi_capture_new_incoming_frame(void *state, struct audio_frame *frame)
Definition sdi.cpp:174
#define FRAME_NETWORK
Definition sdi.cpp:62
static void audio_cap_sdi_probe_embedded(struct device_info **available_devices, int *count, void(**deleter)(void *))
Definition sdi.cpp:97
static const struct audio_capture_info acap_sdi_info_aesebu
Definition sdi.cpp:218
static void audio_cap_sdi_probe_analog(struct device_info **available_devices, int *count, void(**deleter)(void *))
Definition sdi.cpp:109
static const struct audio_capture_info acap_sdi_info_analog
Definition sdi.cpp:225
#define FRAME_CAPTURE
Definition sdi.cpp:63
static const struct audio_capture_info acap_sdi_info_embedded
Definition sdi.cpp:211
static void audio_cap_sdi_probe_common(struct device_info **available_devices, int *count, const char *dev, const char *name)
Definition sdi.cpp:87
static void audio_cap_sdi_help(const char *driver_name)
Definition sdi.cpp:163
static void audio_cap_sdi_probe_aesebu(struct device_info **available_devices, int *count, void(**deleter)(void *))
Definition sdi.cpp:103
static void audio_cap_sdi_done(void *state)
Definition sdi.cpp:153
#define MOD_NAME
Definition sdi.cpp:64
static void * audio_cap_sdi_init(struct module *parent, const char *cfg)
Definition sdi.cpp:115
#define DEFAULT_BUF_SIZE_MS
Definition sdi.cpp:60
static struct audio_frame * audio_cap_sdi_read(void *state)
Definition sdi.cpp:131
const char * parent
Definition settings.cpp:198
const char * name
Definition settings.cpp:193
struct used to comunicate with audio capture/playback device
Definition types.h:99
int sample_rate
Definition types.h:101
int64_t timestamp
Definition types.h:109
char * data
Definition types.h:102
int ch_count
Definition types.h:104
int data_len
Definition types.h:103
int flags
Definition types.h:111
int bps
Definition types.h:100
int max_size
Definition types.h:105
char extra[1024]
Definition types.h:389
char dev[1024]
Definition types.h:383
long buf_size_ms
Definition sdi.cpp:79
condition_variable audio_frame_ready_cv
Definition sdi.cpp:82
struct audio_frame audio_frame[2]
Definition sdi.cpp:80
int64_t timestamp
Definition types.h:331
int flags
Definition types.h:329
This file contains some common data types.
@ TIMESTAMP_VALID
timestamp set by source (in 90 kHz clock)
Definition types.h:223