diff options
-rw-r--r-- | DOCS/man/en/options.rst | 264 | ||||
-rw-r--r-- | options/options.c | 62 | ||||
-rw-r--r-- | options/options.h | 2 | ||||
-rw-r--r-- | stream/stream_pvr.c | 69 | ||||
-rw-r--r-- | stream/stream_tv.c | 48 | ||||
-rw-r--r-- | stream/tv.c | 277 | ||||
-rw-r--r-- | stream/tv.h | 22 | ||||
-rw-r--r-- | stream/tvi_v4l2.c | 22 |
8 files changed, 376 insertions, 390 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index ec5061c4de..58b1345922 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -2395,192 +2395,184 @@ OPTIONS Verify peer certificates when using TLS (e.g. with ``https://...``). (Silently fails with older ffmpeg or libav versions.) -``--tv=<option1:option2:...>`` - This option tunes various properties of the TV capture module. For +``--tv-...`` + These options tune various properties of the TV capture module. For watching TV with mpv, use ``tv://`` or ``tv://<channel_number>`` or - even ``tv://<channel_name>`` (see option ``channels`` for ``channel_name`` + even ``tv://<channel_name>`` (see option ``tv-channels`` for ``channel_name`` below) as a movie URL. You can also use ``tv:///<input_id>`` to start watching a movie from a composite or S-Video input (see option ``input`` for details). - Available options are: - - ``noaudio`` - no sound - - ``automute=<0-255> (v4l and v4l2 only)`` - If signal strength reported by device is less than this value, audio - and video will be muted. In most cases automute=100 will be enough. - Default is 0 (automute disabled). +``--no-tv-audio`` + no sound - ``driver=<value>`` - See ``--tv=driver=help`` for a list of compiled-in TV input drivers. - available: dummy, v4l2 (default: autodetect) +``--tv-automute=<0-255> (v4l and v4l2 only)`` + If signal strength reported by device is less than this value, audio + and video will be muted. In most cases automute=100 will be enough. + Default is 0 (automute disabled). - ``device=<value>`` - Specify TV device (default: ``/dev/video0``). +``--tv-driver=<value>`` + See ``--tv=driver=help`` for a list of compiled-in TV input drivers. + available: dummy, v4l2 (default: autodetect) - ``input=<value>`` - Specify input (default: 0 (TV), see console output for available - inputs). +``--tv-device=<value>`` + Specify TV device (default: ``/dev/video0``). - ``freq=<value>`` - Specify the frequency to set the tuner to (e.g. 511.250). Not - compatible with the channels parameter. +``--tv-input=<value>`` + Specify input (default: 0 (TV), see console output for available + inputs). - ``outfmt=<value>`` - Specify the output format of the tuner with a preset value supported - by the V4L driver (YV12, UYVY, YUY2, I420) or an arbitrary format given - as hex value. +``--tv-freq=<value>`` + Specify the frequency to set the tuner to (e.g. 511.250). Not + compatible with the channels parameter. - ``width=<value>`` - output window width +``--tv-outfmt=<value>`` + Specify the output format of the tuner with a preset value supported + by the V4L driver (YV12, UYVY, YUY2, I420) or an arbitrary format given + as hex value. - ``height=<value>`` - output window height +``--tv-width=<value>`` + output window width - ``fps=<value>`` - framerate at which to capture video (frames per second) +``--tv-height=<value>`` + output window height - ``buffersize=<value>`` - maximum size of the capture buffer in megabytes (default: dynamical) +``--tv-fps=<value>`` + framerate at which to capture video (frames per second) - ``norm=<value>`` - See the console output for a list of all available norms, also see the - ``normid`` option below. +``--tv-buffersize=<value>`` + maximum size of the capture buffer in megabytes (default: dynamical) - ``normid=<value> (v4l2 only)`` - Sets the TV norm to the given numeric ID. The TV norm depends on the - capture card. See the console output for a list of available TV norms. +``--tv-norm=<value>`` + See the console output for a list of all available norms, also see the + ``normid`` option below. - ``channel=<value>`` - Set tuner to <value> channel. +``--tv-normid=<value> (v4l2 only)`` + Sets the TV norm to the given numeric ID. The TV norm depends on the + capture card. See the console output for a list of available TV norms. - ``chanlist=<value>`` - available: argentina, australia, china-bcast, europe-east, - europe-west, france, ireland, italy, japan-bcast, japan-cable, - newzealand, russia, southafrica, us-bcast, us-cable, us-cable-hrc +``--tv-channel=<value>`` + Set tuner to <value> channel. - ``channels=<chan>-<name>[=<norm>],<chan>-<name>[=<norm>],...`` - Set names for channels. - - .. note:: +``--tv-chanlist=<value>`` + available: argentina, australia, china-bcast, europe-east, + europe-west, france, ireland, italy, japan-bcast, japan-cable, + newzealand, russia, southafrica, us-bcast, us-cable, us-cable-hrc - If <chan> is an integer greater than 1000, it will be treated as - frequency (in kHz) rather than channel name from frequency table. - Use _ for spaces in names (or play with quoting ;-) ). The channel - names will then be written using OSD, and the slave commands - ``tv_step_channel``, ``tv_set_channel`` and ``tv_last_channel`` - will be usable for a remote control (see LIRC). Not compatible with - the ``frequency`` parameter. +``--tv-channels=<chan>-<name>[=<norm>],<chan>-<name>[=<norm>],...`` + Set names for channels. - .. note:: + .. note:: - The channel number will then be the position in the 'channels' - list, beginning with 1. + If <chan> is an integer greater than 1000, it will be treated as + frequency (in kHz) rather than channel name from frequency table. + Use _ for spaces in names (or play with quoting ;-) ). The channel + names will then be written using OSD, and the slave commands + ``tv_step_channel``, ``tv_set_channel`` and ``tv_last_channel`` + will be usable for a remote control (see LIRC). Not compatible with + the ``frequency`` parameter. - .. admonition:: Examples + .. note:: - ``tv://1``, ``tv://TV1``, ``tv_set_channel 1``, - ``tv_set_channel TV1`` + The channel number will then be the position in the 'channels' + list, beginning with 1. - ``[brightness|contrast|hue|saturation]=<-100-100>`` - Set the image equalizer on the card. + .. admonition:: Examples - ``audiorate=<value>`` - Set input audio sample rate. + ``tv://1``, ``tv://TV1``, ``tv_set_channel 1``, + ``tv_set_channel TV1`` - ``forceaudio`` - Capture audio even if there are no audio sources reported by v4l. +``--tv-[brightness|contrast|hue|saturation]=<-100-100>`` + Set the image equalizer on the card. - ``alsa`` - Capture from ALSA. +``--tv-audiorate=<value>`` + Set input audio sample rate. - ``amode=<0-3>`` - Choose an audio mode: +``--tv-forceaudio`` + Capture audio even if there are no audio sources reported by v4l. - :0: mono - :1: stereo - :2: language 1 - :3: language 2 +``--tv-alsa`` + Capture from ALSA. - ``forcechan=<1-2>`` - By default, the count of recorded audio channels is determined - automatically by querying the audio mode from the TV card. This option - allows forcing stereo/mono recording regardless of the amode option - and the values returned by v4l. This can be used for troubleshooting - when the TV card is unable to report the current audio mode. +``--tv-amode=<0-3>`` + Choose an audio mode: - ``adevice=<value>`` - Set an audio device. <value> should be ``/dev/xxx`` for OSS and a - hardware ID for ALSA. You must replace any ':' by a '.' in the - hardware ID for ALSA. + :0: mono + :1: stereo + :2: language 1 + :3: language 2 - ``audioid=<value>`` - Choose an audio output of the capture card, if it has more than one. +``--tv-forcechan=<1-2>`` + By default, the count of recorded audio channels is determined + automatically by querying the audio mode from the TV card. This option + allows forcing stereo/mono recording regardless of the amode option + and the values returned by v4l. This can be used for troubleshooting + when the TV card is unable to report the current audio mode. - ``[volume|bass|treble|balance]=<0-100>`` - These options set parameters of the mixer on the video capture card. - They will have no effect, if your card does not have one. For v4l2 50 - maps to the default value of the control, as reported by the driver. +``--tv-adevice=<value>`` + Set an audio device. <value> should be ``/dev/xxx`` for OSS and a + hardware ID for ALSA. You must replace any ':' by a '.' in the + hardware ID for ALSA. - ``gain=<0-100>`` - Set gain control for video devices (usually webcams) to the desired - value and switch off automatic control. A value of 0 enables automatic - control. If this option is omitted, gain control will not be modified. +``--tv-audioid=<value>`` + Choose an audio output of the capture card, if it has more than one. - ``immediatemode=<bool>`` - A value of 0 means capture and buffer audio and video together. A - value of 1 (default) means to do video capture only and let the audio - go through a loopback cable from the TV card to the sound card. +``--tv-[volume|bass|treble|balance]=<0-100>`` + These options set parameters of the mixer on the video capture card. + They will have no effect, if your card does not have one. For v4l2 50 + maps to the default value of the control, as reported by the driver. - ``mjpeg`` - Use hardware MJPEG compression (if the card supports it). When using - this option, you do not need to specify the width and height of the - output window, because mpv will determine it automatically from - the decimation value (see below). +``--tv-gain=<0-100>`` + Set gain control for video devices (usually webcams) to the desired + value and switch off automatic control. A value of 0 enables automatic + control. If this option is omitted, gain control will not be modified. - ``decimation=<1|2|4>`` - choose the size of the picture that will be compressed by hardware - MJPEG compression: +``--tv-immediatemode=<bool>`` + A value of 0 means capture and buffer audio and video together. A + value of 1 (default) means to do video capture only and let the audio + go through a loopback cable from the TV card to the sound card. - :1: full size +``--tv-mjpeg`` + Use hardware MJPEG compression (if the card supports it). When using + this option, you do not need to specify the width and height of the + output window, because mpv will determine it automatically from + the decimation value (see below). - - 704x576 PAL - - 704x480 NTSC +``--tv-decimation=<1|2|4>`` + choose the size of the picture that will be compressed by hardware + MJPEG compression: - :2: medium size + :1: full size - - 352x288 PAL - - 352x240 NTSC + - 704x576 PAL + - 704x480 NTSC - :4: small size + :2: medium size - - 176x144 PAL - - 176x120 NTSC + - 352x288 PAL + - 352x240 NTSC - ``quality=<0-100>`` - Choose the quality of the JPEG compression (< 60 recommended for full - size). + :4: small size -``--tv-scan=<option1:option2:...>`` - Tune the TV channel scanner. mpv will also print value for - ``--tv=channels=`` option, including existing and just found channels. + - 176x144 PAL + - 176x120 NTSC - Available suboptions are: +``--tv-quality=<0-100>`` + Choose the quality of the JPEG compression (< 60 recommended for full + size). - ``autostart`` - Begin channel scanning immediately after startup (default: disabled). +``--tv-scan-autostart`` + Begin channel scanning immediately after startup (default: disabled). - ``period=<0.1-2.0>`` - Specify delay in seconds before switching to next channel (default: - 0.5). Lower values will cause faster scanning, but can detect inactive - TV channels as active. +``--tv-scan-period=<0.1-2.0>`` + Specify delay in seconds before switching to next channel (default: + 0.5). Lower values will cause faster scanning, but can detect inactive + TV channels as active. - ``threshold=<1-100>`` - Threshold value for the signal strength (in percent), as reported by - the device (default: 50). A signal strength higher than this value will - indicate that the currently scanning channel is active. +``--tv-scan-threshold=<1-100>`` + Threshold value for the signal strength (in percent), as reported by + the device (default: 50). A signal strength higher than this value will + indicate that the currently scanning channel is active. ``--use-filedir-conf`` Look for a file-specific configuration file in the same directory as the diff --git a/options/options.c b/options/options.c index e1e8cdb99e..a4d2ebe430 100644 --- a/options/options.c +++ b/options/options.c @@ -62,53 +62,7 @@ static void print_help(struct mp_log *log) mp_info(log, "%s", mp_help_text); } -#if HAVE_TV -static const m_option_t tvopts_conf[]={ - {"immediatemode", &stream_tv_defaults.immediate, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL}, - {"audio", &stream_tv_defaults.noaudio, CONF_TYPE_FLAG, 0, 1, 0, NULL}, - {"audiorate", &stream_tv_defaults.audiorate, CONF_TYPE_INT, 0, 0, 0, NULL}, - {"driver", &stream_tv_defaults.driver, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"device", &stream_tv_defaults.device, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"freq", &stream_tv_defaults.freq, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"channel", &stream_tv_defaults.channel, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"chanlist", &stream_tv_defaults.chanlist, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"norm", &stream_tv_defaults.norm, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"automute", &stream_tv_defaults.automute, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL}, -#if HAVE_TV_V4L2 - {"normid", &stream_tv_defaults.normid, CONF_TYPE_INT, 0, 0, 0, NULL}, -#endif - {"width", &stream_tv_defaults.width, CONF_TYPE_INT, 0, 0, 4096, NULL}, - {"height", &stream_tv_defaults.height, CONF_TYPE_INT, 0, 0, 4096, NULL}, - {"input", &stream_tv_defaults.input, CONF_TYPE_INT, 0, 0, 20, NULL}, - {"outfmt", &stream_tv_defaults.outfmt, CONF_TYPE_FOURCC, 0, 0, 0, NULL}, - {"fps", &stream_tv_defaults.fps, CONF_TYPE_FLOAT, 0, 0, 100.0, NULL}, - {"channels", &stream_tv_defaults.channels, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL}, - {"brightness", &stream_tv_defaults.brightness, CONF_TYPE_INT, CONF_RANGE, -100, 100, NULL}, - {"contrast", &stream_tv_defaults.contrast, CONF_TYPE_INT, CONF_RANGE, -100, 100, NULL}, - {"hue", &stream_tv_defaults.hue, CONF_TYPE_INT, CONF_RANGE, -100, 100, NULL}, - {"saturation", &stream_tv_defaults.saturation, CONF_TYPE_INT, CONF_RANGE, -100, 100, NULL}, - {"gain", &stream_tv_defaults.gain, CONF_TYPE_INT, CONF_RANGE, -1, 100, NULL}, -#if HAVE_TV_V4L2 - {"amode", &stream_tv_defaults.amode, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL}, - {"volume", &stream_tv_defaults.volume, CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL}, - {"bass", &stream_tv_defaults.bass, CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL}, - {"treble", &stream_tv_defaults.treble, CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL}, - {"balance", &stream_tv_defaults.balance, CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL}, - {"forcechan", &stream_tv_defaults.forcechan, CONF_TYPE_INT, CONF_RANGE, 1, 2, NULL}, - {"forceaudio", &stream_tv_defaults.force_audio, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - {"buffersize", &stream_tv_defaults.buffer_size, CONF_TYPE_INT, CONF_RANGE, 16, 1024, NULL}, - {"mjpeg", &stream_tv_defaults.mjpeg, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - {"decimation", &stream_tv_defaults.decimation, CONF_TYPE_INT, CONF_RANGE, 1, 4, NULL}, - {"quality", &stream_tv_defaults.quality, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL}, -#if HAVE_ALSA - {"alsa", &stream_tv_defaults.alsa, CONF_TYPE_FLAG, 0, 0, 1, NULL}, -#endif /* HAVE_ALSA */ -#endif /* HAVE_TV_V4L2 */ - {"adevice", &stream_tv_defaults.adevice, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"audioid", &stream_tv_defaults.audio_id, CONF_TYPE_INT, CONF_RANGE, 0, 9, NULL}, - {NULL, NULL, 0, 0, 0, 0, NULL} -}; -#endif /* HAVE_TV */ +extern const struct m_sub_options tv_params_conf; extern int pvr_param_aspect_ratio; extern int pvr_param_sample_rate; @@ -168,15 +122,6 @@ static const m_option_t mfopts_conf[]={ {NULL, NULL, 0, 0, 0, 0, NULL} }; -#if HAVE_TV -static const 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 - #define OPT_BASE_STRUCT struct MPOpts extern const struct m_sub_options image_writer_conf; @@ -321,7 +266,7 @@ const m_option_t mp_opts[] = { {"mf", (void *) mfopts_conf, CONF_TYPE_SUBCONFIG, 0,0,0, NULL}, #if HAVE_TV - {"tv", (void *) tvopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL}, + OPT_SUBSTRUCT("tv", tv_params, tv_params_conf, 0), #endif /* HAVE_TV */ #if HAVE_PVR {"pvr", (void *) pvropts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL}, @@ -604,9 +549,6 @@ const m_option_t mp_opts[] = { OPT_INTRANGE("key-fifo-size", input.key_fifo_size, CONF_GLOBAL, 2, 65000), OPT_FLAG("input-terminal", consolecontrols, CONF_GLOBAL), OPT_FLAG("input-cursor", vo.enable_mouse_movements, CONF_GLOBAL), -#if HAVE_TV - {"tv-scan", (void *) tvscan_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL}, -#endif /* HAVE_TV */ {"screenshot", (void *) screenshot_conf, CONF_TYPE_SUBCONFIG}, diff --git a/options/options.h b/options/options.h index 05aa8195ae..2451c5f82e 100644 --- a/options/options.h +++ b/options/options.h @@ -238,6 +238,8 @@ typedef struct MPOpts { int network_tls_verify; char *network_tls_ca_file; + struct tv_params *tv_params; + struct lavc_param { int fast; int show_all; diff --git a/stream/stream_pvr.c b/stream/stream_pvr.c index c19e9f05cb..9cdf509325 100644 --- a/stream/stream_pvr.c +++ b/stream/stream_pvr.c @@ -45,6 +45,7 @@ #include "osdep/io.h" #include "common/msg.h" +#include "options/options.h" #include "stream.h" #include "pvr.h" @@ -110,6 +111,7 @@ typedef struct stationlist_s { struct pvr_t { struct mp_log *log; + tv_param_t *tv_params; int dev_fd; char *video_dev; @@ -408,12 +410,12 @@ parse_setup_stationlist (struct pvr_t *pvr) return -1; /* Create our station/channel list */ - if (stream_tv_defaults.chanlist) + if (pvr->tv_params->chanlist) { /* select channel list */ for (i = 0; chanlists[i].name != NULL; i++) { - if (!strcasecmp (chanlists[i].name, stream_tv_defaults.chanlist)) + if (!strcasecmp (chanlists[i].name, pvr->tv_params->chanlist)) { chantab = i; break; @@ -422,7 +424,7 @@ parse_setup_stationlist (struct pvr_t *pvr) if (!chanlists[i].name) { MP_ERR(pvr, "%s unable to find channel list %s, using default %s\n", - LOG_LEVEL_V4L2, stream_tv_defaults.chanlist, chanlists[chantab].name); + LOG_LEVEL_V4L2, pvr->tv_params->chanlist, chanlists[chantab].name); } else { @@ -445,11 +447,11 @@ parse_setup_stationlist (struct pvr_t *pvr) } /* Handle user channel mappings */ - if (stream_tv_defaults.channels) + if (pvr->tv_params->channels) { char channel[PVR_STATION_NAME_SIZE]; char station[PVR_STATION_NAME_SIZE]; - char **channels = stream_tv_defaults.channels; + char **channels = pvr->tv_params->channels; disable_all_stations (pvr); @@ -1094,59 +1096,59 @@ parse_v4l2_tv_options (struct pvr_t *pvr) if (set_station_by_channelname_or_freq (pvr, pvr->param_channel, -1, 0) >= 0) { - if (stream_tv_defaults.freq) + if (pvr->tv_params->freq) { MP_INFO(pvr, "%s tv param freq %s is overwritten by channel setting freq %d\n", LOG_LEVEL_V4L2, - stream_tv_defaults.freq, pvr->freq); + pvr->tv_params->freq, pvr->freq); } } } - if (pvr->freq < 0 && stream_tv_defaults.freq) + if (pvr->freq < 0 && pvr->tv_params->freq) { MP_INFO(pvr, "%s tv param freq %s is used directly\n", - LOG_LEVEL_V4L2, stream_tv_defaults.freq); + LOG_LEVEL_V4L2, pvr->tv_params->freq); if (set_station_by_channelname_or_freq (pvr, NULL, - atoi (stream_tv_defaults.freq), 0)<0) + atoi (pvr->tv_params->freq), 0)<0) { MP_WARN(pvr, "%s tv param freq %s invalid to set station\n", - LOG_LEVEL_V4L2, stream_tv_defaults.freq); + LOG_LEVEL_V4L2, pvr->tv_params->freq); } } - if (stream_tv_defaults.device) + if (pvr->tv_params->device) { free (pvr->video_dev); - pvr->video_dev = strdup (stream_tv_defaults.device); + pvr->video_dev = strdup (pvr->tv_params->device); } - if (stream_tv_defaults.noaudio) - pvr->mute = stream_tv_defaults.noaudio; + if (!pvr->tv_params->audio) + pvr->mute = !pvr->tv_params->audio; - if (stream_tv_defaults.input) - pvr->input = stream_tv_defaults.input; + if (pvr->tv_params->input) + pvr->input = pvr->tv_params->input; - if (stream_tv_defaults.normid) - pvr->normid = stream_tv_defaults.normid; + if (pvr->tv_params->normid) + pvr->normid = pvr->tv_params->normid; - if (stream_tv_defaults.brightness) - pvr->brightness = stream_tv_defaults.brightness; + if (pvr->tv_params->brightness) + pvr->brightness = pvr->tv_params->brightness; - if (stream_tv_defaults.contrast) - pvr->contrast = stream_tv_defaults.contrast; + if (pvr->tv_params->contrast) + pvr->contrast = pvr->tv_params->contrast; - if (stream_tv_defaults.hue) - pvr->hue = stream_tv_defaults.hue; + if (pvr->tv_params->hue) + pvr->hue = pvr->tv_params->hue; - if (stream_tv_defaults.saturation) - pvr->saturation = stream_tv_defaults.saturation; + if (pvr->tv_params->saturation) + pvr->saturation = pvr->tv_params->saturation; - if (stream_tv_defaults.width) - pvr->width = stream_tv_defaults.width; + if (pvr->tv_params->width) + pvr->width = pvr->tv_params->width; - if (stream_tv_defaults.height) - pvr->height = stream_tv_defaults.height; + if (pvr->tv_params->height) + pvr->height = pvr->tv_params->height; } static int @@ -1519,6 +1521,7 @@ pvr_stream_open (stream_t *stream) struct pvr_t *pvr = NULL; pvr = pvr_init (); + pvr->tv_params = stream->opts->tv_params; pvr->log = stream->log; /** @@ -1527,8 +1530,8 @@ pvr_stream_open (stream_t *stream) */ if (stream->url && strlen (stream->url) > 6 && stream->url[6] != '\0') pvr->param_channel = strdup (stream->url + 6); - else if (stream_tv_defaults.channel && strlen (stream_tv_defaults.channel)) - pvr->param_channel = strdup (stream_tv_defaults.channel); + else if (pvr->tv_params->channel && strlen (pvr->tv_params->channel)) + pvr->param_channel = strdup (pvr->tv_params->channel); parse_v4l2_tv_options (pvr); parse_encoder_options (pvr); diff --git a/stream/stream_tv.c b/stream/stream_tv.c index e54fe4bded..3ca4973d1e 100644 --- a/stream/stream_tv.c +++ b/stream/stream_tv.c @@ -32,49 +32,7 @@ #include <stdio.h> -tv_param_t stream_tv_defaults = { - NULL, //freq - NULL, //channel - "europe-east", //chanlist - "pal", //norm - 0, //automute - -1, //normid - NULL, //device - NULL, //driver - -1, //width - -1, //height - 0, //input, used in v4l and bttv - -1, //outfmt - -1.0, //fps - NULL, //channels - 0, //noaudio; - 1, //immediate; - 44100, //audiorate; - 0, //audio_id - -1, //amode - -1, //volume - -1, //bass - -1, //treble - -1, //balance - -1, //forcechan - 0, //force_audio - -1, //buffer_size - 0, //mjpeg - 2, //decimation - 90, //quality - 0, //alsa - NULL, //adevice - 0, //brightness - 0, //contrast - 0, //hue - 0, //saturation - -1, //gain - 0, //scan_autostart - 50, //scan_threshold - 0.5, //scan_period -}; - -#define OPT_BASE_STRUCT tv_param_t +#define OPT_BASE_STRUCT struct tv_stream_params static const m_option_t stream_opts_fields[] = { OPT_STRING("channel", channel, 0), OPT_INT("input", input, 0), @@ -102,7 +60,9 @@ const stream_info_t stream_info_tv = { .open = tv_stream_open, .protocols = (const char*[]){ "tv", NULL }, .priv_size = sizeof(tv_param_t), - .priv_defaults = &stream_tv_defaults, + .priv_defaults = &(const struct tv_stream_params){ + .input = -1, + }, .options = stream_opts_fields, .url_options = (const char*[]){ "hostname=channel", diff --git a/stream/tv.c b/stream/tv.c index c42a81fde1..1e71c08742 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -31,6 +31,7 @@ #include <string.h> #include <ctype.h> #include <sys/time.h> +#include <assert.h> #include <libavutil/avstring.h> #include "config.h" @@ -38,6 +39,10 @@ #include "common/msg.h" +#include "options/m_option.h" +#include "options/m_config.h" +#include "options/options.h" + #include "stream.h" #include "demux/demux.h" #include "demux/stheader.h" @@ -50,10 +55,6 @@ #include "frequencies.h" -tv_channels_t *tv_channel_list; -tv_channels_t *tv_channel_current, *tv_channel_last; -char *tv_channel_last_real; - /* enumerating drivers (like in stream.c) */ extern const tvi_info_t tvi_info_dummy; extern const tvi_info_t tvi_info_v4l2; @@ -67,6 +68,83 @@ static const tvi_info_t* tvi_driver_list[]={ NULL }; +#define OPT_BASE_STRUCT tv_param_t +const struct m_sub_options tv_params_conf = { + .opts = (const m_option_t[]) { + OPT_FLAG("immediatemode", immediate, 0), + OPT_FLAG("audio", audio, 0), + OPT_INT("audiorate", audiorate, 0), + OPT_STRING("driver", driver, 0), + OPT_STRING("device", device, 0), + OPT_STRING("freq", freq, 0), + OPT_STRING("channel", channel, 0), + OPT_STRING("chanlist", chanlist, 0), + OPT_STRING("norm", norm, 0), + OPT_INTRANGE("automute", automute, 0, 0, 255), +#if HAVE_TV_V4L2 + OPT_INT("normid", normid, 0), +#endif + OPT_INTRANGE("width", width, 0, 0, 4096), + OPT_INTRANGE("height", height, 0, 0, 4096), + OPT_INT("input", input, 0), + OPT_GENERAL(int, "outfmt", outfmt, 0, .type = &m_option_type_fourcc), + OPT_FLOAT("fps", fps, 0), + OPT_STRINGLIST("channels", channels, 0), + OPT_INTRANGE("brightness", brightness, 0, -100, 100), + OPT_INTRANGE("contrast", contrast, 0, -100, 100), + OPT_INTRANGE("hue", hue, 0, -100, 100), + OPT_INTRANGE("saturation", saturation, 0, -100, 100), + OPT_INTRANGE("gain", gain, 0, -1, 100), +#if HAVE_TV_V4L2 + OPT_INTRANGE("amode", amode, 0, 0, 3), + OPT_INTRANGE("volume", volume, 0, 0, 65535), + OPT_INTRANGE("bass", bass, 0, 0, 65535), + OPT_INTRANGE("treble", treble, 0, 0, 65535), + OPT_INTRANGE("balance", balance, 0, 0, 65535), + OPT_INTRANGE("forcechan", forcechan, 0, 1, 2), + OPT_FLAG("forceaudio", force_audio, 0), + OPT_INTRANGE("buffersize", buffer_size, 0, 16, 1024), + OPT_FLAG("mjpeg", mjpeg, 0), + OPT_INTRANGE("decimation", decimation, 0, 1, 4), + OPT_INTRANGE("quality", quality, 0, 0, 100), +#if HAVE_ALSA + OPT_FLAG("alsa", alsa, 0), +#endif /* HAVE_ALSA */ +#endif /* HAVE_TV_V4L2 */ + OPT_STRING("adevice", adevice, 0), + OPT_INTRANGE("audioid", audio_id, 0, 0, 9), + OPT_FLAG("scan-autostart", scan, 0), + OPT_INTRANGE("scan-threshold", scan_threshold, 0, 1, 100), + OPT_FLOATRANGE("scan-period", scan_period, 0, 0.1, 2.0), + {0} + }, + .size = sizeof(tv_param_t), + .defaults = &(const tv_param_t){ + .chanlist = "europe-east", + .norm = "pal", + .normid = -1, + .width = -1, + .height = -1, + .outfmt = -1, + .fps = -1.0, + .audio = 1, + .immediate = 1, + .audiorate = 44100, + .amode = -1, + .volume = -1, + .bass = -1, + .treble = -1, + .balance = -1, + .forcechan = -1, + .buffer_size = -1, + .decimation = 2, + .quality = 90, + .gain = -1, + .scan_threshold = 50, + .scan_period = 0.5, + }, +}; + tvi_handle_t *tv_new_handle(int size, struct mp_log *log, const tvi_functions_t *functions) { tvi_handle_t *h = malloc(sizeof(*h)); @@ -144,7 +222,7 @@ static void tv_scan(tvi_handle_t *tvh) if (tv_get_signal(tvh)>tvh->tv_param->scan_threshold) { cl = tvh->chanlist_s[scan->channel_num]; - tv_channel_tmp=tv_channel_list; + tv_channel_tmp=tvh->tv_channel_list; while (tv_channel_tmp) { index++; if (cl.freq==tv_channel_tmp->freq){ @@ -165,11 +243,11 @@ static void tv_scan(tvi_handle_t *tvh) 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; + if (!tvh->tv_channel_list) + tvh->tv_channel_list=tv_channel_tmp; else { tv_channel_add->next=tv_channel_tmp; - tv_channel_list->prev=tv_channel_tmp; + tvh->tv_channel_list->prev=tv_channel_tmp; } }else MP_INFO(tvh, "Found existing channel: %s-%s.\n", @@ -180,7 +258,7 @@ static void tv_scan(tvi_handle_t *tvh) if (scan->channel_num>=chanlists[tvh->chanlist].count) { tvh->tv_param->scan=0; MP_INFO(tvh, "TV scan end. Found %d new channels.\n", scan->new_channels); - tv_channel_tmp=tv_channel_list; + tv_channel_tmp=tvh->tv_channel_list; if(tv_channel_tmp){ MP_INFO(tvh, "channels="); while(tv_channel_tmp){ @@ -191,9 +269,9 @@ static void tv_scan(tvi_handle_t *tvh) } MP_INFO(tvh, "\n"); } - if (!tv_channel_current) tv_channel_current=tv_channel_list; - if (tv_channel_current) - tv_set_freq_float(tvh, tv_channel_current->freq); + if (!tvh->tv_channel_current) tvh->tv_channel_current=tvh->tv_channel_list; + if (tvh->tv_channel_current) + tv_set_freq_float(tvh, tvh->tv_channel_current->freq); free(tvh->scan); tvh->scan=NULL; }else{ @@ -232,7 +310,7 @@ static int demux_tv_fill_buffer(demuxer_t *demux) /* ================== ADD AUDIO PACKET =================== */ - if (want_audio && tvh->tv_param->noaudio == 0 && + if (want_audio && tvh->tv_param->audio && tvh->functions->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) { @@ -306,12 +384,12 @@ static void parse_channels(tvi_handle_t *tvh) char** channels = tvh->tv_param->channels; MP_INFO(tvh, "TV channel names detected.\n"); - tv_channel_list = malloc(sizeof(tv_channels_t)); - tv_channel_list->index=1; - tv_channel_list->next=NULL; - tv_channel_list->prev=NULL; - tv_channel_current = tv_channel_list; - tv_channel_current->norm = tvh->norm; + tvh->tv_channel_list = malloc(sizeof(tv_channels_t)); + tvh->tv_channel_list->index=1; + tvh->tv_channel_list->next=NULL; + tvh->tv_channel_list->prev=NULL; + tvh->tv_channel_current = tvh->tv_channel_list; + tvh->tv_channel_current->norm = tvh->norm; while (*channels) { char* tmp = *(channels++); @@ -321,64 +399,64 @@ static void parse_channels(tvi_handle_t *tvh) if (!sep) continue; // Wrong syntax, but mplayer should not crash - av_strlcpy(tv_channel_current->name, sep + 1, - sizeof(tv_channel_current->name)); + av_strlcpy(tvh->tv_channel_current->name, sep + 1, + sizeof(tvh->tv_channel_current->name)); sep[0] = '\0'; - strncpy(tv_channel_current->number, tmp, 5); - tv_channel_current->number[4]='\0'; + strncpy(tvh->tv_channel_current->number, tmp, 5); + tvh->tv_channel_current->number[4]='\0'; - while ((sep=strchr(tv_channel_current->name, '_'))) + while ((sep=strchr(tvh->tv_channel_current->name, '_'))) sep[0] = ' '; // if channel number is a number and larger than 1000 threat it as frequency // tmp still contain pointer to null-terminated string with channel number here if (atoi(tmp)>1000){ - tv_channel_current->freq=atoi(tmp); + tvh |