summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/mpv.rst3
-rw-r--r--Makefile1
-rwxr-xr-xconfigure42
-rw-r--r--core/av_log.c8
-rw-r--r--demux/demux_lavf.c70
-rw-r--r--stream/stream.c2
-rw-r--r--stream/stream.h1
-rw-r--r--stream/stream_avdevice.c49
8 files changed, 151 insertions, 25 deletions
diff --git a/DOCS/man/en/mpv.rst b/DOCS/man/en/mpv.rst
index 72071dce8f..7398ed8f43 100644
--- a/DOCS/man/en/mpv.rst
+++ b/DOCS/man/en/mpv.rst
@@ -611,6 +611,9 @@ Stream from HTTP:
Stream using RTSP:
``mpv rtsp://server.example.com/streamName``
+Play a libavfilter graph:
+ ``mpv avdevice://lavfi:mandlebrot``
+
AUTHORS
=======
diff --git a/Makefile b/Makefile
index 2e0fae4ec9..552cda71eb 100644
--- a/Makefile
+++ b/Makefile
@@ -210,6 +210,7 @@ SOURCES = talloc.c \
osdep/numcores.c \
osdep/io.c \
stream/stream.c \
+ stream/stream_avdevice.c \
stream/stream_file.c \
stream/stream_lavf.c \
stream/stream_mf.c \
diff --git a/configure b/configure
index 7d8c68dec3..9784addbad 100755
--- a/configure
+++ b/configure
@@ -333,6 +333,8 @@ Optional features:
--disable-libass-osd disable OSD rendering with libass [autodetect]
--enable-rpath enable runtime linker path for extra libs [disabled]
--disable-libpostproc disable postprocess filter (vf_pp) [autodetect]
+ --enable-libavdevice enable libavdevice demuxers [disabled]
+ --enable-libavfilter enable libavfilter [disabled] [unused]
Codecs:
--enable-gif enable GIF support [autodetect]
@@ -490,6 +492,8 @@ _ass=auto
_libass_osd=auto
_rpath=no
libpostproc=auto
+libavfilter=no
+libavdevice=no
_asmalign_pot=auto
_stream_cache=yes
_priority=no
@@ -707,6 +711,10 @@ for ac_option do
--disable-rpath) _rpath=no ;;
--enable-libpostproc) libpostproc=yes ;;
--disable-libpostproc) libpostproc=no ;;
+ --enable-libavdevice) libavdevice=auto ;;
+ --disable-libavdevice) libavdevice=no ;;
+ --enable-libavfilter) libavfilter=auto ;;
+ --disable-libavfilter) libavfilter=no ;;
--enable-enca) _enca=yes ;;
--disable-enca) _enca=no ;;
@@ -2824,6 +2832,36 @@ else
fi
+echocheck "libavfilter >= 3.17.0"
+if test "$libavfilter" = auto ; then
+ libavfilter=no
+ if pkg_config_add "libavfilter >= 3.17.0" ; then
+ libavfilter=yes
+ fi
+fi
+if test "$libavfilter" = yes ; then
+ def_libavfilter='#define CONFIG_LIBAVFILTER 1'
+else
+ def_libavfilter='#undef CONFIG_LIBAVFILTER'
+fi
+echores "$libavfilter"
+
+
+echocheck "libavdevice >= 54.0.0"
+if test "$libavdevice" = auto ; then
+ libavdevice=no
+ if pkg_config_add "libavdevice >= 54.0.0" ; then
+ libavdevice=yes
+ fi
+fi
+if test "$libavdevice" = yes ; then
+ def_libavdevice='#define CONFIG_LIBAVDEVICE 1'
+else
+ def_libavdevice='#undef CONFIG_LIBAVDEVICE'
+fi
+echores "$libavdevice"
+
+
echocheck "libpostproc >= 52.0.0"
if test "$libpostproc" = auto ; then
libpostproc=no
@@ -3245,6 +3283,8 @@ LIBBLURAY = $_bluray
LIBBS2B = $_libbs2b
LCMS2 = $_lcms2
LIBPOSTPROC = $libpostproc
+LIBAVDEVICE = $libavdevice
+LIBAVFILTER = $libavfilter
LIBSMBCLIENT = $_smb
LIBQUVI = $_libquvi
LIBTHEORA = $_theora
@@ -3403,6 +3443,8 @@ $def_mpg123
$def_zlib
$def_libpostproc
+$def_libavdevice
+$def_libavfilter
/* Audio output drivers */
diff --git a/core/av_log.c b/core/av_log.c
index 4a80488a4b..9f6f84a39b 100644
--- a/core/av_log.c
+++ b/core/av_log.c
@@ -33,6 +33,10 @@
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
+#ifdef CONFIG_LIBAVDEVICE
+#include <libavdevice/avdevice.h>
+#endif
+
static int av_log_level_to_mp_level(int av_level)
{
if (av_level > AV_LOG_VERBOSE)
@@ -113,6 +117,10 @@ void init_libav(void)
avcodec_register_all();
av_register_all();
avformat_network_init();
+
+#ifdef CONFIG_LIBAVDEVICE
+ avdevice_register_all();
+#endif
}
#define V(x) (x)>>16, (x)>>8 & 255, (x) & 255
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index ad4f521052..9cf36207a3 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -64,6 +64,7 @@ const m_option_t lavfdopts_conf[] = {
#define BIO_BUFFER_SIZE 32768
typedef struct lavf_priv {
+ char *filename;
AVInputFormat *avif;
AVFormatContext *avfc;
AVIOContext *pb;
@@ -151,6 +152,19 @@ static void list_formats(void)
mp_msg(MSGT_DEMUX, MSGL_INFO, "%15s : %s\n", fmt->name, fmt->long_name);
}
+static char *remove_prefix(char *s, const char **prefixes)
+{
+ for (int n = 0; prefixes[n]; n++) {
+ int len = strlen(prefixes[n]);
+ if (strncmp(s, prefixes[n], len) == 0)
+ return s + len;
+ }
+ return s;
+}
+
+static const char *prefixes[] =
+ {"ffmpeg://", "lavf://", "avdevice://", "av://", NULL};
+
static int lavf_check_file(demuxer_t *demuxer)
{
struct MPOpts *opts = demuxer->opts;
@@ -162,13 +176,37 @@ static int lavf_check_file(demuxer_t *demuxer)
int score;
if (!demuxer->priv)
- demuxer->priv = calloc(sizeof(lavf_priv_t), 1);
+ demuxer->priv = talloc_zero(NULL, lavf_priv_t);
priv = demuxer->priv;
priv->autoselect_sub = -1;
+ priv->filename = demuxer->stream->url;
+ if (!priv->filename) {
+ priv->filename = "mp:unknown";
+ mp_msg(MSGT_DEMUX, MSGL_WARN, "Stream url is not set!\n");
+ }
+
+ priv->filename = remove_prefix(priv->filename, prefixes);
+
+ char *avdevice_format = NULL;
+ if (demuxer->stream->type == STREAMTYPE_AVDEVICE) {
+ // always require filename in the form "format:filename"
+ char *sep = strchr(priv->filename, ':');
+ if (!sep) {
+ mp_msg(MSGT_DEMUX, MSGL_FATAL,
+ "Must specify filename in 'format:filename' form\n");
+ return 0;
+ }
+ avdevice_format = talloc_strndup(priv, priv->filename,
+ sep - priv->filename);
+ priv->filename = sep + 1;
+ }
+
char *format = lavfdopts->format;
if (!format)
format = demuxer->stream->lavf_type;
+ if (!format)
+ format = avdevice_format;
if (format) {
if (strcmp(format, "help") == 0) {
list_formats();
@@ -194,14 +232,7 @@ static int lavf_check_file(demuxer_t *demuxer)
return 0;
}
probe_data_size += read_size;
- avpd.filename = demuxer->stream->url;
- if (!avpd.filename) {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "Stream url is not set!\n");
- avpd.filename = "";
- }
- if (!strncmp(avpd.filename, "ffmpeg://", 9) ||
- !strncmp(avpd.filename, "lavf://", 7))
- avpd.filename += 9;
+ avpd.filename = priv->filename;
avpd.buf_size = probe_data_size;
score = 0;
@@ -619,20 +650,9 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer)
}
}
- char *filename = demuxer->stream->url;
-
- if (filename) {
- if (demuxer->stream->lavf_type && !strcmp(demuxer->stream->lavf_type,
- "rtsp")) {
- // Remove possible leading ffmpeg:// or lavf://
- char *name = strstr(filename, "rtsp:");
- if (name)
- filename = name;
- }
- } else
- filename = "mp:unknown";
-
- if (!(priv->avif->flags & AVFMT_NOFILE)) {
+ if (!(priv->avif->flags & AVFMT_NOFILE) &&
+ demuxer->stream->type != STREAMTYPE_AVDEVICE)
+ {
priv->pb = avio_alloc_context(priv->buffer, BIO_BUFFER_SIZE, 0,
demuxer, mp_read, NULL, mp_seek);
priv->pb->read_seek = mp_read_seek;
@@ -642,7 +662,7 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer)
avfc->pb = priv->pb;
}
- if (avformat_open_input(&avfc, filename, priv->avif, NULL) < 0) {
+ if (avformat_open_input(&avfc, priv->filename, priv->avif, NULL) < 0) {
mp_msg(MSGT_HEADER, MSGL_ERR,
"LAVF_header: avformat_open_input() failed\n");
return NULL;
@@ -1047,7 +1067,7 @@ static void demux_close_lavf(demuxer_t *demuxer)
avformat_close_input(&priv->avfc);
}
av_freep(&priv->pb);
- free(priv);
+ talloc_free(priv);
demuxer->priv = NULL;
}
}
diff --git a/stream/stream.c b/stream/stream.c
index 722a21e57c..94a7c4cf6d 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -81,6 +81,7 @@ extern const stream_info_t stream_info_smb;
extern const stream_info_t stream_info_null;
extern const stream_info_t stream_info_mf;
extern const stream_info_t stream_info_ffmpeg;
+extern const stream_info_t stream_info_avdevice;
extern const stream_info_t stream_info_file;
extern const stream_info_t stream_info_ifo;
extern const stream_info_t stream_info_dvd;
@@ -94,6 +95,7 @@ static const stream_info_t* const auto_open_streams[] = {
&stream_info_cdda,
#endif
&stream_info_ffmpeg, // use for rstp:// before http fallback
+ &stream_info_avdevice,
#ifdef CONFIG_NETWORKING
&stream_info_netstream,
&stream_info_http1,
diff --git a/stream/stream.h b/stream/stream.h
index 87cb6c64db..28557e8c6e 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -53,6 +53,7 @@
#define STREAMTYPE_MF 18
#define STREAMTYPE_RADIO 19
#define STREAMTYPE_BLURAY 20
+#define STREAMTYPE_AVDEVICE 21
#define STREAM_BUFFER_SIZE 2048
#define STREAM_MAX_SECTOR_SIZE (8*1024)
diff --git a/stream/stream_avdevice.c b/stream/stream_avdevice.c
new file mode 100644
index 0000000000..e26d5a9060
--- /dev/null
+++ b/stream/stream_avdevice.c
@@ -0,0 +1,49 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include "stream.h"
+#include "demux/demux.h"
+
+static int fill_buffer(stream_t *s, char *buffer, int max_len)
+{
+ return -1;
+}
+
+static int open_f(stream_t *stream, int mode, void *opts, int *file_format)
+{
+ if (mode != STREAM_READ)
+ return STREAM_ERROR;
+
+ stream->fill_buffer = fill_buffer;
+ stream->type = STREAMTYPE_AVDEVICE;
+
+ *file_format = DEMUXER_TYPE_LAVF;
+ return STREAM_OK;
+}
+
+const stream_info_t stream_info_avdevice = {
+ .info = "FFmpeg libavdevice",
+ .name = "avdevice",
+ .author = "",
+ .comment =
+ "Force a libavformat/libavdevice demuxer with avdevice://demuxer:args",
+ .open = open_f,
+ .protocols = { "avdevice", "av", NULL },
+};