mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
Improved seeking support, especially for short video files
Support inter-page seeking, in case there are multiple packets per page. Also support seeking in single-page files.
This commit is contained in:
@@ -10,6 +10,7 @@ Released: N/A
|
|||||||
* Fixed BezierCurves to error instead of hanging in some situations.
|
* Fixed BezierCurves to error instead of hanging in some situations.
|
||||||
|
|
||||||
* Improved command line argument handling.
|
* Improved command line argument handling.
|
||||||
|
* Improved seeking support, especially for short video files.
|
||||||
|
|
||||||
* Updated the default error handler to allow copying the error to the clipboard when the user decides to do so.
|
* Updated the default error handler to allow copying the error to the clipboard when the user decides to do so.
|
||||||
* Updated love.filesystem.setRequirePath to support multiple template '?' characters in each path.
|
* Updated love.filesystem.setRequirePath to support multiple template '?' characters in each path.
|
||||||
|
|||||||
@@ -270,7 +270,10 @@ void VideoStream::rewind()
|
|||||||
|
|
||||||
void VideoStream::seekDecoder(double target)
|
void VideoStream::seekDecoder(double target)
|
||||||
{
|
{
|
||||||
if (target < 0.01)
|
const double rewindThreshold = 0.01;
|
||||||
|
const double seekThreshold = 0.0001;
|
||||||
|
|
||||||
|
if (target < rewindThreshold)
|
||||||
{
|
{
|
||||||
rewind();
|
rewind();
|
||||||
return;
|
return;
|
||||||
@@ -279,7 +282,7 @@ void VideoStream::seekDecoder(double target)
|
|||||||
double low = 0;
|
double low = 0;
|
||||||
double high = file->getSize();
|
double high = file->getSize();
|
||||||
|
|
||||||
while (high-low > 0.0001)
|
while (high-low > rewindThreshold)
|
||||||
{
|
{
|
||||||
// Determine our next binary search position
|
// Determine our next binary search position
|
||||||
double pos = (high+low)/2;
|
double pos = (high+low)/2;
|
||||||
@@ -289,23 +292,57 @@ void VideoStream::seekDecoder(double target)
|
|||||||
ogg_sync_reset(&sync);
|
ogg_sync_reset(&sync);
|
||||||
ogg_sync_pageseek(&sync, &page);
|
ogg_sync_pageseek(&sync, &page);
|
||||||
|
|
||||||
// Read a packet
|
// Read a page
|
||||||
readPacket(false);
|
readPacket(false);
|
||||||
if (eos)
|
if (eos)
|
||||||
return;
|
{
|
||||||
|
// EOS, so we're definitely past our target (or the target is past
|
||||||
// Determine if this is the right place
|
// the end)
|
||||||
double curTime = th_granule_time(decoder, packet.granulepos);
|
|
||||||
double nextTime = th_granule_time(decoder, packet.granulepos+1);
|
|
||||||
|
|
||||||
if (curTime == -1)
|
|
||||||
continue; // Invalid granule position (magic?)
|
|
||||||
else if (curTime <= target && nextTime > target)
|
|
||||||
break; // the current frame should be displaying right now
|
|
||||||
else if (curTime > target)
|
|
||||||
high = pos;
|
high = pos;
|
||||||
else
|
eos = false;
|
||||||
|
|
||||||
|
// And a workaround for single-page files:
|
||||||
|
if (high < rewindThreshold)
|
||||||
|
rewind();
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now search all packets in this page
|
||||||
|
int result = -1;
|
||||||
|
for (int i = 0; i < ogg_page_packets(&page); ++i)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
readPacket(true);
|
||||||
|
|
||||||
|
// Determine if this is the right place
|
||||||
|
double curTime = th_granule_time(decoder, packet.granulepos);
|
||||||
|
double nextTime = th_granule_time(decoder, packet.granulepos+1);
|
||||||
|
|
||||||
|
if (curTime == -1)
|
||||||
|
continue; // Invalid granule position (magic?)
|
||||||
|
else if (curTime <= target && nextTime > target)
|
||||||
|
{
|
||||||
|
// the current frame should be displaying right now
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (curTime > target)
|
||||||
|
{
|
||||||
|
// No need to check the other packets, they're all past
|
||||||
|
// this one
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sign of result determines the direction
|
||||||
|
if (result == 0)
|
||||||
|
break;
|
||||||
|
else if (result < 0)
|
||||||
low = pos;
|
low = pos;
|
||||||
|
else
|
||||||
|
high = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now update theora and our decoder on this new position of ours
|
// Now update theora and our decoder on this new position of ours
|
||||||
|
|||||||
Reference in New Issue
Block a user