From 3cb3bbbddc1d09dab1471a3630f1a9aa4392ed50 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Tue, 2 Nov 2010 03:17:41 +0200 Subject: Add a simple capture feature (-capture) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a specified key is pressed during playback, the current stream is captured to a file, similar to what -dumpstream achieves. original patch by Pásztor Szilárd, don tricon hu Taken from the following svn commits, but with several fixes and modifications (one obvious user-visible difference is that the default key binding is 'C', not 'c'): git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@32524 b3059339-0415-0410-9bf9-f77b7e298cf2 git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@32529 b3059339-0415-0410-9bf9-f77b7e298cf2 git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@32530 b3059339-0415-0410-9bf9-f77b7e298cf2 --- DOCS/man/en/mplayer.1 | 17 ++++++++++++++++- DOCS/tech/slave.txt | 5 +++++ cfg-mplayer.h | 3 +++ command.c | 38 ++++++++++++++++++++++++++++++++++++++ input/input.c | 2 ++ input/input.h | 1 + options.h | 1 + stream/cache2.c | 2 ++ stream/stream.c | 17 +++++++++++++++++ stream/stream.h | 3 +++ 10 files changed, 88 insertions(+), 1 deletion(-) diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index 7d246a6a25..246b212532 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -273,6 +273,8 @@ Toggle displaying "forced subtitles". Toggle subtitle alignment: top / middle / bottom. .IPs "x and z" Adjust subtitle delay by +/\- 0.1 seconds. +.IPs "C (\-capture only)" +Start/stop capturing the primary stream. .IPs "r and t" Move subtitles up/down. .IPs "i (\-edlout mode only)" @@ -1248,6 +1250,18 @@ from the current position, MPlayer will wait for the cache to be filled to this position rather than performing a stream seek (default: 50). . .TP +.B \-capture (MPlayer only) +Allows capturing the primary stream (not additional audio tracks or other +kind of streams) into the file specified by \-dumpfile or \"stream.dump\" +by default. +If this option is given, capturing can be started and stopped by pressing +the key bound to this function (see section INTERACTIVE CONTROL). +Same as for \-dumpstream, this will likely not produce usable results for +anything else than MPEG streams. +Note that, due to cache latencies, captured data may begin and end +somewhat delayed compared to what you see displayed. +. +.TP .B \-cdda (CDDA only) This option can be used to tune the CD Audio reading feature of MPlayer. .sp 1 @@ -1379,7 +1393,8 @@ on the command line only the last one will work. .TP .B \-dumpfile (MPlayer only) Specify which file MPlayer should dump to. -Should be used together with \-dumpaudio / \-dumpvideo / \-dumpstream. +Should be used together with \-dumpaudio / \-dumpvideo / \-dumpstream / +\-capture. . .TP .B \-dumpstream (MPlayer only) diff --git a/DOCS/tech/slave.txt b/DOCS/tech/slave.txt index 330534cefe..e923232689 100644 --- a/DOCS/tech/slave.txt +++ b/DOCS/tech/slave.txt @@ -76,6 +76,10 @@ audio_delay [abs] If [abs] is non-zero, parameter is set to . is in the range [-100, 100]. +capturing [value] + Toggle/set capturing the primary stream like -dumpstream. + Requires the -capture parameter to be given. + change_rectangle Change the position of the rectangle filter rectangle. @@ -538,6 +542,7 @@ channels int X switch_audio int -2 255 X X X select audio stream switch_angle int -2 255 X X X select DVD angle switch_title int -2 255 X X X select DVD title +capturing flag 0 1 X X X dump primary stream if enabled fullscreen flag 0 1 X X X deinterlace flag 0 1 X X X ontop flag 0 1 X X X diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 2c368ff54c..ba2a912ded 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -294,6 +294,9 @@ const m_option_t mplayer_opts[]={ {"dumpjacosub", &stream_dump_type, CONF_TYPE_FLAG, 0, 0, 8, NULL}, {"dumpsami", &stream_dump_type, CONF_TYPE_FLAG, 0, 0, 9, NULL}, + OPT_FLAG_ON("capture", capture_dump, 0), + OPT_FLAG_OFF("nocapture", capture_dump, 0), + #ifdef CONFIG_LIRC {"lircconf", &lirc_configfile, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL}, #endif diff --git a/command.c b/command.c index 60d04d4248..e367687c5a 100644 --- a/command.c +++ b/command.c @@ -1178,6 +1178,40 @@ static int mp_property_yuv_colorspace(m_option_t *prop, int action, return M_PROPERTY_NOT_IMPLEMENTED; } +static int mp_property_capture(m_option_t *prop, int action, + void *arg, MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; + + if (!mpctx->stream) + return M_PROPERTY_UNAVAILABLE; + + if (!opts->capture_dump) { + mp_tmsg(MSGT_GLOBAL, MSGL_ERR, + "Capturing not enabled (forgot -capture parameter?)\n"); + return M_PROPERTY_ERROR; + } + + int capturing = !!mpctx->stream->capture_file; + + int ret = m_property_flag(prop, action, arg, &capturing); + if (ret == M_PROPERTY_OK && capturing != !!mpctx->stream->capture_file) { + if (capturing) { + mpctx->stream->capture_file = fopen(opts->stream_dump_name, "wb"); + if (!mpctx->stream->capture_file) { + mp_tmsg(MSGT_GLOBAL, MSGL_ERR, + "Error opening capture file: %s\n", strerror(errno)); + ret = M_PROPERTY_ERROR; + } + } else { + fclose(mpctx->stream->capture_file); + mpctx->stream->capture_file = NULL; + } + } + + return ret; +} + /// Panscan (RW) static int mp_property_panscan(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -2158,6 +2192,8 @@ static const m_option_t mp_properties[] = { 0, 0, 0, NULL }, { "pause", mp_property_pause, CONF_TYPE_FLAG, M_OPT_RANGE, 0, 1, NULL }, + { "capturing", mp_property_capture, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, // Audio { "volume", mp_property_volume, CONF_TYPE_FLOAT, @@ -2330,6 +2366,7 @@ static struct property_osd_display { // general { "loop", 0, -1, _("Loop: %s") }, { "chapter", -1, -1, NULL }, + { "capturing", 0, -1, _("Capturing: %s") }, // audio { "volume", OSD_VOLUME, -1, _("Volume") }, { "mute", 0, -1, _("Mute: %s") }, @@ -2456,6 +2493,7 @@ static struct { { "chapter", MP_CMD_SEEK_CHAPTER, 0}, { "angle", MP_CMD_SWITCH_ANGLE, 0}, { "pause", MP_CMD_PAUSE, 0}, + { "capturing", MP_CMD_CAPTURING, 1}, // audio { "volume", MP_CMD_VOLUME, 0}, { "mute", MP_CMD_MUTE, 1}, diff --git a/input/input.c b/input/input.c index 1e2a6e888e..658e34f4dc 100644 --- a/input/input.c +++ b/input/input.c @@ -183,6 +183,7 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_LOADFILE, "loadfile", 1, { {MP_CMD_ARG_STRING, {0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, { MP_CMD_LOADLIST, "loadlist", 1, { {MP_CMD_ARG_STRING, {0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, { MP_CMD_RUN, "run", 1, { {MP_CMD_ARG_STRING,{0}}, {-1,{0}} } }, + { MP_CMD_CAPTURING, "capturing", 0, { {-1,{0}} } }, { MP_CMD_VF_CHANGE_RECTANGLE, "change_rectangle", 2, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}}}}, { MP_CMD_TV_TELETEXT_ADD_DEC, "teletext_add_dec", 1, { {MP_CMD_ARG_STRING,{0}}, {-1,{0}} } }, { MP_CMD_TV_TELETEXT_GO_LINK, "teletext_go_link", 1, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } }, @@ -475,6 +476,7 @@ static const mp_cmd_bind_t def_cmd_binds[] = { #endif { { 'T', 0 }, "vo_ontop" }, { { 'f', 0 }, "vo_fullscreen" }, + { { 'C', 0 }, "step_property_osd capturing" }, { { 's', 0 }, "screenshot 0" }, { { 'S', 0 }, "screenshot 1" }, { { 'w', 0 }, "panscan -0.1" }, diff --git a/input/input.h b/input/input.h index 51d9f6522e..d922655950 100644 --- a/input/input.h +++ b/input/input.h @@ -41,6 +41,7 @@ typedef enum { MP_CMD_TV_STEP_CHANNEL, MP_CMD_TV_STEP_NORM, MP_CMD_TV_STEP_CHANNEL_LIST, + MP_CMD_CAPTURING, MP_CMD_VO_FULLSCREEN, MP_CMD_SUB_POS, MP_CMD_DVDNAV, diff --git a/options.h b/options.h index 84f843552b..91ea2832d2 100644 --- a/options.h +++ b/options.h @@ -28,6 +28,7 @@ typedef struct MPOpts { int osd_level; int osd_duration; char *stream_dump_name; + int capture_dump; int loop_times; int ordered_chapters; int chapterrange[2]; diff --git a/stream/cache2.c b/stream/cache2.c index 3aa24df64d..c4514243e1 100644 --- a/stream/cache2.c +++ b/stream/cache2.c @@ -508,6 +508,8 @@ int cache_stream_fill_buffer(stream_t *s){ s->buf_len=len; s->pos+=len; // printf("[%d]",len);fflush(stdout); + if (s->capture_file) + stream_capture_do(s); return len; } diff --git a/stream/stream.c b/stream/stream.c index 8b325a24d1..ca45f511e5 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -265,6 +265,16 @@ stream_t *open_output_stream(const char *filename, struct MPOpts *options) //=================== STREAMER ========================= +void stream_capture_do(stream_t *s) +{ + 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)); + fclose(s->capture_file); + s->capture_file = NULL; + } +} + int stream_fill_buffer(stream_t *s){ int len; // we will retry even if we already reached EOF previously. @@ -296,6 +306,8 @@ int stream_fill_buffer(stream_t *s){ s->buf_len=len; s->pos+=len; // printf("[%d]",len);fflush(stdout); + if (s->capture_file) + stream_capture_do(s); return len; } @@ -463,6 +475,11 @@ void free_stream(stream_t *s){ #ifdef CONFIG_STREAM_CACHE cache_uninit(s); #endif + if (s->capture_file) { + fclose(s->capture_file); + s->capture_file = NULL; + } + if(s->close) s->close(s); if(s->fd>0){ /* on unix we define closesocket to close diff --git a/stream/stream.h b/stream/stream.h index bd73f6f954..8e4b260ffb 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -22,6 +22,7 @@ #include "config.h" #include "mp_msg.h" #include "url.h" +#include #include #include #include @@ -168,6 +169,7 @@ typedef struct stream { streaming_ctrl_t *streaming_ctrl; #endif unsigned char buffer[STREAM_BUFFER_SIZE>STREAM_MAX_SECTOR_SIZE?STREAM_BUFFER_SIZE:STREAM_MAX_SECTOR_SIZE]; + FILE *capture_file; } stream_t; #ifdef CONFIG_NETWORKING @@ -176,6 +178,7 @@ typedef struct stream { int stream_fill_buffer(stream_t *s); int stream_seek_long(stream_t *s, off_t pos); +void stream_capture_do(stream_t *s); #ifdef CONFIG_STREAM_CACHE int stream_enable_cache(stream_t *stream,int size,int min,int prefill); -- cgit v1.2.3