Mercurial > mplayer.hg
changeset 24105:9e71e0345c35
Automatic TV channels scanning ability for MPlayer.
Code is based on patch from Otvos Attila oattila at chello dot hu
author | voroshil |
---|---|
date | Thu, 23 Aug 2007 16:09:30 +0000 |
parents | b0a47d3bf2f3 |
children | 93c73ce74baa |
files | DOCS/man/en/mplayer.1 DOCS/tech/slave.txt cfg-mplayer.h command.c input/input.c input/input.h stream/stream_tv.c stream/tv.c stream/tv.h stream/tvi_def.h stream/tvi_v4l.c stream/tvi_v4l2.c |
diffstat | 12 files changed, 187 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1 Thu Aug 23 14:20:31 2007 +0000 +++ b/DOCS/man/en/mplayer.1 Thu Aug 23 16:09:30 2007 +0000 @@ -1899,6 +1899,26 @@ .RE . .TP +.B \-tvscan <option1:option2:...> (TV and MPlayer only) +This option tunes various parameters for TV channel scanner. +MPlayer will also print value for "-tv channels=" option, +including existing and just found channels. +.sp 1 +Available suboptions are: +.RSs +.IPs autostart (default: not set) +Begin channel scanning immediately after MPlayer startup. +.IPs period=<0.1-2.0> (default: 0.5) +Specify delay in seconds before switching to next channel. +Lower values will cause faster scanning, but can detect +inactive TV channels as active. +.IPs threshold=<1-100> (default: 50) +Threshold value (in percent) for signal strength, reported by device. +Signal strength higher than this value will indicate that +currently scanning channel is active. +.RE +. +.TP .B \-user <username> (also see \-passwd) (network only) Specify username for HTTP authentication. .
--- a/DOCS/tech/slave.txt Thu Aug 23 14:20:31 2007 +0000 +++ b/DOCS/tech/slave.txt Thu Aug 23 16:09:30 2007 +0000 @@ -330,6 +330,9 @@ - - Delete last digit from page number. (Backspace emulation, works only in page number editing mode.) +tv_start_scan + Start automatic tv channels scaning + tv_step_channel <channel> Select next/previous TV channel.
--- a/cfg-mplayer.h Thu Aug 23 14:20:31 2007 +0000 +++ b/cfg-mplayer.h Thu Aug 23 16:09:30 2007 +0000 @@ -114,6 +114,14 @@ {NULL, NULL, 0, 0, 0, 0, NULL} }; +#ifdef USE_TV +m_option_t tvscan_conf[]={ + {"autostart", &stream_tv_defaults.scan, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"threshold", &stream_tv_defaults.scan_threshold, CONF_TYPE_INT, CONF_RANGE, 1, 100, NULL}, + {"period", &stream_tv_defaults.scan_period, CONF_TYPE_FLOAT, CONF_RANGE, 0.1, 2.0, NULL}, + {NULL, NULL, 0, 0, 0, 0, NULL} +}; +#endif /* * CONF_TYPE_FUNC_FULL : * allows own implementations for passing the params @@ -387,6 +395,11 @@ {"mouse-movements", &enable_mouse_movements, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL}, {"nomouse-movements", &enable_mouse_movements, CONF_TYPE_FLAG, CONF_GLOBAL, 1, 0, NULL}, {"doubleclick-time", &doubleclick_time, CONF_TYPE_INT, CONF_RANGE, 0, 1000, NULL}, +#ifdef USE_TV + {"tvscan", &tvscan_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL}, +#else + {"tvscan", "MPlayer was compiled without TV interface support.\n", CONF_TYPE_PRINT, 0, 0, 0, NULL}, +#endif #define MAIN_CONF #include "cfg-common.h"
--- a/command.c Thu Aug 23 14:20:31 2007 +0000 +++ b/command.c Thu Aug 23 16:09:30 2007 +0000 @@ -2287,6 +2287,10 @@ #endif #ifdef USE_TV + case MP_CMD_TV_START_SCAN: + if (mpctx->file_format == DEMUXER_TYPE_TV) + tv_start_scan((tvi_handle_t *) (mpctx->demuxer->priv),1); + break; case MP_CMD_TV_SET_FREQ: if (mpctx->file_format == DEMUXER_TYPE_TV) tv_set_freq((tvi_handle_t *) (mpctx->demuxer->priv),
--- a/input/input.c Thu Aug 23 14:20:31 2007 +0000 +++ b/input/input.c Thu Aug 23 16:09:30 2007 +0000 @@ -111,6 +111,7 @@ { MP_CMD_GET_META_GENRE, "get_meta_genre", 0, { {-1,{0}} } }, { MP_CMD_SWITCH_AUDIO, "switch_audio", 0, { { MP_CMD_ARG_INT,{-1} }, {-1,{0}} } }, #ifdef USE_TV + { MP_CMD_TV_START_SCAN, "tv_start_scan", 0, { {-1,{0}} }}, { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", 1, { { MP_CMD_ARG_INT ,{0}}, {-1,{0}} }}, { MP_CMD_TV_STEP_NORM, "tv_step_norm",0, { {-1,{0}} } }, { MP_CMD_TV_STEP_CHANNEL_LIST, "tv_step_chanlist", 0, { {-1,{0}} } },
--- a/input/input.h Thu Aug 23 14:20:31 2007 +0000 +++ b/input/input.h Thu Aug 23 16:09:30 2007 +0000 @@ -98,6 +98,7 @@ #define MP_CMD_SUB_SCALE 97 #define MP_CMD_TV_TELETEXT_ADD_DEC 98 #define MP_CMD_TV_TELETEXT_GO_LINK 99 +#define MP_CMD_TV_START_SCAN 100 #define MP_CMD_GUI_EVENTS 5000 #define MP_CMD_GUI_LOADFILE 5001
--- a/stream/stream_tv.c Thu Aug 23 14:20:31 2007 +0000 +++ b/stream/stream_tv.c Thu Aug 23 16:09:30 2007 +0000 @@ -74,7 +74,11 @@ 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)
--- a/stream/tv.c Thu Aug 23 14:20:31 2007 +0000 +++ b/stream/tv.c Thu Aug 23 16:09:30 2007 +0000 @@ -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 @@ 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 @@ ds_add_packet(demux->video,dp); } + if (tvh->tv_param->scan) tv_scan(tvh); return 1; } @@ -738,6 +826,16 @@ 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_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 @@ { 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(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 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(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_last_channel(tvi_handle_t *tvh) { + tvh->tv_param->scan=0; if (tv_channel_list) { tv_channels_t *tmp;
--- a/stream/tv.h Thu Aug 23 14:20:31 2007 +0000 +++ b/stream/tv.h Thu Aug 23 16:09:30 2007 +0000 @@ -50,6 +50,10 @@ 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 @@ 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_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 @@ #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_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
--- a/stream/tvi_def.h Thu Aug 23 14:20:31 2007 +0000 +++ b/stream/tvi_def.h Thu Aug 23 16:09:30 2007 +0000 @@ -43,6 +43,7 @@ h->chanlist_s = NULL; h->norm = -1; h->channel = -1; + h->scan = NULL; return(h); } @@ -51,6 +52,8 @@ if (h) { if (h->priv) free(h->priv); + if (h->scan) + free(h->scan); free(h); } }
--- a/stream/tvi_v4l.c Thu Aug 23 14:20:31 2007 +0000 +++ b/stream/tvi_v4l.c Thu Aug 23 16:09:30 2007 +0000 @@ -1441,6 +1441,16 @@ 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:
--- a/stream/tvi_v4l2.c Thu Aug 23 14:20:31 2007 +0000 +++ b/stream/tvi_v4l2.c Thu Aug 23 16:09:30 2007 +0000 @@ -864,6 +864,14 @@ 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) {