From 47d2896468f451170ed42549dfdc7124a587605e Mon Sep 17 00:00:00 2001
From: Johns <johns98@gmx.net>
Date: Sat, 10 Mar 2012 17:05:41 +0100
Subject: Better Poll(), flush video buffers after replay.

---
 softhddev.c | 64 +++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 21 deletions(-)

diff --git a/softhddev.c b/softhddev.c
index db9c4c9..c99334a 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -1135,6 +1135,7 @@ static int VideoPacketRead;		///< read pointer
 static atomic_t VideoPacketsFilled;	///< how many of the buffer is used
 
 static volatile char VideoClearBuffers;	///< clear video buffers
+static volatile char VideoClearClose;	///< clear video buffers upto close
 static volatile char SkipVideo;		///< skip video
 static volatile char VideoTrickSpeed;	///< current trick speed
 static volatile char VideoTrickCounter;	///< current trick speed counter
@@ -1358,22 +1359,23 @@ int VideoDecode(void)
     if (!filled) {
 	return -1;
     }
-#if 0
-    int f;
-
-    // FIXME: flush buffers, if close is in the queue
-    for (f = 0; f < filled; ++f) {
-	avpkt = &VideoPacketRb[(VideoPacketRead + f) % VIDEO_PACKET_MAX];
-	if ((int)(size_t) avpkt->priv == CODEC_ID_NONE) {
-	    printf("video: close\n");
-	    if (f) {
-		atomic_sub(f, &VideoPacketsFilled);
-		VideoPacketRead = (VideoPacketRead + f) % VIDEO_PACKET_MAX;
+    if (VideoClearClose) {
+	int f;
+
+	// flush buffers, if close is in the queue
+	for (f = 0; f < filled; ++f) {
+	    avpkt = &VideoPacketRb[(VideoPacketRead + f) % VIDEO_PACKET_MAX];
+	    if ((int)(size_t) avpkt->priv == CODEC_ID_NONE) {
+		if (f) {
+		    Debug(3, "video: cleared upto close\n");
+		    atomic_sub(f, &VideoPacketsFilled);
+		    VideoPacketRead = (VideoPacketRead + f) % VIDEO_PACKET_MAX;
+		    VideoClearClose = 0;
+		}
+		break;
 	    }
-	    break;
 	}
     }
-#endif
     avpkt = &VideoPacketRb[VideoPacketRead];
 
     //
@@ -1619,6 +1621,10 @@ int PlayVideo(const uint8_t * data, int size)
 	Error(_("[softhddev] invalid PES video packet\n"));
 	return size;
     }
+    // 0xBE, filler, padding stream
+    if (data[3] == PES_PADDING_STREAM) {	// from DVD plugin
+	return size;
+    }
     n = data[8];			// header size
 
     if (size < 9 + n + 4) {		// wrong size
@@ -1861,9 +1867,11 @@ void Clear(void)
     //NewAudioStream = 1;
     // FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers
 
+    // wait for empty buffers
     for (i = 0; VideoClearBuffers && i < 20; ++i) {
 	usleep(1 * 1000);
     }
+    Debug(3, "[softhddev]%s: buffers %d\n", __FUNCTION__, VideoGetBuffers());
 }
 
 /**
@@ -1991,20 +1999,34 @@ void StillPicture(const uint8_t * data, int size)
 /**
 **	Poll if device is ready.  Called by replay.
 **
+**	This function is useless, the return value is ignored and
+**	all buffers are overrun by vdr.
+**
+**	The dvd plugin is using this correct.
+**
 **	@param timeout	timeout to become ready in ms
 */
 int Poll(int timeout)
 {
-    // buffers are too full
-    if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX * 2 / 3
-	|| AudioFreeBytes() < AUDIO_MIN_BUFFER_FREE * 2) {
-	if (timeout) {			// let display thread work
-	    usleep(timeout * 1000);
+    // poll is only called during replay, flush buffers after replay
+    VideoClearClose = 1;
+    for (;;) {
+	int empty;
+	int t;
+
+	// buffers are too full
+	empty = atomic_read(&VideoPacketsFilled) < VIDEO_PACKET_MAX * 1 / 4
+	    || AudioUsedBytes() < AUDIO_MIN_BUFFER_FREE * 2;
+	if (empty || !timeout) {
+	    return empty;
 	}
-	return atomic_read(&VideoPacketsFilled) < VIDEO_PACKET_MAX * 2 / 3
-	    && AudioFreeBytes() > AUDIO_MIN_BUFFER_FREE;
+	t = 15;
+	if (timeout < t) {
+	    t = timeout;
+	}
+	usleep(t * 1000);		// let display thread work
+	timeout -= t;
     }
-    return 1;
 }
 
 /**
-- 
cgit v1.2.3