diff options
author | Dave Chapman <dave@dchapman.com> | 2006-08-20 23:12:56 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-08-20 23:12:56 +0000 |
commit | c8e69dfb71d936b4bc5e18f6246ac126c629f772 (patch) | |
tree | d43563a0c30011d3ec7af1e13e1892bdfff60a46 /apps/plugins/mpegplayer | |
parent | 18cfe431d7556f8cd7047018febe191073c26a1f (diff) | |
download | rockbox-c8e69dfb71d936b4bc5e18f6246ac126c629f772.tar.gz rockbox-c8e69dfb71d936b4bc5e18f6246ac126c629f772.zip |
Move FPS display out of video_out_rockbox.c and into mpegplayer.c. Also add frame-rate limiting and frame-skipping (skipping display only, not decoding) to try and achieve real-time playback. Frame-rate limiting and frame skipping (and FPS display) are enabled via options in a new menu and are currently all off by default.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10669 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mpegplayer')
-rw-r--r-- | apps/plugins/mpegplayer/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.c | 118 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpeg_settings.h | 14 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/mpegplayer.c | 153 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/video_out_rockbox.c | 25 |
5 files changed, 279 insertions, 32 deletions
diff --git a/apps/plugins/mpegplayer/SOURCES b/apps/plugins/mpegplayer/SOURCES index 2ea6f303ec..4646599440 100644 --- a/apps/plugins/mpegplayer/SOURCES +++ b/apps/plugins/mpegplayer/SOURCES | |||
@@ -7,4 +7,5 @@ idct.c | |||
7 | motion_comp.c | 7 | motion_comp.c |
8 | slice.c | 8 | slice.c |
9 | video_out_rockbox.c | 9 | video_out_rockbox.c |
10 | mpeg_settings.c | ||
10 | mpegplayer.c | 11 | mpegplayer.c |
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c new file mode 100644 index 0000000000..dc63626c10 --- /dev/null +++ b/apps/plugins/mpegplayer/mpeg_settings.c | |||
@@ -0,0 +1,118 @@ | |||
1 | #include "plugin.h" | ||
2 | #include "lib/configfile.h" | ||
3 | |||
4 | #include "mpeg_settings.h" | ||
5 | |||
6 | extern struct plugin_api* rb; | ||
7 | |||
8 | struct mpeg_settings settings; | ||
9 | static struct mpeg_settings old_settings; | ||
10 | |||
11 | #define SETTINGS_VERSION 1 | ||
12 | #define SETTINGS_MIN_VERSION 1 | ||
13 | #define SETTINGS_FILENAME "mpegplayer.cfg" | ||
14 | |||
15 | static char* showfps_options[] = {"No", "Yes"}; | ||
16 | static char* limitfps_options[] = {"No", "Yes"}; | ||
17 | static char* skipframes_options[] = {"No", "Yes"}; | ||
18 | |||
19 | static struct configdata config[] = | ||
20 | { | ||
21 | {TYPE_ENUM, 0, 2, &settings.showfps, "Show FPS", showfps_options, NULL}, | ||
22 | {TYPE_ENUM, 0, 2, &settings.limitfps, "Limit FPS", limitfps_options, NULL}, | ||
23 | {TYPE_ENUM, 0, 2, &settings.skipframes, "Skip frames", skipframes_options, NULL}, | ||
24 | }; | ||
25 | |||
26 | bool mpeg_menu(void) | ||
27 | { | ||
28 | int m; | ||
29 | int result; | ||
30 | int menu_quit=0; | ||
31 | |||
32 | static const struct opt_items noyes[2] = { | ||
33 | { "No", -1 }, | ||
34 | { "Yes", -1 }, | ||
35 | }; | ||
36 | |||
37 | static const struct menu_item items[] = { | ||
38 | { "Display FPS", NULL }, | ||
39 | { "Limit FPS", NULL }, | ||
40 | { "Skip frames", NULL }, | ||
41 | { "Quit mpegplayer", NULL }, | ||
42 | }; | ||
43 | |||
44 | m = rb->menu_init(items, sizeof(items) / sizeof(*items), | ||
45 | NULL, NULL, NULL, NULL); | ||
46 | |||
47 | rb->button_clear_queue(); | ||
48 | |||
49 | while (!menu_quit) { | ||
50 | result=rb->menu_show(m); | ||
51 | |||
52 | switch(result) | ||
53 | { | ||
54 | case 0: /* Show FPS */ | ||
55 | rb->set_option("Display FPS",&settings.showfps,INT, | ||
56 | noyes, 2, NULL); | ||
57 | break; | ||
58 | case 1: /* Limit FPS */ | ||
59 | rb->set_option("Limit FPS",&settings.limitfps,INT, | ||
60 | noyes, 2, NULL); | ||
61 | break; | ||
62 | case 2: /* Skip frames */ | ||
63 | rb->set_option("Skip frames",&settings.skipframes,INT, | ||
64 | noyes, 2, NULL); | ||
65 | break; | ||
66 | default: | ||
67 | menu_quit=1; | ||
68 | break; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | rb->menu_exit(m); | ||
73 | |||
74 | rb->lcd_clear_display(); | ||
75 | rb->lcd_update(); | ||
76 | |||
77 | return (result==3); | ||
78 | } | ||
79 | |||
80 | |||
81 | void init_settings(void) | ||
82 | { | ||
83 | /* Set the default settings */ | ||
84 | settings.showfps = 0; /* Do not show FPS */ | ||
85 | settings.limitfps = 0; /* Do not limit FPS */ | ||
86 | settings.skipframes = 0; /* Do not skip frames */ | ||
87 | |||
88 | configfile_init(rb); | ||
89 | |||
90 | if (configfile_load(SETTINGS_FILENAME, config, | ||
91 | sizeof(config)/sizeof(*config), | ||
92 | SETTINGS_MIN_VERSION | ||
93 | ) < 0) | ||
94 | { | ||
95 | /* If the loading failed, save a new config file (as the disk is | ||
96 | already spinning) */ | ||
97 | configfile_save(SETTINGS_FILENAME, config, | ||
98 | sizeof(config)/sizeof(*config), | ||
99 | SETTINGS_VERSION); | ||
100 | } | ||
101 | |||
102 | /* Keep a copy of the saved version of the settings - so we can check if | ||
103 | the settings have changed when we quit */ | ||
104 | old_settings = settings; | ||
105 | } | ||
106 | |||
107 | void save_settings(void) | ||
108 | { | ||
109 | /* Save the user settings if they have changed */ | ||
110 | if (rb->memcmp(&settings,&old_settings,sizeof(settings))!=0) { | ||
111 | configfile_save(SETTINGS_FILENAME, config, | ||
112 | sizeof(config)/sizeof(*config), | ||
113 | SETTINGS_VERSION); | ||
114 | |||
115 | /* Store the settings in old_settings - to check for future changes */ | ||
116 | old_settings = settings; | ||
117 | } | ||
118 | } | ||
diff --git a/apps/plugins/mpegplayer/mpeg_settings.h b/apps/plugins/mpegplayer/mpeg_settings.h new file mode 100644 index 0000000000..cd2dcd2343 --- /dev/null +++ b/apps/plugins/mpegplayer/mpeg_settings.h | |||
@@ -0,0 +1,14 @@ | |||
1 | |||
2 | #include "plugin.h" | ||
3 | |||
4 | struct mpeg_settings { | ||
5 | int showfps; | ||
6 | int limitfps; | ||
7 | int skipframes; | ||
8 | }; | ||
9 | |||
10 | extern struct mpeg_settings settings; | ||
11 | |||
12 | bool mpeg_menu(void); | ||
13 | void init_settings(void); | ||
14 | void save_settings(void); | ||
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index be028c01f8..67569a7e1c 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "plugin.h" | 27 | #include "plugin.h" |
28 | 28 | ||
29 | #include "mpeg2.h" | 29 | #include "mpeg2.h" |
30 | #include "mpeg_settings.h" | ||
30 | #include "video_out.h" | 31 | #include "video_out.h" |
31 | 32 | ||
32 | PLUGIN_HEADER | 33 | PLUGIN_HEADER |
@@ -41,44 +42,88 @@ extern char iend[]; | |||
41 | 42 | ||
42 | struct plugin_api* rb; | 43 | struct plugin_api* rb; |
43 | 44 | ||
44 | /* The main buffer storing the compressed video data */ | ||
45 | #define BUFFER_SIZE (MEM-6)*1024*1024 | ||
46 | |||
47 | static mpeg2dec_t * mpeg2dec; | 45 | static mpeg2dec_t * mpeg2dec; |
48 | static int total_offset = 0; | 46 | static int total_offset = 0; |
49 | 47 | ||
50 | /* button definitions */ | 48 | /* button definitions */ |
51 | #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) | 49 | #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) |
50 | #define MPEG_MENU BUTTON_MODE | ||
52 | #define MPEG_STOP BUTTON_OFF | 51 | #define MPEG_STOP BUTTON_OFF |
53 | #define MPEG_PAUSE BUTTON_ON | 52 | #define MPEG_PAUSE BUTTON_ON |
54 | 53 | ||
55 | #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) | 54 | #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) |
56 | #define MPEG_STOP BUTTON_MENU | 55 | #define MPEG_MENU BUTTON_MENU |
57 | #define MPEG_PAUSE BUTTON_PLAY | 56 | #define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL) |
57 | #define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT) | ||
58 | 58 | ||
59 | #elif CONFIG_KEYPAD == IAUDIO_X5_PAD | 59 | #elif CONFIG_KEYPAD == IAUDIO_X5_PAD |
60 | #define MPEG_MENU (BUTTON_REC | BUTTON_REL) | ||
60 | #define MPEG_STOP BUTTON_POWER | 61 | #define MPEG_STOP BUTTON_POWER |
61 | #define MPEG_PAUSE BUTTON_PLAY | 62 | #define MPEG_PAUSE BUTTON_PLAY |
62 | 63 | ||
63 | #elif CONFIG_KEYPAD == GIGABEAT_PAD | 64 | #elif CONFIG_KEYPAD == GIGABEAT_PAD |
65 | #define MPEG_MENU BUTTON_MENU | ||
64 | #define MPEG_STOP BUTTON_A | 66 | #define MPEG_STOP BUTTON_A |
65 | #define MPEG_PAUSE BUTTON_SELECT | 67 | #define MPEG_PAUSE BUTTON_SELECT |
66 | 68 | ||
67 | #elif CONFIG_KEYPAD == IRIVER_H10_PAD | 69 | #elif CONFIG_KEYPAD == IRIVER_H10_PAD |
70 | #define MPEG_MENU (BUTTON_REW | BUTTON_REL) | ||
68 | #define MPEG_STOP BUTTON_POWER | 71 | #define MPEG_STOP BUTTON_POWER |
69 | #define MPEG_PAUSE BUTTON_PLAY | 72 | #define MPEG_PAUSE BUTTON_PLAY |
70 | 73 | ||
71 | #else | 74 | #else |
72 | #error MPEGPLAYER: Unsupported keypad | 75 | #error MPEGPLAYER: Unsupported keypad |
73 | #endif | 76 | #endif |
77 | |||
78 | static int tick_enabled = 0; | ||
79 | |||
80 | #define MPEG_CURRENT_TICK ((unsigned int)((*rb->current_tick - tick_offset))) | ||
81 | |||
82 | /* The value to subtract from current_tick to get the current mpeg tick */ | ||
83 | static int tick_offset; | ||
84 | |||
85 | /* The last tick - i.e. the time to reset the tick_offset to when unpausing */ | ||
86 | static int last_tick; | ||
87 | |||
88 | void start_timer(void) | ||
89 | { | ||
90 | last_tick = 0; | ||
91 | tick_offset = *rb->current_tick; | ||
92 | } | ||
93 | |||
94 | void unpause_timer(void) | ||
95 | { | ||
96 | tick_offset = *rb->current_tick - last_tick; | ||
97 | } | ||
98 | |||
99 | void pause_timer(void) | ||
100 | { | ||
101 | /* Save the current MPEG tick */ | ||
102 | last_tick = *rb->current_tick - tick_offset; | ||
103 | } | ||
104 | |||
105 | |||
74 | static bool button_loop(void) | 106 | static bool button_loop(void) |
75 | { | 107 | { |
108 | bool result; | ||
76 | int button = rb->button_get(false); | 109 | int button = rb->button_get(false); |
110 | |||
77 | switch (button) | 111 | switch (button) |
78 | { | 112 | { |
113 | case MPEG_MENU: | ||
114 | pause_timer(); | ||
115 | |||
116 | result = mpeg_menu(); | ||
117 | |||
118 | unpause_timer(); | ||
119 | |||
120 | return result; | ||
121 | |||
79 | case MPEG_STOP: | 122 | case MPEG_STOP: |
80 | return true; | 123 | return true; |
124 | |||
81 | case MPEG_PAUSE: | 125 | case MPEG_PAUSE: |
126 | pause_timer(); /* Freeze time */ | ||
82 | button = BUTTON_NONE; | 127 | button = BUTTON_NONE; |
83 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 128 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
84 | rb->cpu_boost(false); | 129 | rb->cpu_boost(false); |
@@ -91,7 +136,9 @@ static bool button_loop(void) | |||
91 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 136 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
92 | rb->cpu_boost(true); | 137 | rb->cpu_boost(true); |
93 | #endif | 138 | #endif |
139 | unpause_timer(); /* Resume time */ | ||
94 | break; | 140 | break; |
141 | |||
95 | default: | 142 | default: |
96 | if(rb->default_event_handler(button) == SYS_USB_CONNECTED) | 143 | if(rb->default_event_handler(button) == SYS_USB_CONNECTED) |
97 | return true; | 144 | return true; |
@@ -99,10 +146,59 @@ static bool button_loop(void) | |||
99 | return false; | 146 | return false; |
100 | } | 147 | } |
101 | 148 | ||
149 | /* | ||
150 | |||
151 | NOTES: | ||
152 | |||
153 | MPEG System Clock is 27MHz - i.e. 27000000 ticks/second. | ||
154 | |||
155 | FPS is represented in terms of a frame period - this is always an | ||
156 | integer number of 27MHz ticks. | ||
157 | |||
158 | e.g. 29.97fps (30000/1001) NTSC video has an exact frame period of | ||
159 | 900900 27MHz ticks. | ||
160 | |||
161 | In libmpeg2, info->sequence->frame_period contains the frame_period. | ||
162 | |||
163 | Working with Rockbox's 100Hz tick, the common frame rates would need | ||
164 | to be as follows: | ||
165 | |||
166 | FPS | 27Mhz | 100Hz | ||
167 | --------|---------------- | ||
168 | 10* | 2700000 | 10 | ||
169 | 12* | 2250000 | 8.3333 | ||
170 | 15* | 1800000 | 6.6667 | ||
171 | 23.9760 | 1126125 | 4.170833333 | ||
172 | 24 | 1125000 | 4.166667 | ||
173 | 25 | 1080000 | 4 | ||
174 | 29.9700 | 900900 | 3.336667 | ||
175 | 30 | 900000 | 3.333333 | ||
176 | |||
177 | |||
178 | *Unofficial framerates | ||
179 | |||
180 | */ | ||
181 | |||
182 | static uint64_t eta; | ||
183 | |||
102 | static bool decode_mpeg2 (uint8_t * current, uint8_t * end) | 184 | static bool decode_mpeg2 (uint8_t * current, uint8_t * end) |
103 | { | 185 | { |
104 | const mpeg2_info_t * info; | 186 | const mpeg2_info_t * info; |
105 | mpeg2_state_t state; | 187 | mpeg2_state_t state; |
188 | char str[80]; | ||
189 | static int skipped = 0; | ||
190 | static int frame = 0; | ||
191 | static int starttick = 0; | ||
192 | static int lasttick; | ||
193 | unsigned int eta2; | ||
194 | unsigned int x; | ||
195 | |||
196 | int fps; | ||
197 | |||
198 | if (starttick == 0) { | ||
199 | starttick=*rb->current_tick-1; /* Avoid divby0 */ | ||
200 | lasttick=starttick; | ||
201 | } | ||
106 | 202 | ||
107 | mpeg2_buffer (mpeg2dec, current, end); | 203 | mpeg2_buffer (mpeg2dec, current, end); |
108 | total_offset += end - current; | 204 | total_offset += end - current; |
@@ -122,6 +218,7 @@ static bool decode_mpeg2 (uint8_t * current, uint8_t * end) | |||
122 | info->sequence->chroma_width, | 218 | info->sequence->chroma_width, |
123 | info->sequence->chroma_height); | 219 | info->sequence->chroma_height); |
124 | mpeg2_skip (mpeg2dec, false); | 220 | mpeg2_skip (mpeg2dec, false); |
221 | |||
125 | break; | 222 | break; |
126 | case STATE_PICTURE: | 223 | case STATE_PICTURE: |
127 | break; | 224 | break; |
@@ -129,8 +226,44 @@ static bool decode_mpeg2 (uint8_t * current, uint8_t * end) | |||
129 | case STATE_END: | 226 | case STATE_END: |
130 | case STATE_INVALID_END: | 227 | case STATE_INVALID_END: |
131 | /* draw current picture */ | 228 | /* draw current picture */ |
132 | if (info->display_fbuf) | 229 | if (info->display_fbuf) { |
133 | vo_draw_frame(info->display_fbuf->buf); | 230 | /* We start the timer when we draw the first frame */ |
231 | if (!tick_enabled) { | ||
232 | start_timer(); | ||
233 | tick_enabled = 1 ; | ||
234 | } | ||
235 | |||
236 | eta += (info->sequence->frame_period); | ||
237 | eta2 = eta / (27000000 / HZ); | ||
238 | |||
239 | if (settings.limitfps) { | ||
240 | if (eta2 > MPEG_CURRENT_TICK) { | ||
241 | rb->sleep(eta2-MPEG_CURRENT_TICK); | ||
242 | } | ||
243 | } | ||
244 | x = MPEG_CURRENT_TICK; | ||
245 | |||
246 | /* If we are more than 1/20 second behind schedule (and | ||
247 | more than 1/20 second into the decoding), skip frame */ | ||
248 | if (settings.skipframes && (x > HZ/20) && | ||
249 | (eta2 < (x - (HZ/20)))) { | ||
250 | skipped++; | ||
251 | } else { | ||
252 | vo_draw_frame(info->display_fbuf->buf); | ||
253 | } | ||
254 | |||
255 | /* Calculate fps */ | ||
256 | frame++; | ||
257 | if (settings.showfps && (*rb->current_tick-lasttick>=HZ)) { | ||
258 | fps=(frame*(HZ*10))/x; | ||
259 | rb->snprintf(str,sizeof(str),"%d.%d %d %d %d", | ||
260 | (fps/10),fps%10,skipped,x,eta2); | ||
261 | rb->lcd_putsxy(0,0,str); | ||
262 | rb->lcd_update_rect(0,0,LCD_WIDTH,8); | ||
263 | |||
264 | lasttick = *rb->current_tick; | ||
265 | } | ||
266 | } | ||
134 | break; | 267 | break; |
135 | default: | 268 | default: |
136 | break; | 269 | break; |
@@ -147,8 +280,10 @@ static void es_loop (int in_file, uint8_t* buffer, size_t buffer_size) | |||
147 | if (buffer==NULL) | 280 | if (buffer==NULL) |
148 | return; | 281 | return; |
149 | 282 | ||
283 | eta = 0; | ||
150 | do { | 284 | do { |
151 | rb->splash(0,true,"Buffering..."); | 285 | rb->splash(0,true,"Buffering..."); |
286 | save_settings(); /* Save settings (if they have changed) */ | ||
152 | end = buffer + rb->read (in_file, buffer, buffer_size); | 287 | end = buffer + rb->read (in_file, buffer, buffer_size); |
153 | if (decode_mpeg2 (buffer, end)) | 288 | if (decode_mpeg2 (buffer, end)) |
154 | break; | 289 | break; |
@@ -202,6 +337,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
202 | return PLUGIN_ERROR; | 337 | return PLUGIN_ERROR; |
203 | } | 338 | } |
204 | 339 | ||
340 | init_settings(); | ||
341 | |||
205 | mpeg2dec = mpeg2_init (); | 342 | mpeg2dec = mpeg2_init (); |
206 | 343 | ||
207 | if (mpeg2dec == NULL) | 344 | if (mpeg2dec == NULL) |
@@ -230,6 +367,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
230 | rb->cpu_boost(false); | 367 | rb->cpu_boost(false); |
231 | #endif | 368 | #endif |
232 | 369 | ||
370 | save_settings(); /* Save settings (if they have changed) */ | ||
371 | |||
233 | #ifdef CONFIG_BACKLIGHT | 372 | #ifdef CONFIG_BACKLIGHT |
234 | /* reset backlight settings */ | 373 | /* reset backlight settings */ |
235 | rb->backlight_set_timeout(rb->global_settings->backlight_timeout); | 374 | rb->backlight_set_timeout(rb->global_settings->backlight_timeout); |
diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c index 258416fcdd..38a76a7747 100644 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ b/apps/plugins/mpegplayer/video_out_rockbox.c | |||
@@ -30,9 +30,6 @@ extern struct plugin_api* rb; | |||
30 | #include "mpeg2.h" | 30 | #include "mpeg2.h" |
31 | #include "video_out.h" | 31 | #include "video_out.h" |
32 | 32 | ||
33 | static int starttick = 0; | ||
34 | static int lasttick = 0; | ||
35 | |||
36 | #define CSUB_X 2 | 33 | #define CSUB_X 2 |
37 | #define CSUB_Y 2 | 34 | #define CSUB_Y 2 |
38 | 35 | ||
@@ -191,10 +188,6 @@ static void yuv_bitmap_part(unsigned char * const src[3], | |||
191 | 188 | ||
192 | void vo_draw_frame (uint8_t * const * buf) | 189 | void vo_draw_frame (uint8_t * const * buf) |
193 | { | 190 | { |
194 | char str[80]; | ||
195 | static int frame=0; | ||
196 | int ticks,fps; | ||
197 | |||
198 | #ifdef SIMULATOR | 191 | #ifdef SIMULATOR |
199 | yuv_bitmap_part(buf,0,0,image_width, | 192 | yuv_bitmap_part(buf,0,0,image_width, |
200 | output_x,output_y,output_width,output_height); | 193 | output_x,output_y,output_width,output_height); |
@@ -204,24 +197,6 @@ void vo_draw_frame (uint8_t * const * buf) | |||
204 | 0,0,image_width, | 197 | 0,0,image_width, |
205 | output_x,output_y,output_width,output_height); | 198 | output_x,output_y,output_width,output_height); |
206 | #endif | 199 | #endif |
207 | |||
208 | if (starttick==0) { | ||
209 | starttick=*rb->current_tick-1; /* Avoid divby0 */ | ||
210 | lasttick=starttick; | ||
211 | } | ||
212 | |||
213 | /* Calculate fps */ | ||
214 | if (*rb->current_tick-lasttick>=2*HZ) { | ||
215 | ticks=(*rb->current_tick)-starttick; | ||
216 | |||
217 | fps=(frame*1000)/ticks; | ||
218 | rb->snprintf(str,sizeof(str),"%d.%d",(fps/10),fps%10); | ||
219 | rb->lcd_putsxy(0,0,str); | ||
220 | rb->lcd_update_rect(0,0,80,8); | ||
221 | |||
222 | lasttick+=2*HZ; | ||
223 | } | ||
224 | frame++; | ||
225 | } | 200 | } |
226 | 201 | ||
227 | void vo_setup(unsigned int width, unsigned int height, | 202 | void vo_setup(unsigned int width, unsigned int height, |