diff options
-rw-r--r-- | DOCS/man/en/mpv.rst | 3 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rwxr-xr-x | configure | 42 | ||||
-rw-r--r-- | core/av_log.c | 8 | ||||
-rw-r--r-- | demux/demux_lavf.c | 70 | ||||
-rw-r--r-- | stream/stream.c | 2 | ||||
-rw-r--r-- | stream/stream.h | 1 | ||||
-rw-r--r-- | stream/stream_avdevice.c | 49 |
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 ======= @@ -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 \ @@ -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 }, +}; |