12 static boolean gotbroken;
14 typedef struct y4data {
22 static int yuvout, hsize_out, vsize_out;
25 static LiVESList *fw_cards = NULL;
30 if (!yuv4mpeg)
return NULL;
31 yuv4mpeg->
sar = y4m_sar_UNKNOWN;
32 yuv4mpeg->
dar = y4m_dar_4_3;
34 y4m_init_frame_info(&(yuv4mpeg->
frameinfo));
36 yuv4mpeg->
name = NULL;
43 static void *y4open_thread(
void *arg) {
44 y4data *thread_data = (y4data *)arg;
45 int fd =
lives_open2(thread_data->filename, O_RDONLY);
51 static void *y4header_thread(
void *arg) {
52 y4data *thread_data = (y4data *)arg;
54 thread_data->i = y4m_read_stream_header(yuv4mpeg->
fd, &(yuv4mpeg->
streaminfo));
59 static void fill_read(
int fd,
char *buf,
size_t count) {
64 got = read(fd, buf + bytes, count - bytes);
67 }
while (bytes < count);
71 static void *y4frame_thread(
void *arg) {
72 y4data *thread_data = (y4data *)arg;
76 thread_data->i = Y4M_OK;
79 fill_read(yuv4mpeg->
fd, buff, 5);
81 if (strncmp(buff,
"FRAME", 5)) {
83 thread_data->i = Y4M_ERR_MAGIC;
89 fill_read(yuv4mpeg->
fd, buff + 4, 1);
90 }
while (strncmp(buff,
"FRAME", 5));
94 fill_read(yuv4mpeg->
fd, &bchar, 1);
95 }
while (strncmp(&bchar,
"\n", 1));
106 static boolean lives_yuv_stream_start_read(
lives_clip_t *sfile) {
107 double ofps = sfile->
fps;
113 char *filename = yuv4mpeg->
filename, *tmp;
118 int ohsize = sfile->
hsize;
119 int ovsize = sfile->
vsize;
125 if (!filename)
return FALSE;
127 if (yuv4mpeg->
fd == -1) {
130 thread_data.filename = filename;
132 pthread_create(&y4thread, NULL, y4open_thread, (
void *)&thread_data);
137 d_print(
_(
"Waiting for yuv4mpeg frames..."));
141 while ((timeout =
lives_alarm_check(alarm_handle)) > 0 && !pthread_kill(y4thread, 0)) {
150 pthread_cancel(y4thread);
151 pthread_join(y4thread, NULL);
154 d_print(
_(
"Unable to open the incoming video stream\n"));
156 yuv4mpeg->
fd = thread_data.fd;
158 if (yuv4mpeg->
fd >= 0) {
165 pthread_join(y4thread, NULL);
167 yuv4mpeg->
fd = thread_data.fd;
169 if (yuv4mpeg->
fd < 0) {
175 thread_data.yuv4mpeg = yuv4mpeg;
176 pthread_create(&y4thread, NULL, y4header_thread, &thread_data);
179 while ((timeout =
lives_alarm_check(alarm_handle)) > 0 && !pthread_kill(y4thread, 0)) {
188 pthread_cancel(y4thread);
189 pthread_join(y4thread, NULL);
190 d_print(
_(
"Unable to read the stream header\n"));
194 pthread_join(y4thread, NULL);
211 (y4m_si_get_framerate(&(yuv4mpeg->
streaminfo)))), NULL);
219 if (sfile->
hsize != ohsize || sfile->
vsize != ovsize || sfile->
fps != ofps) {
234 y4m_fini_stream_info(&(yuv4mpeg->
streaminfo));
235 y4m_fini_frame_info(&(yuv4mpeg->
frameinfo));
236 yuv4mpeg->
sar = y4m_sar_UNKNOWN;
237 yuv4mpeg->
dar = y4m_dar_4_3;
238 if (yuv4mpeg->
fd != -1) close(yuv4mpeg->
fd);
247 if (yuv4mpeg->
type ==
YUV4_TYPE_FW) fw_cards = lives_list_remove(fw_cards, LIVES_INT_TO_POINTER(yuv4mpeg->
cardno));
249 LIVES_INT_TO_POINTER(yuv4mpeg->
cardno));
266 if (!yuv4mpeg->
ready) lives_yuv_stream_start_read(sfile);
268 weed_set_int_value(layer, WEED_LEAF_WIDTH, sfile->
hsize);
269 weed_set_int_value(layer, WEED_LEAF_HEIGHT, sfile->
vsize);
270 weed_set_int_value(layer, WEED_LEAF_CURRENT_PALETTE, WEED_PALETTE_YUV420P);
271 weed_set_int_value(layer, WEED_LEAF_YUV_SUBSPACE, WEED_YUV_SUBSPACE_YCBCR);
275 if (!yuv4mpeg->
ready) {
279 yuv4mpeg->
pixel_data = weed_get_voidptr_array(layer, WEED_LEAF_PIXEL_DATA, &
error);
283 thread_data.yuv4mpeg = yuv4mpeg;
284 pthread_create(&y4thread, NULL, y4frame_thread, &thread_data);
288 while ((timeout =
lives_alarm_check(alarm_handle)) > 0 && !pthread_kill(y4thread, 0)) {
296 pthread_cancel(y4thread);
297 d_print(
_(
"Unable to read the incoming video frame\n"));
299 }
else gotbroken =
FALSE;
301 pthread_join(y4thread, NULL);
306 weed_set_int_value(layer, WEED_LEAF_YUV_SAMPLING, WEED_YUV_SAMPLING_MPEG);
312 static boolean open_yuv4m_inner(
const char *filename,
const char *fname,
int new_file,
int type,
int cardno) {
321 yuv4mpeg = lives_yuv4mpeg_alloc();
325 yuv4mpeg->
filename = lives_strdup(filename);
326 yuv4mpeg->
name = lives_strdup(fname);
328 yuv4mpeg->
type = type;
329 yuv4mpeg->
cardno = cardno;
331 cfile->ext_src = yuv4mpeg;
362 char *audio_real, *audio_fake;
366 fname = (
_(
"yuv4mpeg stream"));
375 if (!strlen(
prefs->yuvin)) {
376 filename =
choose_file(NULL, NULL, NULL, LIVES_FILE_CHOOSER_ACTION_OPEN,
_(
"Open _yuv4mpeg stream (fifo)"), NULL);
377 if (!filename)
return;
378 }
else filename = lives_strdup(
prefs->yuvin);
380 mkfifo(filename, S_IRUSR | S_IWUSR);
391 if (!lives_yuv_stream_start_read(
cfile)) {
399 lives_snprintf(
cfile->type, 40,
"%s",
_(
"yu4mpeg stream in"));
407 if (
cfile->achans == 0) {
469 if ((yuvout = creat(filename, O_CREAT)) < 0) {
475 y4m_si_set_framerate(&(yuv4mpeg->
streaminfo), y4m_fps_FILM);
477 y4m_si_set_interlace(&(yuv4mpeg->
streaminfo), Y4M_ILACE_NONE);
479 y4m_si_set_width(&(yuv4mpeg->
streaminfo), (hsize_out = hsize));
480 y4m_si_set_height(&(yuv4mpeg->
streaminfo), (vsize_out = vsize));
481 y4m_si_set_sampleaspect(&(yuv4mpeg->
streaminfo), yuv4mpeg->
sar);
483 i = y4m_write_stream_header(yuvout, &(yuv4mpeg->
streaminfo));
485 if (i != Y4M_OK)
return FALSE;
496 uint8_t *pixels = (uint8_t *)pixel_data;
498 planes[0] = &(pixels[0]);
499 planes[1] = &(pixels[hsize_out * vsize_out]);
500 planes[2] = &(pixels[hsize_out * vsize_out * 5 / 4]);
502 i = y4m_write_frame(yuvout, &(yuv4mpeg->
streaminfo),
503 &(yuv4mpeg->
frameinfo), (uint8_t **)&planes[0]);
504 if (i != Y4M_OK)
return FALSE;
510 y4m_fini_stream_info(&(yuv4mpeg->
streaminfo));
511 y4m_fini_frame_info(&(yuv4mpeg->
frameinfo));
556 LiVESWidget *card_dialog;
571 tvcardw = (
lives_tvcardw_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(card_dialog),
"tvcard_data");
574 if (response == LIVES_RESPONSE_CANCEL) {
584 if (lives_list_find(
mainw->
videodevs, LIVES_INT_TO_POINTER(cardno))) {
624 mkfifo(fifofile, S_IRUSR | S_IWUSR);
631 const char *driver = NULL, *outfmt = NULL;
632 int width = 0, height = 0;
644 com =
lives_strdup_printf(
"%s open_tv_card \"%s\" \"%s\" \"%s\" \"%s\" %d %d %d %.3f \"%s\" \"%s\"",
646 devstr, fifofile, input, width, height, fps, driver, outfmt);
663 if (!open_yuv4m_inner(fifofile, fname, new_file,
YUV4_TYPE_TV, cardno)) {
671 lives_snprintf(
cfile->type, 40,
"%s", fname);
695 LiVESWidget *card_dialog;
701 if (response == LIVES_RESPONSE_CANCEL) {
711 if (lives_list_find(fw_cards, LIVES_INT_TO_POINTER(cardno))) {
725 fw_cards = lives_list_append(fw_cards, LIVES_INT_TO_POINTER(cardno));
731 mkfifo(fifofile, S_IRUSR | S_IWUSR);
744 if (!open_yuv4m_inner(fifofile, fname, new_file,
YUV4_TYPE_FW, cardno)) {
750 lives_snprintf(
cfile->type, 40,
"%s", fname);