1 // LiVES - videodev input
2 // (c) G. Finch 2010 - 2019 <salsaman+lives@gmail.com>
3 // released under the GNU GPL 3 or later
4 // see file COPYING or www.gnu.org for details
5
6 #include "main.h"
7
8 #ifdef HAVE_UNICAP
9 #define DEBUG_UNICAP
10
11 #include "videodev.h"
12 #include "interface.h"
13 #include "callbacks.h"
14 #include "effects-weed.h"
15
16 #include <unicap/unicap.h>
17
lives_wait_user_buffer(lives_vdev_t * ldev,unicap_data_buffer_t ** buff,double timeout)18 static boolean lives_wait_user_buffer(lives_vdev_t *ldev, unicap_data_buffer_t **buff, double timeout) {
19 // wait for USER type buffer
20 unicap_status_t status;
21 int ncount;
22 lives_alarm_t alarm_handle = lives_alarm_set(timeout * TICKS_PER_SECOND_DBL);
23
24 do {
25 status = unicap_poll_buffer(ldev->handle, &ncount);
26
27 #ifdef DEBUG_UNICAP
28 if (status != STATUS_SUCCESS) lives_printerr("Unicap poll failed with status %d\n", status);
29 #endif
30 if (ncount >= 0) {
31 lives_alarm_clear(alarm_handle);
32 if (!SUCCESS(unicap_wait_buffer(ldev->handle, buff))) return FALSE;
33 return TRUE;
34 }
35 lives_usleep(prefs->sleep_time);
36 lives_widget_context_update();
37 sched_yield();
38 } while (lives_alarm_check(alarm_handle) > 0);
39
40 return FALSE;
41 }
42
43
lives_wait_system_buffer(lives_vdev_t * ldev,double timeout)44 static boolean lives_wait_system_buffer(lives_vdev_t *ldev, double timeout) {
45 // wait for SYSTEM type buffer
46 lives_alarm_t alarm_handle = lives_alarm_set(timeout * TICKS_PER_SECOND_DBL);
47
48 do {
49 if (ldev->buffer_ready != 0) {
50 lives_alarm_clear(alarm_handle);
51 return TRUE;
52 }
53 lives_usleep(prefs->sleep_time);
54 lives_widget_context_update();
55 sched_yield();
56 } while (lives_alarm_check(alarm_handle) > 0);
57 lives_alarm_clear(alarm_handle);
58
59 return FALSE;
60 }
61
62
new_frame_cb(unicap_event_t event,unicap_handle_t handle,unicap_data_buffer_t * buffer,void * usr_data)63 static void new_frame_cb(unicap_event_t event, unicap_handle_t handle,
64 unicap_data_buffer_t *buffer, void *usr_data) {
65 lives_vdev_t *ldev = (lives_vdev_t *)usr_data;
66 if (!LIVES_IS_PLAYING || (mainw->playing_file != ldev->fileno && mainw->blend_file != ldev->fileno)) {
67 ldev->buffer_ready = 0;
68 return;
69 }
70
71 if (ldev->buffer_ready != 1) {
72 lives_memcpy(ldev->buffer1.data, buffer->data, ldev->buffer1.buffer_size);
73 ldev->buffer_ready = 1;
74 } else {
75 lives_memcpy(ldev->buffer2.data, buffer->data, ldev->buffer2.buffer_size);
76 ldev->buffer_ready = 2;
77 }
78 }
79
80
weed_layer_set_from_lvdev(weed_layer_t * layer,lives_clip_t * sfile,double timeoutsecs)81 boolean weed_layer_set_from_lvdev(weed_layer_t *layer, lives_clip_t *sfile, double timeoutsecs) {
82 lives_vdev_t *ldev = (lives_vdev_t *)sfile->ext_src;
83 unicap_data_buffer_t *returned_buffer = NULL;
84 void **pixel_data;
85 void *odata = ldev->buffer1.data;
86
87 int error;
88
89 weed_set_int_value(layer, WEED_LEAF_WIDTH, sfile->hsize /
90 weed_palette_get_pixels_per_macropixel(ldev->current_palette));
91 weed_set_int_value(layer, WEED_LEAF_HEIGHT, sfile->vsize);
92 weed_set_int_value(layer, WEED_LEAF_CURRENT_PALETTE, ldev->current_palette);
93 weed_set_int_value(layer, WEED_LEAF_YUV_SUBSPACE, WEED_YUV_SUBSPACE_YCBCR); // TODO - handle bt.709
94 weed_set_int_value(layer, WEED_LEAF_YUV_SAMPLING, WEED_YUV_SAMPLING_DEFAULT); // TODO - use ldev->YUV_sampling
95 weed_set_int_value(layer, WEED_LEAF_YUV_CLAMPING, ldev->YUV_clamping);
96
97 create_empty_pixel_data(layer, TRUE, TRUE);
98
99 if (ldev->buffer_type == UNICAP_BUFFER_TYPE_USER) {
100 if (weed_palette_get_nplanes(ldev->current_palette) == 1 || ldev->is_really_grey) {
101 ldev->buffer1.data = (unsigned char *)weed_get_voidptr_value(layer, WEED_LEAF_PIXEL_DATA, &error);
102 }
103
104 unicap_queue_buffer(ldev->handle, &ldev->buffer1);
105
106 if (!lives_wait_user_buffer(ldev, &returned_buffer, timeoutsecs)) {
107 #ifdef DEBUG_UNICAP
108 lives_printerr("Failed to wait for user buffer!\n");
109 unicap_stop_capture(ldev->handle);
110 unicap_dequeue_buffer(ldev->handle, &returned_buffer);
111 unicap_start_capture(ldev->handle);
112 #endif
113 ldev->buffer1.data = (unsigned char *)odata;
114 return FALSE;
115 }
116 } else {
117 // wait for callback to fill buffer
118 if (!lives_wait_system_buffer(ldev, timeoutsecs)) {
119 #ifdef DEBUG_UNICAP
120 lives_printerr("Failed to wait for system buffer!\n");
121 #endif
122 }
123 if (ldev->buffer_ready == 1) returned_buffer = &ldev->buffer1;
124 else returned_buffer = &ldev->buffer2;
125 }
126
127 pixel_data = weed_get_voidptr_array(layer, WEED_LEAF_PIXEL_DATA, &error);
128
129 if (weed_palette_get_nplanes(ldev->current_palette) > 1 && !ldev->is_really_grey) {
130 boolean contig = FALSE;
131 if (weed_get_boolean_value(layer, WEED_LEAF_HOST_PIXEL_DATA_CONTIGUOUS, &error) == WEED_TRUE) contig = TRUE;
132 pixel_data_planar_from_membuf(pixel_data, returned_buffer->data, sfile->hsize * sfile->vsize, ldev->current_palette, contig);
133 } else {
134 if (ldev->buffer_type == UNICAP_BUFFER_TYPE_SYSTEM) {
135 int rowstride = weed_get_int_value(layer, WEED_LEAF_ROWSTRIDES, &error);
136 size_t bsize = rowstride * sfile->vsize;
137 if (bsize > returned_buffer->buffer_size) {
138 #ifdef DEBUG_UNICAP
139 lives_printerr("Warning - returned buffer size too small !\n");
140 #endif
141 bsize = returned_buffer->buffer_size;
142 }
143 lives_memcpy(pixel_data[0], returned_buffer->data, bsize);
144 }
145 }
146
147 // shouldnt be necessary since we specified black_fill in create_empty_pixel_data()
148
149 /* if (ldev->is_really_grey) { */
150 /* // y contains our greyscale data */
151 /* // set u and v planes to 128 */
152 /* memset(pixel_data[1], 128, sfile->hsize * sfile->vsize); */
153 /* memset(pixel_data[2], 128, sfile->hsize * sfile->vsize); */
154 /* } */
155
156 lives_free(pixel_data);
157
158 ldev->buffer1.data = (unsigned char *)odata;
159
160 return TRUE;
161 }
162
163
lvdev_get_best_format(const unicap_format_t * formats,lives_vdev_t * ldev,int palette,int width,int height)164 static unicap_format_t *lvdev_get_best_format(const unicap_format_t *formats,
165 lives_vdev_t *ldev, int palette, int width, int height) {
166 // get nearest format for given palette, width and height
167 // if palette is WEED_PALETTE_END, or cannot be matched, get best quality palette (preferring RGB)
168 // width and height must be set, actual width and height will be set as near to this as possible
169 // giving preference to larger frame size
170
171 // if the device supports no usable formats, returns NULL
172
173 // Note: we match first by palette, then by size
174
175 int format_count, i;
176 unicap_format_t *format;
177 int f = -1;
178 int bestp = WEED_PALETTE_END;
179 int bestw = 0, besth = 0;
180 int cpal;
181
182 // get details
183 for (format_count = 0;
184 SUCCESS(unicap_enumerate_formats(ldev->handle, NULL, (unicap_format_t *)&formats[format_count], format_count))
185 && (format_count < MAX_FORMATS); format_count++) {
186 format = (unicap_format_t *)&formats[format_count];
187
188 // TODO - check if we need to free format->sizes
189
190 // TODO - prefer non-interlaced, YCbCr for YUV
191 cpal = fourccp_to_weedp(format->fourcc, format->bpp, NULL, NULL, NULL, NULL);
192
193 if (cpal == WEED_PALETTE_END || weed_palette_is_alpha(cpal)) {
194 #ifdef DEBUG_UNICAP
195 // set format to try and get more data
196 unicap_set_format(ldev->handle, format);
197 lives_printerr("Unusable palette with fourcc 0x%x bpp=%d, size=%dx%d buf=%d\n", format->fourcc, format->bpp,
198 format->size.width,
199 format->size.height, (int)format->buffer_size);
200 #endif
201 continue;
202 }
203
204 if (bestp == WEED_PALETTE_END || cpal == palette || weed_palette_is_alpha(bestp) ||
205 weed_palette_is_lower_quality(bestp, cpal) ||
206 (weed_palette_is_yuv(bestp) && weed_palette_is_rgb(cpal))) {
207 // got better palette, or exact match
208
209 // prefer exact match on target palette if we have it
210 if (palette != WEED_PALETTE_END && bestp == palette && cpal != palette) continue;
211
212 // otherwise this is our best palette up to now
213 bestp = cpal;
214
215 // TODO - try to minimise aspect delta
216 // for now we just go with the smallest size >= target (or largest frame size if none are >= target)
217
218 if (width >= format->min_size.width && height >= format->min_size.height) {
219 if (format->h_stepping > 0 && format->v_stepping > 0) {
220 #ifdef DEBUG_UNICAP
221 lives_printerr("Can set any size with step %d and %d; min %d x %d, max %d x %d\n",
222 format->h_stepping, format->v_stepping,
223 format->min_size.width, format->min_size.height, format->max_size.width, format->max_size.height);
224 #endif
225 // can set exact size (within stepping limits)
226 format->size.width = (int)(((double)width + (double)format->h_stepping / 2.)
227 / (double)format->h_stepping) * format->h_stepping;
228
229 format->size.height = (int)(((double)height + (double)format->v_stepping / 2.)
230 / (double)format->v_stepping) * format->v_stepping;
231
232 if (format->size.width > format->max_size.width) format->size.width = format->max_size.width;
233 if (format->size.height > format->max_size.height) format->size.height = format->max_size.height;
234
235 if (format->size.width > bestw || format->size.height > besth) {
236 bestw = format->size.width;
237 besth = format->size.height;
238 f = format_count;
239 }
240 } else {
241 // array of sizes supported
242 // step through sizes
243 #ifdef DEBUG_UNICAP
244 lives_printerr("Checking %d array sizes\n", format->size_count);
245 #endif
246
247 if (format->size_count == 0) {
248 // only one size we can use, this is it...
249
250 if ((format->size.width > bestw || format->size.height > besth) && (bestw < width || besth < height)) {
251 // this format supports a better size match
252 bestw = format->size.width;
253 besth = format->size.height;
254 f = format_count;
255 #ifdef DEBUG_UNICAP
256 lives_printerr("Size is best so far\n");
257 #endif
258 }
259 continue;
260 }
261
262 // array of sizes
263 for (i = 0; i < format->size_count; i++) {
264 #ifdef DEBUG_UNICAP
265 lives_printerr("entry %d:%d x %d\n", i, format->sizes[i].width, format->sizes[i].height);
266 #endif
267 if (format->sizes[i].width > bestw && format->sizes[i].height > besth &&
268 (bestw < width || besth < height)) {
269 // this format supports a better size match
270 bestw = format->size.width = format->sizes[i].width;
271 besth = format->size.height = format->sizes[i].height;
272 f = format_count;
273 #ifdef DEBUG_UNICAP
274 lives_printerr("Size is best so far\n");
275 #endif
276 }
277 }
278 }
279 } else {
280 // target is smaller than min width, height
281 if (bestw < format->min_size.width || besth < format->min_size.height) continue; // TODO - minimise aspect delta
282 bestw = format->size.width = format->min_size.width;
283 besth = format->size.height = format->min_size.height;
284 f = format_count;
285 }
286 }
287 }
288
289 if (f > -1) return (unicap_format_t *)(&formats[f]);
290 return NULL;
291 }
292
293
294 /// get devnumber from user and open it to a new clip
295
open_vdev_inner(unicap_device_t * device)296 static boolean open_vdev_inner(unicap_device_t *device) {
297 // create a virtual clip
298 lives_vdev_t *ldev = (lives_vdev_t *)lives_malloc(sizeof(lives_vdev_t));
299 unicap_format_t formats[MAX_FORMATS];
300 unicap_format_t *format;
301
302 // open dev
303 unicap_open(&ldev->handle, device);
304
305 //check return value and take appropriate action
306 if (!ldev->handle) {
307 LIVES_ERROR("vdev input: cannot open device");
308 lives_free(ldev);
309 return FALSE;
310 }
311
312 unicap_lock_stream(ldev->handle);
313
314 format = lvdev_get_best_format(formats, ldev, WEED_PALETTE_END, DEF_GEN_WIDTH, DEF_GEN_HEIGHT);
315
316 if (!format) {
317 LIVES_INFO("No useful formats found");
318 unicap_unlock_stream(ldev->handle);
319 unicap_close(ldev->handle);
320 lives_free(ldev);
321 return FALSE;
322 }
323
324 if (!(format->buffer_types & UNICAP_BUFFER_TYPE_USER)) {
325 // have to use system buffer type
326 format->buffer_type = UNICAP_BUFFER_TYPE_SYSTEM;
327
328 // set a callback for new frame
329 unicap_register_callback(ldev->handle, UNICAP_EVENT_NEW_FRAME, (unicap_callback_t) new_frame_cb,
330 (void *) ldev);
331
332 } else format->buffer_type = UNICAP_BUFFER_TYPE_USER;
333
334 ldev->buffer_type = format->buffer_type;
335
336 // ignore YUV subspace for now
337 ldev->current_palette = fourccp_to_weedp(format->fourcc, format->bpp, (int *)&cfile->interlace,
338 &ldev->YUV_sampling, &ldev->YUV_subspace, &ldev->YUV_clamping);
339
340 #ifdef DEBUG_UNICAP
341 lives_printerr("\nUsing palette with fourcc 0x%x, translated as %s\n", format->fourcc,
342 weed_palette_get_name(ldev->current_palette));
343 #endif
344
345 if (!SUCCESS(unicap_set_format(ldev->handle, format))) {
346 LIVES_ERROR("Unicap error setting format");
347 unicap_unlock_stream(ldev->handle);
348 unicap_close(ldev->handle);
349 lives_free(ldev);
350 return FALSE;
351 }
352
353 g_print("ALLX %ld %d %d %d %d\n", format->buffer_size, format->size.width, format->size.height,
354 weed_palette_get_bits_per_macropixel(
355 ldev->current_palette), weed_palette_get_pixels_per_macropixel(ldev->current_palette));
356
357 if (format->buffer_size != format->size.width * format->size.height * weed_palette_get_bits_per_macropixel(
358 ldev->current_palette) /
359 weed_palette_get_pixels_per_macropixel(ldev->current_palette) / 8) {
360 int wwidth = format->size.width, awidth;
361 int wheight = format->size.height, aheight;
362 // something went wrong setting the size - the buffer is wrongly sized
363 #ifdef DEBUG_UNICAP
364 lives_printerr("Unicap buffer size is wrong, resetting it.\n");
365 #endif
366 // get the size again
367
368 unicap_get_format(ldev->handle, format);
369 awidth = format->size.width;
370 aheight = format->size.height;
371
372 #ifdef DEBUG_UNICAP
373 lives_printerr("Wanted frame size %d x %d, got %d x %d\n", wwidth, wheight, awidth, aheight);
374 #endif
375
376 format->buffer_size = format->size.width * format->size.height * weed_palette_get_bits_per_macropixel(ldev->current_palette) /
377 weed_palette_get_pixels_per_macropixel(ldev->current_palette) / 8;
378 }
379
380 cfile->hsize = format->size.width;
381 cfile->vsize = format->size.height;
382
383 cfile->ext_src = ldev;
384 cfile->ext_src_type = LIVES_EXT_SRC_DEVICE;
385
386 ldev->buffer1.data = (unsigned char *)lives_malloc(format->buffer_size);
387 ldev->buffer1.buffer_size = format->buffer_size;
388
389 ldev->buffer2.data = (unsigned char *)lives_malloc(format->buffer_size);
390 ldev->buffer2.buffer_size = format->buffer_size;
391
392 ldev->buffer_ready = 0;
393 ldev->fileno = mainw->current_file;
394
395 cfile->bpp = format->bpp;
396
397 unicap_start_capture(ldev->handle);
398
399 // if it is greyscale, we will add fake U and V planes
400 if (ldev->current_palette == WEED_PALETTE_A8) {
401 ldev->current_palette = WEED_PALETTE_YUV444P;
402 ldev->is_really_grey = TRUE;
403 } else ldev->is_really_grey = FALSE;
404
405 return TRUE;
406 }
407
408
lives_vdev_free(lives_vdev_t * ldev)409 void lives_vdev_free(lives_vdev_t *ldev) {
410 if (!ldev) return;
411 unicap_stop_capture(ldev->handle);
412 unicap_unlock_stream(ldev->handle);
413 unicap_close(ldev->handle);
414 if (ldev->buffer1.data) lives_free(ldev->buffer1.data);
415 if (ldev->buffer2.data) lives_free(ldev->buffer2.data);
416 }
417
418
on_open_vdev_activate(LiVESMenuItem * menuitem,livespointer user_data)419 boolean on_open_vdev_activate(LiVESMenuItem *menuitem, livespointer user_data) {
420 unicap_device_t devices[MAX_DEVICES];
421
422 LiVESList *devlist = NULL;
423
424 LiVESWidget *card_dialog;
425
426 char *fname;
427
428 int devno = 0;
429
430 int new_file = mainw->first_free_file;
431 int old_file = mainw->current_file;
432
433 int response;
434
435 int dev_count;
436 int status = STATUS_SUCCESS;
437
438 register int i;
439
440 mainw->open_deint = FALSE;
441
442 status = unicap_reenumerate_devices(&dev_count);
443
444 if (dev_count == 0) {
445 do_no_in_vdevs_error();
446 return FALSE;
447 }
448
449 // get device list
450 for (i = 0; SUCCESS(status) && (dev_count < MAX_DEVICES); i++) {
451 status = unicap_enumerate_devices(NULL, &devices[i], i);
452 if (!SUCCESS(status)) {
453 if (i == 0) LIVES_INFO("Unicap failed to get any devices");
454 }
455 }
456
457 if (!user_data) {
458 for (i = 0; i < dev_count; i++) {
459 if (!unicap_is_stream_locked(&devices[i])) {
460 devlist = lives_list_prepend(devlist, devices[i].identifier);
461 }
462 }
463
464 if (!devlist) {
465 do_locked_in_vdevs_error();
466 return FALSE;
467 }
468
469 mainw->fx1_val = 0;
470 mainw->open_deint = FALSE;
471 card_dialog = create_combo_dialog(1, (livespointer)devlist);
472 response = lives_dialog_run(LIVES_DIALOG(card_dialog));
473 lives_list_free(devlist); /// free only after runniong dialog !!!
474 if (response == LIVES_RESPONSE_CANCEL) {
475 return FALSE;
476 }
477 lives_widget_destroy(card_dialog);
478 } else {
479 char *device = (char *)user_data;
480 for (i = 0; i < dev_count; i++) {
481 if (!strcmp(device, devices[i].device)) {
482 mainw->fx1_val = i;
483 break;
484 }
485 }
486 }
487
488 for (i = dev_count - 1; i >= 0; i--) {
489 if (!unicap_is_stream_locked(&devices[i])) {
490 if (mainw->fx1_val == 0) {
491 devno = i;
492 break;
493 }
494 }
495 mainw->fx1_val--;
496 }
497
498 if (*devices[devno].device) fname = lives_strdup(devices[devno].device);
499 else fname = lives_strdup(devices[devno].identifier);
500
501 if (!get_new_handle(new_file, fname)) {
502 lives_free(fname);
503 return FALSE;
504 }
505
506 mainw->current_file = new_file;
507 cfile->clip_type = CLIP_TYPE_VIDEODEV;
508
509 d_print(""); ///< force switchtext
510
511 g_print("checking formats for %s\n", fname);
512
513 if (!open_vdev_inner(&devices[devno])) {
514 d_print(_("Unable to open device %s\n"), fname);
515 lives_free(fname);
516 close_current_file(old_file);
517 return FALSE;
518 }
519
520 if (cfile->interlace != LIVES_INTERLACE_NONE && prefs->auto_deint) cfile->deinterlace = TRUE; ///< auto deinterlace
521 if (!cfile->deinterlace) cfile->deinterlace = mainw->open_deint; ///< user can also force deinterlacing
522
523 cfile->start = cfile->end = cfile->frames = 1;
524 cfile->is_loaded = TRUE;
525 add_to_clipmenu();
526
527 lives_snprintf(cfile->type, 40, "%s", fname);
528
529 d_print(_("Opened device %s\n"), devices[devno].identifier);
530
531 switch_clip(0, new_file, TRUE);
532
533 lives_free(fname);
534
535 return TRUE;
536 }
537
538 #endif
539
540