contrib: cargo: use the 0.6.13 cargo-c version
[vlc.git] / modules / access / v4l2 / vbi.c
blobd645cdfcbf0e47d3e7fa19849850fad47865587b
1 /*****************************************************************************
2 * vbi.c : Video4Linux2 VBI input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2012 the VideoLAN team
6 * Author: Devin Heitmueller <dheitmueller at kernellabs dot com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <fcntl.h>
30 #include <vlc_common.h>
31 #include <vlc_block.h>
32 #include <vlc_fs.h>
33 #include <vlc_demux.h>
35 #include "v4l2.h"
37 #ifdef ZVBI_COMPILED
38 # include <libzvbi.h>
39 # define VBI_NUM_CC_STREAMS 4
41 struct vlc_v4l2_vbi
43 vbi_capture *cap;
44 es_out_id_t *es[VBI_NUM_CC_STREAMS];
47 vlc_v4l2_vbi_t *OpenVBI (demux_t *demux, const char *psz_device)
49 vlc_v4l2_vbi_t *vbi = malloc (sizeof (*vbi));
50 if (unlikely(vbi == NULL))
51 return NULL;
53 int rawfd = vlc_open (psz_device, O_RDWR);
54 if (rawfd == -1)
56 msg_Err (demux, "cannot open device '%s': %s", psz_device,
57 vlc_strerror_c(errno));
58 goto err;
61 //Can put more in here. See osd.c in zvbi package.
62 unsigned int services = VBI_SLICED_CAPTION_525;
63 char *errstr = NULL;
65 vbi->cap = vbi_capture_v4l2k_new (psz_device, rawfd,
66 /* buffers */ 5,
67 &services,
68 /* strict */ 1,
69 &errstr,
70 /* verbose */ 1);
71 if (vbi->cap == NULL)
73 msg_Err (demux, "cannot capture VBI data: %s", errstr);
74 free (errstr);
75 vlc_close (rawfd);
76 goto err;
79 for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
81 es_format_t fmt;
83 es_format_Init (&fmt, SPU_ES, VLC_FOURCC('c', 'c', '1' + i, ' '));
84 if (asprintf (&fmt.psz_description, "Closed captions %d", i + 1) >= 0)
86 msg_Dbg (demux, "new spu es %4.4s", (char *)&fmt.i_codec);
87 vbi->es[i] = es_out_Add (demux->out, &fmt);
91 /* Do a single read and throw away the results so that ZVBI calls
92 the STREAMON ioctl() */
93 GrabVBI(demux, vbi);
95 return vbi;
96 err:
97 free (vbi);
98 return NULL;
101 int GetFdVBI (vlc_v4l2_vbi_t *vbi)
103 return vbi_capture_fd(vbi->cap);
106 void GrabVBI (demux_t *p_demux, vlc_v4l2_vbi_t *vbi)
108 vbi_capture_buffer *sliced_bytes;
109 struct timeval timeout={0,0}; /* poll */
110 int canc = vlc_savecancel ();
112 int r = vbi_capture_pull_sliced (vbi->cap, &sliced_bytes, &timeout);
113 switch (r) {
114 case -1:
115 msg_Err (p_demux, "error reading VBI: %s", vlc_strerror_c(errno));
116 case 0: /* nothing avail */
117 break;
118 case 1: /* got data */
120 int n_lines = sliced_bytes->size / sizeof(vbi_sliced);
121 if (!n_lines)
122 break;
124 int sliced_size = 2; /* Number of bytes per sliced line */
125 int size = (sliced_size + 1) * n_lines;
126 block_t *p_block = block_Alloc (size);
127 if (unlikely(p_block == NULL))
128 break;
130 uint8_t* data = p_block->p_buffer;
131 vbi_sliced *sliced_array = sliced_bytes->data;
132 for (int field = 0; field < n_lines; field++)
134 *data = field;
135 data++;
136 memcpy(data, sliced_array[field].data, sliced_size);
137 data += sliced_size;
139 p_block->i_pts = vlc_tick_now();
141 for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
143 if (vbi->es[i] == NULL)
144 continue;
146 block_t *dup = block_Duplicate(p_block);
147 if (likely(dup != NULL))
148 es_out_Send(p_demux->out, vbi->es[i], dup);
150 block_Release(p_block);
153 vlc_restorecancel (canc);
156 void CloseVBI (vlc_v4l2_vbi_t *vbi)
158 vlc_close (vbi_capture_fd (vbi->cap));
159 vbi_capture_delete (vbi->cap);
160 free (vbi);
162 #endif