forked from len0rd/rockbox
MPEGPlayer: Give the parser a little stronger going over this time so it tolerates odd audio timestamps better.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28965 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
92f602f48f
commit
df6b414515
1 changed files with 53 additions and 42 deletions
|
@ -272,39 +272,40 @@ static bool init_video_info(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_times(struct stream *str)
|
static bool init_times(struct stream *str)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
struct stream tmp_str;
|
struct stream tmp_str;
|
||||||
const ssize_t filesize = disk_buf_filesize();
|
const ssize_t filesize = disk_buf_filesize();
|
||||||
const ssize_t max_probe = MIN(512*1024, filesize);
|
const ssize_t max_probe = MIN(512*1024, filesize);
|
||||||
|
bool found_stream;
|
||||||
|
|
||||||
/* Simply find the first earliest timestamp - this will be the one
|
/* Simply find the first earliest timestamp - this will be the one
|
||||||
* used when streaming anyway */
|
* used when streaming anyway */
|
||||||
DEBUGF("Finding start_pts: 0x%02x\n", str->id);
|
DEBUGF("Finding start_pts: 0x%02x\n", str->id);
|
||||||
|
|
||||||
|
found_stream = false;
|
||||||
|
str->start_pts = INVALID_TIMESTAMP;
|
||||||
|
str->end_pts = INVALID_TIMESTAMP;
|
||||||
|
|
||||||
tmp_str.id = str->id;
|
tmp_str.id = str->id;
|
||||||
tmp_str.hdr.pos = 0;
|
tmp_str.hdr.pos = 0;
|
||||||
tmp_str.hdr.limit = max_probe;
|
tmp_str.hdr.limit = max_probe;
|
||||||
|
|
||||||
str->start_pts = INVALID_TIMESTAMP;
|
/* Probe for many for the start because some stamps could be anoamlous.
|
||||||
|
* Video also can also have things out of order. Just see what it's got.
|
||||||
/* Probe for many for the start because a stamp or two could be anomalous.
|
*/
|
||||||
* Video also can also have things out of order. How many? There isn't any
|
while (1)
|
||||||
* "right" value but just a few seems sufficient to filter some bad cases.
|
|
||||||
* Too many and file loading could take too long. */
|
|
||||||
for (i = 5; i > 0;)
|
|
||||||
{
|
{
|
||||||
switch (parser_get_next_data(&tmp_str, STREAM_PM_RANDOM_ACCESS))
|
switch (parser_get_next_data(&tmp_str, STREAM_PM_RANDOM_ACCESS))
|
||||||
{
|
{
|
||||||
case STREAM_DATA_END:
|
case STREAM_DATA_END:
|
||||||
break;
|
break;
|
||||||
case STREAM_OK:
|
case STREAM_OK:
|
||||||
|
found_stream = true;
|
||||||
if (tmp_str.pkt_flags & PKT_HAS_TS)
|
if (tmp_str.pkt_flags & PKT_HAS_TS)
|
||||||
{
|
{
|
||||||
if (tmp_str.pts < str->start_pts)
|
if (tmp_str.pts < str->start_pts)
|
||||||
str->start_pts = tmp_str.pts;
|
str->start_pts = tmp_str.pts;
|
||||||
i--; /* Decrement timestamp counter */
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -312,6 +313,12 @@ static void init_times(struct stream *str)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found_stream)
|
||||||
|
{
|
||||||
|
DEBUGF(" stream not found:0x%02x\n", str->id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUGF(" start:%u\n", (unsigned)str->start_pts);
|
DEBUGF(" start:%u\n", (unsigned)str->start_pts);
|
||||||
|
|
||||||
/* Use the decoder thread to perform a synchronized search - no
|
/* Use the decoder thread to perform a synchronized search - no
|
||||||
|
@ -320,33 +327,27 @@ static void init_times(struct stream *str)
|
||||||
* precise time at the end of the last frame for the stream. */
|
* precise time at the end of the last frame for the stream. */
|
||||||
DEBUGF("Finding end_pts: 0x%02x\n", str->id);
|
DEBUGF("Finding end_pts: 0x%02x\n", str->id);
|
||||||
|
|
||||||
str->end_pts = INVALID_TIMESTAMP;
|
str_parser.parms.sd.time = MAX_TIMESTAMP;
|
||||||
|
str_parser.parms.sd.sk.pos = filesize - max_probe;
|
||||||
|
str_parser.parms.sd.sk.len = max_probe;
|
||||||
|
str_parser.parms.sd.sk.dir = SSCAN_FORWARD;
|
||||||
|
|
||||||
if (str->start_pts != INVALID_TIMESTAMP)
|
str_send_msg(str, STREAM_RESET, 0);
|
||||||
|
|
||||||
|
if (str_send_msg(str, STREAM_FIND_END_TIME,
|
||||||
|
(intptr_t)&str_parser.parms.sd) == STREAM_PERFECT_MATCH)
|
||||||
{
|
{
|
||||||
str_parser.parms.sd.time = MAX_TIMESTAMP;
|
str->end_pts = str_parser.parms.sd.time;
|
||||||
str_parser.parms.sd.sk.pos = filesize - max_probe;
|
DEBUGF(" end:%u\n", (unsigned)str->end_pts);
|
||||||
str_parser.parms.sd.sk.len = max_probe;
|
|
||||||
str_parser.parms.sd.sk.dir = SSCAN_FORWARD;
|
|
||||||
|
|
||||||
str_send_msg(str, STREAM_RESET, 0);
|
|
||||||
|
|
||||||
if (str_send_msg(str, STREAM_FIND_END_TIME,
|
|
||||||
(intptr_t)&str_parser.parms.sd) == STREAM_PERFECT_MATCH)
|
|
||||||
{
|
|
||||||
str->end_pts = str_parser.parms.sd.time;
|
|
||||||
DEBUGF(" end:%u\n", (unsigned)str->end_pts);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End must be greater than start. If the start PTS is found, the end PTS
|
return true;
|
||||||
* must be valid too. If the start PTS was invalid, then the end will never
|
}
|
||||||
* be scanned above. */
|
|
||||||
if (str->start_pts >= str->end_pts || str->end_pts == INVALID_TIMESTAMP)
|
static bool check_times(const struct stream *str)
|
||||||
{
|
{
|
||||||
str->start_pts = INVALID_TIMESTAMP;
|
return str->start_pts < str->end_pts &&
|
||||||
str->end_pts = INVALID_TIMESTAMP;
|
str->end_pts != INVALID_TIMESTAMP;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the best-fit file offset of a timestamp in the PES where
|
/* Return the best-fit file offset of a timestamp in the PES where
|
||||||
|
@ -1118,10 +1119,7 @@ int parser_init_stream(void)
|
||||||
{
|
{
|
||||||
/* Initalize start_pts and end_pts with the length (in 45kHz units) of
|
/* Initalize start_pts and end_pts with the length (in 45kHz units) of
|
||||||
* the movie. INVALID_TIMESTAMP if the time could not be determined */
|
* the movie. INVALID_TIMESTAMP if the time could not be determined */
|
||||||
init_times(&audio_str);
|
if (!init_times(&video_str) || !check_times(&video_str))
|
||||||
init_times(&video_str);
|
|
||||||
|
|
||||||
if (video_str.start_pts == INVALID_TIMESTAMP)
|
|
||||||
{
|
{
|
||||||
/* Must have video at least */
|
/* Must have video at least */
|
||||||
parser_init_state();
|
parser_init_state();
|
||||||
|
@ -1130,14 +1128,27 @@ int parser_init_stream(void)
|
||||||
|
|
||||||
str_parser.flags |= STREAMF_CAN_SEEK;
|
str_parser.flags |= STREAMF_CAN_SEEK;
|
||||||
|
|
||||||
if (audio_str.start_pts != INVALID_TIMESTAMP)
|
if (init_times(&audio_str))
|
||||||
{
|
{
|
||||||
/* Overall duration is maximum span */
|
|
||||||
str_parser.start_pts = MIN(audio_str.start_pts, video_str.start_pts);
|
|
||||||
str_parser.end_pts = MAX(audio_str.end_pts, video_str.end_pts);
|
|
||||||
|
|
||||||
/* Audio will be part of playback pool */
|
/* Audio will be part of playback pool */
|
||||||
stream_add_stream(&audio_str);
|
stream_add_stream(&audio_str);
|
||||||
|
|
||||||
|
if (check_times(&audio_str))
|
||||||
|
{
|
||||||
|
/* Overall duration is maximum span */
|
||||||
|
str_parser.start_pts = MIN(audio_str.start_pts, video_str.start_pts);
|
||||||
|
str_parser.end_pts = MAX(audio_str.end_pts, video_str.end_pts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bad times on audio - use video times */
|
||||||
|
str_parser.start_pts = video_str.start_pts;
|
||||||
|
str_parser.end_pts = video_str.end_pts;
|
||||||
|
|
||||||
|
/* Questionable: could use bitrate seek and match video to that */
|
||||||
|
audio_str.start_pts = video_str.start_pts;
|
||||||
|
audio_str.end_pts = video_str.end_pts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue