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 *****************************************************************************/
28 #include <sys/types.h>
30 #include <vlc_common.h>
31 #include <vlc_block.h>
33 #include <vlc_demux.h>
39 # define VBI_NUM_CC_STREAMS 4
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))
53 int rawfd = vlc_open (psz_device, O_RDWR);
56 msg_Err (demux, "cannot open device '%s': %s", psz_device,
57 vlc_strerror_c(errno));
61 //Can put more in here. See osd.c in zvbi package.
62 unsigned int services = VBI_SLICED_CAPTION_525;
65 vbi->cap = vbi_capture_v4l2k_new (psz_device, rawfd,
73 msg_Err (demux, "cannot capture VBI data: %s", errstr);
79 for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
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() */
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);
115 msg_Err (p_demux, "error reading VBI: %s", vlc_strerror_c(errno));
116 case 0: /* nothing avail */
118 case 1: /* got data */
120 int n_lines = sliced_bytes->size / sizeof(vbi_sliced);
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))
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++)
136 memcpy(data, sliced_array[field].data, sliced_size);
139 p_block->i_pts = mdate();
141 for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
143 if (vbi->es[i] == NULL)
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 close (vbi_capture_fd (vbi->cap));
159 vbi_capture_delete (vbi->cap);