浏览代码

Catch up on video faster

Previously every (internal) update the decoder would advance 0 or 1 frame. Now
it will advance until it catches up. Like before, if it takes too many steps
(5) before catching up, it seeks instead. This should mostly mean seeking
forwards has less latency.

--HG--
branch : minor
Bart van Strien 8 年之前
父节点
当前提交
de945a528b
共有 2 个文件被更改,包括 54 次插入57 次删除
  1. 54 56
      src/modules/video/theora/TheoraVideoStream.cpp
  2. 0 1
      src/modules/video/theora/TheoraVideoStream.h

+ 54 - 56
src/modules/video/theora/TheoraVideoStream.cpp

@@ -40,7 +40,6 @@ TheoraVideoStream::TheoraVideoStream(love::filesystem::File *file)
 	, frameReady(false)
 	, lastFrame(0)
 	, nextFrame(0)
-	, lagCounter(0)
 {
 	if (demuxer.findStream() != OggDemuxer::TYPE_THEORA)
 		throw love::Exception("Invalid video file, video is not theora");
@@ -214,66 +213,65 @@ void TheoraVideoStream::threadedFillBackBuffer(double dt)
 	if (position < lastFrame)
 		seekDecoder(position);
 
-	// If we're at the end of the stream, or if we're displaying the right frame
-	// stop here
-	if (demuxer.isEos() || position < nextFrame)
-		return;
-
-	th_ycbcr_buffer bufferinfo;
-	th_decode_ycbcr_out(decoder, bufferinfo);
-
-	ogg_int64_t granulePosition;
-	do
+	// Until we are at the end of the stream, or we are displaying the right frame
+	unsigned int lagCounter = 0;
+	while (!demuxer.isEos() && position >= nextFrame)
 	{
-		if (demuxer.readPacket(packet))
-			return;
-	} while (th_decode_packetin(decoder, &packet, &granulePosition) != 0);
-	lastFrame = nextFrame;
-	nextFrame = th_granule_time(decoder, granulePosition);
+		// If we can't catch up, seek
+		if (lagCounter++ > 5)
+		{
+			seekDecoder(position);
+			lagCounter = 0;
+		}
 
-	{
-		// Don't swap whilst we're writing to the backbuffer
-		love::thread::Lock l(bufferMutex);
-		frameReady = false;
-	}
+		th_ycbcr_buffer bufferinfo;
+		th_decode_ycbcr_out(decoder, bufferinfo);
 
-	for (int y = 0; y < backBuffer->yh; ++y)
-	{
-		memcpy(backBuffer->yplane+backBuffer->yw*y,
-				bufferinfo[0].data+
-					bufferinfo[0].stride*(y+yPlaneYOffset)+yPlaneXOffset,
-				backBuffer->yw);
-	}
+		ogg_int64_t granulePosition;
+		do
+		{
+			if (demuxer.readPacket(packet))
+				return;
+		} while (th_decode_packetin(decoder, &packet, &granulePosition) != 0);
+		lastFrame = nextFrame;
+		nextFrame = th_granule_time(decoder, granulePosition);
 
-	for (int y = 0; y < backBuffer->ch; ++y)
-	{
-		memcpy(backBuffer->cbplane+backBuffer->cw*y,
-				bufferinfo[1].data+
-					bufferinfo[1].stride*(y+cPlaneYOffset)+cPlaneXOffset,
-				backBuffer->cw);
-	}
-
-	for (int y = 0; y < backBuffer->ch; ++y)
-	{
-		memcpy(backBuffer->crplane+backBuffer->cw*y,
-				bufferinfo[2].data+
-					bufferinfo[2].stride*(y+cPlaneYOffset)+cPlaneXOffset,
-				backBuffer->cw);
-	}
-
-	// Seeking forwards:
-	// If we're still not on the right frame, either we're lagging or we're seeking
-	// After 5 frames, go for a seek. This is not ideal.. but what is
-	if (position > nextFrame)
-	{
-		if (++lagCounter > 5)
-			seekDecoder(position);
+		// Don't swap whilst we're writing to the backbuffer
+		{
+			love::thread::Lock l(bufferMutex);
+			frameReady = false;
+		}
+
+		for (int y = 0; y < backBuffer->yh; ++y)
+		{
+			memcpy(backBuffer->yplane+backBuffer->yw*y,
+					bufferinfo[0].data+
+						bufferinfo[0].stride*(y+yPlaneYOffset)+yPlaneXOffset,
+					backBuffer->yw);
+		}
+
+		for (int y = 0; y < backBuffer->ch; ++y)
+		{
+			memcpy(backBuffer->cbplane+backBuffer->cw*y,
+					bufferinfo[1].data+
+						bufferinfo[1].stride*(y+cPlaneYOffset)+cPlaneXOffset,
+					backBuffer->cw);
+		}
+
+		for (int y = 0; y < backBuffer->ch; ++y)
+		{
+			memcpy(backBuffer->crplane+backBuffer->cw*y,
+					bufferinfo[2].data+
+						bufferinfo[2].stride*(y+cPlaneYOffset)+cPlaneXOffset,
+					backBuffer->cw);
+		}
+
+		// Re-enable swapping
+		{
+			love::thread::Lock l(bufferMutex);
+			frameReady = true;
+		}
 	}
-	else
-		lagCounter = 0;
-
-	love::thread::Lock l(bufferMutex);
-	frameReady = true;
 }
 
 void TheoraVideoStream::fillBackBuffer()

+ 0 - 1
src/modules/video/theora/TheoraVideoStream.h

@@ -83,7 +83,6 @@ private:
 
 	double lastFrame;
 	double nextFrame;
-	unsigned int lagCounter;
 
 	void parseHeader();
 	void seekDecoder(double target);