summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/mpeg_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpegplayer/mpeg_parser.c')
-rw-r--r--apps/plugins/mpegplayer/mpeg_parser.c95
1 files changed, 53 insertions, 42 deletions
diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c
index 7c7b0c3..771d25c 100644
--- a/apps/plugins/mpegplayer/mpeg_parser.c
+++ b/apps/plugins/mpegplayer/mpeg_parser.c
@@ -272,39 +272,40 @@ static bool init_video_info(void)
return false;
}
-static void init_times(struct stream *str)
+static bool init_times(struct stream *str)
{
- int i;
struct stream tmp_str;
const ssize_t filesize = disk_buf_filesize();
const ssize_t max_probe = MIN(512*1024, filesize);
+ bool found_stream;
/* Simply find the first earliest timestamp - this will be the one
* used when streaming anyway */
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.hdr.pos = 0;
tmp_str.hdr.limit = max_probe;
- str->start_pts = INVALID_TIMESTAMP;
-
- /* 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
- * "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;)
+ /* 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.
+ */
+ while (1)
{
switch (parser_get_next_data(&tmp_str, STREAM_PM_RANDOM_ACCESS))
{
case STREAM_DATA_END:
break;
case STREAM_OK:
+ found_stream = true;
if (tmp_str.pkt_flags & PKT_HAS_TS)
{
if (tmp_str.pts < str->start_pts)
str->start_pts = tmp_str.pts;
- i--; /* Decrement timestamp counter */
}
continue;
}
@@ -312,6 +313,12 @@ static void init_times(struct stream *str)
break;
}
+ if (!found_stream)
+ {
+ DEBUGF(" stream not found:0x%02x\n", str->id);
+ return false;
+ }
+
DEBUGF(" start:%u\n", (unsigned)str->start_pts);
/* 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. */
DEBUGF("Finding end_pts: 0x%02x\n", str->id);
- str->end_pts = INVALID_TIMESTAMP;
-
- if (str->start_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;
+ 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;
- str_send_msg(str, STREAM_RESET, 0);
+ 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
- * 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)
+ if (str_send_msg(str, STREAM_FIND_END_TIME,
+ (intptr_t)&str_parser.parms.sd) == STREAM_PERFECT_MATCH)
{
- str->start_pts = INVALID_TIMESTAMP;
- str->end_pts = INVALID_TIMESTAMP;
+ str->end_pts = str_parser.parms.sd.time;
+ DEBUGF(" end:%u\n", (unsigned)str->end_pts);
}
+
+ return true;
+}
+
+static bool check_times(const struct stream *str)
+{
+ return str->start_pts < str->end_pts &&
+ str->end_pts != INVALID_TIMESTAMP;
}
/* 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
* the movie. INVALID_TIMESTAMP if the time could not be determined */
- init_times(&audio_str);
- init_times(&video_str);
-
- if (video_str.start_pts == INVALID_TIMESTAMP)
+ if (!init_times(&video_str) || !check_times(&video_str))
{
/* Must have video at least */
parser_init_state();
@@ -1130,14 +1128,27 @@ int parser_init_stream(void)
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 */
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
{