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
= vlc_tick_now();
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 vlc_close (vbi_capture_fd (vbi
->cap
));
159 vbi_capture_delete (vbi
->cap
);