1 /*
2  *  libzvbi -- Linux DVB driver interface
3  *
4  *  (c) 2004, 2005, 2007 Michael H. Schimek
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public
17  *  License along with this library; if not, write to the
18  *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA  02110-1301  USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25 
26 #ifdef ENABLE_DVB
27 
28 #include <unistd.h>		/* read() */
29 #include <errno.h>
30 #include <sys/select.h>
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 
35 #ifndef HAVE_S64_U64
36   /* Linux 2.6.x asm/types.h defines __s64 and __u64 only
37      if __GNUC__ is defined. */
38 typedef int64_t __s64;
39 typedef uint64_t __u64;
40 #endif
41 #include "dvb/dmx.h"
42 
43 #include "io.h"
44 #include "vbi.h"		/* vbi_init_once */
45 #include "dvb_demux.h"
46 
47 typedef struct {
48 	vbi_capture		capture;
49 
50 	int			fd;
51 
52 	/* FIXME This may be too small? */
53 	uint8_t			pes_buffer[1024 * 8];
54 	const uint8_t *		bp;
55 	unsigned int		b_left;
56 
57 	vbi_dvb_demux *		demux;
58 
59 	vbi_capture_buffer	sliced_buffer;
60 	vbi_sliced		sliced_data[256];
61 	double			sample_time;
62 	int64_t			last_pts;
63 
64 	vbi_bool		do_trace;
65 	vbi_bool		bug_compatible;
66 } vbi_capture_dvb;
67 
68 #define printv(format, args...)						\
69 do {									\
70 	if (dvb->do_trace) {						\
71 		fprintf (stderr, "libzvbi: " format ,##args);		\
72 		fflush (stderr);					\
73 	}								\
74 } while (0)
75 
76 static __inline__ void
timeval_subtract(struct timeval * delta,const struct timeval * tv1,const struct timeval * tv2)77 timeval_subtract		(struct timeval *	delta,
78 				 const struct timeval *	tv1,
79 				 const struct timeval *	tv2)
80 {
81 	if (tv1->tv_usec < tv2->tv_usec) {
82 		delta->tv_sec = tv1->tv_sec - tv2->tv_sec - 1;
83 		delta->tv_usec = 1000000 + tv1->tv_usec - tv2->tv_usec;
84 	} else {
85 		delta->tv_sec = tv1->tv_sec - tv2->tv_sec;
86 		delta->tv_usec = tv1->tv_usec - tv2->tv_usec;
87 	}
88 }
89 
90 static void
timeout_subtract_elapsed(struct timeval * result,const struct timeval * timeout,const struct timeval * now,const struct timeval * start)91 timeout_subtract_elapsed	(struct timeval *	result,
92 				 const struct timeval *	timeout,
93 				 const struct timeval *	now,
94 				 const struct timeval *	start)
95 {
96 	struct timeval elapsed;
97 
98 	timeval_subtract (&elapsed, now, start);
99 
100 	if ((elapsed.tv_sec | elapsed.tv_usec) > 0) {
101 		timeval_subtract (result, timeout, &elapsed);
102 
103 		if ((result->tv_sec | result->tv_usec) < 0) {
104 			result->tv_sec = 0;
105 			result->tv_usec = 0;
106 		}
107 	} else {
108 		*result = *timeout;
109 	}
110 }
111 
112 static ssize_t
select_read(vbi_capture_dvb * dvb,struct timeval * now,const struct timeval * start,const struct timeval * timeout)113 select_read			(vbi_capture_dvb *	dvb,
114 				 struct timeval *	now,
115 				 const struct timeval *	start,
116 				 const struct timeval *	timeout)
117 {
118 	struct timeval tv;
119 	ssize_t actual;
120 
121  select_again:
122 	/* tv = timeout - (now - start). */
123 	timeout_subtract_elapsed (&tv, timeout, now, start);
124 
125 	/* Shortcut: don't wait if timeout is zero or elapsed. */
126 	if ((tv.tv_sec | tv.tv_usec) > 0) {
127 		fd_set set;
128 		int r;
129 
130  select_again_with_timeout:
131 		FD_ZERO (&set);
132 		FD_SET (dvb->fd, &set);
133 
134 		/* Note Linux select() may change tv. */
135 		r = select (dvb->fd + 1,
136 			    /* readable */ &set,
137 			    /* writeable */ NULL,
138 			    /* in exception */ NULL,
139 			    &tv);
140 
141 		switch (r) {
142 		case -1: /* error */
143 			switch (errno) {
144 			case EINTR:
145 				gettimeofday (now, /* timezone */ NULL);
146 				goto select_again;
147 
148 			default:
149 				return -1; /* error */
150 			}
151 
152 		case 0: /* timeout */
153 			if (dvb->bug_compatible)
154 				return -1; /* error */
155 
156 			return 0; /* timeout */
157 
158 		default:
159 			break;
160 		}
161 	}
162 
163  read_again:
164 	/* Non-blocking. */
165 	actual = read (dvb->fd,
166 		       dvb->pes_buffer,
167 		       sizeof (dvb->pes_buffer));
168 
169 	switch (actual) {
170 	case -1: /* error */
171 		switch (errno) {
172 		case EAGAIN:
173 			if (dvb->bug_compatible)
174 				return -1; /* error */
175 
176 			if ((timeout->tv_sec | timeout->tv_usec) <= 0)
177 				return 0; /* timeout */
178 
179 			gettimeofday (now, /* timezone */ NULL);
180 			timeout_subtract_elapsed (&tv, timeout, now, start);
181 
182 			if ((tv.tv_sec | tv.tv_usec) <= 0)
183 				return 0; /* timeout */
184 
185 			goto select_again_with_timeout;
186 
187 		case EINTR:
188 			goto read_again;
189 
190 		default:
191 			return -1; /* error */
192 		}
193 
194 	case 0: /* EOF? */
195 		printv ("End of file\n");
196 
197 		errno = 0;
198 
199 		return -1; /* error */
200 
201 	default:
202 		break;
203 	}
204 
205 	return actual;
206 }
207 
208 static int
dvb_read(vbi_capture * cap,vbi_capture_buffer ** raw,vbi_capture_buffer ** sliced,const struct timeval * timeout)209 dvb_read			(vbi_capture *		cap,
210 				 vbi_capture_buffer **	raw,
211 				 vbi_capture_buffer **	sliced,
212 				 const struct timeval *	timeout)
213 {
214 	vbi_capture_dvb *dvb = PARENT (cap, vbi_capture_dvb, capture);
215 	vbi_capture_buffer *sb;
216 	struct timeval start;
217 	struct timeval now;
218 	unsigned int n_lines;
219 	int64_t pts;
220 
221 	if (!sliced || !(sb = *sliced)) {
222 		sb = &dvb->sliced_buffer;
223 		sb->data = dvb->sliced_data;
224 	}
225 
226 	start.tv_sec = 0;
227 	start.tv_usec = 0;
228 
229 	/* When timeout is zero elapsed time doesn't matter. */
230 	if ((timeout->tv_sec | timeout->tv_usec) > 0)
231 		gettimeofday (&start, /* timezone */ NULL);
232 
233 	now = start;
234 
235 	for (;;) {
236 		if (0 == dvb->b_left) {
237 			ssize_t actual;
238 
239 			actual = select_read (dvb, &now, &start, timeout);
240 			if (actual <= 0)
241 				return actual;
242 
243 			gettimeofday (&now, /* timezone */ NULL);
244 
245 			/* XXX inaccurate. Should be the time when we
246 			   received the first byte of the first packet
247 			   containing data of the returned frame. Or so. */
248 			dvb->sample_time = now.tv_sec
249 				+ now.tv_usec * (1 / 1e6);
250 
251 			dvb->bp = dvb->pes_buffer;
252 			dvb->b_left = actual;
253 		}
254 
255 		/* Demultiplexer coroutine. Returns when one frame is complete
256 		   or the buffer is empty, advancing bp and b_left. Don't
257 		   change sb->data in flight. */
258 		/* XXX max sliced lines needs an API change. Currently this
259 		   value is determined by vbi_raw_decoder line count below,
260 		   256 / 2 because fields don't really apply here and in
261 		   practice even 32 should be enough. */
262 		n_lines = vbi_dvb_demux_cor (dvb->demux,
263 					     sb->data,
264 					     /* max sliced lines */ 128,
265 					     &pts,
266 					     &dvb->bp,
267 					     &dvb->b_left);
268 		if (n_lines > 0)
269 			break;
270 
271 		if (dvb->bug_compatible) {
272 			/* Only one read(), timeout ignored. */
273 			return 0; /* timeout */
274 		} else {
275 			/* Read until EAGAIN, another error or the
276 			   timeout expires, in this order. */
277 		}
278 	}
279 
280 	if (sliced) {
281 		sb->size = n_lines * sizeof (vbi_sliced);
282 		sb->timestamp = dvb->sample_time;
283 
284 		/* XXX PTS needs an API change.
285 		   sb->sample_time = dvb->sample_time;
286 		   sb->stream_time = pts; (first sliced line) */
287 		dvb->last_pts = pts;
288 
289 		*sliced = sb;
290 	}
291 
292 	if (raw && *raw) {
293 		/* Not implemented yet. */
294 		sb = *raw;
295 		sb->size = 0;
296 	}
297 
298 	return 1; /* success */
299 }
300 
301 static vbi_raw_decoder *
dvb_parameters(vbi_capture * cap)302 dvb_parameters			(vbi_capture *		cap)
303 {
304 	/* This is kinda silly but we keep it for compatibility
305 	   with earlier versions of the library. */
306 	static vbi_raw_decoder raw = {
307 		.count = { 128, 128 }, /* see dvb_read() */
308 	};
309 
310 	cap = cap; /* unused, no warning please */
311 
312 	return &raw;
313 }
314 
315 static unsigned int
dvb_update_services(vbi_capture * cap,vbi_bool reset,vbi_bool commit,unsigned int services,int strict,char ** errstr)316 dvb_update_services		(vbi_capture *		cap,
317 				 vbi_bool		reset,
318 				 vbi_bool		commit,
319 				 unsigned int		services,
320 				 int			strict,
321 				 char **		errstr)
322 {
323 	cap = cap; /* unused, no warning please */
324 	reset = reset;
325 	commit = commit;
326 	services = services;
327 	strict = strict;
328 	errstr = errstr;
329 
330 	return (VBI_SLICED_TELETEXT_B |
331 		VBI_SLICED_VPS |
332 		VBI_SLICED_CAPTION_625 |
333 		VBI_SLICED_WSS_625);
334 }
335 
336 static void
dvb_flush(vbi_capture * cap)337 dvb_flush			(vbi_capture *		cap)
338 {
339 	vbi_capture_dvb *dvb = PARENT (cap, vbi_capture_dvb, capture);
340 
341 	vbi_dvb_demux_reset (dvb->demux);
342 
343 	dvb->bp = dvb->pes_buffer;
344 	dvb->b_left = 0;
345 }
346 
347 static VBI_CAPTURE_FD_FLAGS
dvb_get_fd_flags(vbi_capture * cap)348 dvb_get_fd_flags		(vbi_capture *		cap)
349 {
350 	cap = cap; /* unused, no warning please */
351 
352 	return (VBI_FD_HAS_SELECT |
353 		VBI_FD_IS_DEVICE);
354 }
355 
356 static int
dvb_get_fd(vbi_capture * cap)357 dvb_get_fd			(vbi_capture *		cap)
358 {
359 	vbi_capture_dvb *dvb = PARENT (cap, vbi_capture_dvb, capture);
360 
361 	return dvb->fd;
362 }
363 
364 int64_t
vbi_capture_dvb_last_pts(const vbi_capture * cap)365 vbi_capture_dvb_last_pts	(const vbi_capture *	cap)
366 {
367 	const vbi_capture_dvb *dvb =
368 		CONST_PARENT (cap, vbi_capture_dvb, capture);
369 
370 	return dvb->last_pts;
371 }
372 
373 int
vbi_capture_dvb_filter(vbi_capture * cap,int pid)374 vbi_capture_dvb_filter		(vbi_capture *		cap,
375 				 int			pid)
376 {
377 	vbi_capture_dvb *dvb = PARENT (cap, vbi_capture_dvb, capture);
378 	struct dmx_pes_filter_params filter;
379 
380 	CLEAR (filter);
381 
382 	filter.pid	= pid;
383 	filter.input	= DMX_IN_FRONTEND;
384 	filter.output	= DMX_OUT_TAP;
385 	filter.pes_type	= DMX_PES_OTHER;
386 	filter.flags	= DMX_IMMEDIATE_START;
387 
388 	if (-1 == ioctl (dvb->fd, DMX_SET_PES_FILTER, &filter))
389 		return -1;
390 
391 	printv ("Capturing PES packets with PID %d\n", pid);
392 
393 	return 0;
394 }
395 
396 static void
dvb_delete(vbi_capture * cap)397 dvb_delete			(vbi_capture *		cap)
398 {
399 	vbi_capture_dvb *dvb;
400 
401 	if (NULL == cap)
402 		return;
403 
404 	dvb = PARENT (cap, vbi_capture_dvb, capture);
405 
406 	if (-1 != dvb->fd) {
407 		/* Error ignored. */
408 		device_close (dvb->capture.sys_log_fp, dvb->fd);
409 	}
410 
411 	vbi_dvb_demux_delete (dvb->demux);
412 
413 	/* Make unusable. */
414 	CLEAR (*dvb);
415 
416 	free (dvb);
417 }
418 
419 static vbi_bool
open_device(vbi_capture_dvb * dvb,const char * device_name,char ** errstr)420 open_device			(vbi_capture_dvb *	dvb,
421 				 const char *		device_name,
422 				 char **		errstr)
423 {
424 	int saved_errno;
425 	struct stat st;
426 
427 	if (-1 == stat (device_name, &st))
428 		goto io_error;
429 
430 	if (!S_ISCHR (st.st_mode)) {
431 		asprintf (errstr, _("%s is not a device."),
432 			  device_name);
433 		saved_errno = 0;
434 		goto failed;
435 	}
436 
437 	/* XXX Can we check if this is really a DVB demux device? */
438 
439 	dvb->fd = device_open (dvb->capture.sys_log_fp,
440 			       device_name,
441 			       O_RDONLY | O_NONBLOCK,
442 			       /* mode */ 0);
443 	if (-1 == dvb->fd)
444 		goto io_error;
445 
446 	return TRUE;
447 
448  io_error:
449 	saved_errno = errno;
450 
451 	asprintf (errstr, _("Cannot open '%s': %s."),
452 		  device_name, strerror (saved_errno));
453 
454 	/* fall through */
455 
456  failed:
457 	dvb->fd = -1;
458 
459 	errno = saved_errno;
460 
461 	return FALSE;
462 }
463 
464 vbi_capture *
vbi_capture_dvb_new2(const char * device_name,unsigned int pid,char ** errstr,vbi_bool trace)465 vbi_capture_dvb_new2		(const char *		device_name,
466 				 unsigned int		pid,
467 				 char **		errstr,
468 				 vbi_bool		trace)
469 {
470 	char *error = NULL;
471 	int saved_errno;
472 	vbi_capture_dvb *dvb;
473 
474 	pthread_once (&vbi_init_once, vbi_init);
475 
476 	if (NULL == errstr)
477 		errstr = &error;
478 	*errstr = NULL;
479 
480 	dvb = vbi_malloc (sizeof (*dvb));
481 	if (NULL == dvb)
482 		goto no_memory;
483 
484 	CLEAR (*dvb);
485 
486 	dvb->capture.read		= dvb_read;
487 	dvb->capture.sampling_point	= NULL;
488 	dvb->capture.debug		= NULL;
489 	dvb->capture.parameters		= dvb_parameters;
490 	dvb->capture.update_services	= dvb_update_services;
491 	dvb->capture.get_scanning	= NULL;
492 	dvb->capture.flush		= dvb_flush;
493 	dvb->capture.get_fd		= dvb_get_fd;
494 	dvb->capture.get_fd_flags	= dvb_get_fd_flags;
495 	dvb->capture.set_video_path	= NULL;
496 	dvb->capture._delete		= dvb_delete;
497 
498 	dvb->fd = -1;
499 
500 	dvb->do_trace = trace;
501 
502 	dvb->demux = vbi_dvb_pes_demux_new (/* callback */ NULL,
503 					    /* user_data */ NULL);
504 	if (NULL == dvb->demux)
505 		goto no_memory;
506 
507 	if (!open_device (dvb, device_name, errstr)) {
508 		saved_errno = errno;
509 		goto failed;
510 	}
511 
512 	printv ("Opened device %s\n", device_name);
513 
514 	if (0 != pid) {
515 		if (-1 == vbi_capture_dvb_filter (&dvb->capture, pid)) {
516 			saved_errno = errno;
517 			asprintf (errstr, _("DMX_SET_PES_FILTER failed: %s."),
518 				  strerror (errno));
519 			goto failed;
520 		}
521 	}
522 
523 	dvb_flush (&dvb->capture);
524 
525 	if (errstr == &error) {
526 		free (error);
527 		error = NULL;
528 	}
529 
530 	return &dvb->capture;
531 
532  no_memory:
533 	asprintf (errstr, _("Virtual memory exhausted."));
534 
535 	saved_errno = ENOMEM;
536 
537 	/* fall through */
538 
539  failed:
540 	if (NULL != dvb) {
541 		dvb_delete (&dvb->capture);
542 		dvb = NULL;
543 	}
544 
545 	if (errstr == &error) {
546 		free (error);
547 		error = NULL;
548 	}
549 
550 	errno = saved_errno;
551 
552 	return NULL;
553 }
554 
555 vbi_capture *
vbi_capture_dvb_new(char * dev,int scanning,unsigned int * services,int strict,char ** errstr,vbi_bool trace)556 vbi_capture_dvb_new		(char *			dev,
557 				 int			scanning,
558 				 unsigned int *		services,
559 				 int			strict,
560 				 char **		errstr,
561 				 vbi_bool		trace)
562 {
563 	char *error = NULL;
564 	vbi_capture *cap;
565 	vbi_capture_dvb *dvb;
566 
567 	scanning = scanning; /* unused, no warning please */
568 	services = services;
569 	strict = strict;
570 
571 	if (NULL == errstr)
572 		errstr = &error;
573 	*errstr = NULL;
574 
575 	cap = vbi_capture_dvb_new2 (dev, /* pid */ 0, errstr, trace);
576 	if (NULL == cap)
577 		goto failed;
578 
579 	dvb = PARENT (cap, vbi_capture_dvb, capture);
580 
581 	dvb->bug_compatible = TRUE;
582 
583  failed:
584 	if (errstr == &error) {
585 		free (error);
586 		error = NULL;
587 	}
588 
589 	return cap;
590 }
591 
592 #else /* !ENABLE_DVB */
593 
594 #include "io.h"
595 #include "vbi.h"
596 
597 /**
598  * @param cap Initialized DVB vbi_capture context.
599  *
600  * Returns the presentation time stamp associated with the data
601  * last read from the context. The PTS refers to the first sliced
602  * VBI line, not the last packet containing data of that frame.
603  *
604  * Note timestamps returned by vbi_capture read functions contain
605  * the system time (gettimeofday()) when the packet containing the
606  * first sliced line was captured, not the PTS.
607  *
608  * @returns
609  * Presentation time stamp (33 bits).
610  *
611  * @bug
612  * The read functions should return the PTS along with
613  * the capture timestamp.
614  *
615  * @since 0.2.13
616  */
617 int64_t
vbi_capture_dvb_last_pts(const vbi_capture * cap)618 vbi_capture_dvb_last_pts	(const vbi_capture *	cap)
619 {
620 	cap = cap; /* unused, no warning please */
621 
622 	return 0;
623 }
624 
625 /**
626  * @param cap Initialized DVB vbi_capture context.
627  * @param pid Filter out a stream with this PID.
628  *
629  * Programs the DVB device transport stream demultiplexer on the
630  * DVB capture device to filter out packets with this PID.
631  *
632  * @returns
633  * -1 on failure, 0 on success.
634  */
635 int
vbi_capture_dvb_filter(vbi_capture * cap,int pid)636 vbi_capture_dvb_filter		(vbi_capture *		cap,
637 				 int			pid)
638 {
639 	cap = cap; /* unused, no warning please */
640 	pid = pid;
641 
642 	return -1;
643 }
644 
645 /**
646  * @param device_name Name of the DVB device to open.
647  * @param pid Filter out a stream with this PID. You can pass 0 here
648  *   and set or change the PID later with vbi_capture_dvb_filter().
649  * @param errstr If not @c NULL the function stores a pointer to an error
650  *   description here. You must free() this string when no longer needed.
651  * @param trace If @c TRUE print progress and warning messages on stderr.
652  *
653  * Initializes a vbi_capture context reading from a Linux DVB device.
654  *
655  * @returns
656  * Initialized vbi_capture context, @c NULL on failure.
657  *
658  * @since 0.2.13
659  */
660 vbi_capture *
vbi_capture_dvb_new2(const char * device_name,unsigned int pid,char ** errstr,vbi_bool trace)661 vbi_capture_dvb_new2		(const char *		device_name,
662 				 unsigned int		pid,
663 				 char **		errstr,
664 				 vbi_bool		trace)
665 {
666 	device_name = device_name; /* unused, no warning please */
667 	pid = pid;
668 	trace = trace;
669 
670 	if (NULL != errstr)
671 		asprintf (errstr, _("DVB interface not compiled."));
672 
673 	return NULL;
674 }
675 
676 /**
677  * @param dev Name of the DVB device to open.
678  * @param scanning Ignored.
679  * @param services Ignored.
680  * @param strict Ignored.
681  * @param errstr If not @c NULL the function stores a pointer to an error
682  *   description here. You must free() this string when no longer needed.
683  * @param trace If @c TRUE print progress and warning messages on stderr.
684  *
685  * @deprecated
686  * This function is deprecated. Use vbi_capture_dvb_new2() instead.
687  *
688  * Initializes a vbi_capture context reading from a Linux DVB device.
689  * You must call vbi_capture_dvb_filter() before you can read.
690  *
691  * @returns
692  * Initialized vbi_capture context, @c NULL on failure.
693  *
694  * @bug
695  * This function ignores the scanning, services and strict parameter.
696  * The read method of this DVB capture context returns -1 on timeout
697  * instead of 0. It returns 0 when a single read() does not complete
698  * a frame, regardless if the timeout expired. (Decoding resumes with
699  * the next call.) Older versions pass select or read EINTR errors
700  * back to the caller. They may return partial frames when VBI data
701  * of one frame is distributed across multiple PES packets. They will
702  * not return VPS, CC, or WSS data and can malfunction or segfault
703  * given unusual PES streams. On error and select timeout older versions
704  * invariably print a warning on stderr.
705  */
706 vbi_capture *
vbi_capture_dvb_new(char * dev,int scanning,unsigned int * services,int strict,char ** errstr,vbi_bool trace)707 vbi_capture_dvb_new		(char *			dev,
708 				 int			scanning,
709 				 unsigned int *		services,
710 				 int			strict,
711 				 char **		errstr,
712 				 vbi_bool		trace)
713 {
714 	dev = dev; /* unused, no warning please */
715 	scanning = scanning;
716 	services = services;
717 	strict = strict;
718 	trace = trace;
719 
720 	if (NULL != errstr)
721 		asprintf (errstr, _("DVB interface not compiled."));
722 
723 	return NULL;
724 }
725 
726 #endif /* !ENABLE_DVB */
727 
728 /*
729 Local variables:
730 c-set-style: K&R
731 c-basic-offset: 8
732 End:
733 */
734