diff options
-rw-r--r-- | DOCS/man/en/input.rst | 1 | ||||
-rw-r--r-- | DOCS/man/en/options.rst | 9 | ||||
-rw-r--r-- | core/cfg-mplayer.h | 2 | ||||
-rw-r--r-- | core/command.c | 15 | ||||
-rw-r--r-- | core/mplayer.c | 2 | ||||
-rw-r--r-- | core/options.h | 1 | ||||
-rw-r--r-- | stream/cache2.c | 1 | ||||
-rw-r--r-- | stream/stream.c | 34 | ||||
-rw-r--r-- | stream/stream.h | 6 |
9 files changed, 71 insertions, 0 deletions
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst index 638172289c..5ae78ca06d 100644 --- a/DOCS/man/en/input.rst +++ b/DOCS/man/en/input.rst @@ -341,6 +341,7 @@ sub-scale x subtitle font size multiplicator ass-use-margins x see ``--ass-use-margins`` ass-vsfilter-aspect-compat x see ``--ass-vsfilter-aspect-compat`` ass-style-override x see ``--ass-style-override`` +stream-capture x a filename, see ``--capture`` tv-brightness x tv-contrast x tv-saturation x diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index cd1b4ab90a..2f3e5bf38d 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -1528,6 +1528,15 @@ Print out a custom string during playback instead of the standard status line. Expands properties. See ``--playing-msg``. +--stream-capture=<filename> + Allows capturing the primary stream (not additional audio tracks or other + kind of streams) into the given file. Capturing can also be started and + stopped changing the filename with the ``stream-capture`` slave property. + Generally this will not produce usable results for anything else than MPEG + or raw streams, unless capturing includes the file headers and is not + interrupted. Note that, due to cache latencies, captured data may begin and + end somewhat delayed compared to what you see displayed. + --playlist=<filename> Play files according to a playlist file (ASX, Winamp, SMIL, or one-file-per-line format). diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h index baf0820f48..9feb82f9cd 100644 --- a/core/cfg-mplayer.h +++ b/core/cfg-mplayer.h @@ -634,6 +634,8 @@ const m_option_t mplayer_opts[]={ OPT_FLAG("untimed", untimed, 0), + OPT_STRING("stream-capture", stream_capture, 0), + #ifdef CONFIG_LIRC {"lircconf", &lirc_configfile, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL}, #endif diff --git a/core/command.c b/core/command.c index d8a8882c26..e9d3d0d679 100644 --- a/core/command.c +++ b/core/command.c @@ -197,6 +197,20 @@ static int mp_property_stream_path(m_option_t *prop, int action, void *arg, return m_property_strdup_ro(prop, action, arg, stream->url); } +static int mp_property_stream_capture(m_option_t *prop, int action, + void *arg, MPContext *mpctx) +{ + if (!mpctx->stream) + return M_PROPERTY_UNAVAILABLE; + + if (action == M_PROPERTY_SET) { + char *filename = *(char **)arg; + stream_set_capture_file(mpctx->stream, filename); + // fall through to mp_property_generic_option + } + return mp_property_generic_option(prop, action, arg, mpctx); +} + /// Demuxer name (RO) static int mp_property_demuxer(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -1357,6 +1371,7 @@ static const m_option_t mp_properties[] = { 0, 0, 0, NULL }, { "stream-path", mp_property_stream_path, CONF_TYPE_STRING, 0, 0, 0, NULL }, + M_OPTION_PROPERTY_CUSTOM("stream-capture", mp_property_stream_capture), { "demuxer", mp_property_demuxer, CONF_TYPE_STRING, 0, 0, 0, NULL }, { "stream-pos", mp_property_stream_pos, CONF_TYPE_INT64, diff --git a/core/mplayer.c b/core/mplayer.c index 361d3d5466..ed8de9eb36 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -4233,6 +4233,8 @@ goto_enable_cache: ; if (demux_was_interrupted(mpctx)) goto terminate_playback; + stream_set_capture_file(mpctx->stream, opts->stream_capture); + //============ Open DEMUXERS --- DETECT file type ======================= mpctx->audio_delay = opts->audio_delay; diff --git a/core/options.h b/core/options.h index 11286bf883..09cf20c852 100644 --- a/core/options.h +++ b/core/options.h @@ -85,6 +85,7 @@ typedef struct MPOpts { int osd_fractions; char *vobsub_name; int untimed; + char *stream_capture; int loop_times; int ordered_chapters; int chapter_merge_threshold; diff --git a/stream/cache2.c b/stream/cache2.c index 38c57d0af9..1337e44e37 100644 --- a/stream/cache2.c +++ b/stream/cache2.c @@ -593,6 +593,7 @@ int cache_stream_fill_buffer(stream_t *s){ s->buf_len=len; s->pos+=len; // printf("[%d]",len);fflush(stdout); + stream_capture_write(s); return len; } diff --git a/stream/stream.c b/stream/stream.c index 36594d8556..caf78851c3 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -41,6 +41,7 @@ #include <winsock2.h> #endif +#include "core/bstr.h" #include "core/mp_msg.h" #include "osdep/shmem.h" #include "osdep/timer.h" @@ -312,6 +313,37 @@ static int stream_reconnect(stream_t *s) return 0; } +void stream_set_capture_file(stream_t *s, const char *filename) +{ + if (!bstr_equals(bstr0(s->capture_filename), bstr0(filename))) { + if (s->capture_file) + fclose(s->capture_file); + talloc_free(s->capture_filename); + s->capture_file = NULL; + s->capture_filename = NULL; + if (filename) { + s->capture_file = fopen(filename, "wb"); + if (s->capture_file) { + s->capture_filename = talloc_strdup(NULL, filename); + } else { + mp_tmsg(MSGT_GLOBAL, MSGL_ERR, + "Error opening capture file: %s\n", strerror(errno)); + } + } + } +} + +void stream_capture_write(stream_t *s) +{ + if (s->capture_file) { + if (fwrite(s->buffer, s->buf_len, 1, s->capture_file) < 1) { + mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "Error writing capture file: %s\n", + strerror(errno)); + stream_set_capture_file(s, NULL); + } + } +} + int stream_read_internal(stream_t *s, void *buf, int len) { int orig_len = len; @@ -367,6 +399,7 @@ int stream_fill_buffer(stream_t *s) s->buf_pos = 0; s->buf_len = len; // printf("[%d]",len);fflush(stdout); + stream_capture_write(s); return len; } @@ -566,6 +599,7 @@ void free_stream(stream_t *s) #ifdef CONFIG_STREAM_CACHE cache_uninit(s); #endif + stream_set_capture_file(s, NULL); if (s->close) s->close(s); diff --git a/stream/stream.h b/stream/stream.h index df4188ed94..ad2d7dd19a 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -188,6 +188,9 @@ typedef struct stream { unsigned char buffer[STREAM_BUFFER_SIZE > STREAM_MAX_SECTOR_SIZE ? STREAM_BUFFER_SIZE : STREAM_MAX_SECTOR_SIZE]; + + FILE *capture_file; + char *capture_filename; } stream_t; #ifdef CONFIG_NETWORKING @@ -197,6 +200,9 @@ typedef struct stream { int stream_fill_buffer(stream_t *s); int stream_seek_long(stream_t *s, int64_t pos); +void stream_set_capture_file(stream_t *s, const char *filename); +void stream_capture_write(stream_t *s); + #ifdef CONFIG_STREAM_CACHE int stream_enable_cache_percent(stream_t *stream, int64_t stream_cache_size, float stream_cache_min_percent, |