[MPlayer-dev-eng] [RFC] Playing growing file

Doc Holliday doc4holliday at gmail.com
Sun Jan 1 03:28:53 CET 2012


Vlad Seryakov <vseryakov <at> gmail.com> writes:

> Hi,
> 
> This is just some crazy idea i am thinking about while trying to figure out
how to play MPEG TS recordings with
> mplayer. Really this is not full timeshift solution and never be, player is
just a player but supporting
> growing file may be very useful.
> I decided to try with adding one function to stream_file.c which will handle 
> pipe://
>  urls and just use different fill_buffer function which indefinitely reads
from file but process events to
> avoid hangs.
> Just wondetng what other think about this solution.
> 
> Thanks

Hi Vlad,
I've run into a slight problem with your file. Specifically, while playing a
test mkv file, mplayer would just freeze. I realized that in some cases demux
might try to search all the way to the end of the file (eg in order to determine
its length), which will cause it to freeze.

So I took liberty in adding a few lines and making it into an actual patch
(attached). I also changed the prefix from pipe:// to grow://. Hope you don't
mind ;)

-Doc

==

>From 846db1c1c9ceeecf5dd253302bd1dc69bc333d0c Mon Sep 17 00:00:00 2001
From: Doc Holliday <doc4holliday at gmail.com>
Date: Fri, 30 Dec 2011 21:14:08 -0500
Subject: [PATCH] Wait for data

When file is opened as grow://file.ext, mplayer will
continue waiting for new data even after it reaches EOF.
---
 mplayer.c            |    7 ++++++
 stream/stream.h      |    1 +
 stream/stream_file.c |   53 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 60 insertions(+), 1 deletions(-)

diff --git a/mplayer.c b/mplayer.c
index 53139dd..ef60bbc 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -3292,8 +3292,15 @@ if(stream_cache_size>0){
 //============ Open DEMUXERS --- DETECT file type =======================
 current_module="demux_open";
 
+// HACK temporarily disable STREAM_GROW, as some demuxers like to seek
+// all the way to the end to find out length of the stream
+int grow = mpctx->stream->flags & STREAM_GROW;
+mpctx->stream->flags &= ~STREAM_GROW;
+
 mpctx->demuxer=demux_open(mpctx->stream,mpctx->file_format,audio_id,video_id,dvdsub_id,filename);
 
+mpctx->stream->flags |= grow;
+
 // HACK to get MOV Reference Files working
 
 if (mpctx->demuxer && mpctx->demuxer->type==DEMUXER_TYPE_PLAYLIST)
diff --git a/stream/stream.h b/stream/stream.h
index 184d569..500577e 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -75,6 +75,7 @@
     separation between stream an demuxer and thus is not
     actually a stream cache can not be used */
 #define STREAM_NON_CACHEABLE 8
+#define STREAM_GROW 16
 
 //////////// Open return code
 #define STREAM_REDIRECTED -2
diff --git a/stream/stream_file.c b/stream/stream_file.c
index 9af6013..6192bbf 100644
--- a/stream/stream_file.c
+++ b/stream/stream_file.c
@@ -23,6 +23,9 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#if HAVE_SETMODE
+#include <io.h>
+#endif
 
 #include "mp_msg.h"
 #include "stream.h"
@@ -30,6 +33,10 @@
 #include "m_option.h"
 #include "m_struct.h"
 
+#include "input/input.h"
+#include "libmpdemux/demuxer.h"
+#include <errno.h>
+
 static struct stream_priv_s {
   char* filename;
   char *filename2;
@@ -109,6 +116,45 @@ static int control(stream_t *s, int cmd, void *arg) {
   return STREAM_UNSUPPORTED;
 }
 
+static int grow_fill_buffer(stream_t *s, char* buffer, int max_len)
+{
+  int nread = 0, nodata = 0;
+
+again:
+  nread = read(s->fd, buffer, max_len);
+  if (nread < 0) {
+    if (errno == EINTR) goto again;
+    s->eof = 1;
+    return -1;
+  }
+
+  struct stat st;
+  s->end_pos = fstat(s->fd, &st) ? s->end_pos : st.st_size;
+
+  if (nread == 0)
+    if (s->flags & STREAM_GROW) {
+      mp_cmd_t *cmd = mp_input_get_cmd(0, 0, 1);
+      switch (cmd ? cmd->id : 0) {
+      case MP_CMD_QUIT:
+      case MP_CMD_STOP:
+        s->eof = 1;
+        return -1;
+      }
+      nodata++;
+  
+      // Report periodically but keep spinning
+      if (nodata % 1000 == 0) {
+        mp_msg(MSGT_STREAM,MSGL_ERR, "[ts] nodata=%d, file=%s, len=%d,
pos=%lld, size=%lld\n", nodata, s->url, max_len, s->pos, s->end_pos);
+      }
+      usleep(5000);
+      goto again;
+    }
+    else nread = -1;
+
+  return nread;
+}
+
+
 static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
   int f;
   mode_t m = 0;
@@ -198,6 +244,11 @@ static int open_f(stream_t *stream,int mode, void* opts,
int* file_format) {
   stream->control = control;
   stream->read_chunk = 64*1024;
 
+  if (!stream->url || strncmp(stream->url, "grow://", 7) == 0) {
+    stream->fill_buffer = grow_fill_buffer;
+    stream->flags|=STREAM_GROW;
+  }
+
   m_struct_free(&stream_opts,opts);
   return STREAM_OK;
 }
@@ -208,7 +259,7 @@ const stream_info_t stream_info_file = {
   "Albeu",
   "based on the code from ??? (probably Arpi)",
   open_f,
-  { "file", "", NULL },
+  { "file", "grow", "", NULL },
   &stream_opts,
   1 // Urls are an option string
 };
-- 
1.7.8.1





More information about the MPlayer-dev-eng mailing list