diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/mpeg.c | 282 |
1 files changed, 136 insertions, 146 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c index b1d1facc73..0406376e00 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c | |||
@@ -47,21 +47,23 @@ | |||
47 | #include "hwcompat.h" | 47 | #include "hwcompat.h" |
48 | #endif /* !SIMULATOR */ | 48 | #endif /* !SIMULATOR */ |
49 | 49 | ||
50 | #ifndef SIMULATOR | ||
51 | extern unsigned long mas_version_code; | ||
52 | #endif | ||
53 | |||
50 | #if CONFIG_HWCODEC == MAS3587F | 54 | #if CONFIG_HWCODEC == MAS3587F |
51 | static void init_recording(void); | 55 | extern enum /* from mp3_playback.c */ |
52 | static void start_prerecording(void); | 56 | { |
53 | static void start_recording(void); | 57 | MPEG_DECODER, |
54 | static void stop_recording(void); | 58 | MPEG_ENCODER |
55 | static int get_unsaved_space(void); | 59 | } mpeg_mode; |
56 | static void pause_recording(void); | ||
57 | static void resume_recording(void); | ||
58 | #endif /* CONFIG_HWCODEC == MAS3587F */ | 60 | #endif /* CONFIG_HWCODEC == MAS3587F */ |
59 | 61 | ||
60 | #ifndef SIMULATOR | 62 | extern char* playlist_peek(int steps); |
61 | static int get_unplayed_space(void); | 63 | extern bool playlist_check(int steps); |
62 | static int get_playable_space(void); | 64 | extern int playlist_next(int steps); |
63 | static int get_unswapped_space(void); | 65 | extern int playlist_amount(void); |
64 | #endif /* !SIMULATOR */ | 66 | extern int playlist_update_resume_info(const struct mp3entry* id3); |
65 | 67 | ||
66 | #define MPEG_PLAY 1 | 68 | #define MPEG_PLAY 1 |
67 | #define MPEG_STOP 2 | 69 | #define MPEG_STOP 2 |
@@ -82,20 +84,6 @@ static int get_unswapped_space(void); | |||
82 | #define MPEG_SAVE_DATA 102 | 84 | #define MPEG_SAVE_DATA 102 |
83 | #define MPEG_STOP_DONE 103 | 85 | #define MPEG_STOP_DONE 103 |
84 | 86 | ||
85 | #if CONFIG_HWCODEC == MAS3587F | ||
86 | extern enum /* from mp3_playback.c */ | ||
87 | { | ||
88 | MPEG_DECODER, | ||
89 | MPEG_ENCODER | ||
90 | } mpeg_mode; | ||
91 | #endif /* CONFIG_HWCODEC == MAS3587F */ | ||
92 | |||
93 | extern char* playlist_peek(int steps); | ||
94 | extern bool playlist_check(int steps); | ||
95 | extern int playlist_next(int steps); | ||
96 | extern int playlist_amount(void); | ||
97 | extern int playlist_update_resume_info(const struct mp3entry* id3); | ||
98 | |||
99 | /* list of tracks in memory */ | 87 | /* list of tracks in memory */ |
100 | #define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */ | 88 | #define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */ |
101 | #define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1) | 89 | #define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1) |
@@ -109,26 +97,131 @@ struct trackdata | |||
109 | 97 | ||
110 | static struct trackdata trackdata[MAX_TRACK_ENTRIES]; | 98 | static struct trackdata trackdata[MAX_TRACK_ENTRIES]; |
111 | 99 | ||
112 | static bool v1first = false; | ||
113 | |||
114 | static unsigned int current_track_counter = 0; | 100 | static unsigned int current_track_counter = 0; |
115 | static unsigned int last_track_counter = 0; | 101 | static unsigned int last_track_counter = 0; |
116 | 102 | ||
117 | #ifndef SIMULATOR | 103 | #ifndef SIMULATOR |
118 | |||
119 | static int track_read_idx = 0; | 104 | static int track_read_idx = 0; |
120 | static int track_write_idx = 0; | 105 | static int track_write_idx = 0; |
106 | #endif /* !SIMULATOR */ | ||
107 | |||
108 | static const char mpeg_thread_name[] = "mpeg"; | ||
109 | static unsigned int mpeg_errno; | ||
110 | |||
111 | static bool v1first = false; | ||
112 | |||
113 | static bool playing = false; /* We are playing an MP3 stream */ | ||
114 | static bool is_playing = false; /* We are (attempting to) playing MP3 files */ | ||
115 | static bool paused; /* playback is paused */ | ||
121 | 116 | ||
117 | #ifdef SIMULATOR | ||
118 | static char mpeg_stack[DEFAULT_STACK_SIZE]; | ||
119 | static struct mp3entry taginfo; | ||
120 | |||
121 | #else /* !SIMULATOR */ | ||
122 | static struct event_queue mpeg_queue; | ||
123 | static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; | ||
124 | |||
125 | static int audiobuflen; | ||
126 | static int audiobuf_write; | ||
127 | static int audiobuf_swapwrite; | ||
128 | static int audiobuf_read; | ||
129 | |||
130 | static int mpeg_file; | ||
131 | |||
132 | static bool play_pending; /* We are about to start playing */ | ||
133 | static bool filling; /* We are filling the buffer with data from disk */ | ||
134 | static bool dma_underrun; /* True when the DMA has stopped because of | ||
135 | slow disk reading (read error, shaking) */ | ||
136 | static bool mpeg_stop_done; | ||
137 | |||
138 | static int last_dma_tick = 0; | ||
139 | static int last_dma_chunk_size; | ||
140 | |||
141 | static long low_watermark; /* Dynamic low watermark level */ | ||
142 | static long low_watermark_margin; /* Extra time in seconds for watermark */ | ||
143 | static long lowest_watermark_level; /* Debug value to observe the buffer | ||
144 | usage */ | ||
145 | #if CONFIG_HWCODEC == MAS3587F | ||
146 | static char recording_filename[MAX_PATH]; /* argument to thread */ | ||
147 | static char delayed_filename[MAX_PATH]; /* internal copy of above */ | ||
148 | |||
149 | static bool init_recording_done; | ||
150 | static bool init_playback_done; | ||
151 | static bool prerecording; /* True if prerecording is enabled */ | ||
152 | static bool is_prerecording; /* True if we are prerecording */ | ||
153 | static bool is_recording; /* We are recording */ | ||
154 | static bool disable_xing_header; /* When splitting files */ | ||
155 | |||
156 | static enum { | ||
157 | NOT_SAVING = 0, /* reasons to save data, sorted by importance */ | ||
158 | BUFFER_FULL, | ||
159 | NEW_FILE, | ||
160 | STOP_RECORDING | ||
161 | } saving_status; | ||
162 | |||
163 | static int rec_frequency_index; /* For create_xing_header() calls */ | ||
164 | static int rec_version_index; /* For create_xing_header() calls */ | ||
165 | |||
166 | static int prerecord_buffer[MPEG_MAX_PRERECORD_SECONDS]; | ||
167 | /* Array of buffer indexes for each prerecorded second */ | ||
168 | static int prerecord_index; /* Current index in the prerecord buffer */ | ||
169 | static int prerecording_max_seconds; /* Max number of seconds to store */ | ||
170 | static int prerecord_count; /* Number of seconds in the prerecord buffer */ | ||
171 | static int prerecord_timeout; /* The tick count of the next prerecord data | ||
172 | store */ | ||
173 | |||
174 | unsigned long record_start_time; /* Value of current_tick when recording | ||
175 | was started */ | ||
176 | unsigned long pause_start_time; /* Value of current_tick when pause was | ||
177 | started */ | ||
178 | static unsigned long num_rec_bytes; | ||
179 | static unsigned long num_recorded_frames; | ||
180 | |||
181 | /* Shadow MAS registers */ | ||
182 | unsigned long shadow_encoder_control = 0; | ||
183 | #endif /* CONFIG_HWCODEC == MAS3587F */ | ||
184 | |||
185 | #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) | ||
186 | unsigned long shadow_io_control_main = 0; | ||
187 | unsigned long shadow_soft_mute = 0; | ||
188 | unsigned shadow_codec_reg0; | ||
189 | #endif /* (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */ | ||
190 | |||
191 | #ifdef HAVE_RECORDING | ||
192 | const unsigned char empty_id3_header[] = | ||
193 | { | ||
194 | 'I', 'D', '3', 0x03, 0x00, 0x00, | ||
195 | 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */ | ||
196 | }; | ||
197 | #endif /* HAVE_RECORDING */ | ||
198 | |||
199 | |||
200 | static int get_unplayed_space(void); | ||
201 | static int get_playable_space(void); | ||
202 | static int get_unswapped_space(void); | ||
203 | #endif /* !SIMULATOR */ | ||
204 | |||
205 | #if CONFIG_HWCODEC == MAS3587F | ||
206 | static void init_recording(void); | ||
207 | static void start_prerecording(void); | ||
208 | static void start_recording(void); | ||
209 | static void stop_recording(void); | ||
210 | static int get_unsaved_space(void); | ||
211 | static void pause_recording(void); | ||
212 | static void resume_recording(void); | ||
213 | #endif /* CONFIG_HWCODEC == MAS3587F */ | ||
214 | |||
215 | |||
216 | #ifndef SIMULATOR | ||
122 | static int num_tracks_in_memory(void) | 217 | static int num_tracks_in_memory(void) |
123 | { | 218 | { |
124 | return (track_write_idx - track_read_idx) & MAX_TRACK_ENTRIES_MASK; | 219 | return (track_write_idx - track_read_idx) & MAX_TRACK_ENTRIES_MASK; |
125 | } | 220 | } |
126 | #endif /* !SIMULATOR */ | ||
127 | 221 | ||
128 | #ifndef SIMULATOR | 222 | #ifdef DEBUG_TAGS |
129 | static void debug_tags(void) | 223 | static void debug_tags(void) |
130 | { | 224 | { |
131 | #ifdef DEBUG_TAGS | ||
132 | int i; | 225 | int i; |
133 | 226 | ||
134 | for(i = 0;i < MAX_TRACK_ENTRIES;i++) | 227 | for(i = 0;i < MAX_TRACK_ENTRIES;i++) |
@@ -137,8 +230,10 @@ static void debug_tags(void) | |||
137 | } | 230 | } |
138 | DEBUGF("read: %d, write :%d\n", track_read_idx, track_write_idx); | 231 | DEBUGF("read: %d, write :%d\n", track_read_idx, track_write_idx); |
139 | DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory()); | 232 | DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory()); |
140 | #endif /* DEBUG_TAGS */ | ||
141 | } | 233 | } |
234 | #else /* !DEBUG_TAGS */ | ||
235 | #define debug_tags() | ||
236 | #endif /* !DEBUG_TAGS */ | ||
142 | 237 | ||
143 | static void remove_current_tag(void) | 238 | static void remove_current_tag(void) |
144 | { | 239 | { |
@@ -305,88 +400,8 @@ unsigned long mpeg_get_last_header(void) | |||
305 | #endif /* !SIMULATOR */ | 400 | #endif /* !SIMULATOR */ |
306 | } | 401 | } |
307 | 402 | ||
308 | static bool paused; /* playback is paused */ | ||
309 | |||
310 | static unsigned int mpeg_errno; | ||
311 | |||
312 | #ifdef SIMULATOR | ||
313 | static bool is_playing = false; | ||
314 | static bool playing = false; | ||
315 | #else /* !SIMULATOR */ | ||
316 | static int last_dma_tick = 0; | ||
317 | |||
318 | extern unsigned long mas_version_code; | ||
319 | |||
320 | static struct event_queue mpeg_queue; | ||
321 | static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; | ||
322 | static const char mpeg_thread_name[] = "mpeg"; | ||
323 | |||
324 | static int audiobuflen; | ||
325 | static int audiobuf_write; | ||
326 | static int audiobuf_swapwrite; | ||
327 | static int audiobuf_read; | ||
328 | |||
329 | static int last_dma_chunk_size; | ||
330 | |||
331 | static bool playing; /* We are playing an MP3 stream */ | ||
332 | static bool play_pending; /* We are about to start playing */ | ||
333 | static bool is_playing; /* We are (attempting to) playing MP3 files */ | ||
334 | static bool filling; /* We are filling the buffer with data from disk */ | ||
335 | static bool dma_underrun; /* True when the DMA has stopped because of | ||
336 | slow disk reading (read error, shaking) */ | ||
337 | static long low_watermark; /* Dynamic low watermark level */ | ||
338 | static long low_watermark_margin; /* Extra time in seconds for watermark */ | ||
339 | static long lowest_watermark_level; /* Debug value to observe the buffer | ||
340 | usage */ | ||
341 | #if CONFIG_HWCODEC == MAS3587F | ||
342 | static bool is_recording; /* We are recording */ | ||
343 | unsigned long record_start_time; /* Value of current_tick when recording | ||
344 | was started */ | ||
345 | unsigned long pause_start_time; /* Value of current_tick when pause was | ||
346 | started */ | ||
347 | static enum { | ||
348 | NOT_SAVING = 0, /* reasons to save data, sorted by importance */ | ||
349 | BUFFER_FULL, | ||
350 | NEW_FILE, | ||
351 | STOP_RECORDING | ||
352 | } saving_status; | ||
353 | |||
354 | static char recording_filename[MAX_PATH]; /* argument to thread */ | ||
355 | static char delayed_filename[MAX_PATH]; /* internal copy of above */ | ||
356 | static int rec_frequency_index; /* For create_xing_header() calls */ | ||
357 | static int rec_version_index; /* For create_xing_header() calls */ | ||
358 | static bool disable_xing_header; /* When splitting files */ | ||
359 | |||
360 | static bool prerecording; /* True if prerecording is enabled */ | ||
361 | static bool is_prerecording; /* True if we are prerecording */ | ||
362 | static int prerecord_buffer[MPEG_MAX_PRERECORD_SECONDS]; /* Array of buffer | ||
363 | indexes for each | ||
364 | prerecorded | ||
365 | second */ | ||
366 | static int prerecord_index; /* Current index in the prerecord buffer */ | ||
367 | static int prerecording_max_seconds; /* Max number of seconds to store */ | ||
368 | static int prerecord_count; /* Number of seconds in the prerecord buffer */ | ||
369 | static int prerecord_timeout; /* The tick count of the next prerecord data store */ | ||
370 | |||
371 | /* Shadow MAS registers */ | ||
372 | unsigned long shadow_encoder_control = 0; | ||
373 | #endif /* CONFIG_HWCODEC == MAS3587F */ | ||
374 | |||
375 | #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) | ||
376 | unsigned long shadow_io_control_main = 0; | ||
377 | unsigned long shadow_soft_mute = 0; | ||
378 | unsigned shadow_codec_reg0; | ||
379 | #endif /* (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */ | ||
380 | |||
381 | static int mpeg_file; | ||
382 | |||
383 | /* Synchronization variables */ | ||
384 | #if CONFIG_HWCODEC == MAS3587F | ||
385 | static bool init_recording_done; | ||
386 | static bool init_playback_done; | ||
387 | #endif /* CONFIG_HWCODEC == MAS3587F */ | ||
388 | static bool mpeg_stop_done; | ||
389 | 403 | ||
404 | #ifndef SIMULATOR | ||
390 | static void recalculate_watermark(int bitrate) | 405 | static void recalculate_watermark(int bitrate) |
391 | { | 406 | { |
392 | int bytes_per_sec; | 407 | int bytes_per_sec; |
@@ -518,15 +533,6 @@ static int get_unsaved_space(void) | |||
518 | space += audiobuflen; | 533 | space += audiobuflen; |
519 | return space; | 534 | return space; |
520 | } | 535 | } |
521 | #endif /* CONFIG_HWCODEC == MAS3587F */ | ||
522 | |||
523 | #if CONFIG_HWCODEC == MAS3587F | ||
524 | #ifdef DEBUG | ||
525 | static long timing_info_index = 0; | ||
526 | static long timing_info[1024]; | ||
527 | #endif /* DEBUG */ | ||
528 | static unsigned long num_rec_bytes; | ||
529 | static unsigned long num_recorded_frames; | ||
530 | 536 | ||
531 | static void drain_dma_buffer(void) | 537 | static void drain_dma_buffer(void) |
532 | { | 538 | { |
@@ -542,6 +548,11 @@ static void drain_dma_buffer(void) | |||
542 | } | 548 | } |
543 | } | 549 | } |
544 | 550 | ||
551 | #ifdef DEBUG | ||
552 | static long timing_info_index = 0; | ||
553 | static long timing_info[1024]; | ||
554 | #endif /* DEBUG */ | ||
555 | |||
545 | void rec_tick (void) __attribute__ ((section (".icode"))); | 556 | void rec_tick (void) __attribute__ ((section (".icode"))); |
546 | void rec_tick(void) | 557 | void rec_tick(void) |
547 | { | 558 | { |
@@ -984,14 +995,6 @@ static bool swap_one_chunk(void) | |||
984 | return true; | 995 | return true; |
985 | } | 996 | } |
986 | 997 | ||
987 | #ifdef HAVE_RECORDING | ||
988 | const unsigned char empty_id3_header[] = | ||
989 | { | ||
990 | 'I', 'D', '3', 0x03, 0x00, 0x00, | ||
991 | 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */ | ||
992 | }; | ||
993 | #endif /* HAVE_RECORDING */ | ||
994 | |||
995 | static void mpeg_thread(void) | 998 | static void mpeg_thread(void) |
996 | { | 999 | { |
997 | static int pause_tick = 0; | 1000 | static int pause_tick = 0; |
@@ -1551,15 +1554,13 @@ static void mpeg_thread(void) | |||
1551 | is_playing = false; | 1554 | is_playing = false; |
1552 | paused = false; | 1555 | paused = false; |
1553 | stop_playing(); | 1556 | stop_playing(); |
1554 | #ifndef SIMULATOR //CHECKME | 1557 | |
1555 | |||
1556 | /* Tell the USB thread that we are safe */ | 1558 | /* Tell the USB thread that we are safe */ |
1557 | DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n"); | 1559 | DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n"); |
1558 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | 1560 | usb_acknowledge(SYS_USB_CONNECTED_ACK); |
1559 | 1561 | ||
1560 | /* Wait until the USB cable is extracted again */ | 1562 | /* Wait until the USB cable is extracted again */ |
1561 | usb_wait_for_disconnect(&mpeg_queue); | 1563 | usb_wait_for_disconnect(&mpeg_queue); |
1562 | #endif /* !SIMULATOR */ | ||
1563 | break; | 1564 | break; |
1564 | #endif /* !USB_NONE */ | 1565 | #endif /* !USB_NONE */ |
1565 | 1566 | ||
@@ -1913,10 +1914,6 @@ static void mpeg_thread(void) | |||
1913 | } | 1914 | } |
1914 | #endif /* !SIMULATOR */ | 1915 | #endif /* !SIMULATOR */ |
1915 | 1916 | ||
1916 | #ifdef SIMULATOR | ||
1917 | static struct mp3entry taginfo; | ||
1918 | #endif /* SIMULATOR */ | ||
1919 | |||
1920 | void mpeg_id3_options(bool _v1first) | 1917 | void mpeg_id3_options(bool _v1first) |
1921 | { | 1918 | { |
1922 | v1first = _v1first; | 1919 | v1first = _v1first; |
@@ -1969,11 +1966,7 @@ void audio_init_playback(void) | |||
1969 | 1966 | ||
1970 | 1967 | ||
1971 | /**************************************************************************** | 1968 | /**************************************************************************** |
1972 | ** | 1969 | * Recording functions |
1973 | ** | ||
1974 | ** Recording functions | ||
1975 | ** | ||
1976 | ** | ||
1977 | ***************************************************************************/ | 1970 | ***************************************************************************/ |
1978 | void mpeg_init_recording(void) | 1971 | void mpeg_init_recording(void) |
1979 | { | 1972 | { |
@@ -2528,7 +2521,6 @@ void audio_stop(void) | |||
2528 | is_playing = false; | 2521 | is_playing = false; |
2529 | playing = false; | 2522 | playing = false; |
2530 | #endif /* SIMULATOR */ | 2523 | #endif /* SIMULATOR */ |
2531 | |||
2532 | } | 2524 | } |
2533 | 2525 | ||
2534 | void audio_pause(void) | 2526 | void audio_pause(void) |
@@ -2659,8 +2651,6 @@ void audio_error_clear(void) | |||
2659 | } | 2651 | } |
2660 | 2652 | ||
2661 | #ifdef SIMULATOR | 2653 | #ifdef SIMULATOR |
2662 | static char mpeg_stack[DEFAULT_STACK_SIZE]; | ||
2663 | static const char mpeg_thread_name[] = "mpeg"; | ||
2664 | static void mpeg_thread(void) | 2654 | static void mpeg_thread(void) |
2665 | { | 2655 | { |
2666 | struct mp3entry* id3; | 2656 | struct mp3entry* id3; |