Commit 2e3d6b3b authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

v4l2: gather most VBI code and all zvbi deps to vbi.c

Also, fix a small leak in vlc_clone() error path.
parent 564e94a3
......@@ -60,8 +60,7 @@ struct demux_sys_t
mtime_t start;
#ifdef ZVBI_COMPILED
vbi_capture *vbi_cap;
es_out_id_t *p_es_subt[VBI_NUM_CC_STREAMS];
vlc_v4l2_vbi_t *vbi;
#endif
};
......@@ -70,9 +69,6 @@ static void *MmapThread (void *);
static void *ReadThread (void *);
static int DemuxControl( demux_t *, int, va_list );
static int InitVideo (demux_t *, int fd, uint32_t caps);
#ifdef ZVBI_COMPILED
static int InitVBI (demux_t *);
#endif
int DemuxOpen( vlc_object_t *obj )
{
......@@ -83,7 +79,7 @@ int DemuxOpen( vlc_object_t *obj )
return VLC_ENOMEM;
demux->p_sys = sys;
#ifdef ZVBI_COMPILED
sys->vbi_cap = NULL;
sys->vbi = NULL;
#endif
ParseMRL( obj, demux->psz_location );
......@@ -452,18 +448,21 @@ static int InitVideo (demux_t *demux, int fd, uint32_t caps)
}
#ifdef ZVBI_COMPILED
char *vbi_path = var_InheritString (demux, CFG_PREFIX"vbidev");
if (vbi_path != NULL && (std & V4L2_STD_NTSC_M))
if (std & V4L2_STD_NTSC_M)
{
sys->vbi_cap = OpenVBIDev ((vlc_object_t *) demux, vbi_path);
if (sys->vbi_cap)
InitVBI(demux);
char *vbi_path = var_InheritString (demux, CFG_PREFIX"vbidev");
if (vbi_path != NULL)
sys->vbi = OpenVBI (demux, vbi_path);
free(vbi_path);
}
free(vbi_path);
#endif
if (vlc_clone (&sys->thread, entry, demux, VLC_THREAD_PRIORITY_INPUT))
{
#ifdef ZVBI_COMPILED
if (sys->vbi != NULL)
CloseVBI (sys->vbi);
#endif
if (sys->bufv != NULL)
StopMmap (sys->fd, sys->bufv, sys->bufc);
return -1;
......@@ -471,31 +470,6 @@ static int InitVideo (demux_t *demux, int fd, uint32_t caps)
return 0;
}
#ifdef ZVBI_COMPILED
static int InitVBI (demux_t *demux)
{
demux_sys_t *sys = demux->p_sys;
for (int i = 0; i < VBI_NUM_CC_STREAMS; i++)
{
es_format_t fmt;
es_format_Init( &fmt, SPU_ES, VLC_FOURCC('c', 'c', '1' + i, ' ') );
if (asprintf(&fmt.psz_description, "Closed captions %d", i + 1) >= 0)
{
msg_Dbg( demux, "new spu es %4.4s", (char*)&fmt.i_codec );
sys->p_es_subt[i] = es_out_Add( demux->out, &fmt );
}
}
/* Do a single read and throw away the results so that ZVBI calls
the STREAMON ioctl() */
GrabVBI(demux, sys->vbi_cap, sys->p_es_subt, VBI_NUM_CC_STREAMS);
return 0;
}
#endif
void DemuxClose( vlc_object_t *obj )
{
demux_t *demux = (demux_t *)obj;
......@@ -509,11 +483,8 @@ void DemuxClose( vlc_object_t *obj )
v4l2_close (sys->fd);
#ifdef ZVBI_COMPILED
if( sys->vbi_cap )
{
close(vbi_capture_fd(sys->vbi_cap));
vbi_capture_delete( sys->vbi_cap );
}
if (sys->vbi != NULL)
CloseVBI (sys->vbi);
#endif
free( sys );
......@@ -567,9 +538,9 @@ static void *UserPtrThread (void *data)
ufd[0].events = POLLIN;
#ifdef ZVBI_COMPILED
if ( sys->vbi_cap )
if (sys->vbi != NULL)
{
ufd[1].fd = vbi_capture_fd(sys->vbi_cap);
ufd[1].fd = GetFdVBI (sys->vbi);
ufd[1].events = POLLIN;
numfds++;
}
......@@ -612,8 +583,8 @@ static void *UserPtrThread (void *data)
es_out_Send (demux->out, sys->es, block);
}
#ifdef ZVBI_COMPILED
if( sys->vbi_cap && ufd[1].revents )
GrabVBI(demux, sys->vbi_cap, sys->p_es_subt, VBI_NUM_CC_STREAMS);
if (sys->vbi != NULL && ufd[1].revents)
GrabVBI (demux, sys->vbi);
#endif
}
vlc_restorecancel (canc); /* <- hmm, this is purely cosmetic */
......@@ -632,9 +603,9 @@ static void *MmapThread (void *data)
ufd[0].events = POLLIN;
#ifdef ZVBI_COMPILED
if ( sys->vbi_cap )
if (sys->vbi != NULL)
{
ufd[1].fd = vbi_capture_fd(sys->vbi_cap);
ufd[1].fd = GetFdVBI (sys->vbi);
ufd[1].events = POLLIN;
numfds++;
}
......@@ -664,8 +635,8 @@ static void *MmapThread (void *data)
vlc_restorecancel (canc);
}
#ifdef ZVBI_COMPILED
if( sys->vbi_cap && ufd[1].revents )
GrabVBI(demux, sys->vbi_cap, sys->p_es_subt, VBI_NUM_CC_STREAMS);
if (sys->vbi != NULL && ufd[1].revents)
GrabVBI (demux, sys->vbi);
#endif
}
......@@ -684,9 +655,9 @@ static void *ReadThread (void *data)
ufd[0].events = POLLIN;
#ifdef ZVBI_COMPILED
if ( sys->vbi_cap )
if (sys->vbi != NULL)
{
ufd[1].fd = vbi_capture_fd(sys->vbi_cap);
ufd[1].fd = GetFdVBI (sys->vbi);
ufd[1].events = POLLIN;
numfds++;
}
......@@ -727,8 +698,8 @@ static void *ReadThread (void *data)
vlc_restorecancel (canc);
}
#ifdef ZVBI_COMPILED
if( sys->vbi_cap && ufd[1].revents )
GrabVBI(demux, sys->vbi_cap, sys->p_es_subt, VBI_NUM_CC_STREAMS);
if (sys->vbi != NULL && ufd[1].revents)
GrabVBI (demux, sys->vbi);
#endif
}
assert (0);
......
......@@ -20,10 +20,6 @@
#include "videodev2.h"
#ifdef ZVBI_COMPILED
# include <libzvbi.h>
#endif
/* libv4l2 functions */
extern int v4l2_fd_open (int, int);
extern int (*v4l2_close) (int);
......@@ -63,10 +59,12 @@ block_t* GrabVideo (vlc_object_t *, int, const struct buffer_t *);
#ifdef ZVBI_COMPILED
/* vbi.c */
vbi_capture* OpenVBIDev( vlc_object_t *, const char *);
void GrabVBI( demux_t *p_demux, vbi_capture *vbi_cap,
es_out_id_t **p_es_subt, int num_streams);
#define VBI_NUM_CC_STREAMS 4
typedef struct vlc_v4l2_vbi vlc_v4l2_vbi_t;
vlc_v4l2_vbi_t *OpenVBI (demux_t *, const char *);
int GetFdVBI (vlc_v4l2_vbi_t *);
void GrabVBI (demux_t *p_demux, vlc_v4l2_vbi_t *);
void CloseVBI (vlc_v4l2_vbi_t *);
#endif
/* demux.c */
......
......@@ -35,98 +35,126 @@
#include "v4l2.h"
#ifdef ZVBI_COMPILED
# include <libzvbi.h>
# define VBI_NUM_CC_STREAMS 4
vbi_capture* OpenVBIDev( vlc_object_t *p_obj, const char *psz_device)
struct vlc_v4l2_vbi
{
vbi_capture *cap;
char* errstr = NULL;
es_out_id_t *es[VBI_NUM_CC_STREAMS];
};
//Can put more in here. See osd.c in zvbi package.
unsigned int services = VBI_SLICED_CAPTION_525;
vlc_v4l2_vbi_t *OpenVBI (demux_t *demux, const char *psz_device)
{
vlc_v4l2_vbi_t *vbi = malloc (sizeof (*vbi));
if (unlikely(vbi == NULL))
return NULL;
int rawfd = vlc_open (psz_device, O_RDWR);
if (rawfd == -1)
{
msg_Err ( p_obj, "cannot open device '%s': %m", psz_device );
return NULL;
msg_Err (demux, "cannot open device '%s': %m", psz_device);
goto err;
}
//Can put more in here. See osd.c in zvbi package.
unsigned int services = VBI_SLICED_CAPTION_525;
char *errstr = NULL;
vbi->cap = vbi_capture_v4l2k_new (psz_device, rawfd,
/* buffers */ 5,
&services,
/* strict */ 1,
&errstr,
/* verbose */ 1);
if (vbi->cap == NULL)
{
msg_Err (demux, "cannot capture VBI data: %s", errstr);
free (errstr);
goto err;
}
cap = vbi_capture_v4l2k_new (psz_device,
rawfd,
/* buffers */ 5,
&services,
/* strict */ 1,
&errstr,
/* verbose */ 1);
if (cap == NULL)
for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
{
msg_Err( p_obj, "Cannot capture vbi data with v4l2 interface (%s)",
errstr );
free(errstr);
es_format_t fmt;
es_format_Init (&fmt, SPU_ES, VLC_FOURCC('c', 'c', '1' + i, ' '));
if (asprintf (&fmt.psz_description, "Closed captions %d", i + 1) >= 0)
{
msg_Dbg (demux, "new spu es %4.4s", (char *)&fmt.i_codec);
vbi->es[i] = es_out_Add (demux->out, &fmt);
}
}
return cap;
/* Do a single read and throw away the results so that ZVBI calls
the STREAMON ioctl() */
GrabVBI(demux, vbi);
return vbi;
err:
free (vbi);
return NULL;
}
int GetFdVBI (vlc_v4l2_vbi_t *vbi)
{
return vbi_capture_fd(vbi->cap);
}
void GrabVBI( demux_t *p_demux, vbi_capture *vbi_cap,
es_out_id_t **p_es_subt, int num_streams)
void GrabVBI (demux_t *p_demux, vlc_v4l2_vbi_t *vbi)
{
block_t *p_block=NULL;
vbi_capture_buffer *sliced_bytes;
struct timeval timeout={0,0}; /* poll */
int n_lines;
int canc = vlc_savecancel ();
int r = vbi_capture_pull_sliced (vbi_cap, &sliced_bytes, &timeout);
int r = vbi_capture_pull_sliced (vbi->cap, &sliced_bytes, &timeout);
switch (r) {
case -1:
msg_Err( p_demux, "Error reading VBI (%m)" );
break;
msg_Err (p_demux, "error reading VBI: %m");
case 0: /* nothing avail */
break;
case 1: /* got data */
n_lines = sliced_bytes->size / sizeof(vbi_sliced);
if (n_lines)
{
int n_lines = sliced_bytes->size / sizeof(vbi_sliced);
if (!n_lines)
break;
int sliced_size = 2; /* Number of bytes per sliced line */
int size = (sliced_size + 1) * n_lines;
block_t *p_block = block_Alloc (size);
if (unlikely(p_block == NULL))
break;
uint8_t* data = p_block->p_buffer;
vbi_sliced *sliced_array = sliced_bytes->data;
for (int field = 0; field < n_lines; field++)
{
int sliced_size = 2; /* Number of bytes per sliced line */
int size = (sliced_size + 1) * n_lines;
if( !( p_block = block_Alloc( size ) ) )
{
msg_Err( p_demux, "cannot get block" );
}
else
{
int field;
uint8_t* data = p_block->p_buffer;
vbi_sliced *sliced_array = sliced_bytes->data;
for(field=0; field<n_lines; field++)
{
*data = field;
data++;
memcpy(data, sliced_array[field].data, sliced_size);
data += sliced_size;
}
p_block->i_buffer = size;
p_block->i_pts = mdate();
}
*data = field;
data++;
memcpy(data, sliced_array[field].data, sliced_size);
data += sliced_size;
}
}
p_block->i_pts = mdate();
if( p_block )
{
for (int i = 0; i < num_streams; i++)
{
block_t *p_sblock;
if (p_es_subt[i] == NULL)
continue;
p_sblock = block_Duplicate(p_block);
if (p_sblock)
es_out_Send(p_demux->out, p_es_subt[i], p_sblock);
for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
{
if (vbi->es[i] == NULL)
continue;
block_t *dup = block_Duplicate(p_block);
if (likely(dup != NULL))
es_out_Send(p_demux->out, vbi->es[i], dup);
}
block_Release(p_block);
}
block_Release(p_block);
}
vlc_restorecancel (canc);
}
void CloseVBI (vlc_v4l2_vbi_t *vbi)
{
close (vbi_capture_fd (vbi->cap));
vbi_capture_delete (vbi->cap);
free (vbi);
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment