mirror of
https://github.com/mpv-player/mpv
synced 2025-01-18 13:14:36 +00:00
tv: remove global option variables
Pretty much nothing changes, but using -tv-scan with suboptions doesn't work anymore (instead of "-tv-scan x" it's "-tv scan-x" now). Flat options ("-tv-scan-x") stay compatible.
This commit is contained in:
parent
98c0930f9b
commit
383cf20785
@ -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:
|
||||
``--no-tv-audio``
|
||||
no sound
|
||||
|
||||
``noaudio``
|
||||
no sound
|
||||
``--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).
|
||||
|
||||
``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).
|
||||
``--tv-driver=<value>``
|
||||
See ``--tv=driver=help`` for a list of compiled-in TV input drivers.
|
||||
available: dummy, v4l2 (default: autodetect)
|
||||
|
||||
``driver=<value>``
|
||||
See ``--tv=driver=help`` for a list of compiled-in TV input drivers.
|
||||
available: dummy, v4l2 (default: autodetect)
|
||||
``--tv-device=<value>``
|
||||
Specify TV device (default: ``/dev/video0``).
|
||||
|
||||
``device=<value>``
|
||||
Specify TV device (default: ``/dev/video0``).
|
||||
``--tv-input=<value>``
|
||||
Specify input (default: 0 (TV), see console output for available
|
||||
inputs).
|
||||
|
||||
``input=<value>``
|
||||
Specify input (default: 0 (TV), see console output for available
|
||||
inputs).
|
||||
``--tv-freq=<value>``
|
||||
Specify the frequency to set the tuner to (e.g. 511.250). Not
|
||||
compatible with the channels parameter.
|
||||
|
||||
``freq=<value>``
|
||||
Specify the frequency to set the tuner to (e.g. 511.250). Not
|
||||
compatible with the channels parameter.
|
||||
``--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.
|
||||
|
||||
``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-width=<value>``
|
||||
output window width
|
||||
|
||||
``width=<value>``
|
||||
output window width
|
||||
``--tv-height=<value>``
|
||||
output window height
|
||||
|
||||
``height=<value>``
|
||||
output window height
|
||||
``--tv-fps=<value>``
|
||||
framerate at which to capture video (frames per second)
|
||||
|
||||
``fps=<value>``
|
||||
framerate at which to capture video (frames per second)
|
||||
``--tv-buffersize=<value>``
|
||||
maximum size of the capture buffer in megabytes (default: dynamical)
|
||||
|
||||
``buffersize=<value>``
|
||||
maximum size of the capture buffer in megabytes (default: dynamical)
|
||||
``--tv-norm=<value>``
|
||||
See the console output for a list of all available norms, also see the
|
||||
``normid`` option below.
|
||||
|
||||
``norm=<value>``
|
||||
See the console output for a list of all available norms, also see the
|
||||
``normid`` option below.
|
||||
``--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.
|
||||
|
||||
``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-channel=<value>``
|
||||
Set tuner to <value> channel.
|
||||
|
||||
``channel=<value>``
|
||||
Set tuner to <value> channel.
|
||||
``--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
|
||||
|
||||
``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-channels=<chan>-<name>[=<norm>],<chan>-<name>[=<norm>],...``
|
||||
Set names for channels.
|
||||
|
||||
``channels=<chan>-<name>[=<norm>],<chan>-<name>[=<norm>],...``
|
||||
Set names for channels.
|
||||
.. note::
|
||||
|
||||
.. note::
|
||||
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.
|
||||
|
||||
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.
|
||||
.. note::
|
||||
|
||||
.. note::
|
||||
The channel number will then be the position in the 'channels'
|
||||
list, beginning with 1.
|
||||
|
||||
The channel number will then be the position in the 'channels'
|
||||
list, beginning with 1.
|
||||
.. admonition:: Examples
|
||||
|
||||
.. admonition:: Examples
|
||||
``tv://1``, ``tv://TV1``, ``tv_set_channel 1``,
|
||||
``tv_set_channel TV1``
|
||||
|
||||
``tv://1``, ``tv://TV1``, ``tv_set_channel 1``,
|
||||
``tv_set_channel TV1``
|
||||
``--tv-[brightness|contrast|hue|saturation]=<-100-100>``
|
||||
Set the image equalizer on the card.
|
||||
|
||||
``[brightness|contrast|hue|saturation]=<-100-100>``
|
||||
Set the image equalizer on the card.
|
||||
``--tv-audiorate=<value>``
|
||||
Set input audio sample rate.
|
||||
|
||||
``audiorate=<value>``
|
||||
Set input audio sample rate.
|
||||
``--tv-forceaudio``
|
||||
Capture audio even if there are no audio sources reported by v4l.
|
||||
|
||||
``forceaudio``
|
||||
Capture audio even if there are no audio sources reported by v4l.
|
||||
``--tv-alsa``
|
||||
Capture from ALSA.
|
||||
|
||||
``alsa``
|
||||
Capture from ALSA.
|
||||
``--tv-amode=<0-3>``
|
||||
Choose an audio mode:
|
||||
|
||||
``amode=<0-3>``
|
||||
Choose an audio mode:
|
||||
:0: mono
|
||||
:1: stereo
|
||||
:2: language 1
|
||||
:3: language 2
|
||||
|
||||
:0: mono
|
||||
:1: stereo
|
||||
:2: language 1
|
||||
:3: language 2
|
||||
``--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.
|
||||
|
||||
``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-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.
|
||||
|
||||
``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.
|
||||
``--tv-audioid=<value>``
|
||||
Choose an audio output of the capture card, if it has more than one.
|
||||
|
||||
``audioid=<value>``
|
||||
Choose an audio output of the capture card, if it has more than one.
|
||||
``--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.
|
||||
|
||||
``[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-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.
|
||||
|
||||
``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-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.
|
||||
|
||||
``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-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).
|
||||
|
||||
``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-decimation=<1|2|4>``
|
||||
choose the size of the picture that will be compressed by hardware
|
||||
MJPEG compression:
|
||||
|
||||
``decimation=<1|2|4>``
|
||||
choose the size of the picture that will be compressed by hardware
|
||||
MJPEG compression:
|
||||
:1: full size
|
||||
|
||||
:1: full size
|
||||
- 704x576 PAL
|
||||
- 704x480 NTSC
|
||||
|
||||
- 704x576 PAL
|
||||
- 704x480 NTSC
|
||||
:2: medium size
|
||||
|
||||
:2: medium size
|
||||
- 352x288 PAL
|
||||
- 352x240 NTSC
|
||||
|
||||
- 352x288 PAL
|
||||
- 352x240 NTSC
|
||||
:4: small size
|
||||
|
||||
:4: small size
|
||||
- 176x144 PAL
|
||||
- 176x120 NTSC
|
||||
|
||||
- 176x144 PAL
|
||||
- 176x120 NTSC
|
||||
``--tv-quality=<0-100>``
|
||||
Choose the quality of the JPEG compression (< 60 recommended for full
|
||||
size).
|
||||
|
||||
``quality=<0-100>``
|
||||
Choose the quality of the JPEG compression (< 60 recommended for full
|
||||
size).
|
||||
``--tv-scan-autostart``
|
||||
Begin channel scanning immediately after startup (default: disabled).
|
||||
|
||||
``--tv-scan=<option1:option2:...>``
|
||||
Tune the TV channel scanner. mpv will also print value for
|
||||
``--tv=channels=`` option, including existing and just found channels.
|
||||
``--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.
|
||||
|
||||
Available suboptions are:
|
||||
|
||||
``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.
|
||||
|
||||
``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
|
||||
|
@ -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},
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
275
stream/tv.c
275
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->tv_channel_current->freq=atoi(tmp);
|
||||
}else{
|
||||
tv_channel_current->freq = 0;
|
||||
tvh->tv_channel_current->freq = 0;
|
||||
for (i = 0; i < chanlists[tvh->chanlist].count; i++) {
|
||||
cl = tvh->chanlist_s[i];
|
||||
if (!strcasecmp(cl.name, tv_channel_current->number)) {
|
||||
tv_channel_current->freq=cl.freq;
|
||||
if (!strcasecmp(cl.name, tvh->tv_channel_current->number)) {
|
||||
tvh->tv_channel_current->freq=cl.freq;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tv_channel_current->freq == 0)
|
||||
if (tvh->tv_channel_current->freq == 0)
|
||||
MP_ERR(tvh, "Couldn't find frequency for channel %s (%s)\n",
|
||||
tv_channel_current->number, tv_channel_current->name);
|
||||
tvh->tv_channel_current->number, tvh->tv_channel_current->name);
|
||||
else {
|
||||
sep = strchr(tv_channel_current->name, '-');
|
||||
if ( !sep ) sep = strchr(tv_channel_current->name, '+');
|
||||
sep = strchr(tvh->tv_channel_current->name, '-');
|
||||
if ( !sep ) sep = strchr(tvh->tv_channel_current->name, '+');
|
||||
|
||||
if ( sep ) {
|
||||
i = atoi (sep+1);
|
||||
if ( sep[0] == '+' ) tv_channel_current->freq += i * 100;
|
||||
if ( sep[0] == '-' ) tv_channel_current->freq -= i * 100;
|
||||
if ( sep[0] == '+' ) tvh->tv_channel_current->freq += i * 100;
|
||||
if ( sep[0] == '-' ) tvh->tv_channel_current->freq -= i * 100;
|
||||
sep[0] = '\0';
|
||||
}
|
||||
|
||||
sep = strchr(tv_channel_current->name, '=');
|
||||
sep = strchr(tvh->tv_channel_current->name, '=');
|
||||
if ( sep ) {
|
||||
tv_channel_current->norm = norm_from_string(tvh, sep+1);
|
||||
tvh->tv_channel_current->norm = norm_from_string(tvh, sep+1);
|
||||
sep[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*MP_INFO(tvh, "-- Detected channel %s - %s (%5.3f)\n",
|
||||
tv_channel_current->number, tv_channel_current->name,
|
||||
(float)tv_channel_current->freq/1000);*/
|
||||
tvh->tv_channel_current->number, tvh->tv_channel_current->name,
|
||||
(float)tvh->tv_channel_current->freq/1000);*/
|
||||
|
||||
tv_channel_current->next = malloc(sizeof(tv_channels_t));
|
||||
tv_channel_current->next->index = tv_channel_current->index + 1;
|
||||
tv_channel_current->next->prev = tv_channel_current;
|
||||
tv_channel_current->next->next = NULL;
|
||||
tv_channel_current = tv_channel_current->next;
|
||||
tv_channel_current->norm = tvh->norm;
|
||||
tvh->tv_channel_current->next = malloc(sizeof(tv_channels_t));
|
||||
tvh->tv_channel_current->next->index = tvh->tv_channel_current->index + 1;
|
||||
tvh->tv_channel_current->next->prev = tvh->tv_channel_current;
|
||||
tvh->tv_channel_current->next->next = NULL;
|
||||
tvh->tv_channel_current = tvh->tv_channel_current->next;
|
||||
tvh->tv_channel_current->norm = tvh->norm;
|
||||
}
|
||||
if (tv_channel_current->prev)
|
||||
tv_channel_current->prev->next = NULL;
|
||||
free(tv_channel_current);
|
||||
if (tvh->tv_channel_current->prev)
|
||||
tvh->tv_channel_current->prev->next = NULL;
|
||||
free(tvh->tv_channel_current);
|
||||
}
|
||||
|
||||
int tv_set_norm(tvi_handle_t *tvh, char* norm)
|
||||
@ -544,9 +622,9 @@ static int open_tv(tvi_handle_t *tvh)
|
||||
if (tvh->tv_param->channels) {
|
||||
parse_channels(tvh);
|
||||
} else
|
||||
tv_channel_last_real = malloc(5);
|
||||
tvh->tv_channel_last_real = malloc(5);
|
||||
|
||||
if (tv_channel_list) {
|
||||
if (tvh->tv_channel_list) {
|
||||
int channel = 0;
|
||||
if (tvh->tv_param->channel)
|
||||
{
|
||||
@ -558,27 +636,27 @@ static int open_tv(tvi_handle_t *tvh)
|
||||
/* if tvh->tv_param->channel does not begin with a digit
|
||||
set the first channel that contains tvh->tv_param->channel in its name */
|
||||
|
||||
tv_channel_current = tv_channel_list;
|
||||
while ( tv_channel_current ) {
|
||||
if ( strstr(tv_channel_current->name, tvh->tv_param->channel) )
|
||||
tvh->tv_channel_current = tvh->tv_channel_list;
|
||||
while ( tvh->tv_channel_current ) {
|
||||
if ( strstr(tvh->tv_channel_current->name, tvh->tv_param->channel) )
|
||||
break;
|
||||
tv_channel_current = tv_channel_current->next;
|
||||
tvh->tv_channel_current = tvh->tv_channel_current->next;
|
||||
}
|
||||
if ( !tv_channel_current ) tv_channel_current = tv_channel_list;
|
||||
if ( !tvh->tv_channel_current ) tvh->tv_channel_current = tvh->tv_channel_list;
|
||||
}
|
||||
}
|
||||
else
|
||||
channel = 1;
|
||||
|
||||
if ( channel ) {
|
||||
tv_channel_current = tv_channel_list;
|
||||
tvh->tv_channel_current = tvh->tv_channel_list;
|
||||
for (int n = 1; n < channel; n++)
|
||||
if (tv_channel_current->next)
|
||||
tv_channel_current = tv_channel_current->next;
|
||||
if (tvh->tv_channel_current->next)
|
||||
tvh->tv_channel_current = tvh->tv_channel_current->next;
|
||||
}
|
||||
|
||||
set_norm_and_freq(tvh, tv_channel_current);
|
||||
tv_channel_last = tv_channel_current;
|
||||
set_norm_and_freq(tvh, tvh->tv_channel_current);
|
||||
tvh->tv_channel_last = tvh->tv_channel_current;
|
||||
} else {
|
||||
/* we need to set frequency */
|
||||
if (tvh->tv_param->freq)
|
||||
@ -604,7 +682,7 @@ static int open_tv(tvi_handle_t *tvh)
|
||||
// i, cl.name, cl.freq);
|
||||
if (!strcasecmp(cl.name, tvh->tv_param->channel))
|
||||
{
|
||||
strcpy(tv_channel_last_real, cl.name);
|
||||
strcpy(tvh->tv_channel_last_real, cl.name);
|
||||
tvh->channel = i;
|
||||
MP_INFO(tvh, "Selected channel: %s (freq: %.3f)\n",
|
||||
cl.name, cl.freq/1000.0);
|
||||
@ -669,7 +747,8 @@ static tvi_handle_t *tv_begin(tv_param_t* tv_param, struct mp_log *log)
|
||||
tvi_driver_list[i]->name,
|
||||
tvi_driver_list[i]->author,
|
||||
tvi_driver_list[i]->comment?tvi_driver_list[i]->comment:"");
|
||||
tv_param->driver=strdup(tvi_driver_list[i]->short_name);
|
||||
talloc_free(tv_param->driver);
|
||||
tv_param->driver=talloc_strdup(NULL, tvi_driver_list[i]->short_name);
|
||||
return h;
|
||||
}
|
||||
}
|
||||
@ -704,8 +783,18 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
|
||||
if (check > DEMUX_CHECK_REQUEST || demuxer->stream->type != STREAMTYPE_TV)
|
||||
return -1;
|
||||
|
||||
demuxer->priv=NULL;
|
||||
if(!(tvh=tv_begin(demuxer->stream->priv, demuxer->log))) return -1;
|
||||
tv_param_t *params = m_sub_options_copy(demuxer, &tv_params_conf,
|
||||
demuxer->opts->tv_params);
|
||||
struct tv_stream_params *sparams = demuxer->stream->priv;
|
||||
if (sparams->channel && sparams->channel[0]) {
|
||||
talloc_free(params->channel);
|
||||
params->channel = talloc_strdup(NULL, sparams->channel);
|
||||
}
|
||||
if (sparams->input >= 0)
|
||||
params->input = sparams->input;
|
||||
|
||||
assert(demuxer->priv==NULL);
|
||||
if(!(tvh=tv_begin(params, demuxer->log))) return -1;
|
||||
if (!tvh->functions->init(tvh->priv)) return -1;
|
||||
|
||||
tvh->demuxer = demuxer;
|
||||
@ -747,7 +836,7 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
|
||||
if(tvh->tv_param->immediate == 1)
|
||||
{
|
||||
funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0);
|
||||
tvh->tv_param->noaudio = 1;
|
||||
tvh->tv_param->audio = 0;
|
||||
}
|
||||
|
||||
/* set width */
|
||||
@ -759,7 +848,7 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
|
||||
demuxer->seekable = 0;
|
||||
|
||||
/* here comes audio init */
|
||||
if (tvh->tv_param->noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
|
||||
if (tvh->tv_param->audio && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
|
||||
{
|
||||
int audio_format;
|
||||
|
||||
@ -955,7 +1044,7 @@ int tv_step_channel_real(tvi_handle_t *tvh, int direction)
|
||||
{
|
||||
if (tvh->channel-1 >= 0)
|
||||
{
|
||||
strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
strcpy(tvh->tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
cl = tvh->chanlist_s[--tvh->channel];
|
||||
MP_INFO(tvh, "Selected channel: %s (freq: %.3f)\n",
|
||||
cl.name, cl.freq/1000.0);
|
||||
@ -967,7 +1056,7 @@ int tv_step_channel_real(tvi_handle_t *tvh, int direction)
|
||||
{
|
||||
if (tvh->channel+1 < chanlists[tvh->chanlist].count)
|
||||
{
|
||||
strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
strcpy(tvh->tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
cl = tvh->chanlist_s[++tvh->channel];
|
||||
MP_INFO(tvh, "Selected channel: %s (freq: %.3f)\n",
|
||||
cl.name, cl.freq/1000.0);
|
||||
@ -979,23 +1068,23 @@ 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 (tvh->tv_channel_list) {
|
||||
if (direction == TV_CHANNEL_HIGHER) {
|
||||
tv_channel_last = tv_channel_current;
|
||||
if (tv_channel_current->next)
|
||||
tv_channel_current = tv_channel_current->next;
|
||||
tvh->tv_channel_last = tvh->tv_channel_current;
|
||||
if (tvh->tv_channel_current->next)
|
||||
tvh->tv_channel_current = tvh->tv_channel_current->next;
|
||||
else
|
||||
tv_channel_current = tv_channel_list;
|
||||
set_norm_and_freq(tvh, tv_channel_current);
|
||||
tvh->tv_channel_current = tvh->tv_channel_list;
|
||||
set_norm_and_freq(tvh, tvh->tv_channel_current);
|
||||
}
|
||||
if (direction == TV_CHANNEL_LOWER) {
|
||||
tv_channel_last = tv_channel_current;
|
||||
if (tv_channel_current->prev)
|
||||
tv_channel_current = tv_channel_current->prev;
|
||||
tvh->tv_channel_last = tvh->tv_channel_current;
|
||||
if (tvh->tv_channel_current->prev)
|
||||
tvh->tv_channel_current = tvh->tv_channel_current->prev;
|
||||
else
|
||||
while (tv_channel_current->next)
|
||||
tv_channel_current = tv_channel_current->next;
|
||||
set_norm_and_freq(tvh, tv_channel_current);
|
||||
while (tvh->tv_channel_current->next)
|
||||
tvh->tv_channel_current = tvh->tv_channel_current->next;
|
||||
set_norm_and_freq(tvh, tvh->tv_channel_current);
|
||||
}
|
||||
} else tv_step_channel_real(tvh, direction);
|
||||
return 1;
|
||||
@ -1006,7 +1095,7 @@ int tv_set_channel_real(tvi_handle_t *tvh, char *channel) {
|
||||
struct CHANLIST cl;
|
||||
|
||||
tvh->tv_param->scan=0;
|
||||
strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
strcpy(tvh->tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
for (i = 0; i < chanlists[tvh->chanlist].count; i++)
|
||||
{
|
||||
cl = tvh->chanlist_s[i];
|
||||
@ -1028,14 +1117,14 @@ 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;
|
||||
if (tvh->tv_channel_list) {
|
||||
tvh->tv_channel_last = tvh->tv_channel_current;
|
||||
channel_int = atoi(channel);
|
||||
tv_channel_current = tv_channel_list;
|
||||
tvh->tv_channel_current = tvh->tv_channel_list;
|
||||
for (i = 1; i < channel_int; i++)
|
||||
if (tv_channel_current->next)
|
||||
tv_channel_current = tv_channel_current->next;
|
||||
set_norm_and_freq(tvh, tv_channel_current);
|
||||
if (tvh->tv_channel_current->next)
|
||||
tvh->tv_channel_current = tvh->tv_channel_current->next;
|
||||
set_norm_and_freq(tvh, tvh->tv_channel_current);
|
||||
} else tv_set_channel_real(tvh, channel);
|
||||
return 1;
|
||||
}
|
||||
@ -1043,14 +1132,14 @@ 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) {
|
||||
if (tvh->tv_channel_list) {
|
||||
tv_channels_t *tmp;
|
||||
|
||||
tmp = tv_channel_last;
|
||||
tv_channel_last = tv_channel_current;
|
||||
tv_channel_current = tmp;
|
||||
tmp = tvh->tv_channel_last;
|
||||
tvh->tv_channel_last = tvh->tv_channel_current;
|
||||
tvh->tv_channel_current = tmp;
|
||||
|
||||
set_norm_and_freq(tvh, tv_channel_current);
|
||||
set_norm_and_freq(tvh, tvh->tv_channel_current);
|
||||
} else {
|
||||
int i;
|
||||
struct CHANLIST cl;
|
||||
@ -1058,9 +1147,9 @@ int tv_last_channel(tvi_handle_t *tvh) {
|
||||
for (i = 0; i < chanlists[tvh->chanlist].count; i++)
|
||||
{
|
||||
cl = tvh->chanlist_s[i];
|
||||
if (!strcasecmp(cl.name, tv_channel_last_real))
|
||||
if (!strcasecmp(cl.name, tvh->tv_channel_last_real))
|
||||
{
|
||||
strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
strcpy(tvh->tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
|
||||
tvh->channel = i;
|
||||
MP_INFO(tvh, "Selected channel: %s (freq: %.3f)\n",
|
||||
cl.name, cl.freq/1000.0);
|
||||
|
22
stream/tv.h
22
stream/tv.h
@ -27,7 +27,7 @@
|
||||
|
||||
struct mp_log;
|
||||
|
||||
typedef struct tv_param_s {
|
||||
typedef struct tv_params {
|
||||
char *freq;
|
||||
char *channel;
|
||||
char *chanlist;
|
||||
@ -42,7 +42,7 @@ typedef struct tv_param_s {
|
||||
int outfmt;
|
||||
float fps;
|
||||
char **channels;
|
||||
int noaudio;
|
||||
int audio;
|
||||
int immediate;
|
||||
int audiorate;
|
||||
int audio_id;
|
||||
@ -68,14 +68,12 @@ typedef struct tv_param_s {
|
||||
int scan;
|
||||
int scan_threshold;
|
||||
float scan_period;
|
||||
/**
|
||||
Terminate stream with video renderer instead of Null renderer
|
||||
Will help if video freezes but audio does not.
|
||||
May not work with -vo directx and -vf crop combination.
|
||||
*/
|
||||
} tv_param_t;
|
||||
|
||||
extern tv_param_t stream_tv_defaults;
|
||||
struct tv_stream_params {
|
||||
char *channel;
|
||||
int input;
|
||||
};
|
||||
|
||||
typedef struct tvi_info_s
|
||||
{
|
||||
@ -115,6 +113,10 @@ typedef struct tvi_handle_s {
|
||||
int channel;
|
||||
tv_param_t * tv_param;
|
||||
void * scan;
|
||||
|
||||
struct tv_channels_s *tv_channel_list;
|
||||
struct tv_channels_s *tv_channel_current, *tv_channel_last;
|
||||
char *tv_channel_last_real;
|
||||
} tvi_handle_t;
|
||||
|
||||
typedef struct tv_channels_s {
|
||||
@ -127,10 +129,6 @@ typedef struct tv_channels_s {
|
||||
struct tv_channels_s *prev;
|
||||
} tv_channels_t;
|
||||
|
||||
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;
|
||||
|
@ -401,7 +401,7 @@ static void init_audio(priv_t *priv)
|
||||
{
|
||||
if (priv->audio_initialized) return;
|
||||
|
||||
if (!priv->tv_param->noaudio) {
|
||||
if (priv->tv_param->audio) {
|
||||
#if HAVE_ALSA
|
||||
if (priv->tv_param->alsa)
|
||||
audio_in_init(&priv->audio_in, priv->log, AUDIO_IN_ALSA);
|
||||
@ -995,7 +995,7 @@ static int uninit(priv_t *priv)
|
||||
}
|
||||
|
||||
/* stop audio thread */
|
||||
if (!priv->tv_param->noaudio && priv->audio_grabber_thread) {
|
||||
if (priv->tv_param->audio && priv->audio_grabber_thread) {
|
||||
pthread_join(priv->audio_grabber_thread, NULL);
|
||||
pthread_mutex_destroy(&priv->skew_mutex);
|
||||
pthread_mutex_destroy(&priv->audio_mutex);
|
||||
@ -1015,7 +1015,7 @@ static int uninit(priv_t *priv)
|
||||
}
|
||||
free(priv->video_ringbuffer);
|
||||
}
|
||||
if (!priv->tv_param->noaudio) {
|
||||
if (priv->tv_param->audio) {
|
||||
free(priv->audio_ringbuffer);
|
||||
free(priv->audio_skew_buffer);
|
||||
free(priv->audio_skew_delta_buffer);
|
||||
@ -1245,7 +1245,7 @@ static int start(priv_t *priv)
|
||||
/* setup audio parameters */
|
||||
|
||||
init_audio(priv);
|
||||
if (!priv->tv_param->noaudio && !priv->audio_initialized) return 0;
|
||||
if (priv->tv_param->audio && !priv->audio_initialized) return 0;
|
||||
|
||||
/* we need this to size the audio buffer properly */
|
||||
if (priv->immediate_mode) {
|
||||
@ -1254,7 +1254,7 @@ static int start(priv_t *priv)
|
||||
priv->video_buffer_size_max = get_capture_buffer_size(priv);
|
||||
}
|
||||
|
||||
if (!priv->tv_param->noaudio) {
|
||||
if (priv->tv_param->audio) {
|
||||
setup_audio_buffer_sizes(priv);
|
||||
priv->audio_skew_buffer = calloc(priv->aud_skew_cnt, sizeof(long long));
|
||||
if (!priv->audio_skew_buffer) {
|
||||
@ -1296,7 +1296,7 @@ static int start(priv_t *priv)
|
||||
}
|
||||
|
||||
/* setup video parameters */
|
||||
if (!priv->tv_param->noaudio) {
|
||||
if (priv->tv_param->audio) {
|
||||
if (priv->video_buffer_size_max < 3*getfps(priv)*priv->audio_secs_per_block) {
|
||||
MP_ERR(priv, "Video buffer shorter than 3 times audio frame duration.\n"
|
||||
"You will probably experience heavy framedrops.\n");
|
||||
@ -1433,7 +1433,7 @@ static void *video_grabber(void *data)
|
||||
}
|
||||
priv->streamon = 1;
|
||||
|
||||
if (!priv->tv_param->noaudio) {
|
||||
if (priv->tv_param->audio) {
|
||||
pthread_create(&priv->audio_grabber_thread, NULL, audio_grabber, priv);
|
||||
}
|
||||
|
||||
@ -1510,9 +1510,9 @@ static void *video_grabber(void *data)
|
||||
|
||||
/* store the timestamp of the very first frame as reference */
|
||||
if (!priv->frames++) {
|
||||
if (!priv->tv_param->noaudio) pthread_mutex_lock(&priv->skew_mutex);
|
||||
if (priv->tv_param->audio) pthread_mutex_lock(&priv->skew_mutex);
|
||||
priv->first_frame = (long long)1e6*buf.timestamp.tv_sec + buf.timestamp.tv_usec;
|
||||
if (!priv->tv_param->noaudio) pthread_mutex_unlock(&priv->skew_mutex);
|
||||
if (priv->tv_param->audio) pthread_mutex_unlock(&priv->skew_mutex);
|
||||
}
|
||||
priv->curr_frame = (long long)buf.timestamp.tv_sec*1e6+buf.timestamp.tv_usec;
|
||||
// fprintf(stderr, "idx = %d, ts = %f\n", buf.index, (double)(priv->curr_frame) / 1e6);
|
||||
@ -1522,9 +1522,9 @@ static void *video_grabber(void *data)
|
||||
|
||||
if (!priv->immediate_mode) {
|
||||
// interpolate the skew in time
|
||||
if (!priv->tv_param->noaudio) pthread_mutex_lock(&priv->skew_mutex);
|
||||
if (priv->tv_param->audio) pthread_mutex_lock(&priv->skew_mutex);
|
||||
xskew = priv->audio_skew + (interval - priv->audio_skew_measure_time)*priv->audio_skew_factor;
|
||||
if (!priv->tv_param->noaudio) pthread_mutex_unlock(&priv->skew_mutex);
|
||||
if (priv->tv_param->audio) pthread_mutex_unlock(&priv->skew_mutex);
|
||||
// correct extreme skew changes to avoid (especially) moving backwards in time
|
||||
if (xskew - prev_skew > delta*MAX_SKEW_DELTA) {
|
||||
skew = prev_skew + delta*MAX_SKEW_DELTA;
|
||||
|
Loading…
Reference in New Issue
Block a user