summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-01-04 20:28:00 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-01-04 20:28:00 +0000
commitdf6b41451587915697f3cf723202b7ca4d57a4e1 (patch)
treeb6b7b0024dcb1157c5c8726650897926d8306b4d
parent92f602f48f43843a61529ad83c2a95e94ec93627 (diff)
downloadrockbox-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
-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 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
275static void init_times(struct stream *str) 275static 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
347static 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 {