diff options
Diffstat (limited to 'stream')
-rw-r--r-- | stream/stream_tv.c | 6 | ||||
-rw-r--r-- | stream/tv.c | 104 | ||||
-rw-r--r-- | stream/tv.h | 15 | ||||
-rw-r--r-- | stream/tvi_def.h | 3 | ||||
-rw-r--r-- | stream/tvi_v4l.c | 10 | ||||
-rw-r--r-- | stream/tvi_v4l2.c | 8 |
6 files changed, 145 insertions, 1 deletions
diff --git a/stream/stream_tv.c b/stream/stream_tv.c index 8332b07477..bbddac1aff 100644 --- a/stream/stream_tv.c +++ b/stream/stream_tv.c @@ -74,7 +74,11 @@ tv_param_t stream_tv_defaults = { 0, //saturation NULL, //tdevice 0, //tformat - 100 //tpage + 100, //tpage + + 0, //scan_autostart + 50, //scan_threshold + 0.5 //scan_period }; #define ST_OFF(f) M_ST_OFF(tv_param_t,f) diff --git a/stream/tv.c b/stream/tv.c index 12d23895b9..ce1622b468 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -30,6 +30,7 @@ #include "libaf/af_format.h" #include "libmpcodecs/img_format.h" #include "libavutil/avstring.h" +#include "osdep/timer.h" #include "tv.h" @@ -65,6 +66,92 @@ static const tvi_info_t* tvi_driver_list[]={ NULL }; +void tv_start_scan(tvi_handle_t *tvh, int start) +{ + mp_msg(MSGT_TV,MSGL_INFO,"start scan\n"); + tvh->tv_param->scan=start?1:0; +} + +static void tv_scan(tvi_handle_t *tvh) +{ + unsigned int now; + struct CHANLIST cl; + tv_channels_t *tv_channel_tmp=NULL; + tv_channels_t *tv_channel_add=NULL; + tv_scan_t* scan; + int found=0, index=1; + + scan = tvh->scan; + now=GetTimer(); + if (!scan) { + scan=calloc(1,sizeof(tv_scan_t)); + tvh->scan=scan; + cl = tvh->chanlist_s[scan->channel_num]; + tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16)); + scan->scan_timer=now+1e6*tvh->tv_param->scan_period; + } + if(scan->scan_timer>now) + return; + + if (tv_get_signal(tvh)>tvh->tv_param->scan_threshold) { + cl = tvh->chanlist_s[scan->channel_num]; + tv_channel_tmp=tv_channel_list; + while (tv_channel_tmp) { + index++; + if (cl.freq==tv_channel_tmp->freq){ + found=1; + break; + } + tv_channel_add=tv_channel_tmp; + tv_channel_tmp=tv_channel_tmp->next; + } + if (!found) { + mp_msg(MSGT_TV, MSGL_INFO, "Found new channel: %s (#%d). \n",cl.name,index); + scan->new_channels++; + tv_channel_tmp = malloc(sizeof(tv_channels_t)); + tv_channel_tmp->index=index; + tv_channel_tmp->next=NULL; + tv_channel_tmp->prev=tv_channel_add; + tv_channel_tmp->freq=cl.freq; + snprintf(tv_channel_tmp->name,sizeof(tv_channel_tmp->name),"ch%d",index); + strncpy(tv_channel_tmp->number, cl.name, 5); + tv_channel_tmp->number[4]='\0'; + if (!tv_channel_list) + tv_channel_list=tv_channel_tmp; + else { + tv_channel_add->next=tv_channel_tmp; + tv_channel_list->prev=tv_channel_tmp; + } + }else + mp_msg(MSGT_TV, MSGL_INFO, "Found existing channel: %s-%s.\n", + tv_channel_tmp->number,tv_channel_tmp->name); + } + scan->channel_num++; + scan->scan_timer=now+1e6*tvh->tv_param->scan_period; + if (scan->channel_num>=chanlists[tvh->chanlist].count) { + tvh->tv_param->scan=0; + mp_msg(MSGT_TV, MSGL_INFO, "TV scan end. Found %d new channels.\n", scan->new_channels); + tv_channel_tmp=tv_channel_list; + if(tv_channel_tmp){ + mp_msg(MSGT_TV,MSGL_INFO,"channels="); + while(tv_channel_tmp){ + mp_msg(MSGT_TV,MSGL_INFO,"%s-%s",tv_channel_tmp->number,tv_channel_tmp->name); + if(tv_channel_tmp->next) + mp_msg(MSGT_TV,MSGL_INFO,","); + tv_channel_tmp=tv_channel_tmp->next; + } + } + if (!tv_channel_current) tv_channel_current=tv_channel_list; + if (tv_channel_current) + tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16)); + free(tvh->scan); + tvh->scan=NULL; + }else{ + cl = tvh->chanlist_s[scan->channel_num]; + tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16)); + mp_msg(MSGT_TV, MSGL_INFO, "Trying: %s (%.2f). \n",cl.name,1e-3*cl.freq); + } +} /* ================== DEMUX_TV ===================== */ /* @@ -106,6 +193,7 @@ static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds) ds_add_packet(demux->video,dp); } + if (tvh->tv_param->scan) tv_scan(tvh); return 1; } @@ -738,6 +826,16 @@ int tv_set_freq(tvi_handle_t *tvh, unsigned long freq) return(1); } +int tv_get_signal(tvi_handle_t *tvh) +{ + int signal=0; + if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE || + tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_SIGNAL, &signal)!=TVI_CONTROL_TRUE) + return 0; + + return signal; +} + /***************************************************************** * \brief tune current frequency by step_interval value * \parameter step_interval increment value in 1/16 MHz @@ -748,6 +846,7 @@ int tv_set_freq(tvi_handle_t *tvh, unsigned long freq) int tv_step_freq(tvi_handle_t* tvh, float step_interval){ unsigned long frequency; + tvh->tv_param->scan=0; tv_get_freq(tvh,&frequency); frequency+=step_interval; return tv_set_freq(tvh,frequency); @@ -757,6 +856,7 @@ int tv_step_channel_real(tvi_handle_t *tvh, int direction) { struct CHANLIST cl; + tvh->tv_param->scan=0; if (direction == TV_CHANNEL_LOWER) { if (tvh->channel-1 >= 0) @@ -784,6 +884,7 @@ int tv_step_channel_real(tvi_handle_t *tvh, int direction) } int tv_step_channel(tvi_handle_t *tvh, int direction) { + tvh->tv_param->scan=0; if (tv_channel_list) { if (direction == TV_CHANNEL_HIGHER) { tv_channel_last = tv_channel_current; @@ -814,6 +915,7 @@ int tv_set_channel_real(tvi_handle_t *tvh, char *channel) { int i; struct CHANLIST cl; + tvh->tv_param->scan=0; strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name); for (i = 0; i < chanlists[tvh->chanlist].count; i++) { @@ -835,6 +937,7 @@ int tv_set_channel_real(tvi_handle_t *tvh, char *channel) { int tv_set_channel(tvi_handle_t *tvh, char *channel) { int i, channel_int; + tvh->tv_param->scan=0; if (tv_channel_list) { tv_channel_last = tv_channel_current; channel_int = atoi(channel); @@ -851,6 +954,7 @@ int tv_set_channel(tvi_handle_t *tvh, char *channel) { int tv_last_channel(tvi_handle_t *tvh) { + tvh->tv_param->scan=0; if (tv_channel_list) { tv_channels_t *tmp; diff --git a/stream/tv.h b/stream/tv.h index 415fa2c006..c61c4b6c87 100644 --- a/stream/tv.h +++ b/stream/tv.h @@ -50,6 +50,10 @@ typedef struct tv_param_s { char *tdevice; ///< teletext device int tformat; ///< teletext display format int tpage; ///< start teletext page + + int scan; + int scan_threshold; + float scan_period; } tv_param_t; extern tv_param_t stream_tv_defaults; @@ -86,6 +90,7 @@ typedef struct tvi_handle_s { const struct CHANLIST *chanlist_s; int channel; tv_param_t * tv_param; + void * scan; } tvi_handle_t; typedef struct tv_channels_s { @@ -101,6 +106,12 @@ extern tv_channels_t *tv_channel_list; extern tv_channels_t *tv_channel_current, *tv_channel_last; extern char *tv_channel_last_real; +typedef struct { + unsigned int scan_timer; + int channel_num; + int new_channels; +} tv_scan_t; + #define TVI_CONTROL_FALSE 0 #define TVI_CONTROL_TRUE 1 #define TVI_CONTROL_NA -1 @@ -147,6 +158,7 @@ extern char *tv_channel_last_real; #define TVI_CONTROL_TUN_SET_TUNER 0x204 /* update priv->tuner struct for used input */ #define TVI_CONTROL_TUN_GET_NORM 0x205 #define TVI_CONTROL_TUN_SET_NORM 0x206 +#define TVI_CONTROL_TUN_GET_SIGNAL 0x207 /* AUDIO controls */ #define TVI_CONTROL_AUD_GET_FORMAT 0x301 @@ -215,10 +227,13 @@ int tv_step_chanlist(tvi_handle_t *tvh); int tv_set_freq(tvi_handle_t *tvh, unsigned long freq); int tv_get_freq(tvi_handle_t *tvh, unsigned long *freq); +int tv_get_signal(tvi_handle_t *tvh); int tv_step_freq(tvi_handle_t *tvh, float step_interval); int tv_set_norm(tvi_handle_t *tvh, char* norm); +void tv_start_scan(tvi_handle_t *tvh, int start); + #define TV_NORM_PAL 1 #define TV_NORM_NTSC 2 #define TV_NORM_SECAM 3 diff --git a/stream/tvi_def.h b/stream/tvi_def.h index 6dff1c8924..c47b0dfe36 100644 --- a/stream/tvi_def.h +++ b/stream/tvi_def.h @@ -43,6 +43,7 @@ static tvi_handle_t *new_handle(void) h->chanlist_s = NULL; h->norm = -1; h->channel = -1; + h->scan = NULL; return(h); } @@ -51,6 +52,8 @@ static void free_handle(tvi_handle_t *h) if (h) { if (h->priv) free(h->priv); + if (h->scan) + free(h->scan); free(h); } } diff --git a/stream/tvi_v4l.c b/stream/tvi_v4l.c index bfcf62d916..adbdf927c7 100644 --- a/stream/tvi_v4l.c +++ b/stream/tvi_v4l.c @@ -1441,6 +1441,16 @@ static int control(priv_t *priv, int cmd, void *arg) return(TVI_CONTROL_TRUE); } + case TVI_CONTROL_TUN_GET_SIGNAL: + { + if (ioctl(priv->video_fd, VIDIOCGTUNER, &priv->tuner) == -1) + { + mp_msg(MSGT_TV, MSGL_ERR, "ioctl get tuner failed: %s\n", strerror(errno)); + return(TVI_CONTROL_FALSE); + } + *(int*)arg=100*(priv->tuner.signal>>8)/255; + return(TVI_CONTROL_TRUE); + } /* ========== AUDIO controls =========== */ case TVI_CONTROL_AUD_GET_FORMAT: diff --git a/stream/tvi_v4l2.c b/stream/tvi_v4l2.c index d808cc6838..10c92b3163 100644 --- a/stream/tvi_v4l2.c +++ b/stream/tvi_v4l2.c @@ -864,6 +864,14 @@ static int control(priv_t *priv, int cmd, void *arg) case TVI_CONTROL_TUN_GET_NORM: *(int *)arg = priv->standard.index; return TVI_CONTROL_TRUE; + case TVI_CONTROL_TUN_GET_SIGNAL: + if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) { + mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n", + info.short_name, strerror(errno)); + return TVI_CONTROL_FALSE; + } + *(int*)arg=100*(priv->tuner.signal>>8)/255; + return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_SET_NORM: priv->standard.index = *(int *)arg; if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) { |