[MPlayer-dev-eng] [PATCH] Teletext support try3 (3/5 raw data grabber)
Vladimir Voroshilov
voroshil at gmail.com
Sun Jul 15 12:59:12 CEST 2007
Hi, All
Here is third of 5 teletext patches.
TODO: add v4l1, bsdbktr support
See also contents of first patch for some details.
--
Regards,
Vladimir Voroshilov mailto:voroshil at gmail.com
JID: voroshil at gmail.com, voroshil at jabber.ru
ICQ: 95587719
-------------- next part --------------
Index: stream/tvi_v4l2.c
===================================================================
--- stream/tvi_v4l2.c (revision 23784)
+++ stream/tvi_v4l2.c (working copy)
@@ -77,6 +77,14 @@
/* video */
char *video_dev;
int video_fd;
+#ifdef HAVE_TV_TELETEXT
+ char *vbi_dev;
+ int vbi_fd;
+ int vbi_bufsize;
+ int vbi_shutdown;
+ pthread_t vbi_grabber_thread;
+ void *priv_vbi;
+#endif
int mp_format;
struct v4l2_capability capability;
struct v4l2_input input;
@@ -549,6 +557,127 @@
return TVI_CONTROL_TRUE;
}
+#ifdef HAVE_TV_TELETEXT
+static int vbi_init(priv_t* priv,char* device)
+{
+ int vbi_fd=0;
+ struct v4l2_capability cap;
+ struct v4l2_format fmt;
+ int res;
+
+ if(!device)
+ return TVI_CONTROL_FALSE;
+
+ priv->vbi_dev=strdup(device);
+
+ vbi_fd=open(priv->vbi_dev,O_RDWR);
+ if(vbi_fd<0){
+ mp_msg(MSGT_TV,MSGL_ERR,"vbi: could not open device %s\n",priv->vbi_dev);
+ return TVI_CONTROL_FALSE;
+ }
+
+ if(ioctl(vbi_fd,VIDIOC_QUERYCAP,&cap)<0){
+ mp_msg(MSGT_TV,MSGL_ERR,"vbi: Query capatibilities failed for %s\n",priv->vbi_dev);
+ close(vbi_fd);
+ return TVI_CONTROL_FALSE;
+ }
+ if(!cap.capabilities & V4L2_CAP_VBI_CAPTURE){
+ mp_msg(MSGT_TV,MSGL_ERR,"vbi: %s does not support VBI capture\n",priv->vbi_dev);
+ close(vbi_fd);
+ return TVI_CONTROL_FALSE;
+ }
+
+ memset(&fmt,0,sizeof(struct v4l2_format));
+ fmt.type=V4L2_BUF_TYPE_VBI_CAPTURE;
+ if((res=ioctl(vbi_fd,VIDIOC_G_FMT,&fmt))<0){
+ mp_msg(MSGT_TV,MSGL_ERR,"vbi: Query format failed: %x\n",res);
+ close(vbi_fd);
+ return TVI_CONTROL_FALSE;
+ }
+ if(fmt.fmt.vbi.sample_format!=V4L2_PIX_FMT_GREY){
+ mp_msg(MSGT_TV,MSGL_ERR,"vbi: format 0x%x is not supported\n",fmt.fmt.vbi.sample_format);
+ close(vbi_fd);
+ return TVI_CONTROL_FALSE;
+ }
+ priv->vbi_fd=vbi_fd;
+ mp_msg(MSGT_TV,MSGL_DBG3,"vbi: init ok\n");
+ return TVI_CONTROL_TRUE;
+}
+static int vbi_get_props(priv_t* priv,tt_stream_props* ptsp)
+{
+ struct v4l2_format fmt;
+ int res;
+ if(!priv || !ptsp)
+ return TVI_CONTROL_FALSE;
+
+ memset(&fmt,0,sizeof(struct v4l2_format));
+ fmt.type=V4L2_BUF_TYPE_VBI_CAPTURE;
+ if((res=ioctl(priv->vbi_fd,VIDIOC_G_FMT,&fmt))<0){
+ mp_msg(MSGT_TV,MSGL_ERR,"vbi_get_props: Query format failed: %x\n",res);
+ return TVI_CONTROL_FALSE;
+ }
+
+ ptsp->interlaced=(fmt.fmt.vbi.flags& V4L2_VBI_INTERLACED?1:0);
+
+ ptsp->offset=fmt.fmt.vbi.offset;
+ ptsp->sampling_rate=fmt.fmt.vbi.sampling_rate;
+ ptsp->samples_per_line=fmt.fmt.vbi.samples_per_line,
+
+ ptsp->count[0]=fmt.fmt.vbi.count[0];
+ ptsp->count[1]=fmt.fmt.vbi.count[1];
+ ptsp->bufsize = ptsp->samples_per_line * (ptsp->count[0] + ptsp->count[1]);
+
+ mp_msg(MSGT_TV,MSGL_V,"vbi_get_props: sampling_rate=%d,offset:%d,samples_per_line: %d\n interlaced:%s, count=[%d,%d]\n",
+ ptsp->sampling_rate,
+ ptsp->offset,
+ ptsp->samples_per_line,
+ ptsp->interlaced?"Yes":"No",
+ ptsp->count[0],
+ ptsp->count[1]);
+
+ return TVI_CONTROL_TRUE;
+}
+static void *vbi_grabber(void *data)
+{
+ priv_t *priv = (priv_t *) data;
+ int bytes,seq,prev_seq;
+ unsigned char* buf;
+ tt_stream_props tsp;
+
+ if(!priv->priv_vbi){
+ mp_msg(MSGT_TV,MSGL_WARN,"vbi: vbi not initialized. stopping thread.\n");
+ return NULL;
+ }
+
+ if(vbi_get_props(priv,&tsp)!=TVI_CONTROL_TRUE)
+ return NULL;
+
+ buf=malloc(tsp.bufsize);
+ seq=0;
+ prev_seq=0;
+ mp_msg(MSGT_TV,MSGL_V,"vbi: vbi capture thread started.\n");
+
+ while (!priv->vbi_shutdown){
+ bytes=read(priv->vbi_fd,buf,tsp.bufsize);
+ if (bytes!=tsp.bufsize){
+ mp_msg(MSGT_TV,MSGL_WARN,"vbi: expecting bytes: %d, got: %d",tsp.bufsize,bytes);
+ break;
+ }
+ seq=*(int*)(buf+bytes-4);
+ if(seq<=1) continue;
+ if (prev_seq && seq!=prev_seq+1){
+ prev_seq=0;
+ seq=0;
+ }
+ prev_seq=seq;
+ teletext_control(priv->priv_vbi,TV_VBI_CONTROL_DECODE_PAGE,&buf);
+ mp_msg(MSGT_TV,MSGL_DBG3,"grabber: se:%d\n",seq);
+ }
+ free(buf);
+ return NULL;
+}
+#endif //HAVE_TV_TELETEXT
+
static int control(priv_t *priv, int cmd, void *arg)
{
struct v4l2_control control;
@@ -817,7 +946,28 @@
if (audio_in_set_samplerate(&priv->audio_in, *(int*)arg) < 0) return TVI_CONTROL_FALSE;
// setup_audio_buffer_sizes(priv);
return TVI_CONTROL_TRUE;
+#ifdef HAVE_TV_TELETEXT
+ case TVI_CONTROL_VBI_INIT:
+ {
+ void* ptr;
+ tt_stream_props tsp;
+
+ if (vbi_init(priv,*(char**)arg)!=TVI_CONTROL_TRUE)
+ return TVI_CONTROL_FALSE;
+ if(vbi_get_props(priv,&tsp)==TVI_CONTROL_TRUE)
+ {
+ ptr=&tsp;
+ if(teletext_control(NULL,TV_VBI_CONTROL_START,&ptr)==TVI_CONTROL_TRUE)
+ priv->priv_vbi=ptr;
+ else
+ priv->priv_vbi=NULL;
+ }
+ return TVI_CONTROL_TRUE;
}
+ default:
+ return teletext_control(priv->priv_vbi,cmd,arg);
+#endif
+ }
mp_msg(MSGT_TV, MSGL_V, "%s: unknown control: %d\n", info.short_name, cmd);
return(TVI_CONTROL_UNKNOWN);
}
@@ -862,6 +1012,26 @@
{
int i, frames, dropped = 0;
+#ifdef HAVE_TV_TELETEXT
+ priv->vbi_shutdown=1;
+ if(priv->vbi_grabber_thread)
+ pthread_join(priv->vbi_grabber_thread, NULL);
+
+ teletext_control(priv->priv_vbi,TV_VBI_CONTROL_STOP,(void*)1);
+ priv->priv_vbi=NULL;
+
+ if(priv->vbi_fd){
+ close(priv->vbi_fd);
+ priv->vbi_fd=0;
+ }
+
+ if(priv->vbi_dev){
+ free(priv->vbi_dev);
+ priv->vbi_dev=0;
+ }
+
+#endif
+
priv->shutdown = 1;
if(priv->video_grabber_thread)
pthread_join(priv->video_grabber_thread, NULL);
@@ -1298,6 +1468,13 @@
}
}
+#ifdef HAVE_TV_TELETEXT
+ /* start vbi thread */
+ if(priv->priv_vbi){
+ priv->vbi_shutdown = 0;
+ pthread_create(&priv->vbi_grabber_thread, NULL, vbi_grabber, priv);
+ }
+#endif
/* start audio thread */
priv->shutdown = 0;
priv->audio_skew_measure_time = 0;
More information about the MPlayer-dev-eng
mailing list