summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-12-19 08:28:03 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-12-19 08:28:03 +0000
commit31af1a3ac21646c8f07b1b93e497d45a060ee36d (patch)
tree30b7541bd15a3291311c8d1b48b1b6a95d7a1ba5
parentfd01bf3e4cfedf073824b1a98662932796b6cd32 (diff)
downloadrockbox-31af1a3ac21646c8f07b1b93e497d45a060ee36d.tar.gz
rockbox-31af1a3ac21646c8f07b1b93e497d45a060ee36d.zip
MPEGPlayer: Move some code that's probably better situated in the stream manager rather than the parser. Fix visibility checking in video out. Extra message sending for new stream isn't needed; just do full decoder sequence reset when requesting dimensions.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28855 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/mpegplayer/mpeg_parser.c172
-rw-r--r--apps/plugins/mpegplayer/parser.h2
-rw-r--r--apps/plugins/mpegplayer/stream_mgr.c48
-rw-r--r--apps/plugins/mpegplayer/video_out_rockbox.c6
-rw-r--r--apps/plugins/mpegplayer/video_thread.c12
5 files changed, 119 insertions, 121 deletions
diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c
index 1be11a467b..b683efe1c9 100644
--- a/apps/plugins/mpegplayer/mpeg_parser.c
+++ b/apps/plugins/mpegplayer/mpeg_parser.c
@@ -564,84 +564,6 @@ static off_t mpeg_parser_seek_PTS(uint32_t time, unsigned id)
564 return pos; 564 return pos;
565} 565}
566 566
567static bool prepare_image(uint32_t time)
568{
569 struct stream_scan sk;
570 int tries;
571 int result;
572
573 stream_scan_init(&sk);
574
575 if (!str_send_msg(&video_str, STREAM_NEEDS_SYNC, time))
576 {
577 DEBUGF("Image was ready\n");
578 return true; /* Should already have the image */
579 }
580
581#ifdef HAVE_ADJUSTABLE_CPU_FREQ
582 rb->cpu_boost(true); /* No interference with trigger_cpu_boost */
583#endif
584
585 str_send_msg(&video_str, STREAM_RESET, 0);
586
587 sk.pos = parser_can_seek() ?
588 mpeg_parser_seek_PTS(time, video_str.id) : 0;
589 sk.len = sk.pos;
590 sk.dir = SSCAN_REVERSE;
591
592 tries = 1;
593try_again:
594
595 if (mpeg_parser_scan_start_code(&sk, MPEG_START_GOP))
596 {
597 DEBUGF("GOP found at: %ld\n", sk.pos);
598
599 unsigned id = mpeg_parser_scan_pes(&sk);
600
601 if (id != video_str.id && sk.pos > 0)
602 {
603 /* Not part of our stream */
604 DEBUGF(" wrong stream: 0x%02x\n", id);
605 goto try_again;
606 }
607
608 /* This will hit the PES header since it's known to be there */
609 uint32_t pts = mpeg_parser_scan_pts(&sk, id);
610
611 if (pts == INVALID_TIMESTAMP || pts > time)
612 {
613 DEBUGF(" wrong timestamp: %u\n", (unsigned)pts);
614 goto try_again;
615 }
616 }
617
618 str_parser.parms.sd.time = time;
619 str_parser.parms.sd.sk.pos = MAX(sk.pos, 0);
620 str_parser.parms.sd.sk.len = 1024*1024;
621 str_parser.parms.sd.sk.dir = SSCAN_FORWARD;
622
623 DEBUGF("thumb pos:%ld len:%ld\n", str_parser.parms.sd.sk.pos,
624 (long)str_parser.parms.sd.sk.len);
625
626 result = str_send_msg(&video_str, STREAM_SYNC,
627 (intptr_t)&str_parser.parms.sd);
628
629 if (result != STREAM_PERFECT_MATCH)
630 {
631 /* Two tries should be all that is nescessary to find the exact frame
632 * if the first GOP actually started later than the timestamp - the
633 * GOP just prior must then start on or earlier. */
634 if (++tries <= 2)
635 goto try_again;
636 }
637
638#ifdef HAVE_ADJUSTABLE_CPU_FREQ
639 rb->cpu_boost(false);
640#endif
641
642 return result > STREAM_OK;
643}
644
645static void prepare_audio(uint32_t time) 567static void prepare_audio(uint32_t time)
646{ 568{
647 off_t pos; 569 off_t pos;
@@ -1037,41 +959,82 @@ static int parse_elementary(struct stream *str, enum stream_parse_mode type)
1037 return STREAM_OK; 959 return STREAM_OK;
1038} 960}
1039 961
1040intptr_t parser_send_video_msg(long id, intptr_t data) 962bool parser_prepare_image(uint32_t time)
1041{ 963{
1042 intptr_t retval = 0; 964 struct stream_scan sk;
965 int tries;
966 int result;
967
968 stream_scan_init(&sk);
1043 969
1044 if (video_str.thread != 0 && disk_buf.in_file >= 0) 970 if (!str_send_msg(&video_str, STREAM_NEEDS_SYNC, time))
1045 { 971 {
1046 /* Hook certain messages since they involve multiple operations 972 DEBUGF("Image was ready\n");
1047 * behind the scenes */ 973 return true; /* Should already have the image */
1048 switch (id) 974 }
1049 {
1050 case VIDEO_DISPLAY_SHOW:
1051 if (data != 0 && disk_buf_status() == STREAM_STOPPED)
1052 { /* Only prepare image if showing and not playing */
1053 prepare_image(str_parser.last_seek_time);
1054 }
1055 break;
1056 975
1057 case VIDEO_PRINT_FRAME: 976#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1058 if (data) 977 rb->cpu_boost(true); /* No interference with trigger_cpu_boost */
1059 break; 978#endif
1060 case VIDEO_PRINT_THUMBNAIL:
1061 if (disk_buf_status() != STREAM_STOPPED)
1062 break; /* Prepare image if not playing */
1063 979
1064 if (!prepare_image(str_parser.last_seek_time)) 980 str_send_msg(&video_str, STREAM_RESET, 0);
1065 return false; /* Preparation failed */
1066 981
1067 /* Image ready - pass message to video thread */ 982 sk.pos = parser_can_seek() ?
1068 break; 983 mpeg_parser_seek_PTS(time, video_str.id) : 0;
984 sk.len = sk.pos;
985 sk.dir = SSCAN_REVERSE;
986
987 tries = 1;
988try_again:
989
990 if (mpeg_parser_scan_start_code(&sk, MPEG_START_GOP))
991 {
992 DEBUGF("GOP found at: %ld\n", sk.pos);
993
994 unsigned id = mpeg_parser_scan_pes(&sk);
995
996 if (id != video_str.id && sk.pos > 0)
997 {
998 /* Not part of our stream */
999 DEBUGF(" wrong stream: 0x%02x\n", id);
1000 goto try_again;
1001 }
1002
1003 /* This will hit the PES header since it's known to be there */
1004 uint32_t pts = mpeg_parser_scan_pts(&sk, id);
1005
1006 if (pts == INVALID_TIMESTAMP || pts > time)
1007 {
1008 DEBUGF(" wrong timestamp: %u\n", (unsigned)pts);
1009 goto try_again;
1069 } 1010 }
1011 }
1012
1013 str_parser.parms.sd.time = time;
1014 str_parser.parms.sd.sk.pos = MAX(sk.pos, 0);
1015 str_parser.parms.sd.sk.len = 1024*1024;
1016 str_parser.parms.sd.sk.dir = SSCAN_FORWARD;
1070 1017
1071 retval = str_send_msg(&video_str, id, data); 1018 DEBUGF("thumb pos:%ld len:%ld\n", str_parser.parms.sd.sk.pos,
1019 (long)str_parser.parms.sd.sk.len);
1020
1021 result = str_send_msg(&video_str, STREAM_SYNC,
1022 (intptr_t)&str_parser.parms.sd);
1023
1024 if (result != STREAM_PERFECT_MATCH)
1025 {
1026 /* Two tries should be all that is nescessary to find the exact frame
1027 * if the first GOP actually started later than the timestamp - the
1028 * GOP just prior must then start on or earlier. */
1029 if (++tries <= 2)
1030 goto try_again;
1072 } 1031 }
1073 1032
1074 return retval; 1033#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1034 rb->cpu_boost(false);
1035#endif
1036
1037 return result > STREAM_OK;
1075} 1038}
1076 1039
1077/* Seek parser to the specified time and return absolute time. 1040/* Seek parser to the specified time and return absolute time.
@@ -1095,7 +1058,7 @@ void parser_prepare_streaming(void)
1095 DEBUGF("parser_prepare_streaming\n"); 1058 DEBUGF("parser_prepare_streaming\n");
1096 1059
1097 /* Prepare initial video frame */ 1060 /* Prepare initial video frame */
1098 prepare_image(str_parser.last_seek_time); 1061 parser_prepare_image(str_parser.last_seek_time);
1099 1062
1100 /* Sync audio stream */ 1063 /* Sync audio stream */
1101 if (audio_str.start_pts != INVALID_TIMESTAMP) 1064 if (audio_str.start_pts != INVALID_TIMESTAMP)
@@ -1215,7 +1178,6 @@ int parser_init_stream(void)
1215 1178
1216void parser_close_stream(void) 1179void parser_close_stream(void)
1217{ 1180{
1218 str_send_msg(&video_str, STREAM_CLOSE, 0);
1219 stream_remove_streams(); 1181 stream_remove_streams();
1220 parser_init_state(); 1182 parser_init_state();
1221} 1183}
diff --git a/apps/plugins/mpegplayer/parser.h b/apps/plugins/mpegplayer/parser.h
index 4c58d2b6ec..ba2181e98b 100644
--- a/apps/plugins/mpegplayer/parser.h
+++ b/apps/plugins/mpegplayer/parser.h
@@ -86,7 +86,7 @@ off_t mpeg_stream_stream_seek_PTS(uint32_t time, int id);
86/* General parsing */ 86/* General parsing */
87bool parser_init(void); 87bool parser_init(void);
88void str_initialize(struct stream *str, off_t pos); 88void str_initialize(struct stream *str, off_t pos);
89intptr_t parser_send_video_msg(long id, intptr_t data); 89bool parser_prepare_image(uint32_t time);
90bool parser_get_video_size(struct vo_ext *sz); 90bool parser_get_video_size(struct vo_ext *sz);
91int parser_init_stream(void); 91int parser_init_stream(void);
92void parser_close_stream(void); 92void parser_close_stream(void);
diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c
index b88c6d70c7..67ec16cbb6 100644
--- a/apps/plugins/mpegplayer/stream_mgr.c
+++ b/apps/plugins/mpegplayer/stream_mgr.c
@@ -668,13 +668,51 @@ void stream_clear_notify(struct stream *str, int for_msg)
668 } 668 }
669} 669}
670 670
671/* Special handling for certain messages since they involve multiple
672 * operations behind the scenes */
673static intptr_t send_video_msg(long id, intptr_t data)
674{
675 intptr_t retval = 0;
676
677 if (video_str.thread != 0 && disk_buf.in_file >= 0)
678 {
679
680 switch (id)
681 {
682 case VIDEO_DISPLAY_SHOW:
683 if (data != 0 && disk_buf_status() == STREAM_STOPPED)
684 { /* Only prepare image if showing and not playing */
685 parser_prepare_image(str_parser.last_seek_time);
686 }
687 break;
688
689 case VIDEO_PRINT_FRAME:
690 if (data)
691 break;
692 case VIDEO_PRINT_THUMBNAIL:
693 if (disk_buf_status() != STREAM_STOPPED)
694 break; /* Prepare image if not playing */
695
696 if (!parser_prepare_image(str_parser.last_seek_time))
697 return false; /* Preparation failed */
698
699 /* Image ready - pass message to video thread */
700 break;
701 }
702
703 retval = str_send_msg(&video_str, id, data);
704 }
705
706 return retval;
707}
708
671/* Show/hide the video output */ 709/* Show/hide the video output */
672bool stream_show_vo(bool show) 710bool stream_show_vo(bool show)
673{ 711{
674 bool vis; 712 bool vis;
675 stream_mgr_lock(); 713 stream_mgr_lock();
676 714
677 vis = parser_send_video_msg(VIDEO_DISPLAY_SHOW, show); 715 vis = send_video_msg(VIDEO_DISPLAY_SHOW, show);
678#ifndef HAVE_LCD_COLOR 716#ifndef HAVE_LCD_COLOR
679 grey_show(show); 717 grey_show(show);
680#endif 718#endif
@@ -688,7 +726,7 @@ bool stream_vo_is_visible(void)
688{ 726{
689 bool vis; 727 bool vis;
690 stream_mgr_lock(); 728 stream_mgr_lock();
691 vis = parser_send_video_msg(VIDEO_DISPLAY_IS_VISIBLE, 0); 729 vis = send_video_msg(VIDEO_DISPLAY_IS_VISIBLE, 0);
692 stream_mgr_unlock(); 730 stream_mgr_unlock();
693 return vis; 731 return vis;
694} 732}
@@ -721,7 +759,7 @@ void stream_vo_set_clip(const struct vo_rect *rc)
721 rc = &stream_mgr.parms.rc; 759 rc = &stream_mgr.parms.rc;
722 } 760 }
723 761
724 parser_send_video_msg(VIDEO_SET_CLIP_RECT, (intptr_t)rc); 762 send_video_msg(VIDEO_SET_CLIP_RECT, (intptr_t)rc);
725 763
726 stream_mgr_unlock(); 764 stream_mgr_unlock();
727} 765}
@@ -750,7 +788,7 @@ bool stream_display_thumb(const struct vo_rect *rc)
750 stream_mgr_lock(); 788 stream_mgr_lock();
751 789
752 stream_mgr.parms.rc = *rc; 790 stream_mgr.parms.rc = *rc;
753 retval = parser_send_video_msg(VIDEO_PRINT_THUMBNAIL, 791 retval = send_video_msg(VIDEO_PRINT_THUMBNAIL,
754 (intptr_t)&stream_mgr.parms.rc); 792 (intptr_t)&stream_mgr.parms.rc);
755 793
756 stream_mgr_unlock(); 794 stream_mgr_unlock();
@@ -763,7 +801,7 @@ bool stream_draw_frame(bool no_prepare)
763 bool retval; 801 bool retval;
764 stream_mgr_lock(); 802 stream_mgr_lock();
765 803
766 retval = parser_send_video_msg(VIDEO_PRINT_FRAME, no_prepare); 804 retval = send_video_msg(VIDEO_PRINT_FRAME, no_prepare);
767 805
768 stream_mgr_unlock(); 806 stream_mgr_unlock();
769 807
diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c
index cf47982ab7..fe3deafd01 100644
--- a/apps/plugins/mpegplayer/video_out_rockbox.c
+++ b/apps/plugins/mpegplayer/video_out_rockbox.c
@@ -116,9 +116,11 @@ static inline void yuv_blit(uint8_t * const * buf, int src_x, int src_y,
116 116
117void vo_draw_frame(uint8_t * const * buf) 117void vo_draw_frame(uint8_t * const * buf)
118{ 118{
119 if (vo.flags == 0) 119 if ((vo.flags & (VO_NON_NULL_RECT | VO_VISIBLE)) !=
120 (VO_NON_NULL_RECT | VO_VISIBLE))
120 { 121 {
121 /* Frame is hidden - copout */ 122 /* Frame is hidden - either by being set invisible or is clipped
123 * away - copout */
122 DEBUGF("vo hidden\n"); 124 DEBUGF("vo hidden\n");
123 return; 125 return;
124 } 126 }
diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c
index 4ccdc8b844..69d94f8ba0 100644
--- a/apps/plugins/mpegplayer/video_thread.c
+++ b/apps/plugins/mpegplayer/video_thread.c
@@ -124,7 +124,8 @@ static int video_str_scan(struct video_thread_data *td,
124 tmp_str.hdr.pos = sd->sk.pos; 124 tmp_str.hdr.pos = sd->sk.pos;
125 tmp_str.hdr.limit = sd->sk.pos + sd->sk.len; 125 tmp_str.hdr.limit = sd->sk.pos + sd->sk.len;
126 126
127 mpeg2_reset(td->mpeg2dec, false); 127 /* Fully reset if obtaining size for a new stream */
128 mpeg2_reset(td->mpeg2dec, td->ev.id == VIDEO_GET_SIZE);
128 mpeg2_skip(td->mpeg2dec, 1); 129 mpeg2_skip(td->mpeg2dec, 1);
129 130
130 while (1) 131 while (1)
@@ -503,12 +504,6 @@ static void video_thread_msg(struct video_thread_data *td)
503 reply = true; 504 reply = true;
504 break; 505 break;
505 506
506 case STREAM_CLOSE:
507 vo_cleanup();
508 mpeg2_close(td->mpeg2dec);
509 reply = true;
510 break;
511
512 case VIDEO_DISPLAY_IS_VISIBLE: 507 case VIDEO_DISPLAY_IS_VISIBLE:
513 reply = vo_is_visible(); 508 reply = vo_is_visible();
514 break; 509 break;
@@ -605,8 +600,9 @@ static void video_thread_msg(struct video_thread_data *td)
605 case VIDEO_GET_SIZE: 600 case VIDEO_GET_SIZE:
606 { 601 {
607 if (td->state != TSTATE_INIT) 602 if (td->state != TSTATE_INIT)
608 break; 603 break; /* Can only use after a reset was issued */
609 604
605 /* This will reset the decoder in full for this particular event */
610 if (init_sequence(td)) 606 if (init_sequence(td))
611 { 607 {
612 reply = true; 608 reply = true;