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 ...@@ -60,8 +60,7 @@ struct demux_sys_t
mtime_t start; mtime_t start;
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
vbi_capture *vbi_cap; vlc_v4l2_vbi_t *vbi;
es_out_id_t *p_es_subt[VBI_NUM_CC_STREAMS];
#endif #endif
}; };
...@@ -70,9 +69,6 @@ static void *MmapThread (void *); ...@@ -70,9 +69,6 @@ static void *MmapThread (void *);
static void *ReadThread (void *); static void *ReadThread (void *);
static int DemuxControl( demux_t *, int, va_list ); static int DemuxControl( demux_t *, int, va_list );
static int InitVideo (demux_t *, int fd, uint32_t caps); 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 ) int DemuxOpen( vlc_object_t *obj )
{ {
...@@ -83,7 +79,7 @@ int DemuxOpen( vlc_object_t *obj ) ...@@ -83,7 +79,7 @@ int DemuxOpen( vlc_object_t *obj )
return VLC_ENOMEM; return VLC_ENOMEM;
demux->p_sys = sys; demux->p_sys = sys;
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
sys->vbi_cap = NULL; sys->vbi = NULL;
#endif #endif
ParseMRL( obj, demux->psz_location ); ParseMRL( obj, demux->psz_location );
...@@ -452,18 +448,21 @@ static int InitVideo (demux_t *demux, int fd, uint32_t caps) ...@@ -452,18 +448,21 @@ static int InitVideo (demux_t *demux, int fd, uint32_t caps)
} }
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
char *vbi_path = var_InheritString (demux, CFG_PREFIX"vbidev"); if (std & V4L2_STD_NTSC_M)
if (vbi_path != NULL && (std & V4L2_STD_NTSC_M))
{ {
sys->vbi_cap = OpenVBIDev ((vlc_object_t *) demux, vbi_path); char *vbi_path = var_InheritString (demux, CFG_PREFIX"vbidev");
if (sys->vbi_cap) if (vbi_path != NULL)
InitVBI(demux); sys->vbi = OpenVBI (demux, vbi_path);
free(vbi_path);
} }
free(vbi_path);
#endif #endif
if (vlc_clone (&sys->thread, entry, demux, VLC_THREAD_PRIORITY_INPUT)) 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) if (sys->bufv != NULL)
StopMmap (sys->fd, sys->bufv, sys->bufc); StopMmap (sys->fd, sys->bufv, sys->bufc);
return -1; return -1;
...@@ -471,31 +470,6 @@ static int InitVideo (demux_t *demux, int fd, uint32_t caps) ...@@ -471,31 +470,6 @@ static int InitVideo (demux_t *demux, int fd, uint32_t caps)
return 0; 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 ) void DemuxClose( vlc_object_t *obj )
{ {
demux_t *demux = (demux_t *)obj; demux_t *demux = (demux_t *)obj;
...@@ -509,11 +483,8 @@ void DemuxClose( vlc_object_t *obj ) ...@@ -509,11 +483,8 @@ void DemuxClose( vlc_object_t *obj )
v4l2_close (sys->fd); v4l2_close (sys->fd);
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
if( sys->vbi_cap ) if (sys->vbi != NULL)
{ CloseVBI (sys->vbi);
close(vbi_capture_fd(sys->vbi_cap));
vbi_capture_delete( sys->vbi_cap );
}
#endif #endif
free( sys ); free( sys );
...@@ -567,9 +538,9 @@ static void *UserPtrThread (void *data) ...@@ -567,9 +538,9 @@ static void *UserPtrThread (void *data)
ufd[0].events = POLLIN; ufd[0].events = POLLIN;
#ifdef ZVBI_COMPILED #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; ufd[1].events = POLLIN;
numfds++; numfds++;
} }
...@@ -612,8 +583,8 @@ static void *UserPtrThread (void *data) ...@@ -612,8 +583,8 @@ static void *UserPtrThread (void *data)
es_out_Send (demux->out, sys->es, block); es_out_Send (demux->out, sys->es, block);
} }
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
if( sys->vbi_cap && ufd[1].revents ) if (sys->vbi != NULL && ufd[1].revents)
GrabVBI(demux, sys->vbi_cap, sys->p_es_subt, VBI_NUM_CC_STREAMS); GrabVBI (demux, sys->vbi);
#endif #endif
} }
vlc_restorecancel (canc); /* <- hmm, this is purely cosmetic */ vlc_restorecancel (canc); /* <- hmm, this is purely cosmetic */
...@@ -632,9 +603,9 @@ static void *MmapThread (void *data) ...@@ -632,9 +603,9 @@ static void *MmapThread (void *data)
ufd[0].events = POLLIN; ufd[0].events = POLLIN;
#ifdef ZVBI_COMPILED #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; ufd[1].events = POLLIN;
numfds++; numfds++;
} }
...@@ -664,8 +635,8 @@ static void *MmapThread (void *data) ...@@ -664,8 +635,8 @@ static void *MmapThread (void *data)
vlc_restorecancel (canc); vlc_restorecancel (canc);
} }
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
if( sys->vbi_cap && ufd[1].revents ) if (sys->vbi != NULL && ufd[1].revents)
GrabVBI(demux, sys->vbi_cap, sys->p_es_subt, VBI_NUM_CC_STREAMS); GrabVBI (demux, sys->vbi);
#endif #endif
} }
...@@ -684,9 +655,9 @@ static void *ReadThread (void *data) ...@@ -684,9 +655,9 @@ static void *ReadThread (void *data)
ufd[0].events = POLLIN; ufd[0].events = POLLIN;
#ifdef ZVBI_COMPILED #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; ufd[1].events = POLLIN;
numfds++; numfds++;
} }
...@@ -727,8 +698,8 @@ static void *ReadThread (void *data) ...@@ -727,8 +698,8 @@ static void *ReadThread (void *data)
vlc_restorecancel (canc); vlc_restorecancel (canc);
} }
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
if( sys->vbi_cap && ufd[1].revents ) if (sys->vbi != NULL && ufd[1].revents)
GrabVBI(demux, sys->vbi_cap, sys->p_es_subt, VBI_NUM_CC_STREAMS); GrabVBI (demux, sys->vbi);
#endif #endif
} }
assert (0); assert (0);
......
...@@ -20,10 +20,6 @@ ...@@ -20,10 +20,6 @@
#include "videodev2.h" #include "videodev2.h"
#ifdef ZVBI_COMPILED
# include <libzvbi.h>
#endif
/* libv4l2 functions */ /* libv4l2 functions */
extern int v4l2_fd_open (int, int); extern int v4l2_fd_open (int, int);
extern int (*v4l2_close) (int); extern int (*v4l2_close) (int);
...@@ -63,10 +59,12 @@ block_t* GrabVideo (vlc_object_t *, int, const struct buffer_t *); ...@@ -63,10 +59,12 @@ block_t* GrabVideo (vlc_object_t *, int, const struct buffer_t *);
#ifdef ZVBI_COMPILED #ifdef ZVBI_COMPILED
/* vbi.c */ /* vbi.c */
vbi_capture* OpenVBIDev( vlc_object_t *, const char *); typedef struct vlc_v4l2_vbi vlc_v4l2_vbi_t;
void GrabVBI( demux_t *p_demux, vbi_capture *vbi_cap,
es_out_id_t **p_es_subt, int num_streams); vlc_v4l2_vbi_t *OpenVBI (demux_t *, const char *);
#define VBI_NUM_CC_STREAMS 4 int GetFdVBI (vlc_v4l2_vbi_t *);
void GrabVBI (demux_t *p_demux, vlc_v4l2_vbi_t *);
void CloseVBI (vlc_v4l2_vbi_t *);
#endif #endif
/* demux.c */ /* demux.c */
......
...@@ -35,98 +35,126 @@ ...@@ -35,98 +35,126 @@
#include "v4l2.h" #include "v4l2.h"
#ifdef ZVBI_COMPILED #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; 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. vlc_v4l2_vbi_t *OpenVBI (demux_t *demux, const char *psz_device)
unsigned int services = VBI_SLICED_CAPTION_525; {
vlc_v4l2_vbi_t *vbi = malloc (sizeof (*vbi));
if (unlikely(vbi == NULL))
return NULL;
int rawfd = vlc_open (psz_device, O_RDWR); int rawfd = vlc_open (psz_device, O_RDWR);
if (rawfd == -1) if (rawfd == -1)
{ {
msg_Err ( p_obj, "cannot open device '%s': %m", psz_device ); msg_Err (demux, "cannot open device '%s': %m", psz_device);
return NULL; 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, for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
rawfd,
/* buffers */ 5,
&services,
/* strict */ 1,
&errstr,
/* verbose */ 1);
if (cap == NULL)
{ {
msg_Err( p_obj, "Cannot capture vbi data with v4l2 interface (%s)", es_format_t fmt;
errstr );
free(errstr); 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, void GrabVBI (demux_t *p_demux, vlc_v4l2_vbi_t *vbi)
es_out_id_t **p_es_subt, int num_streams)
{ {
block_t *p_block=NULL;
vbi_capture_buffer *sliced_bytes; vbi_capture_buffer *sliced_bytes;
struct timeval timeout={0,0}; /* poll */ struct timeval timeout={0,0}; /* poll */
int n_lines;
int canc = vlc_savecancel (); 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) { switch (r) {
case -1: case -1:
msg_Err( p_demux, "Error reading VBI (%m)" ); msg_Err (p_demux, "error reading VBI: %m");
break;
case 0: /* nothing avail */ case 0: /* nothing avail */
break; break;
case 1: /* got data */ 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 */ *data = field;
data++;
int size = (sliced_size + 1) * n_lines; memcpy(data, sliced_array[field].data, sliced_size);
if( !( p_block = block_Alloc( size ) ) ) data += sliced_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();
}
} }
} p_block->i_pts = mdate();
if( p_block ) for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
{ {
for (int i = 0; i < num_streams; i++) if (vbi->es[i] == NULL)
{ continue;
block_t *p_sblock;
if (p_es_subt[i] == NULL) block_t *dup = block_Duplicate(p_block);
continue; if (likely(dup != NULL))
p_sblock = block_Duplicate(p_block); es_out_Send(p_demux->out, vbi->es[i], dup);
if (p_sblock) }
es_out_Send(p_demux->out, p_es_subt[i], p_sblock); block_Release(p_block);
} }
block_Release(p_block);
} }
vlc_restorecancel (canc); vlc_restorecancel (canc);
} }
void CloseVBI (vlc_v4l2_vbi_t *vbi)
{
close (vbi_capture_fd (vbi->cap));
vbi_capture_delete (vbi->cap);
free (vbi);
}
#endif #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