diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-01-04 20:28:00 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-01-04 20:28:00 +0000 |
commit | df6b41451587915697f3cf723202b7ca4d57a4e1 (patch) | |
tree | b6b7b0024dcb1157c5c8726650897926d8306b4d /apps/plugins/mpegplayer | |
parent | 92f602f48f43843a61529ad83c2a95e94ec93627 (diff) | |
download | rockbox-df6b41451587915697f3cf723202b7ca4d57a4e1.tar.gz rockbox-df6b41451587915697f3cf723202b7ca4d57a4e1.zip |
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
Diffstat (limited to 'apps/plugins/mpegplayer')
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_parser.c | 95 |
1 files changed, 53 insertions, 42 deletions
diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c index 7c7b0c30ac..771d25c703 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) | |||
272 | return false; | 272 | return false; |
273 | } | 273 | } |
274 | 274 | ||
275 | static void init_times(struct stream *str) | 275 | static bool init_times(struct stream *str) |
276 | { | 276 | { |
277 | int i; | ||
278 | struct stream tmp_str; | 277 | struct stream tmp_str; |
279 | const ssize_t filesize = disk_buf_filesize(); | 278 | const ssize_t filesize = disk_buf_filesize(); |
280 | const ssize_t max_probe = MIN(512*1024, filesize); | 279 | const ssize_t max_probe = MIN(512*1024, filesize); |
280 | bool found_stream; | ||
281 | 281 | ||
282 | /* Simply find the first earliest timestamp - this will be the one | 282 | /* Simply find the first earliest timestamp - this will be the one |
283 | * used when streaming anyway */ | 283 | * used when streaming anyway */ |
284 | DEBUGF("Finding start_pts: 0x%02x\n", str->id); | 284 | DEBUGF("Finding start_pts: 0x%02x\n", str->id); |
285 | 285 | ||
286 | found_stream = false; | ||
287 | str->start_pts = INVALID_TIMESTAMP; | ||
288 | str->end_pts = INVALID_TIMESTAMP; | ||
289 | |||
286 | tmp_str.id = str->id; | 290 | tmp_str.id = str->id; |
287 | tmp_str.hdr.pos = 0; | 291 | tmp_str.hdr.pos = 0; |
288 | tmp_str.hdr.limit = max_probe; | 292 | tmp_str.hdr.limit = max_probe; |
289 | 293 | ||
290 | str->start_pts = INVALID_TIMESTAMP; | 294 | /* Probe for many for the start because some stamps could be anoamlous. |
291 | 295 | * Video also can also have things out of order. Just see what it's got. | |
292 | /* Probe for many for the start because a stamp or two could be anomalous. | 296 | */ |
293 | * Video also can also have things out of order. How many? There isn't any | 297 | while (1) |
294 | * "right" value but just a few seems sufficient to filter some bad cases. | ||
295 | * Too many and file loading could take too long. */ | ||
296 | for (i = 5; i > 0;) | ||
297 | { | 298 | { |
298 | switch (parser_get_next_data(&tmp_str, STREAM_PM_RANDOM_ACCESS)) | 299 | switch (parser_get_next_data(&tmp_str, STREAM_PM_RANDOM_ACCESS)) |
299 | { | 300 | { |
300 | case STREAM_DATA_END: | 301 | case STREAM_DATA_END: |
301 | break; | 302 | break; |
302 | case STREAM_OK: | 303 | case STREAM_OK: |
304 | found_stream = true; | ||
303 | if (tmp_str.pkt_flags & PKT_HAS_TS) | 305 | if (tmp_str.pkt_flags & PKT_HAS_TS) |
304 | { | 306 | { |
305 | if (tmp_str.pts < str->start_pts) | 307 | if (tmp_str.pts < str->start_pts) |
306 | str->start_pts = tmp_str.pts; | 308 | str->start_pts = tmp_str.pts; |
307 | i--; /* Decrement timestamp counter */ | ||
308 | } | 309 | } |
309 | continue; | 310 | continue; |
310 | } | 311 | } |
@@ -312,6 +313,12 @@ static void init_times(struct stream *str) | |||
312 | break; | 313 | break; |
313 | } | 314 | } |
314 | 315 | ||
316 | if (!found_stream) | ||
317 | { | ||
318 | DEBUGF(" stream not found:0x%02x\n", str->id); | ||
319 | return false; | ||
320 | } | ||
321 | |||
315 | DEBUGF(" start:%u\n", (unsigned)str->start_pts); | 322 | DEBUGF(" start:%u\n", (unsigned)str->start_pts); |
316 | 323 | ||
317 | /* Use the decoder thread to perform a synchronized search - no | 324 | /* Use the decoder thread to perform a synchronized search - no |
@@ -320,33 +327,27 @@ static void init_times(struct stream *str) | |||
320 | * precise time at the end of the last frame for the stream. */ | 327 | * precise time at the end of the last frame for the stream. */ |
321 | DEBUGF("Finding end_pts: 0x%02x\n", str->id); | 328 | DEBUGF("Finding end_pts: 0x%02x\n", str->id); |
322 | 329 | ||
323 | str->end_pts = INVALID_TIMESTAMP; | 330 | str_parser.parms.sd.time = MAX_TIMESTAMP; |
324 | 331 | str_parser.parms.sd.sk.pos = filesize - max_probe; | |
325 | if (str->start_pts != INVALID_TIMESTAMP) | 332 | str_parser.parms.sd.sk.len = max_probe; |
326 | { | 333 | str_parser.parms.sd.sk.dir = SSCAN_FORWARD; |
327 | str_parser.parms.sd.time = MAX_TIMESTAMP; | ||
328 | str_parser.parms.sd.sk.pos = filesize - max_probe; | ||
329 | str_parser.parms.sd.sk.len = max_probe; | ||
330 | str_parser.parms.sd.sk.dir = SSCAN_FORWARD; | ||
331 | 334 | ||
332 | str_send_msg(str, STREAM_RESET, 0); | 335 | str_send_msg(str, STREAM_RESET, 0); |
333 | 336 | ||
334 | if (str_send_msg(str, STREAM_FIND_END_TIME, | 337 | if (str_send_msg(str, STREAM_FIND_END_TIME, |
335 | (intptr_t)&str_parser.parms.sd) == STREAM_PERFECT_MATCH) | 338 | (intptr_t)&str_parser.parms.sd) == STREAM_PERFECT_MATCH) |
336 | { | ||
337 | str->end_pts = str_parser.parms.sd.time; | ||
338 | DEBUGF(" end:%u\n", (unsigned)str->end_pts); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | /* End must be greater than start. If the start PTS is found, the end PTS | ||
343 | * must be valid too. If the start PTS was invalid, then the end will never | ||
344 | * be scanned above. */ | ||
345 | if (str->start_pts >= str->end_pts || str->end_pts == INVALID_TIMESTAMP) | ||
346 | { | 339 | { |
347 | str->start_pts = INVALID_TIMESTAMP; | 340 | str->end_pts = str_parser.parms.sd.time; |
348 | str->end_pts = INVALID_TIMESTAMP; | 341 | DEBUGF(" end:%u\n", (unsigned)str->end_pts); |
349 | } | 342 | } |
343 | |||
344 | return true; | ||
345 | } | ||
346 | |||
347 | static bool check_times(const struct stream *str) | ||
348 | { | ||
349 | return str->start_pts < str->end_pts && | ||
350 | str->end_pts != INVALID_TIMESTAMP; | ||
350 | } | 351 | } |
351 | 352 | ||
352 | /* Return the best-fit file offset of a timestamp in the PES where | 353 | /* Return the best-fit file offset of a timestamp in the PES where |
@@ -1118,10 +1119,7 @@ int parser_init_stream(void) | |||
1118 | { | 1119 | { |
1119 | /* Initalize start_pts and end_pts with the length (in 45kHz units) of | 1120 | /* Initalize start_pts and end_pts with the length (in 45kHz units) of |
1120 | * the movie. INVALID_TIMESTAMP if the time could not be determined */ | 1121 | * the movie. INVALID_TIMESTAMP if the time could not be determined */ |
1121 | init_times(&audio_str); | 1122 | if (!init_times(&video_str) || !check_times(&video_str)) |
1122 | init_times(&video_str); | ||
1123 | |||
1124 | if (video_str.start_pts == INVALID_TIMESTAMP) | ||
1125 | { | 1123 | { |
1126 | /* Must have video at least */ | 1124 | /* Must have video at least */ |
1127 | parser_init_state(); | 1125 | parser_init_state(); |
@@ -1130,14 +1128,27 @@ int parser_init_stream(void) | |||
1130 | 1128 | ||
1131 | str_parser.flags |= STREAMF_CAN_SEEK; | 1129 | str_parser.flags |= STREAMF_CAN_SEEK; |
1132 | 1130 | ||
1133 | if (audio_str.start_pts != INVALID_TIMESTAMP) | 1131 | if (init_times(&audio_str)) |
1134 | { | 1132 | { |
1135 | /* Overall duration is maximum span */ | ||
1136 | str_parser.start_pts = MIN(audio_str.start_pts, video_str.start_pts); | ||
1137 | str_parser.end_pts = MAX(audio_str.end_pts, video_str.end_pts); | ||
1138 | |||
1139 | /* Audio will be part of playback pool */ | 1133 | /* Audio will be part of playback pool */ |
1140 | stream_add_stream(&audio_str); | 1134 | stream_add_stream(&audio_str); |
1135 | |||
1136 | if (check_times(&audio_str)) | ||
1137 | { | ||
1138 | /* Overall duration is maximum span */ | ||
1139 | str_parser.start_pts = MIN(audio_str.start_pts, video_str.start_pts); | ||
1140 | str_parser.end_pts = MAX(audio_str.end_pts, video_str.end_pts); | ||
1141 | } | ||
1142 | else | ||
1143 | { | ||
1144 | /* Bad times on audio - use video times */ | ||
1145 | str_parser.start_pts = video_str.start_pts; | ||
1146 | str_parser.end_pts = video_str.end_pts; | ||
1147 | |||
1148 | /* Questionable: could use bitrate seek and match video to that */ | ||
1149 | audio_str.start_pts = video_str.start_pts; | ||
1150 | audio_str.end_pts = video_str.end_pts; | ||
1151 | } | ||
1141 | } | 1152 | } |
1142 | else | 1153 | else |
1143 | { | 1154 | { |