UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
bitflow.cpp
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2017-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
43
44#include "bitflow/BFciLib.h"
45#include <inttypes.h>
46
47#include "debug.h"
48#include "lib_common.h"
49#include "video.h"
50#include "video_capture.h"
51
52
54 tCIp sCIp; /* device open token */
55 int sNdx; /* device index */
56 tCIU32 nPtrs;
57 tCIU8 **uPtrs;
59 tCIU32 nFrames;
60};
61
62static void vidcap_bitflow_done(void *state);
63
65 tCIRC circ;
66 if (kCIEnoErr != (circ = CiMapFrameBuffers(s->sCIp,
67 0, // 0-read only, 1- read/write
68 &s->nPtrs,
69 &s->uPtrs)))
70 {
71 log_msg(LOG_LEVEL_ERROR, "CiMapFrameBuffers gave '%s'\n",CiErrStr(circ));
72 if ((NULL != s->uPtrs) && (kCIEnoErr != (circ = CiUnmapFrameBuffers(s->sCIp)))){
73 log_msg(LOG_LEVEL_ERROR, "CiUnmapFrameBuffers gave '%s'\n",CiErrStr(circ));
74 }
75 return false;
76 }
77 if (s->nPtrs != s->nFrames) {
78 log_msg(LOG_LEVEL_ERROR, "Error requested - %" PRIu32 ", mapped :%p\n", s->nFrames, s->nPtrs);
79 }
80
81 return true;
82}
83
85 tCIRC circ;
86 if (kCIEnoErr != (circ = CiAqSWreset(s->sCIp))) {
87 log_msg(LOG_LEVEL_ERROR, "CiAqSWreset gave '%s'\n", CiErrStr(circ));
88 if ((NULL != s->uPtrs) && (kCIEnoErr != (circ = CiUnmapFrameBuffers(s->sCIp)))){
89 log_msg(LOG_LEVEL_ERROR, "CiUnmapFrameBuffers gave '%s'\n",CiErrStr(circ));
90 }
91 return false;
92 }
93
94 return true;
95}
96
98 tCIRC circ;
99 int numberOfFrames = 0;
100 if (kCIEnoErr != (circ = CiAqStart(s->sCIp, numberOfFrames))) // 0-continous, n-frame number
101 {
102 log_msg(LOG_LEVEL_ERROR, "CiAqStart gave '%s'\n",CiErrStr(circ));
103 if ((NULL != s->uPtrs) && (kCIEnoErr != (circ = CiUnmapFrameBuffers(s->sCIp)))){
104 log_msg(LOG_LEVEL_ERROR, "CiUnmapFrameBuffers gave '%s'\n",CiErrStr(circ));
105 }
106 return false;
107 }
108 return true;
109}
110
111static float get_fps(struct vidcap_state_bitflow *s) {
112 tCIRC circ;
113 tCITDP cfgFN, cfg, camFN, cam, firmFN, firm, serial, cxp, spare;
114
115 if (kCIEnoErr != (circ = CiVFGinquire2(s->sCIp, &cfgFN, &cfg, &camFN,
116 &cam, &firmFN, &firm, &serial, &cxp, &spare))) {
117 log_msg(LOG_LEVEL_ERROR, "CiVFGinquire gave '%s'\n", CiErrStr(circ));
118 return 0.0f;
119 }
120
121 int x = 0;
122 while (cam[x].descriptor != NULL) {
123 if (strcmp(cam[x].descriptor, "CAMREGAFTER") == 0) {
124 tCIU32 *ptr = (tCIU32 *)(cam[x].datap);
125 int y = *ptr++;
126 while (y-- > 0) {
127 if (ptr[0] == 0x000200C4) {
128 return *(float *) (ptr + 1);
129 }
130 ptr += 2;
131 }
132 }
133 x += 1;
134 }
135
136 return 0;
137}
138
140{
143 }
144 struct vidcap_state_bitflow *s = (struct vidcap_state_bitflow *) calloc(1, sizeof(struct vidcap_state_bitflow));
145
146 s->sNdx = 0;
147
148 tCIRC circ;
149 //Open the ndx'th frame grabber with write permission.
150 if (kCIEnoErr != (circ = CiVFGopen(s->sNdx,
151 kCIBO_writeAccess,
152 &s->sCIp)))
153 {
154 log_msg(LOG_LEVEL_ERROR, "CiVFGopen gave '%s'\n",CiErrStr(circ));
155 goto error;
156 }
157
158 if (kCIEnoErr != (circ = CiVFGinitialize(s->sCIp,NULL)))
159 {
160 log_msg(LOG_LEVEL_ERROR, "CiVFGinitialize gave '%s'\n",CiErrStr(circ));
161 goto error;
162 }
163
164 if (kCIEnoErr != (circ = CiDrvrBuffConfigure(s->sCIp, 20, 0, 0, 0, 0))) {
165 log_msg(LOG_LEVEL_ERROR, "CiDrvrBuffConfigure gave '%s'\n",CiErrStr(circ));
166 goto error;
167 }
168
169 tCIU32 bitsPerPix, hROIsize, vROIsize, hROIoffset, vROIoffset, stride;
170 if (kCIEnoErr != (circ = CiBufferInterrogate(s->sCIp, &s->nFrames, &bitsPerPix, &hROIoffset, &hROIsize, &vROIoffset, &vROIsize, &stride)))
171 {
172 log_msg(LOG_LEVEL_ERROR, "CiBufferInterrogate gave '%s'\n",CiErrStr(circ));
173 goto error;
174 }
175
176 s->desc = {hROIsize, vROIsize, RGB, get_fps(s), PROGRESSIVE, 1};
177
178 if (s->desc.fps == 0) {
179 log_msg(LOG_LEVEL_ERROR, "Unable to get FPS!");
180 goto error;
181 }
182
183 if (!map_frame_buffers(s)) {
184 goto error;
185 }
186
187 if (!reset_acquisition(s)) {
188 goto error;
189 }
190
191 if (!start_acquisition(s)) {
192 goto error;
193 }
194
195 *state = s;
196 return VIDCAP_INIT_OK;
197
198error:
200 return -1;
201}
202
203static void vidcap_bitflow_done(void *state)
204{
205 struct vidcap_state_bitflow *s = (struct vidcap_state_bitflow *) state;
206 tCIRC circ;
207
208 /*
209 ** Unmap the frame buffers.
210 */
211 if ((NULL != s->uPtrs) && (kCIEnoErr != (circ = CiUnmapFrameBuffers(s->sCIp)))){
212 log_msg(LOG_LEVEL_ERROR, "CiUnmapFrameBuffers gave '%s'\n",CiErrStr(circ));
213 }
214 /*
215 ** Close the access.
216 */
217 if ((NULL != s->sCIp) && (kCIEnoErr != (circ = CiVFGclose(s->sCIp)))) {
218 log_msg(LOG_LEVEL_ERROR, "CiVFGclose gave '%s'\n",CiErrStr(circ));
219 }
220
221 free(s);
222}
223
224static void debayer(char *out, char *in, int width, int height)
225{
226 for (int y = 0; y < height; y += 2) {
227 for (int x = 0; x < width; ++x) {
228 *out++ = in[x + 1];
229 *out++ = in[x];
230 *out++ = in[x + width];
231 }
232 for (int x = 0; x < width; ++x) {
233 *out++ = in[x + 1];
234 *out++ = in[x + width + 1];
235 *out++ = in[x + width];
236 }
237
238 in += 2 * width;
239 }
240}
241
243{
244 if (!map_frame_buffers(s)) {
245 goto fail;
246 }
247
248 if (!reset_acquisition(s)) {
249 goto fail;
250 }
251
252 if (!start_acquisition(s)) {
253 goto fail;
254 }
255
256 return;
257fail:
258 log_msg(LOG_LEVEL_FATAL, "[bitflow] Unable to restart acquisition!\n");
259 exit_uv(1);
260}
261
263{
264 struct vidcap_state_bitflow *s = (struct vidcap_state_bitflow *) state;
265
266 tCIU32 frameID;
267 tCIU8 *frameP;
268 tCIRC circ;
269
270 //Check to see if a frame is already available before waiting.
271 circ = CiGetOldestNotDeliveredFrame(s->sCIp, &frameID, &frameP);
272
273 switch (circ) {
274 case kCIEnoErr:
275 // we have the frame
276 break;
277 case kCIEnoNewData:
278 if (kCIEnoErr != (circ = CiWaitNextUndeliveredFrame(s->sCIp,-1))) // negative - infinite wait
279 {
280 switch (circ) {
281 case kCIEaqAbortedErr:
282 log_msg(LOG_LEVEL_ERROR, "CiWaitNextUndeliveredFrame gave '%s'\n",CiErrStr(circ));
283 break;
284 case kCIEdataHWerr:
285 log_msg(LOG_LEVEL_ERROR, "CiWaitNextUndeliveredFrame gave '%s'\n",CiErrStr(circ));
287
288 break;
289 default:
290 log_msg(LOG_LEVEL_ERROR, "CiWaitNextUndeliveredFrame gave '%s'\n",CiErrStr(circ));
291 }
292 return NULL;
293 }
294 circ = CiGetOldestNotDeliveredFrame(s->sCIp, &frameID, &frameP);
295 if (circ == kCIEnoErr) {
296 break;
297 } else {
298 return NULL;
299 }
300 case kCIEaqAbortedErr:
301 log_msg(LOG_LEVEL_ERROR, "CiGetOldestNotDeliveredFrame: acquistion aborted\n");
302 return NULL;
303 case kCIEdataHWerr:
304 log_msg(LOG_LEVEL_ERROR, "CiWaitNextUndeliveredFrame gave '%s'\n",CiErrStr(circ));
306 return NULL;
307 default:
308 log_msg(LOG_LEVEL_ERROR, "CiGetOldestNotDeliveredFrame gave '%s'\n",CiErrStr(circ));
309 return NULL;
310 }
311
312 tCIU32 count;
313 switch (circ = CiGetUndeliveredCount(s->sCIp,&count)) {
314 case kCIEnoErr:
315 /*
316 ** We have the frame.
317 */
318 break;
319 case kCIEnoNewData:
320 /*
321 ** We need to wait for another frame.
322 */
323 log_msg(LOG_LEVEL_ERROR, "CiGetUndeliveredCount error\n");
324 return NULL;
325 case kCIEaqAbortedErr:
326 log_msg(LOG_LEVEL_ERROR, "CiGetOldestNotDeliveredFrame: acquistion aborted\n");
327 return NULL;
328 default:
329 log_msg(LOG_LEVEL_ERROR, "CiGetOldestNotDeliveredFrame gave '%s'\n",CiErrStr(circ));
330 return NULL;
331 }
332
333 if (count > 0) {
334 log_msg(LOG_LEVEL_WARNING, "Undelivered count: %" PRIu32 "\n");
335 }
336
338 debayer((char *) out->tiles[0].data, (char *) frameP, s->desc.width, s->desc.height);
340
341 *audio = NULL;
342 return out;
343}
344
345static void vidcap_bitflow_probe(device_info **available_cards, int *count, void (**deleter)(void *))
346{
347 *available_cards = nullptr;
348 *count = 0;
349 *deleter = free;
350}
351
359
361
void ** state
struct audio_frame ** audio
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
static float get_fps(struct vidcap_state_bitflow *s)
Definition bitflow.cpp:111
static bool reset_acquisition(struct vidcap_state_bitflow *s)
Definition bitflow.cpp:84
static void debayer(char *out, char *in, int width, int height)
Definition bitflow.cpp:224
static const struct video_capture_info vidcap_bitflow_info
Definition bitflow.cpp:352
static void restartAcquisition(struct vidcap_state_bitflow *s)
Definition bitflow.cpp:242
static bool start_acquisition(struct vidcap_state_bitflow *s)
Definition bitflow.cpp:97
static bool map_frame_buffers(struct vidcap_state_bitflow *s)
Definition bitflow.cpp:64
static struct video_frame * vidcap_bitflow_grab(void *state, struct audio_frame **audio)
Definition bitflow.cpp:262
static void vidcap_bitflow_done(void *state)
Definition bitflow.cpp:203
static int vidcap_bitflow_init(struct vidcap_params *params, void **state)
Definition bitflow.cpp:139
static void vidcap_bitflow_probe(device_info **available_cards, int *count, void(**deleter)(void *))
Definition bitflow.cpp:345
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_FATAL
errors that prevent UG run
Definition debug.h:58
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define VIDCAP_INIT_OK
initialization successful
#define VIDCAP_NO_GENERIC_FPS_INDICATOR
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_AUDIO_NOT_SUPPORTED
card does not support audio
int count
Definition hd-rum.c:44
void exit_uv(int status)
Definition host.cpp:625
@ LIBRARY_CLASS_VIDEO_CAPTURE
Definition lib_common.h:78
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
struct used to comunicate with audio capture/playback device
Definition types.h:99
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
struct video_desc desc
Definition bitflow.cpp:58
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
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 tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
struct video_frame_callbacks callbacks
Definition types.h:324
@ PROGRESSIVE
progressive frame
Definition types.h:164
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
This is an umbrella header for video functions.
unsigned int vidcap_params_get_flags(const struct vidcap_params *params)
#define VIDCAP_FLAG_AUDIO_ANY