From 698a189619d15ba5df8333501a083923e614365a Mon Sep 17 00:00:00 2001
From: Mark Calderbank <mark@vomp.tv>
Date: Sat, 24 Jun 2006 12:23:20 +0000
Subject: [PATCH] MVP/Windows convergence: Stream; DrainTarget

---
 afeed.cc      |   2 +-
 audio.h       |   4 -
 audiomvp.cc   |  21 ++---
 audiomvp.h    |  12 +--
 audiowin.cc   |  19 +++-
 audiowin.h    |   7 +-
 defines.h     |   4 -
 demuxer.cc    |   4 +-
 demuxer.h     |   4 +-
 draintarget.h |  67 ++++++++------
 player.cc     |   2 +
 stream.cc     | 242 ++++++++++++--------------------------------------
 stream.h      |  15 ++--
 vfeed.cc      |   2 +-
 video.h       |   4 -
 videomvp.cc   |  40 +++++----
 videomvp.h    |  18 ++--
 videowin.cc   |  19 +++-
 videowin.h    |   7 +-
 19 files changed, 205 insertions(+), 288 deletions(-)

diff --git a/afeed.cc b/afeed.cc
index 7bc8fbf..5f86445 100644
--- a/afeed.cc
+++ b/afeed.cc
@@ -60,7 +60,7 @@ void AFeed::stop()
 
 void AFeed::threadMethod()
 {
-  int alen;
+  bool alen;
 
   while(1)
   {
diff --git a/audio.h b/audio.h
index a240121..0baaeb2 100644
--- a/audio.h
+++ b/audio.h
@@ -58,10 +58,6 @@ class Audio : public DrainTarget
     virtual int mute()=0;
     virtual int unMute()=0;
 
-#ifndef NEW_DEMUXER
-    virtual int write(UCHAR* buffer, ULONG length)=0;
-#endif
-
     int volumeUp();
     int volumeDown();
     int getVolume();
diff --git a/audiomvp.cc b/audiomvp.cc
index f7a4ab4..3ef84e1 100644
--- a/audiomvp.cc
+++ b/audiomvp.cc
@@ -228,23 +228,20 @@ int AudioMVP::test()
 }
 #endif
 
-
-#ifdef NEW_DEMUXER
-
-UINT AudioMVP::DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos)
+void AudioMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
 {
-  return 0;
+  packet = mplist.front();
 }
 
-void AudioMVP::ResetTimeOffsets()
+UINT AudioMVP::DeliverMediaSample(const UCHAR* buffer, UINT* samplepos)
 {
+  int written = ::write(fdAudio, buffer + packet.pos_buffer + *samplepos,
+                                 packet.length - *samplepos);
+  if (written == (int)(packet.length - *samplepos)) {*samplepos = 0; return 1;}
+  if (written > 0) *samplepos += written;
+  return 0;
 }
 
-#else
-
-int AudioMVP::write(UCHAR* buffer, ULONG length)
+void AudioMVP::ResetTimeOffsets()
 {
-  return ::write(fdAudio, buffer, length);
 }
-
-#endif
diff --git a/audiomvp.h b/audiomvp.h
index 0178514..52c3b53 100644
--- a/audiomvp.h
+++ b/audiomvp.h
@@ -55,14 +55,11 @@ class AudioMVP : public Audio
     int mute();
     int unMute();
 
-#ifdef NEW_DEMUXER
-    //Writing Data to Audiodevice -- unused in MVP code so far
-    virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos);
+    //Writing Data to Audiodevice
+    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
+    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos);
     virtual long long SetStartOffset(long long curreftime, bool *rsync) { return 0; };
     virtual void ResetTimeOffsets();
-#else
-    int write(UCHAR* buffer, ULONG length);
-#endif
 
 #ifdef DEV
     int test();
@@ -72,6 +69,9 @@ class AudioMVP : public Audio
     int initAllParams();
     UCHAR streamType;
     int fdAudio;
+
+    MediaPacket packet;
+    UINT packetpos;
 };
 
 #endif
diff --git a/audiowin.cc b/audiowin.cc
index 189731b..097247f 100644
--- a/audiowin.cc
+++ b/audiowin.cc
@@ -145,8 +145,23 @@ int AudioWin::unMute()
   return 1;
 }
 
-UINT AudioWin::DeliverMediaSample(MediaPacket packet,
-     UCHAR* buffer,
+void AudioWin::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
+{
+  mediapacket = mplist.front();
+}
+
+UINT AudioWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
+{
+  DeliverMediaPacket(mediapacket, buffer, samplepos);
+  if (*samplepos == mediapacket.length) {
+    *samplepos = 0;
+    return 1;
+  }
+  else return 0;
+}
+
+UINT AudioWin::DeliverMediaPacket(MediaPacket packet,
+     const UCHAR* buffer,
      UINT *samplepos)
 {
   /*First Check, if we have an audio sample*/
diff --git a/audiowin.h b/audiowin.h
index 52690b5..b297519 100644
--- a/audiowin.h
+++ b/audiowin.h
@@ -49,7 +49,12 @@ class AudioWin : public Audio
     int write(char *buf, int len);
 
     // Writing Data to Audiodevice
-    virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos);
+    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
+    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos);
+    UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos);
+  private:
+    MediaPacket mediapacket;
+  public:
     virtual long long SetStartOffset(long long curreftime, bool *rsync);
   virtual void ResetTimeOffsets();
 
diff --git a/defines.h b/defines.h
index d3c1f0d..a1a7d7d 100644
--- a/defines.h
+++ b/defines.h
@@ -21,10 +21,6 @@
 #ifndef DEFINES_H
 #define DEFINES_H
 
-//#define NEW_DEMUXER //Switch for the new demuxer code
-//At the beginning the changed code will be switchable
-//in order to apply the changes also to the mvp code
-
 typedef unsigned char UCHAR;
 typedef unsigned short USHORT;
 typedef unsigned int UINT;
diff --git a/demuxer.cc b/demuxer.cc
index 8e97ec6..90db814 100644
--- a/demuxer.cc
+++ b/demuxer.cc
@@ -145,12 +145,12 @@ void Demuxer::setAspectRatio(enum AspectRatio ar)
     arcnt = 0;
 }
 
-int Demuxer::writeAudio()
+bool Demuxer::writeAudio()
 {
   return audiostream.drain();
 }
 
-int Demuxer::writeVideo()
+bool Demuxer::writeVideo()
 {
   return videostream.drain();
 }
diff --git a/demuxer.h b/demuxer.h
index 7e0f88d..c4c9392 100644
--- a/demuxer.h
+++ b/demuxer.h
@@ -73,8 +73,8 @@ protected:
     void seek();
     void setVideoStream(int id);
     void setAudioStream(int id);
-    int writeAudio();
-    int writeVideo();
+    bool writeAudio();
+    bool writeVideo();
 
     virtual int scan(UCHAR* buf, int len) = 0;
     virtual int findVideoPTS(UCHAR* buf, int len, ULLONG* dest) = 0;
diff --git a/draintarget.h b/draintarget.h
index 380979b..74d5862 100644
--- a/draintarget.h
+++ b/draintarget.h
@@ -24,55 +24,66 @@
 #include "defines.h"
 #include <list>
 
-
-#ifdef NEW_DEMUXER
-
 struct MediaPacket
 {
-  ULLONG recording_byte_pos; //position in recording
-  ULLONG pts;
   ULONG pos_buffer; //position in stream buffer
   ULONG length; //length of the packet
-  //The last to are only needed on windows, for memory reasons they can be excluded in mvp
+  // The fields below are not needed by the MVP
+#ifdef WIN32
+  ULLONG recording_byte_pos; //position in recording
+  ULLONG pts;
   long long presentation_time;/* in 100 ns units*/
   bool synched;
   bool disconti;
+#endif
 };
 
 using namespace std;
-
 typedef list<MediaPacket> MediaPacketList;
 
-#endif
-
 class DrainTarget
 {
   public:
     DrainTarget();
     virtual ~DrainTarget();
 
-#ifdef NEW_DEMUXER
-
-    virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos)=0;
-
-    /* This function behaviour should be:
-    Try to deliver the Data from packet.pos_buffer+samplepos to packet.pos_buffer+packet.length,
-    with considering the bufferwraparound according to buffersize.
-    Then increasing samplepos, so that on the next call delivering can proceed. So if writebytes are
-    writen samplepos=samplepos+writebytes!
-    If samplepos>=packet.length is returned, the next packet can be used for the next call.*/
-
     virtual long long SetStartOffset(long long curreftime, bool *rsync)=0;
     virtual void ResetTimeOffsets()=0;
 
-#else
-    virtual int write(UCHAR* buffer, ULONG length)=0;
-#endif
-
+// The following two functions are used by the Stream
+// to deliver media packets to the front end (DrainTarget).
+//
+// First, the Stream calls PrepareMediaSample, which gives the front end
+// read-only access to the Stream's MediaPacketList. PrepareMediaSample should
+// examine the list to determine how much it wishes to consume, and
+// should copy any data it requires from the MediaPacket objects into
+// local storage.
+// This function call takes place under a mutex lock to ensure integrity
+// of the list structure. It should be fast and must not contain any
+// cancellation points, such as I/O calls for logging.
+//
+// Second, the Stream releases the mutex and calls DeliverMediaSample.
+// This function delivers data from the Stream buffer to the presentation
+// device and returns information to the Stream regarding how many MediaPackets
+// were consumed. Any data copied from the MediaPackets objects during
+// PrepareMediaSample is guaranteed by the Stream still to be valid
+// during the following DeliverMediaSample call.
+
+    // samplepos is equal to the number of bytes from the first MediaPacket
+    // in the list that have already been consumed in a previous call.
+    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos)=0;
+
+    // The Stream guarantees that the value of *samplepos passed to
+    // DeliverMediaSample will be equal to the value of samplepos passed to
+    // PrepareMediaSample in the previous call.
+    // This function should consume data from the buffer according to the
+    // decisions made in PrepareMediaSample. Its return value and *samplepos
+    // tell the Stream how much data it consumed.
+    // If DeliverMediaSample returns X, the Stream will remove packets 0 to X-1
+    // (inclusive) from the list before the next call.
+    // DeliverMediaSample must also set *samplepos equal to the number of bytes
+    // processed from packet X (usually zero).
+    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)=0;
 };
 
-
-
-
 #endif
-
diff --git a/player.cc b/player.cc
index bdacba5..7477586 100644
--- a/player.cc
+++ b/player.cc
@@ -293,6 +293,8 @@ int Player::playInt(bool* doUnlock)
   else // do prebuffering
   {
     logger->log("Player", Log::DEBUG, "Prebuffering...");
+//    afeed.start();
+//    vfeed.start();
     preBuffering = true;
   }
 
diff --git a/stream.cc b/stream.cc
index 6a4531e..21b847a 100644
--- a/stream.cc
+++ b/stream.cc
@@ -1,5 +1,5 @@
 /*
-    Copyright 2005 Mark Calderbank
+    Copyright 2005-2006 Mark Calderbank
 
     This file is part of VOMP.
 
@@ -19,14 +19,13 @@
 */
 
 #include "stream.h"
+#include "log.h"
 
 Stream::Stream()
 {
   initted = 0;
-  draintarget=NULL;
-#ifdef NEW_DEMUXER
-  cur_packet_pos=0;
-#endif
+  draintarget = NULL;
+  cur_packet_pos = 0;
 }
 
 Stream::~Stream()
@@ -36,16 +35,14 @@ Stream::~Stream()
 
 void Stream::shutdown()
 {
-  if (initted) {
-	  free(outbuf);
-#ifdef NEW_DEMUXER
+  if (initted)
+  {
+    free(outbuf);
 #ifdef WIN32
-  CloseHandle(mutex);
-#endif
+    CloseHandle(mutex);
 #endif
   }
   initted = 0;
-
 }
 
 int Stream::init(DrainTarget* tdt, int bufsize)
@@ -54,82 +51,31 @@ int Stream::init(DrainTarget* tdt, int bufsize)
   if (!outbuf) return 0;
   draintarget = tdt;
   bufferSize = bufsize;
-  bufferHead = 0;
-  bufferTail = 0;
-  bufferMark = -1;
   initted = 1;
-#ifdef NEW_DEMUXER
 #ifndef WIN32
   pthread_mutex_init(&mutex, NULL);
 #else
   mutex=CreateMutex(NULL,FALSE,NULL);
-#endif
 #endif
   return 1;
 }
 
 void Stream::flush()
 {
-#ifdef NEW_DEMUXER
   lock();
   mediapackets.clear();
   unLock();
   if (draintarget) draintarget->ResetTimeOffsets();
-#endif
-  bufferHead = 0;
-  bufferTail = 0;
-  bufferMark = -1;
 }
 
-#ifndef NEW_DEMUXER
-int Stream::put(UCHAR* inbuf, int len)
+int Stream::put(const UCHAR* inbuf, int len)
 {
   int ret = 0;
-  int tail = bufferTail;
-  int head = bufferHead;
-  if (tail == 0) tail = bufferSize;
-
-  if (head < tail)
-  {
-    // The free space is in one continuous chunk.
-    if (len < tail - head)
-    {
-      memcpy(outbuf + head, inbuf, len);
-      bufferHead += len;
-      ret = len;
-    }
-  }
-  else if (len <= bufferSize - head)
-  {
-    // There is enough space above the Head.
-    memcpy(outbuf + head, inbuf, len);
-    if (head + len == bufferSize)
-      bufferHead = 0;
-    else
-      bufferHead += len;
-    ret = len;
-  }
-  else if (len < tail)
-  {
-    bufferMark = head;
-    memcpy(outbuf, inbuf, len);
-    bufferHead = len;
-    ret = len;
-  }
-  return ret;
-}
-#else
-int Stream::put(UCHAR* inbuf, int len)
-{
-  int ret = 0;
-  int tail = bufferTail;
-  int head = bufferHead;
-  if (tail == 0) tail = bufferSize;
-
   if (!draintarget) return 0;
   MediaPacket newPacket;
-  newPacket.length=len;
-  newPacket.pos_buffer=0;
+  newPacket.length = len;
+  newPacket.pos_buffer = 0;
+#ifdef WIN32
   newPacket.synched=false;
   newPacket.disconti=false;
   newPacket.pts=0;
@@ -146,142 +92,66 @@ int Stream::put(UCHAR* inbuf, int len)
     newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL);
     newPacket.presentation_time-=draintarget->SetStartOffset(newPacket.presentation_time,&newPacket.disconti);
   }
+#endif
 
-  if (head < tail)
+  lock();
+  int front, back;
+  if (mediapackets.empty())
   {
-    // The free space is in one continuous chunk.
-    if (len < tail - head)
-    {
-      memcpy(outbuf + head, inbuf, len);
-      bufferHead += len;
-      ret = len;
-      newPacket.pos_buffer=head;
-	  lock();
-      mediapackets.push_front(newPacket);
-	  unLock();
-    }
+    back = 0; front = bufferSize;
   }
-  else if (len <= bufferSize - head)
+  else
   {
-    // There is enough space above the Head.
-    memcpy(outbuf + head, inbuf, len);
-    if (head + len == bufferSize)
-      bufferHead = 0;
-    else
-      bufferHead += len;
-
-    newPacket.pos_buffer=head;
-	lock();
-    mediapackets.push_front(newPacket);
-	unLock();
+    front = mediapackets.front().pos_buffer;
+    back = mediapackets.back().pos_buffer + mediapackets.back().length;
+    if (back == bufferSize) back = 0;
+  }
+  unLock();
 
+  if (back <= front)
+  {
+    // The free space (if any) is in one continuous chunk.
+    if (len <= front - back) ret = len; // Is there enough of it?
+  }
+  else if (len <= bufferSize - back)
+  {
+    // There is enough space at the end of the buffer
     ret = len;
   }
-  else if (len < tail)
+  else if (len <= front)
   {
-    bufferMark = head;
-    memcpy(outbuf, inbuf, len);
-    bufferHead = len;
+    // There is enough space at the start of the buffer
+    back = 0;
     ret = len;
-    newPacket.pos_buffer=0;
-	lock();
-    mediapackets.push_front(newPacket);
-	unLock();
   }
-  return ret;
-}
-#endif
-
-#ifndef NEW_DEMUXER
-
-int Stream::drain()
-{
-  int ret = 0;
-  int head = bufferHead;
-  int tail = bufferTail;
-  int mark = bufferMark;
-  int written;
 
-  if (mark == -1 && tail > head) mark = bufferSize;
-
-  if (mark >= 0)
+  if (ret) // Nonzero if we managed to find room for the packet
   {
-    // Drain up to the marker.
-#ifndef WIN32
-    written = draintarget->write(outbuf + tail, (mark - tail));
-#else
-    written=mark-tail;
-    MILLISLEEP(1);
-#endif
-    if (written < 0) return ret;
-    ret += written;
-    if (written == (mark - tail))
-    {
-      bufferMark = -1;
-      bufferTail = tail = 0;
-    }
-    else
-    {
-      bufferTail += written;
-      return ret;
-    }
+    memcpy(outbuf + back, inbuf, len);
+    newPacket.pos_buffer = back;
+    lock();
+    mediapackets.push_back(newPacket);
+    unLock();
   }
-
-  if (tail == head) return ret; // Empty
-#ifndef WIN32
-  written = draintarget->write(outbuf + tail, (head - tail));
-#else
-  written=(head - tail);
-  MILLISLEEP(1);
-#endif
-  if (written < 0) return ret;
-  ret += written;
-  bufferTail = tail + written;
   return ret;
 }
 
-#else
-
-int Stream::drain()
+bool Stream::drain()
 {
-  int ret = 0;
-  int written=1;
-//  draintarget=dt; // this is now set in init, is this ok?
-
-
-
-  if (mediapackets.empty()) {
-    return 0;
-  }
-   // using mediapackets, may be this is slower but it is more flexible
- // while (!mediapackets.empty() && written) {
-
-  int head = bufferHead;
-  int tail = bufferTail;
-  int mark = bufferMark;
-  if (mark == -1 && tail > head) mark = bufferSize;
+  bool ret = false;
   lock();
-  MediaPacket cur_mp=mediapackets.back();
-  unLock();
-  written=0;
-  written=draintarget->DeliverMediaSample(cur_mp,outbuf,&cur_packet_pos);
-
-  ret+=written;
-
-  if (cur_packet_pos==cur_mp.length) {
-    cur_packet_pos=0;
-	lock();
-    mediapackets.pop_back();
-	unLock();
-    if ((((ULONG)tail)+cur_mp.length) < ((ULONG)mark)) {
-      bufferTail=tail+cur_mp.length;
-    } else {
-      bufferTail=0;
-      bufferMark=-1;
-    }
-
+  UINT listlength = mediapackets.size();
+  if (listlength != 0)
+  {
+    draintarget->PrepareMediaSample(mediapackets, cur_packet_pos);
+    unLock();
+    UINT consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos);
+    lock();
+    if (consumed != 0) ret = true;
+    if (consumed > listlength) consumed = listlength;
+    while (consumed--) mediapackets.pop_front();
   }
-
+  unLock();
   return ret;
 }
 
@@ -289,7 +159,7 @@ void Stream::lock()
 {
 #ifndef WIN32
   pthread_mutex_lock(&mutex);
-  logger->log("Player", Log::DEBUG, "LOCKED");
+  //logger->log("Player", Log::DEBUG, "LOCKED");
 
 #else
    WaitForSingleObject(mutex, INFINITE );
@@ -299,11 +169,9 @@ void Stream::lock()
 void Stream::unLock()
 {
 #ifndef WIN32
-  logger->log("Player", Log::DEBUG, "UNLOCKING");
+  //logger->log("Player", Log::DEBUG, "UNLOCKING");
   pthread_mutex_unlock(&mutex);
 #else
    ReleaseMutex(mutex);
 #endif
 }
-
-#endif
diff --git a/stream.h b/stream.h
index 507855b..d963330 100644
--- a/stream.h
+++ b/stream.h
@@ -21,6 +21,10 @@
 #ifndef STREAM_H
 #define STREAM_H
 
+#ifndef WIN32
+#include <pthread.h>
+#endif
+
 #include <stdlib.h>
 #ifndef WIN32
 #include <unistd.h>
@@ -32,8 +36,6 @@
 #include "defines.h"
 #include "draintarget.h"
 
-
-
 class Stream
 {
   public:
@@ -42,11 +44,10 @@ class Stream
     int init(DrainTarget* tdt, int bufsize);
     void shutdown();
     void flush();
-    int put(UCHAR* inbuf, int len);
-    int drain();
+    int put(const UCHAR* inbuf, int len);
+    bool drain();
 
   private:
-#ifdef NEW_DEMUXER
     MediaPacketList mediapackets;
     UINT cur_packet_pos;
 #ifndef WIN32
@@ -56,15 +57,11 @@ class Stream
 #endif
   	void lock();
   	void unLock();
-#endif
 
     DrainTarget* draintarget;
     int initted;
     UCHAR* outbuf;
     int bufferSize;
-    volatile int bufferHead;
-    volatile int bufferTail;
-    volatile int bufferMark;
 };
 
 #endif
diff --git a/vfeed.cc b/vfeed.cc
index 4fd4657..0255b98 100644
--- a/vfeed.cc
+++ b/vfeed.cc
@@ -53,7 +53,7 @@ void VFeed::release()
 
 void VFeed::threadMethod()
 {
-  int vlen;
+  bool vlen;
 
   threadWaitForSignal(); // Don't feed video until audio has started
 
diff --git a/video.h b/video.h
index 660e3e9..026aee2 100644
--- a/video.h
+++ b/video.h
@@ -65,10 +65,6 @@ class Video: public DrainTarget
     virtual ULONG timecodeToFrameNumber(ULLONG timecode)=0;
     virtual ULLONG getCurrentTimestamp()=0;
 
-#ifndef NEW_DEMUXER
-    virtual int write(UCHAR* buffer, ULONG length)=0;
-#endif
-
     virtual void turnVideoOn(){};
     virtual void turnVideoOff(){};
     virtual ULLONG frameNumberToTimecode(ULONG timecode) { return 0; };
diff --git a/videomvp.cc b/videomvp.cc
index 43e84a7..279a134 100644
--- a/videomvp.cc
+++ b/videomvp.cc
@@ -366,25 +366,35 @@ int VideoMVP::test2()
 }
 #endif
 
-
-
-#ifdef NEW_DEMUXER
-
-UINT VideoMVP::DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos)
-{
-  return 0;
+void VideoMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
+{
+  MediaPacketList::const_iterator iter = mplist.begin();
+  deliver_start = iter->pos_buffer + samplepos;
+  mediapacket_len[0] = deliver_length = iter->length;
+  deliver_count = 1;
+  while (++iter != mplist.end() &&
+           iter->pos_buffer == deliver_start + deliver_length)
+  {
+    deliver_length += iter->length;
+    mediapacket_len[deliver_count] = iter->length;
+    ++deliver_count;
+    if (deliver_length >= WRITE_LENGTH ||
+        deliver_count == WRITE_PACKETS) break;
+  }
 }
 
-void VideoMVP::ResetTimeOffsets()
+UINT VideoMVP::DeliverMediaSample(const UCHAR* buffer, UINT* samplepos)
 {
+  int written = ::write(fdVideo, buffer + deliver_start, deliver_length);
+  if (written == (int)deliver_length) { *samplepos = 0; return deliver_count;}
+  if (written <= 0) return 0;
+  // Handle a partial write. Is this possible? Should we bother?
+  UINT i = 0;
+  while ((written -= mediapacket_len[i]) >= 0) i++;
+  *samplepos = mediapacket_len[i] + written;
+  return i;
 }
 
-#else
-
-int VideoMVP::write(UCHAR* buffer, ULONG length)
+void VideoMVP::ResetTimeOffsets()
 {
-  return ::write(fdVideo, buffer, length);
 }
-
-#endif
-
diff --git a/videomvp.h b/videomvp.h
index 3f626d2..b8db9c6 100644
--- a/videomvp.h
+++ b/videomvp.h
@@ -36,6 +36,9 @@
 #include "video.h"
 #include "stb.h"
 
+#define WRITE_LENGTH (32*1024) // Consume up to 32K at a time from Stream
+#define WRITE_PACKETS 16       // But no more than 16 packets
+
 class VideoMVP : public Video
 {
   public:
@@ -68,14 +71,12 @@ class VideoMVP : public Video
     ULONG timecodeToFrameNumber(ULLONG timecode);
     ULLONG getCurrentTimestamp();
 
-#ifdef NEW_DEMUXER
-    //Writing Data to Videodevice
-    virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos);
-    virtual long long SetStartOffset(long long curreftime, bool *rsync) { return 0; };
+    // Writing Data to Videodevice
+    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
+    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT* samplepos);
+    virtual long long SetStartOffset(long long curreftime, bool *rsync)
+    { return 0; };
     virtual void ResetTimeOffsets();
-#else
-    int write(UCHAR* buffer, ULONG length);
-#endif
 
 #ifdef DEV
     int test();
@@ -85,6 +86,9 @@ class VideoMVP : public Video
   private:
     int checkSCART();
     void setLetterboxBorder(char* border);
+
+    UINT deliver_start, deliver_length, deliver_count;
+    UINT mediapacket_len[WRITE_PACKETS];
 };
 
 #endif
diff --git a/videowin.cc b/videowin.cc
index d029886..35ddff6 100644
--- a/videowin.cc
+++ b/videowin.cc
@@ -453,9 +453,24 @@ void VideoWin::CleanupDS()
 
 }
 
+void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
+     UINT samplepos)
+{
+  mediapacket = mplist.front();
+}
+
+UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
+{
+  DeliverMediaPacket(mediapacket, buffer, samplepos);
+  if (*samplepos == mediapacket.length) {
+    *samplepos = 0;
+    return 1;
+  }
+  else return 0;
+}
 
-UINT VideoWin::DeliverMediaSample(MediaPacket packet,
-     UCHAR* buffer,
+UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
+     const UCHAR* buffer,
      UINT *samplepos)
 {
   /*First Check, if we have an audio sample*/
diff --git a/videowin.h b/videowin.h
index 5176d6a..23f558f 100644
--- a/videowin.h
+++ b/videowin.h
@@ -73,7 +73,12 @@ class VideoWin : public Video
     ULLONG getCurrentTimestamp();
 
     //Writing Data to Videodevice
-    virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos);
+    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
+    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos);
+    UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos);
+  private:
+    MediaPacket mediapacket;
+  public:
 
     int getCurrentAudioMediaSample(IMediaSample** ms);
     int DeliverAudioMediaSample();
-- 
2.39.5