diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2010-12-19 08:28:03 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2010-12-19 08:28:03 +0000 |
commit | 31af1a3ac21646c8f07b1b93e497d45a060ee36d (patch) | |
tree | 30b7541bd15a3291311c8d1b48b1b6a95d7a1ba5 /apps/plugins | |
parent | fd01bf3e4cfedf073824b1a98662932796b6cd32 (diff) | |
download | rockbox-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
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_parser.c | 172 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/parser.h | 2 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/stream_mgr.c | 48 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/video_out_rockbox.c | 6 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/video_thread.c | 12 |
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 | ||
567 | static 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; | ||
593 | try_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 | |||
645 | static void prepare_audio(uint32_t time) | 567 | static 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 | ||
1040 | intptr_t parser_send_video_msg(long id, intptr_t data) | 962 | bool 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; | ||
988 | try_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 | ||
1216 | void parser_close_stream(void) | 1179 | void 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 */ |
87 | bool parser_init(void); | 87 | bool parser_init(void); |
88 | void str_initialize(struct stream *str, off_t pos); | 88 | void str_initialize(struct stream *str, off_t pos); |
89 | intptr_t parser_send_video_msg(long id, intptr_t data); | 89 | bool parser_prepare_image(uint32_t time); |
90 | bool parser_get_video_size(struct vo_ext *sz); | 90 | bool parser_get_video_size(struct vo_ext *sz); |
91 | int parser_init_stream(void); | 91 | int parser_init_stream(void); |
92 | void parser_close_stream(void); | 92 | void 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 */ | ||
673 | static 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 */ |
672 | bool stream_show_vo(bool show) | 710 | bool 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 | ||
117 | void vo_draw_frame(uint8_t * const * buf) | 117 | void 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; |