summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/mpegplayer/SOURCES1
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c118
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.h14
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c153
-rw-r--r--apps/plugins/mpegplayer/video_out_rockbox.c25
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
7motion_comp.c 7motion_comp.c
8slice.c 8slice.c
9video_out_rockbox.c 9video_out_rockbox.c
10mpeg_settings.c
10mpegplayer.c 11mpegplayer.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
6extern struct plugin_api* rb;
7
8struct mpeg_settings settings;
9static struct mpeg_settings old_settings;
10
11#define SETTINGS_VERSION 1
12#define SETTINGS_MIN_VERSION 1
13#define SETTINGS_FILENAME "mpegplayer.cfg"
14
15static char* showfps_options[] = {"No", "Yes"};
16static char* limitfps_options[] = {"No", "Yes"};
17static char* skipframes_options[] = {"No", "Yes"};
18
19static 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
26bool 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
81void 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
107void 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
4struct mpeg_settings {
5 int showfps;
6 int limitfps;
7 int skipframes;
8};
9
10extern struct mpeg_settings settings;
11
12bool mpeg_menu(void);
13void init_settings(void);
14void 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
32PLUGIN_HEADER 33PLUGIN_HEADER
@@ -41,44 +42,88 @@ extern char iend[];
41 42
42struct plugin_api* rb; 43struct plugin_api* rb;
43 44
44/* The main buffer storing the compressed video data */
45#define BUFFER_SIZE (MEM-6)*1024*1024
46
47static mpeg2dec_t * mpeg2dec; 45static mpeg2dec_t * mpeg2dec;
48static int total_offset = 0; 46static 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
78static 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 */
83static int tick_offset;
84
85/* The last tick - i.e. the time to reset the tick_offset to when unpausing */
86static int last_tick;
87
88void start_timer(void)
89{
90 last_tick = 0;
91 tick_offset = *rb->current_tick;
92}
93
94void unpause_timer(void)
95{
96 tick_offset = *rb->current_tick - last_tick;
97}
98
99void pause_timer(void)
100{
101 /* Save the current MPEG tick */
102 last_tick = *rb->current_tick - tick_offset;
103}
104
105
74static bool button_loop(void) 106static 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
151NOTES:
152
153MPEG System Clock is 27MHz - i.e. 27000000 ticks/second.
154
155FPS is represented in terms of a frame period - this is always an
156integer number of 27MHz ticks.
157
158e.g. 29.97fps (30000/1001) NTSC video has an exact frame period of
159900900 27MHz ticks.
160
161In libmpeg2, info->sequence->frame_period contains the frame_period.
162
163Working with Rockbox's 100Hz tick, the common frame rates would need
164to be as follows:
165
166FPS | 27Mhz | 100Hz
167--------|----------------
16810* | 2700000 | 10
16912* | 2250000 | 8.3333
17015* | 1800000 | 6.6667
17123.9760 | 1126125 | 4.170833333
17224 | 1125000 | 4.166667
17325 | 1080000 | 4
17429.9700 | 900900 | 3.336667
17530 | 900000 | 3.333333
176
177
178*Unofficial framerates
179
180*/
181
182static uint64_t eta;
183
102static bool decode_mpeg2 (uint8_t * current, uint8_t * end) 184static 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
33static int starttick = 0;
34static 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
192void vo_draw_frame (uint8_t * const * buf) 189void 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
227void vo_setup(unsigned int width, unsigned int height, 202void vo_setup(unsigned int width, unsigned int height,