fix yellow and some house cleaning
[Rockbox.git] / apps / plugins / mpegplayer / mpegplayer.c
blobb5e11980db89d61656f3b0e78f61343884b0916c
1 /*
2 * mpegplayer.c - based on :
3 * - mpeg2dec.c
4 * - m2psd.c (http://www.brouhaha.com/~eric/software/m2psd/)
6 * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
7 * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
9 * m2psd: MPEG 2 Program Stream Demultiplexer
10 * Copyright (C) 2003 Eric Smith <eric@brouhaha.com>
12 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
13 * See http://libmpeg2.sourceforge.net/ for updates.
15 * mpeg2dec is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * mpeg2dec is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 NOTES:
34 mpegplayer is structured as follows:
36 1) Video thread (running on the COP for PortalPlayer targets).
37 2) Audio thread (running on the main CPU to maintain consistency with
38 the audio FIQ hander on PP).
39 3) The main thread which takes care of buffering.
41 Using the main thread for buffering wastes the 8KB main stack which is
42 in IRAM. However, 8KB is not enough for the audio thread to run (it
43 needs somewhere between 8KB and 9KB), so we create a new thread in
44 order to`give it a larger stack.
46 We use 4.5KB of the main stack for a libmad buffer (making use of
47 otherwise unused IRAM). There is also the possiblity of stealing the
48 main Rockbox codec thread's 9KB of IRAM stack and using that for
49 mpegplayer's audio thread - but we should only implement that if we
50 can put the IRAM to good use.
52 The button loop (and hence pause/resume, main menu and, in the future,
53 seeking) is placed in the audio thread. This keeps it on the main CPU
54 in PP targets and also allows buffering to continue in the background
55 whilst the main thread is filling the buffer.
57 A/V sync is not yet implemented but is planned to be achieved by
58 syncing the master clock with the audio, and then (as is currently
59 implemented), syncing video with the master clock. This can happen in
60 the audio thread, along with resyncing after pause.
62 Seeking should probably happen in the main thread, as that's where the
63 buffering happens.
65 On PortalPlayer targets, the main CPU is not being fully utilised -
66 the bottleneck is the video decoding on the COP. One way to improve
67 that might be to move the rendering of the frames (i.e. the
68 lcd_yuv_blit() call) from the COP back to the main CPU. Ideas and
69 patches for that are welcome!
71 Notes about MPEG files:
73 MPEG System Clock is 27MHz - i.e. 27000000 ticks/second.
75 FPS is represented in terms of a frame period - this is always an
76 integer number of 27MHz ticks.
78 e.g. 29.97fps (30000/1001) NTSC video has an exact frame period of
79 900900 27MHz ticks.
81 In libmpeg2, info->sequence->frame_period contains the frame_period.
83 Working with Rockbox's 100Hz tick, the common frame rates would need
84 to be as follows:
86 FPS | 27Mhz | 100Hz | 44.1KHz | 48KHz
87 --------|-----------------------------------------------------------
88 10* | 2700000 | 10 | 4410 | 4800
89 12* | 2250000 | 8.3333 | 3675 | 4000
90 15* | 1800000 | 6.6667 | 2940 | 3200
91 23.9760 | 1126125 | 4.170833333 | 1839.3375 | 2002
92 24 | 1125000 | 4.166667 | 1837.5 | 2000
93 25 | 1080000 | 4 | 1764 | 1920
94 29.9700 | 900900 | 3.336667 | 1471,47 | 1601.6
95 30 | 900000 | 3.333333 | 1470 | 1600
98 *Unofficial framerates
103 #include "mpeg2dec_config.h"
105 #include "plugin.h"
106 #include "gray.h"
107 #include "helper.h"
109 #include "mpeg2.h"
110 #include "mpeg_settings.h"
111 #include "video_out.h"
112 #include "../../codecs/libmad/mad.h"
114 PLUGIN_HEADER
115 PLUGIN_IRAM_DECLARE
117 /* button definitions */
118 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
119 #define MPEG_MENU BUTTON_MODE
120 #define MPEG_STOP BUTTON_OFF
121 #define MPEG_PAUSE BUTTON_ON
122 #define MPEG_VOLDOWN BUTTON_DOWN
123 #define MPEG_VOLUP BUTTON_UP
125 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
126 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
127 #define MPEG_MENU BUTTON_MENU
128 #define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL)
129 #define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT)
130 #define MPEG_VOLDOWN BUTTON_SCROLL_BACK
131 #define MPEG_VOLUP BUTTON_SCROLL_FWD
133 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
134 #define MPEG_MENU (BUTTON_REC | BUTTON_REL)
135 #define MPEG_STOP BUTTON_POWER
136 #define MPEG_PAUSE BUTTON_PLAY
137 #define MPEG_VOLDOWN BUTTON_DOWN
138 #define MPEG_VOLUP BUTTON_UP
140 #elif CONFIG_KEYPAD == GIGABEAT_PAD
141 #define MPEG_MENU BUTTON_MENU
142 #define MPEG_STOP BUTTON_POWER
143 #define MPEG_PAUSE BUTTON_SELECT
144 #define MPEG_VOLDOWN BUTTON_LEFT
145 #define MPEG_VOLUP BUTTON_RIGHT
146 #define MPEG_VOLDOWN2 BUTTON_VOL_DOWN
147 #define MPEG_VOLUP2 BUTTON_VOL_UP
149 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
150 #define MPEG_MENU (BUTTON_REW | BUTTON_REL)
151 #define MPEG_STOP BUTTON_POWER
152 #define MPEG_PAUSE BUTTON_PLAY
153 #define MPEG_VOLDOWN BUTTON_SCROLL_DOWN
154 #define MPEG_VOLUP BUTTON_SCROLL_UP
156 #elif CONFIG_KEYPAD == SANSA_E200_PAD
157 #define MPEG_MENU BUTTON_SELECT
158 #define MPEG_STOP BUTTON_POWER
159 #define MPEG_PAUSE BUTTON_UP
160 #define MPEG_VOLDOWN BUTTON_SCROLL_UP
161 #define MPEG_VOLUP BUTTON_SCROLL_DOWN
163 #elif CONFIG_KEYPAD == SANSA_C200_PAD
164 #define MPEG_MENU BUTTON_SELECT
165 #define MPEG_STOP BUTTON_POWER
166 #define MPEG_PAUSE BUTTON_UP
167 #define MPEG_VOLDOWN BUTTON_VOL_DOWN
168 #define MPEG_VOLUP BUTTON_VOL_UP
170 #else
171 #error MPEGPLAYER: Unsupported keypad
172 #endif
174 struct plugin_api* rb;
176 CACHE_FUNCTION_WRAPPERS(rb);
178 extern void *mpeg_malloc(size_t size, mpeg2_alloc_t reason);
179 extern size_t mpeg_alloc_init(unsigned char *buf, size_t mallocsize,
180 size_t libmpeg2size);
182 static mpeg2dec_t * mpeg2dec NOCACHEBSS_ATTR;
183 static int total_offset NOCACHEBSS_ATTR = 0;
184 static int num_drawn NOCACHEBSS_ATTR = 0;
185 static int count_start NOCACHEBSS_ATTR = 0;
187 /* Streams */
188 typedef struct
190 struct thread_entry *thread; /* Stream's thread */
191 int status; /* Current stream status */
192 struct event ev; /* Event sent to steam */
193 int have_msg; /* 1=event pending */
194 int replied; /* 1=replied to last event */
195 int reply; /* reply value */
196 struct mutex msg_lock; /* serialization for event senders */
197 uint8_t* curr_packet; /* Current stream packet beginning */
198 uint8_t* curr_packet_end; /* Current stream packet end */
200 uint8_t* prev_packet; /* Previous stream packet beginning */
201 size_t prev_packet_length; /* Lenth of previous packet */
202 size_t buffer_remaining; /* How much data is left in the buffer */
203 uint32_t curr_pts; /* Current presentation timestamp */
204 uint32_t curr_time; /* Current time in samples */
205 uint32_t tagged; /* curr_pts is valid */
207 int id;
208 } Stream;
210 static Stream audio_str IBSS_ATTR;
211 static Stream video_str IBSS_ATTR;
213 /* Messages */
214 enum
216 STREAM_PLAY,
217 STREAM_PAUSE,
218 STREAM_QUIT
221 /* Status */
222 enum
224 STREAM_ERROR = -4,
225 STREAM_STOPPED = -3,
226 STREAM_TERMINATED = -2,
227 STREAM_DONE = -1,
228 STREAM_PLAYING = 0,
229 STREAM_PAUSED,
230 STREAM_BUFFERING
233 /* Returns true if a message is waiting */
234 static inline bool str_have_msg(Stream *str)
236 return str->have_msg != 0;
239 /* Waits until a message is sent */
240 static void str_wait_msg(Stream *str)
242 int spin_count = 0;
244 while (str->have_msg == 0)
246 if (spin_count < 100)
248 rb->yield();
249 spin_count++;
250 continue;
253 rb->sleep(0);
257 /* Returns a message waiting or blocks until one is available - removes the
258 event */
259 static void str_get_msg(Stream *str, struct event *ev)
261 str_wait_msg(str);
262 ev->id = str->ev.id;
263 ev->data = str->ev.data;
264 str->have_msg = 0;
267 /* Peeks at the current message without blocking, returns the data but
268 does not remove the event */
269 static bool str_look_msg(Stream *str, struct event *ev)
271 if (!str_have_msg(str))
272 return false;
274 ev->id = str->ev.id;
275 ev->data = str->ev.data;
276 return true;
279 /* Replies to the last message pulled - has no effect if last message has not
280 been pulled or already replied */
281 static void str_reply_msg(Stream *str, int reply)
283 if (str->replied == 1 || str->have_msg != 0)
284 return;
286 str->reply = reply;
287 str->replied = 1;
290 /* Sends a message to a stream and waits for a reply */
291 static intptr_t str_send_msg(Stream *str, int id, intptr_t data)
293 int spin_count = 0;
294 intptr_t reply;
296 #if 0
297 if (str->thread == rb->thread_get_current())
298 return str->dispatch_fn(str, msg);
299 #endif
301 /* Only one thread at a time, please */
302 rb->spinlock_lock(&str->msg_lock);
304 str->ev.id = id;
305 str->ev.data = data;
306 str->reply = 0;
307 str->replied = 0;
308 str->have_msg = 1;
310 while (str->replied == 0 && str->status != STREAM_TERMINATED)
312 if (spin_count < 100)
314 rb->yield();
315 spin_count++;
316 continue;
319 rb->sleep(0);
322 reply = str->reply;
324 rb->spinlock_unlock(&str->msg_lock);
326 return reply;
329 /* NOTE: Putting the following variables in IRAM cause audio corruption
330 on the ipod (reason unknown)
332 static uint8_t *disk_buf_start IBSS_ATTR; /* Start pointer */
333 static uint8_t *disk_buf_end IBSS_ATTR; /* End of buffer pointer less
334 MPEG_GUARDBUF_SIZE. The
335 guard space is used to wrap
336 data at the buffer start to
337 pass continuous data
338 packets */
339 static uint8_t *disk_buf_tail IBSS_ATTR; /* Location of last data + 1
340 filled into the buffer */
341 static size_t disk_buf_size IBSS_ATTR; /* The total buffer length
342 including the guard
343 space */
344 static size_t file_remaining IBSS_ATTR;
346 #if NUM_CORES > 1
347 /* Some stream variables are shared between cores */
348 struct mutex stream_lock IBSS_ATTR;
349 static inline void init_stream_lock(void)
350 { rb->spinlock_init(&stream_lock); }
351 static inline void lock_stream(void)
352 { rb->spinlock_lock(&stream_lock); }
353 static inline void unlock_stream(void)
354 { rb->spinlock_unlock(&stream_lock); }
355 #else
356 /* No RMW issue here */
357 static inline void init_stream_lock(void)
359 static inline void lock_stream(void)
361 static inline void unlock_stream(void)
363 #endif
365 static int audio_sync_start IBSS_ATTR; /* If 0, the audio thread
366 yields waiting on the video
367 thread to synchronize with
368 the stream */
369 static uint32_t audio_sync_time IBSS_ATTR; /* The time that the video
370 thread has reached after
371 synchronizing. The
372 audio thread now needs
373 to advance to this
374 time */
375 static int video_sync_start IBSS_ATTR; /* While 0, the video thread
376 yields until the audio
377 thread has reached the
378 audio_sync_time */
379 static int video_thumb_print IBSS_ATTR; /* If 1, the video thread is
380 only decoding one frame for
381 use in the menu. If 0,
382 normal operation */
383 static int play_time IBSS_ATTR; /* The movie time as represented by
384 the maximum audio PTS tag in the
385 stream converted to half minutes */
386 char *filename; /* hack for resume time storage */
389 /* Various buffers */
390 /* TODO: Can we reduce the PCM buffer size? */
391 #define PCMBUFFER_SIZE ((512*1024)-PCMBUFFER_GUARD_SIZE)
392 #define PCMBUFFER_GUARD_SIZE (1152*4 + sizeof (struct pcm_frame_header))
393 #define MPA_MAX_FRAME_SIZE 1729 /* Largest frame - MPEG1, Layer II, 384kbps, 32kHz, pad */
394 #define MPABUF_SIZE (64*1024 + ALIGN_UP(MPA_MAX_FRAME_SIZE + 2*MAD_BUFFER_GUARD, 4))
395 #define LIBMPEG2BUFFER_SIZE (2*1024*1024)
397 /* 65536+6 is required since each PES has a 6 byte header with a 16 bit packet length field */
398 #define MPEG_GUARDBUF_SIZE (65*1024) /* Keep a bit extra - excessive for now */
399 #define MPEG_LOW_WATERMARK (1024*1024)
401 static void pcm_playback_play_pause(bool play);
403 /* libmad related functions/definitions */
404 #define INPUT_CHUNK_SIZE 8192
406 struct mad_stream stream IBSS_ATTR;
407 struct mad_frame frame IBSS_ATTR;
408 struct mad_synth synth IBSS_ATTR;
410 unsigned char mad_main_data[MAD_BUFFER_MDLEN]; /* 2567 bytes */
412 /* There isn't enough room for this in IRAM on PortalPlayer, but there
413 is for Coldfire. */
415 #ifdef CPU_COLDFIRE
416 static mad_fixed_t mad_frame_overlap[2][32][18] IBSS_ATTR; /* 4608 bytes */
417 #else
418 static mad_fixed_t mad_frame_overlap[2][32][18] __attribute__((aligned(16))); /* 4608 bytes */
419 #endif
421 static void init_mad(void* mad_frame_overlap)
423 rb->memset(&stream, 0, sizeof(struct mad_stream));
424 rb->memset(&frame, 0, sizeof(struct mad_frame));
425 rb->memset(&synth, 0, sizeof(struct mad_synth));
427 mad_stream_init(&stream);
428 mad_frame_init(&frame);
430 /* We do this so libmad doesn't try to call codec_calloc() */
431 frame.overlap = mad_frame_overlap;
433 rb->memset(mad_main_data, 0, sizeof(mad_main_data));
434 stream.main_data = &mad_main_data;
437 /* MPEG related headers */
439 /* Macros for comparing memory bytes to a series of constant bytes in an
440 efficient manner - evaluate to true if corresponding bytes match */
441 #if defined (CPU_ARM)
442 /* ARM must load 32-bit values at addres % 4 == 0 offsets but this data
443 isn't aligned nescessarily, so just byte compare */
444 #define CMP_3_CONST(_a, _b) \
445 ({ \
446 int _x; \
447 asm volatile ( \
448 "ldrb %[x], [%[a], #0] \r\n" \
449 "eors %[x], %[x], %[b0] \r\n" \
450 "ldreqb %[x], [%[a], #1] \r\n" \
451 "eoreqs %[x], %[x], %[b1] \r\n" \
452 "ldreqb %[x], [%[a], #2] \r\n" \
453 "eoreqs %[x], %[x], %[b2] \r\n" \
454 : [x]"=&r"(_x) \
455 : [a]"r"(_a), \
456 [b0]"i"((_b) >> 24), \
457 [b1]"i"((_b) << 8 >> 24), \
458 [b2]"i"((_b) << 16 >> 24) \
459 ); \
460 _x == 0; \
462 #define CMP_4_CONST(_a, _b) \
463 ({ \
464 int _x; \
465 asm volatile ( \
466 "ldrb %[x], [%[a], #0] \r\n" \
467 "eors %[x], %[x], %[b0] \r\n" \
468 "ldreqb %[x], [%[a], #1] \r\n" \
469 "eoreqs %[x], %[x], %[b1] \r\n" \
470 "ldreqb %[x], [%[a], #2] \r\n" \
471 "eoreqs %[x], %[x], %[b2] \r\n" \
472 "ldreqb %[x], [%[a], #3] \r\n" \
473 "eoreqs %[x], %[x], %[b3] \r\n" \
474 : [x]"=&r"(_x) \
475 : [a]"r"(_a), \
476 [b0]"i"((_b) >> 24), \
477 [b1]"i"((_b) << 8 >> 24), \
478 [b2]"i"((_b) << 16 >> 24), \
479 [b3]"i"((_b) << 24 >> 24) \
480 ); \
481 _x == 0; \
483 #elif defined (CPU_COLDFIRE)
484 /* Coldfire can just load a 32 bit value at any offset but ASM is not the best way
485 to integrate this with the C code */
486 #define CMP_3_CONST(a, b) \
487 (((*(uint32_t *)(a) >> 8) ^ ((uint32_t)(b) >> 8)) == 0)
488 #define CMP_4_CONST(a, b) \
489 ((*(uint32_t *)(a) ^ (b)) == 0)
490 #else
491 /* Don't know what this is - use bytewise comparisons */
492 #define CMP_3_CONST(a, b) \
493 (( ((a)[0] ^ (((b) >> 24) & 0xff)) | \
494 ((a)[1] ^ (((b) >> 16) & 0xff)) | \
495 ((a)[2] ^ (((b) >> 8) & 0xff)) ) == 0)
496 #define CMP_4_CONST(a, b) \
497 (( ((a)[0] ^ (((b) >> 24) & 0xff)) | \
498 ((a)[1] ^ (((b) >> 16) & 0xff)) | \
499 ((a)[2] ^ (((b) >> 8) & 0xff)) | \
500 ((a)[3] ^ ((b) & 0xff)) ) == 0)
501 #endif
503 /* Codes for various header byte sequences - MSB represents lowest memory
504 address */
505 #define PACKET_START_CODE_PREFIX 0x00000100ul
506 #define END_CODE 0x000001b9ul
507 #define PACK_START_CODE 0x000001baul
508 #define SYSTEM_HEADER_START_CODE 0x000001bbul
510 /* p = base pointer, b0 - b4 = byte offsets from p */
511 /* We only care about the MS 32 bits of the 33 and so the ticks are 45kHz */
512 #define TS_FROM_HEADER(p, b0, b1, b2, b3, b4) \
513 ((uint32_t)(((p)[b0] >> 1 << 29) | \
514 ((p)[b1] << 21) | \
515 ((p)[b2] >> 1 << 14) | \
516 ((p)[b3] << 6) | \
517 ((p)[b4] >> 2 )))
519 /* This function synchronizes the mpeg stream. The function returns
520 true on error */
521 bool sync_data_stream(uint8_t **p)
523 for (;;)
525 while ( !CMP_4_CONST(*p, PACK_START_CODE) && (*p) < disk_buf_tail )
526 (*p)++;
527 if ( (*p) >= disk_buf_tail )
528 break;
529 uint8_t *p_save = (*p);
530 if ( ((*p)[4] & 0xc0) == 0x40 ) /* mpeg-2 */
531 (*p) += 14 + ((*p)[13] & 7);
532 else if ( ((*p)[4] & 0xf0) == 0x20 ) /* mpeg-1 */
533 (*p) += 12;
534 else
535 (*p) += 5;
536 if ( (*p) >= disk_buf_tail )
537 break;
538 if ( CMP_3_CONST(*p, PACKET_START_CODE_PREFIX) )
540 (*p) = p_save;
541 break;
543 else
544 (*p) = p_save+1;
547 if ( (*p) >= disk_buf_tail )
548 return true;
549 else
550 return false;
553 /* This function demuxes the streams and gives the next stream data
554 pointer. Type 0 is normal operation. Type 1 and 2 have been added
555 for rapid seeks into the data stream. Type 1 and 2 ignore the
556 video_sync_start state (a signal to yield for refilling the
557 buffer). Type 1 will append more data to the buffer tail (minumal
558 bufer size reads that are increased only as needed). */
559 static int get_next_data( Stream* str, uint8_t type )
561 uint8_t *p;
562 uint8_t *header;
563 int stream;
565 static int mpeg1_skip_table[16] =
566 { 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
568 if ( (p=str->curr_packet_end) == NULL)
569 p = disk_buf_start;
571 while (1)
573 int length, bytes;
575 /* Yield for buffer filling */
576 if ( (type == 0) && (str->buffer_remaining < 120*1024) && (file_remaining > 0) )
577 while ( (str->buffer_remaining < 512*1024) && (file_remaining > 0) )
578 rb->yield();
580 /* The packet start position (plus an arbitrary header length)
581 has exceeded the amount of data in the buffer */
582 if ( type == 1 && (p+50) >= disk_buf_tail )
584 DEBUGF("disk buffer overflow\n");
585 return 1;
588 /* are we at the end of file? */
590 size_t tmp_length;
591 if (p < str->prev_packet)
592 tmp_length = (disk_buf_end - str->prev_packet) +
593 (p - disk_buf_start);
594 else
595 tmp_length = (p - str->prev_packet);
596 if (0 == str->buffer_remaining-tmp_length-str->prev_packet_length)
598 str->curr_packet_end = str->curr_packet = NULL;
599 break;
603 /* wrap the disk buffer */
604 if (p >= disk_buf_end)
605 p = disk_buf_start + (p - disk_buf_end);
607 /* wrap packet header if needed */
608 if ( (p+50) >= disk_buf_end )
609 rb->memcpy(disk_buf_end, disk_buf_start, 50);
611 /* Pack header, skip it */
612 if (CMP_4_CONST(p, PACK_START_CODE))
614 if ((p[4] & 0xc0) == 0x40) /* mpeg-2 */
616 p += 14 + (p[13] & 7);
618 else if ((p[4] & 0xf0) == 0x20) /* mpeg-1 */
620 p += 12;
622 else
624 rb->splash( 30, "Weird Pack header!" );
625 p += 5;
629 /* System header, parse and skip it - four bytes */
630 if (CMP_4_CONST(p, SYSTEM_HEADER_START_CODE))
632 int header_length;
634 p += 4; /*skip start code*/
635 header_length = *p++ << 8;
636 header_length += *p++;
638 p += header_length;
640 if ( p >= disk_buf_end )
641 p = disk_buf_start + (p - disk_buf_end);
644 /* Packet header, parse it */
645 if (!CMP_3_CONST(p, PACKET_START_CODE_PREFIX))
647 /* Problem */
648 rb->splash( HZ*3, "missing packet start code prefix : %X%X at %lX",
649 *p, *(p+2), (long unsigned int)(p-disk_buf_start) );
651 /* not 64bit safe
652 DEBUGF("end diff: %X,%X,%X,%X,%X,%X\n",(int)str->curr_packet_end,
653 (int)audio_str.curr_packet_end,(int)video_str.curr_packet_end,
654 (int)disk_buf_start,(int)disk_buf_end,(int)disk_buf_tail);
657 str->curr_packet_end = str->curr_packet = NULL;
658 break;
661 /* We retrieve basic infos */
662 stream = p[3];
663 length = (p[4] << 8) | p[5];
665 if (stream != str->id)
667 /* End of stream ? */
668 if (stream == 0xB9)
670 str->curr_packet_end = str->curr_packet = NULL;
671 break;
674 /* It's not the packet we're looking for, skip it */
675 p += length + 6;
676 continue;
679 /* Ok, it's our packet */
680 str->curr_packet_end = p + length+6;
681 header = p;
683 if ((header[6] & 0xc0) == 0x80) /* mpeg2 */
685 length = 9 + header[8];
687 /* header points to the mpeg2 pes header */
688 if (header[7] & 0x80)
690 /* header has a pts */
691 uint32_t pts = TS_FROM_HEADER(header, 9, 10, 11, 12, 13);
693 if (stream >= 0xe0)
695 /* video stream - header may have a dts as well */
696 uint32_t dts = (header[7] & 0x40) == 0 ?
697 pts : TS_FROM_HEADER(header, 14, 15, 16, 17, 18);
699 mpeg2_tag_picture (mpeg2dec, pts, dts);
701 else
703 str->curr_pts = pts;
704 str->tagged = 1;
708 else /* mpeg1 */
710 int len_skip;
711 uint8_t * ptsbuf;
713 length = 7;
715 while (header[length - 1] == 0xff)
717 length++;
718 if (length > 23)
720 rb->splash( 30, "Too much stuffing" );
721 DEBUGF("Too much stuffing" );
722 break;
726 if ( (header[length - 1] & 0xc0) == 0x40 )
727 length += 2;
729 len_skip = length;
730 length += mpeg1_skip_table[header[length - 1] >> 4];
732 /* header points to the mpeg1 pes header */
733 ptsbuf = header + len_skip;
735 if ((ptsbuf[-1] & 0xe0) == 0x20)
737 /* header has a pts */
738 uint32_t pts = TS_FROM_HEADER(ptsbuf, -1, 0, 1, 2, 3);
740 if (stream >= 0xe0)
742 /* video stream - header may have a dts as well */
743 uint32_t dts = (ptsbuf[-1] & 0xf0) != 0x30 ?
744 pts : TS_FROM_HEADER(ptsbuf, 4, 5, 6, 7, 18);
746 mpeg2_tag_picture (mpeg2dec, pts, dts);
748 else
750 str->curr_pts = pts;
751 str->tagged = 1;
756 p += length;
757 bytes = 6 + (header[4] << 8) + header[5] - length;
759 if (bytes > 0)
761 str->curr_packet_end = p + bytes;
763 if (str->curr_packet != NULL)
765 lock_stream();
767 str->buffer_remaining -= str->prev_packet_length;
768 if (str->curr_packet < str->prev_packet)
769 str->prev_packet_length = (disk_buf_end - str->prev_packet) +
770 (str->curr_packet - disk_buf_start);
771 else
772 str->prev_packet_length = (str->curr_packet - str->prev_packet);
774 unlock_stream();
776 str->prev_packet = str->curr_packet;
779 str->curr_packet = p;
781 if (str->curr_packet_end > disk_buf_end)
782 rb->memcpy(disk_buf_end, disk_buf_start,
783 str->curr_packet_end - disk_buf_end );
786 break;
787 } /* end while */
788 return 0;
791 /* Our clock rate in ticks/second - this won't be a constant for long */
792 #define CLOCK_RATE 44100
794 /* For simple lowpass filtering of sync variables */
795 #define AVERAGE(var, x, count) (((var) * (count-1) + (x)) / (count))
796 /* Convert 45kHz PTS/DTS ticks to our clock ticks */
797 #define TS_TO_TICKS(pts) ((uint64_t)CLOCK_RATE*(pts) / 45000)
798 /* Convert 27MHz ticks to our clock ticks */
799 #define TIME_TO_TICKS(stamp) ((uint64_t)CLOCK_RATE*(stamp) / 27000000)
801 /** MPEG audio stream buffer */
802 uint8_t* mpa_buffer NOCACHEBSS_ATTR;
804 static bool init_mpabuf(void)
806 mpa_buffer = mpeg_malloc(MPABUF_SIZE,-2);
807 return mpa_buffer != NULL;
810 #define PTS_QUEUE_LEN (1 << 5) /* 32 should be way more than sufficient -
811 if not, the case is handled */
812 #define PTS_QUEUE_MASK (PTS_QUEUE_LEN-1)
813 struct pts_queue_slot
815 uint32_t pts; /* Time stamp for packet */
816 ssize_t size; /* Number of bytes left in packet */
817 } pts_queue[PTS_QUEUE_LEN] __attribute__((aligned(16)));
819 /* This starts out wr == rd but will never be emptied to zero during
820 streaming again in order to support initializing the first packet's
821 pts value without a special case */
822 static unsigned pts_queue_rd NOCACHEBSS_ATTR;
823 static unsigned pts_queue_wr NOCACHEBSS_ATTR;
825 /* Increments the queue head postion - should be used to preincrement */
826 static bool pts_queue_add_head(void)
828 if (pts_queue_wr - pts_queue_rd >= PTS_QUEUE_LEN-1)
829 return false;
831 pts_queue_wr++;
832 return true;
835 /* Increments the queue tail position - leaves one slot as current */
836 static bool pts_queue_remove_tail(void)
838 if (pts_queue_wr - pts_queue_rd <= 1u)
839 return false;
841 pts_queue_rd++;
842 return true;
845 /* Returns the "head" at the index just behind the write index */
846 static struct pts_queue_slot * pts_queue_head(void)
848 return &pts_queue[(pts_queue_wr - 1) & PTS_QUEUE_MASK];
851 /* Returns a pointer to the current tail */
852 static struct pts_queue_slot * pts_queue_tail(void)
854 return &pts_queue[pts_queue_rd & PTS_QUEUE_MASK];
857 /* Resets the pts queue - call when starting and seeking */
858 static void pts_queue_reset(void)
860 struct pts_queue_slot *pts;
861 pts_queue_rd = pts_queue_wr;
862 pts = pts_queue_tail();
863 pts->pts = 0;
864 pts->size = 0;
867 struct pcm_frame_header /* Header added to pcm data every time a decoded
868 mpa frame is sent out */
870 uint32_t size; /* size of this frame - including header */
871 uint32_t time; /* timestamp for this frame - derived from PTS */
872 unsigned char data[]; /* open array of audio data */
875 #define PCMBUF_PLAY_ALL 1l /* Forces buffer to play back all data */
876 #define PCMBUF_PLAY_NONE LONG_MAX /* Keeps buffer from playing any data */
877 static volatile uint64_t pcmbuf_read IBSS_ATTR;
878 static volatile uint64_t pcmbuf_written IBSS_ATTR;
879 static volatile ssize_t pcmbuf_threshold IBSS_ATTR;
880 static struct pcm_frame_header *pcm_buffer IBSS_ATTR;
881 static struct pcm_frame_header *pcmbuf_end IBSS_ATTR;
882 static struct pcm_frame_header * volatile pcmbuf_head IBSS_ATTR;
883 static struct pcm_frame_header * volatile pcmbuf_tail IBSS_ATTR;
885 static volatile uint32_t samplesplayed IBSS_ATTR; /* Our base clock */
886 static volatile uint32_t samplestart IBSS_ATTR; /* Clock at playback start */
887 static volatile int32_t sampleadjust IBSS_ATTR; /* Clock drift adjustment */
889 static ssize_t pcmbuf_used(void)
891 return (ssize_t)(pcmbuf_written - pcmbuf_read);
894 static bool init_pcmbuf(void)
896 pcm_buffer = mpeg_malloc(PCMBUFFER_SIZE + PCMBUFFER_GUARD_SIZE, -2);
898 if (pcm_buffer == NULL)
899 return false;
901 pcmbuf_head = pcm_buffer;
902 pcmbuf_tail = pcm_buffer;
903 pcmbuf_end = SKIPBYTES(pcm_buffer, PCMBUFFER_SIZE);
904 pcmbuf_read = 0;
905 pcmbuf_written = 0;
907 return true;
910 /* Advance a PCM buffer pointer by size bytes circularly */
911 static inline void pcm_advance_buffer(struct pcm_frame_header * volatile *p,
912 size_t size)
914 *p = SKIPBYTES(*p, size);
915 if (*p >= pcmbuf_end)
916 *p = pcm_buffer;
919 static void get_more(unsigned char** start, size_t* size)
921 /* 25ms @ 44.1kHz */
922 static unsigned char silence[4412] __attribute__((aligned (4))) = { 0 };
923 size_t sz;
925 if (pcmbuf_used() >= pcmbuf_threshold)
927 uint32_t time = pcmbuf_tail->time;
928 sz = pcmbuf_tail->size;
930 *start = (unsigned char *)pcmbuf_tail->data;
932 pcm_advance_buffer(&pcmbuf_tail, sz);
934 pcmbuf_read += sz;
936 sz -= sizeof (*pcmbuf_tail);
938 *size = sz;
940 /* Drift the clock towards the audio timestamp values */
941 sampleadjust = AVERAGE(sampleadjust, (int32_t)(time - samplesplayed), 8);
943 /* Update master clock */
944 samplesplayed += sz >> 2;
945 return;
948 /* Keep clock going at all times */
949 sz = sizeof (silence);
950 *start = silence;
951 *size = sz;
953 samplesplayed += sz >> 2;
955 if (pcmbuf_read > pcmbuf_written)
956 pcmbuf_read = pcmbuf_written;
959 /* Flushes the buffer - clock keeps counting */
960 static void pcm_playback_flush(void)
962 bool was_playing = rb->pcm_is_playing();
964 if (was_playing)
965 rb->pcm_play_stop();
967 pcmbuf_read = 0;
968 pcmbuf_written = 0;
969 pcmbuf_head = pcmbuf_tail;
971 if (was_playing)
972 rb->pcm_play_data(get_more, NULL, 0);
975 /* Seek the reference clock to the specified time - next audio data ready to
976 go to DMA should be on the buffer with the same time index or else the PCM
977 buffer should be empty */
978 static void pcm_playback_seek_time(uint32_t time)
980 bool was_playing = rb->pcm_is_playing();
982 if (was_playing)
983 rb->pcm_play_stop();
985 samplesplayed = time;
986 samplestart = time;
987 sampleadjust = 0;
989 if (was_playing)
990 rb->pcm_play_data(get_more, NULL, 0);
993 /* Start pcm playback with the reference clock set to the specified time */
994 static void pcm_playback_play(uint32_t time)
996 pcm_playback_seek_time(time);
998 if (!rb->pcm_is_playing())
999 rb->pcm_play_data(get_more, NULL, 0);
1002 /* Pauses playback - and the clock */
1003 static void pcm_playback_play_pause(bool play)
1005 rb->pcm_play_pause(play);
1008 /* Stops all playback and resets the clock */
1009 static void pcm_playback_stop(void)
1011 if (rb->pcm_is_playing())
1012 rb->pcm_play_stop();
1014 pcm_playback_flush();
1016 sampleadjust =
1017 samplestart =
1018 samplesplayed = 0;
1021 static uint32_t get_stream_time(void)
1023 return samplesplayed + sampleadjust - (rb->pcm_get_bytes_waiting() >> 2);
1026 static uint32_t get_playback_time(void)
1028 return samplesplayed + sampleadjust -
1029 samplestart - (rb->pcm_get_bytes_waiting() >> 2);
1032 static inline int32_t clip_sample(int32_t sample)
1034 if ((int16_t)sample != sample)
1035 sample = 0x7fff ^ (sample >> 31);
1037 return sample;
1040 static int button_loop(void)
1042 bool result;
1043 int vol, minvol, maxvol;
1044 int button;
1046 if (video_sync_start==1) {
1048 if (str_have_msg(&audio_str))
1050 struct event ev;
1051 str_get_msg(&audio_str, &ev);
1053 if (ev.id == STREAM_QUIT)
1055 audio_str.status = STREAM_STOPPED;
1056 goto quit;
1058 else
1060 str_reply_msg(&audio_str, 0);
1064 button = rb->button_get(false);
1066 switch (button)
1068 case MPEG_VOLUP:
1069 case MPEG_VOLUP|BUTTON_REPEAT:
1070 #ifdef MPEG_VOLUP2
1071 case MPEG_VOLUP2:
1072 case MPEG_VOLUP2|BUTTON_REPEAT:
1073 #endif
1074 vol = rb->global_settings->volume;
1075 maxvol = rb->sound_max(SOUND_VOLUME);
1077 if (vol < maxvol) {
1078 vol++;
1079 rb->sound_set(SOUND_VOLUME, vol);
1080 rb->global_settings->volume = vol;
1082 break;
1084 case MPEG_VOLDOWN:
1085 case MPEG_VOLDOWN|BUTTON_REPEAT:
1086 #ifdef MPEG_VOLDOWN2
1087 case MPEG_VOLDOWN2:
1088 case MPEG_VOLDOWN2|BUTTON_REPEAT:
1089 #endif
1090 vol = rb->global_settings->volume;
1091 minvol = rb->sound_min(SOUND_VOLUME);
1093 if (vol > minvol) {
1094 vol--;
1095 rb->sound_set(SOUND_VOLUME, vol);
1096 rb->global_settings->volume = vol;
1098 break;
1100 case MPEG_MENU:
1101 pcm_playback_play_pause(false);
1102 audio_str.status = STREAM_PAUSED;
1103 str_send_msg(&video_str, STREAM_PAUSE, 0);
1104 #ifndef HAVE_LCD_COLOR
1105 gray_show(false);
1106 #endif
1107 result = mpeg_menu();
1108 count_start = get_playback_time();
1109 num_drawn = 0;
1111 #ifndef HAVE_LCD_COLOR
1112 gray_show(true);
1113 #endif
1115 /* The menu can change the font, so restore */
1116 rb->lcd_setfont(FONT_SYSFIXED);
1118 if (result) {
1119 settings.resume_time = (int)(get_stream_time()/44100/30);
1120 str_send_msg(&video_str, STREAM_QUIT, 0);
1121 audio_str.status = STREAM_STOPPED;
1122 } else {
1123 audio_str.status = STREAM_PLAYING;
1124 str_send_msg(&video_str, STREAM_PLAY, 0);
1125 pcm_playback_play_pause(true);
1127 break;
1129 case MPEG_STOP:
1130 settings.resume_time = (int)(get_stream_time()/44100/30);
1131 str_send_msg(&video_str, STREAM_QUIT, 0);
1132 audio_str.status = STREAM_STOPPED;
1133 break;
1135 case MPEG_PAUSE:
1136 str_send_msg(&video_str, STREAM_PAUSE, 0);
1137 audio_str.status = STREAM_PAUSED;
1138 pcm_playback_play_pause(false);
1140 button = BUTTON_NONE;
1141 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1142 rb->cpu_boost(false);
1143 #endif
1144 do {
1145 button = rb->button_get(true);
1146 if (button == MPEG_STOP) {
1147 str_send_msg(&video_str, STREAM_QUIT, 0);
1148 audio_str.status = STREAM_STOPPED;
1149 goto quit;
1151 } while (button != MPEG_PAUSE);
1153 str_send_msg(&video_str, STREAM_PLAY, 0);
1154 audio_str.status = STREAM_PLAYING;
1155 pcm_playback_play_pause(true);
1156 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1157 rb->cpu_boost(true);
1158 #endif
1159 break;
1161 default:
1162 if(rb->default_event_handler(button) == SYS_USB_CONNECTED) {
1163 str_send_msg(&video_str, STREAM_QUIT, 0);
1164 audio_str.status = STREAM_STOPPED;
1168 quit:
1169 return audio_str.status;
1172 static void audio_thread(void)
1174 uint8_t *mpabuf = mpa_buffer;
1175 ssize_t mpabuf_used = 0;
1176 int mad_errors = 0; /* A count of the errors in each frame */
1177 struct pts_queue_slot *pts;
1179 /* We need this here to init the EMAC for Coldfire targets */
1180 mad_synth_init(&synth);
1182 /* Init pts queue */
1183 pts_queue_reset();
1184 pts = pts_queue_tail();
1186 /* Keep buffer from playing */
1187 pcmbuf_threshold = PCMBUF_PLAY_NONE;
1189 /* Start clock */
1190 pcm_playback_play(0);
1192 /* Get first packet */
1193 get_next_data(&audio_str, 0 );
1195 /* skip audio packets here */
1196 while (audio_sync_start==0)
1198 audio_str.status = STREAM_PLAYING;
1199 rb->yield();
1202 if (audio_sync_time>10000)
1204 while (TS_TO_TICKS(audio_str.curr_pts) < audio_sync_time - 10000)
1206 get_next_data(&audio_str, 0 );
1207 rb->priority_yield();
1211 if (audio_str.curr_packet == NULL)
1212 goto done;
1214 /* This is the decoding loop. */
1215 while (1)
1217 int mad_stat;
1218 size_t len;
1220 if (button_loop() == STREAM_STOPPED)
1221 goto audio_thread_quit;
1223 if (pts->size <= 0)
1225 /* Carry any overshoot to the next size since we're technically
1226 -pts->size bytes into it already. If size is negative an audio
1227 frame was split accross packets. Old has to be saved before
1228 moving the tail. */
1229 if (pts_queue_remove_tail())
1231 struct pts_queue_slot *old = pts;
1232 pts = pts_queue_tail();
1233 pts->size += old->size;
1234 old->size = 0;
1238 /** Buffering **/
1239 if (mpabuf_used >= MPA_MAX_FRAME_SIZE + MAD_BUFFER_GUARD)
1241 /* Above low watermark - do nothing */
1243 else if (audio_str.curr_packet != NULL)
1247 /* Get data from next audio packet */
1248 len = audio_str.curr_packet_end - audio_str.curr_packet;
1250 if (audio_str.tagged)
1252 struct pts_queue_slot *stamp = pts;
1254 if (pts_queue_add_head())
1256 stamp = pts_queue_head();
1257 stamp->pts = TS_TO_TICKS(audio_str.curr_pts);
1258 /* pts->size should have been zeroed when slot was
1259 freed */
1261 /* else queue full - just count up from the last to make
1262 it look like more data in the same packet */
1263 stamp->size += len;
1264 audio_str.tagged = 0;
1266 else
1268 /* Add to the one just behind the head - this may be the
1269 tail or the previouly added head - whether or not we'll
1270 ever reach this is quite in question since audio always
1271 seems to have every packet timestamped */
1272 pts_queue_head()->size += len;
1275 /* Slide any remainder over to beginning - avoid function
1276 call overhead if no data remaining as well */
1277 if (mpabuf > mpa_buffer && mpabuf_used > 0)
1278 rb->memmove(mpa_buffer, mpabuf, mpabuf_used);
1280 /* Splice this packet onto any remainder */
1281 rb->memcpy(mpa_buffer + mpabuf_used, audio_str.curr_packet,
1282 len);
1284 mpabuf_used += len;
1285 mpabuf = mpa_buffer;
1287 /* Get data from next audio packet */
1288 get_next_data(&audio_str, 0 );
1290 while (audio_str.curr_packet != NULL &&
1291 mpabuf_used < MPA_MAX_FRAME_SIZE + MAD_BUFFER_GUARD);
1293 else if (mpabuf_used <= 0)
1295 /* Used up remainder of mpa buffer so quit */
1296 break;
1299 /** Decoding **/
1300 mad_stream_buffer(&stream, mpabuf, mpabuf_used);
1302 mad_stat = mad_frame_decode(&frame, &stream);
1304 if (stream.next_frame == NULL)
1306 /* What to do here? (This really is fatal) */
1307 DEBUGF("/* What to do here? */\n");
1308 break;
1311 /* Next mad stream buffer is the next frame postion */
1312 mpabuf = (uint8_t *)stream.next_frame;
1314 /* Adjust sizes by the frame size */
1315 len = stream.next_frame - stream.this_frame;
1316 mpabuf_used -= len;
1317 pts->size -= len;
1319 if (mad_stat != 0)
1321 if (stream.error == MAD_FLAG_INCOMPLETE
1322 || stream.error == MAD_ERROR_BUFLEN)
1324 /* This makes the codec support partially corrupted files */
1325 if (++mad_errors > 30)
1326 break;
1328 stream.error = 0;
1329 rb->priority_yield();
1330 continue;
1332 else if (MAD_RECOVERABLE(stream.error))
1334 stream.error = 0;
1335 rb->priority_yield();
1336 continue;
1338 else
1340 /* Some other unrecoverable error */
1341 DEBUGF("Unrecoverable error\n");
1344 break;
1347 mad_errors = 0; /* Clear errors */
1349 /* Generate the pcm samples */
1350 mad_synth_frame(&synth, &frame);
1352 /** Output **/
1354 /* TODO: Output through core dsp. We'll still use our own PCM buffer
1355 since the core pcm buffer has no timestamping or clock facilities */
1357 /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */
1358 if (synth.pcm.length > 0)
1360 int16_t *audio_data = (int16_t *)pcmbuf_head->data;
1361 size_t size = sizeof (*pcmbuf_head) + synth.pcm.length*4;
1362 size_t wait_for = size + 32*1024;
1364 /* Leave at least 32KB free (this will be the currently
1365 playing chunk) */
1366 while (pcmbuf_used() + wait_for > PCMBUFFER_SIZE)
1368 if (str_have_msg(&audio_str))
1370 struct event ev;
1371 str_look_msg(&audio_str, &ev);
1373 if (ev.id == STREAM_QUIT)
1374 goto audio_thread_quit;
1377 rb->priority_yield();
1380 if (video_sync_start == 0 &&
1381 pts->pts+(uint32_t)synth.pcm.length<audio_sync_time) {
1382 synth.pcm.length = 0;
1383 size = 0;
1384 rb->yield();
1387 /* TODO: This part will be replaced with dsp calls soon */
1388 if (MAD_NCHANNELS(&frame.header) == 2)
1390 int32_t *left = &synth.pcm.samples[0][0];
1391 int32_t *right = &synth.pcm.samples[1][0];
1392 int i = synth.pcm.length;
1396 /* libmad outputs s3.28 */
1397 *audio_data++ = clip_sample(*left++ >> 13);
1398 *audio_data++ = clip_sample(*right++ >> 13);
1400 while (--i > 0);
1402 else /* mono */
1404 int32_t *mono = &synth.pcm.samples[0][0];
1405 int i = synth.pcm.length;
1409 int32_t s = clip_sample(*mono++ >> 13);
1410 *audio_data++ = s;
1411 *audio_data++ = s;
1413 while (--i > 0);
1415 /**/
1417 pcmbuf_head->time = pts->pts;
1418 pcmbuf_head->size = size;
1420 /* As long as we're on this timestamp, the time is just incremented
1421 by the number of samples */
1422 pts->pts += synth.pcm.length;
1424 pcm_advance_buffer(&pcmbuf_head, size);
1426 if (pcmbuf_threshold != PCMBUF_PLAY_ALL && pcmbuf_used() >= 64*1024)
1428 /* We've reached our size treshold so start playing back the
1429 audio in the buffer and set the buffer to play all data */
1430 audio_str.status = STREAM_PLAYING;
1431 pcmbuf_threshold = PCMBUF_PLAY_ALL;
1432 pcm_playback_seek_time(pcmbuf_tail->time);
1433 video_sync_start = 1;
1436 /* Make this data available to DMA */
1437 pcmbuf_written += size;
1440 rb->yield();
1441 } /* end decoding loop */
1443 done:
1444 if (audio_str.status == STREAM_STOPPED)
1445 goto audio_thread_quit;
1447 /* Force any residue to play if audio ended before reaching the
1448 threshold */
1449 if (pcmbuf_threshold != PCMBUF_PLAY_ALL && pcmbuf_used() > 0)
1451 pcm_playback_play(pcmbuf_tail->time);
1452 pcmbuf_threshold = PCMBUF_PLAY_ALL;
1455 if (rb->pcm_is_playing() && !rb->pcm_is_paused())
1457 /* Wait for audio to finish */
1458 while (pcmbuf_used() > 0)
1460 if (button_loop() == STREAM_STOPPED)
1461 goto audio_thread_quit;
1462 rb->sleep(HZ/10);
1466 audio_str.status = STREAM_DONE;
1468 /* Process events until finished */
1469 while (button_loop() != STREAM_STOPPED)
1470 rb->sleep(HZ/4);
1472 audio_thread_quit:
1473 pcm_playback_stop();
1475 audio_str.status = STREAM_TERMINATED;
1478 /* End of libmad stuff */
1480 /* TODO: Running in the main thread, libmad needs 8.25KB of stack.
1481 The codec thread uses a 9KB stack. So we can probable reduce this a
1482 little, but leave at 9KB for now to be safe. */
1483 #define AUDIO_STACKSIZE (9*1024)
1484 uint32_t audio_stack[AUDIO_STACKSIZE / sizeof(uint32_t)] IBSS_ATTR;
1486 /* TODO: Check if 4KB is appropriate - it works for my test streams,
1487 so maybe we can reduce it. */
1488 #define VIDEO_STACKSIZE (4*1024)
1489 static uint32_t video_stack[VIDEO_STACKSIZE / sizeof(uint32_t)] IBSS_ATTR;
1491 static void video_thread(void)
1493 struct event ev;
1494 const mpeg2_info_t * info;
1495 mpeg2_state_t state;
1496 char str[80];
1497 uint32_t curr_time = 0;
1498 uint32_t period = 0; /* Frame period in clock ticks */
1499 uint32_t eta_audio = UINT_MAX, eta_video = 0;
1500 int32_t eta_early = 0, eta_late = 0;
1501 int frame_drop_level = 0;
1502 int skip_level = 0;
1503 int num_skipped = 0;
1504 /* Used to decide when to display FPS */
1505 unsigned long last_showfps = *rb->current_tick - HZ;
1506 /* Used to decide whether or not to force a frame update */
1507 unsigned long last_render = last_showfps;
1509 mpeg2dec = mpeg2_init();
1510 if (mpeg2dec == NULL)
1512 rb->splash(0, "mpeg2_init failed");
1513 /* Commit suicide */
1514 video_str.status = STREAM_TERMINATED;
1515 return;
1518 /* Clear the display - this is mainly just to indicate that the
1519 video thread has started successfully. */
1520 if (!video_thumb_print)
1522 rb->lcd_clear_display();
1523 rb->lcd_update();
1526 /* Request the first packet data */
1527 get_next_data( &video_str, 0 );
1529 if (video_str.curr_packet == NULL)
1530 goto video_thread_quit;
1532 mpeg2_buffer (mpeg2dec, video_str.curr_packet, video_str.curr_packet_end);
1533 total_offset += video_str.curr_packet_end - video_str.curr_packet;
1535 info = mpeg2_info (mpeg2dec);
1537 while (1)
1539 /* quickly check mailbox first */
1540 if (video_thumb_print)
1542 if (video_str.status == STREAM_STOPPED)
1543 break;
1545 else if (str_have_msg(&video_str))
1547 while (1)
1549 str_get_msg(&video_str, &ev);
1551 switch (ev.id)
1553 case STREAM_QUIT:
1554 video_str.status = STREAM_STOPPED;
1555 goto video_thread_quit;
1556 case STREAM_PAUSE:
1557 #if NUM_CORES > 1
1558 flush_icache();
1559 #endif
1560 video_str.status = STREAM_PAUSED;
1561 str_reply_msg(&video_str, 1);
1562 continue;
1565 break;
1568 video_str.status = STREAM_PLAYING;
1569 str_reply_msg(&video_str, 1);
1572 state = mpeg2_parse (mpeg2dec);
1573 rb->yield();
1575 /* Prevent idle poweroff */
1576 rb->reset_poweroff_timer();
1578 switch (state)
1580 case STATE_BUFFER:
1581 /* Request next packet data */
1582 get_next_data( &video_str, 0 );
1584 mpeg2_buffer (mpeg2dec, video_str.curr_packet, video_str.curr_packet_end);
1585 total_offset += video_str.curr_packet_end - video_str.curr_packet;
1586 info = mpeg2_info (mpeg2dec);
1588 if (video_str.curr_packet == NULL)
1590 /* No more data. */
1591 goto video_thread_quit;
1593 continue;
1595 case STATE_SEQUENCE:
1596 /* New GOP, inform output of any changes */
1597 vo_setup(info->sequence);
1598 break;
1600 case STATE_PICTURE:
1602 int skip = 0; /* Assume no skip */
1604 if (frame_drop_level >= 1 || skip_level > 0)
1606 /* A frame will be dropped in the decoder */
1608 /* Frame type: I/P/B/D */
1609 int type = info->current_picture->flags & PIC_MASK_CODING_TYPE;
1611 switch (type)
1613 case PIC_FLAG_CODING_TYPE_I:
1614 case PIC_FLAG_CODING_TYPE_D:
1615 /* Level 5: Things are extremely late and all frames will be
1616 dropped until the next key frame */
1617 if (frame_drop_level >= 1)
1618 frame_drop_level = 0; /* Key frame - reset drop level */
1619 if (skip_level >= 5)
1621 frame_drop_level = 1;
1622 skip_level = 0; /* reset */
1624 break;
1625 case PIC_FLAG_CODING_TYPE_P:
1626 /* Level 4: Things are very late and all frames will be
1627 dropped until the next key frame */
1628 if (skip_level >= 4)
1630 frame_drop_level = 1;
1631 skip_level = 0; /* reset */
1633 break;
1634 case PIC_FLAG_CODING_TYPE_B:
1635 /* We want to drop something, so this B frame won't even
1636 be decoded. Drawing can happen on the next frame if so
1637 desired. Bring the level down as skips are done. */
1638 skip = 1;
1639 if (skip_level > 0)
1640 skip_level--;
1643 skip |= frame_drop_level;
1646 mpeg2_skip(mpeg2dec, skip);
1647 break;
1650 case STATE_SLICE:
1651 case STATE_END:
1652 case STATE_INVALID_END:
1654 int32_t offset; /* Tick adjustment to keep sync */
1656 /* draw current picture */
1657 if (!info->display_fbuf)
1658 break;
1660 /* No limiting => no dropping - draw this frame */
1661 if (!settings.limitfps && (video_thumb_print == 0))
1663 audio_sync_start = 1;
1664 video_sync_start = 1;
1665 goto picture_draw;
1668 /* Get presentation times in audio samples - quite accurate
1669 enough - add previous frame duration if not stamped */
1670 curr_time = (info->display_picture->flags & PIC_FLAG_TAGS) ?
1671 TS_TO_TICKS(info->display_picture->tag) : (curr_time + period);
1673 period = TIME_TO_TICKS(info->sequence->frame_period);
1675 if ( (video_thumb_print == 1 || video_sync_start == 0) &&
1676 ((int)(info->current_picture->flags & PIC_MASK_CODING_TYPE)
1677 == PIC_FLAG_CODING_TYPE_B))
1678 break;
1680 eta_video = curr_time;
1682 audio_sync_time = eta_video;
1683 audio_sync_start = 1;
1685 while (video_sync_start == 0)
1686 rb->yield();
1688 eta_audio = get_stream_time();
1690 /* How early/late are we? > 0 = late, < 0 early */
1691 offset = eta_audio - eta_video;
1693 if (!settings.skipframes)
1695 /* Make no effort to determine whether this frame should be
1696 drawn or not since no action can be taken to correct the
1697 situation. We'll just wait if we're early and correct for
1698 lateness as much as possible. */
1699 if (offset < 0)
1700 offset = 0;
1702 eta_late = AVERAGE(eta_late, offset, 4);
1703 offset = eta_late;
1705 if ((uint32_t)offset > eta_video)
1706 offset = eta_video;
1708 eta_video -= offset;
1709 goto picture_wait;
1712 /** Possibly skip this frame **/
1714 /* Frameskipping has the following order of preference:
1716 * Frame Type Who Notes/Rationale
1717 * B decoder arbitrarily drop - no decode or draw
1718 * Any renderer arbitrarily drop - will be I/D/P
1719 * P decoder must wait for I/D-frame - choppy
1720 * I/D decoder must wait for I/D-frame - choppy
1722 * If a frame can be drawn and it has been at least 1/2 second,
1723 * the image will be updated no matter how late it is just to
1724 * avoid looking stuck.
1727 /* If we're late, set the eta to play the frame early so
1728 we may catch up. If early, especially because of a drop,
1729 mitigate a "snap" by moving back gradually. */
1730 if (offset >= 0) /* late or on time */
1732 eta_early = 0; /* Not early now :( */
1734 eta_late = AVERAGE(eta_late, offset, 4);
1735 offset = eta_late;
1737 if ((uint32_t)offset > eta_video)
1738 offset = eta_video;
1740 eta_video -= offset;
1742 else
1744 eta_late = 0; /* Not late now :) */
1746 if (offset > eta_early)
1748 /* Just dropped a frame and we're now early or we're
1749 coming back from being early */
1750 eta_early = offset;
1751 if ((uint32_t)-offset > eta_video)
1752 offset = -eta_video;
1754 eta_video += offset;
1756 else
1758 /* Just early with an offset, do exponential drift back */
1759 if (eta_early != 0)
1761 eta_early = AVERAGE(eta_early, 0, 8);
1762 eta_video = ((uint32_t)-eta_early > eta_video) ?
1763 0 : (eta_video + eta_early);
1766 offset = eta_early;
1770 if (info->display_picture->flags & PIC_FLAG_SKIP)
1772 /* This frame was set to skip so skip it after having updated
1773 timing information */
1774 num_skipped++;
1775 eta_early = INT32_MIN;
1776 goto picture_skip;
1779 if (skip_level == 3 && TIME_BEFORE(*rb->current_tick, last_render + HZ/2))
1781 /* Render drop was set previously but nothing was dropped in the
1782 decoder or it's been to long since drawing the last frame. */
1783 skip_level = 0;
1784 num_skipped++;
1785 eta_early = INT32_MIN;
1786 goto picture_skip;
1789 /* At this point a frame _will_ be drawn - a skip may happen on
1790 the next however */
1791 skip_level = 0;
1793 if (offset > CLOCK_RATE*110/1000)
1795 /* Decide which skip level is needed in order to catch up */
1797 /* TODO: Calculate this rather than if...else - this is rather
1798 exponential though */
1799 if (offset > CLOCK_RATE*367/1000)
1800 skip_level = 5; /* Decoder skip: I/D */
1801 if (offset > CLOCK_RATE*233/1000)
1802 skip_level = 4; /* Decoder skip: P */
1803 else if (offset > CLOCK_RATE*167/1000)
1804 skip_level = 3; /* Render skip */
1805 else if (offset > CLOCK_RATE*133/1000)
1806 skip_level = 2; /* Decoder skip: B */
1807 else
1808 skip_level = 1; /* Decoder skip: B */
1811 picture_wait:
1812 /* Wait until audio catches up */
1813 if (video_thumb_print)
1814 video_str.status = STREAM_STOPPED;
1815 else
1816 while (eta_video > eta_audio)
1818 rb->priority_yield();
1820 /* Make sure not to get stuck waiting here forever */
1821 if (str_have_msg(&video_str))
1823 str_look_msg(&video_str, &ev);
1825 /* If not to play, process up top */
1826 if (ev.id != STREAM_PLAY)
1827 goto rendering_finished;
1829 /* Told to play but already playing */
1830 str_get_msg(&video_str, &ev);
1831 str_reply_msg(&video_str, 1);
1834 eta_audio = get_stream_time();
1837 picture_draw:
1838 /* Record last frame time */
1839 last_render = *rb->current_tick;
1841 if (video_thumb_print)
1842 vo_draw_frame_thumb(info->display_fbuf->buf);
1843 else
1844 vo_draw_frame(info->display_fbuf->buf);
1846 num_drawn++;
1848 picture_skip:
1849 if (!settings.showfps)
1850 break;
1852 /* Calculate and display fps */
1853 if (TIME_AFTER(*rb->current_tick, last_showfps + HZ))
1855 uint32_t clock_ticks = get_playback_time() - count_start;
1856 int fps = 0;
1858 if (clock_ticks != 0)
1859 fps = num_drawn*CLOCK_RATE*10ll / clock_ticks;
1861 rb->snprintf(str, sizeof(str), "%d.%d %d %d ",
1862 fps / 10, fps % 10, num_skipped,
1863 info->display_picture->temporal_reference);
1864 rb->lcd_putsxy(0, 0, str);
1865 rb->lcd_update_rect(0, 0, LCD_WIDTH, 8);
1867 last_showfps = *rb->current_tick;
1869 break;
1872 default:
1873 break;
1875 rendering_finished:
1877 rb->yield();
1880 video_thread_quit:
1881 /* if video ends before time sync'd,
1882 besure the audio thread is closed */
1883 if (video_sync_start == 0)
1885 audio_str.status = STREAM_STOPPED;
1886 audio_sync_start = 1;
1889 #if NUM_CORES > 1
1890 flush_icache();
1891 #endif
1893 mpeg2_close (mpeg2dec);
1895 /* Commit suicide */
1896 video_str.status = STREAM_TERMINATED;
1899 void initialize_stream( Stream *str, uint8_t *buffer_start, size_t disk_buf_len, int id )
1901 str->curr_packet_end = str->curr_packet = NULL;
1902 str->prev_packet_length = 0;
1903 str->prev_packet = str->curr_packet_end = buffer_start;
1904 str->buffer_remaining = disk_buf_len;
1905 str->id = id;
1908 void display_thumb(int in_file)
1910 size_t disk_buf_len;
1912 video_thumb_print = 1;
1913 audio_sync_start = 1;
1914 video_sync_start = 1;
1916 disk_buf_len = rb->read (in_file, disk_buf_start, disk_buf_size - MPEG_GUARDBUF_SIZE);
1917 disk_buf_tail = disk_buf_start + disk_buf_len;
1918 file_remaining = 0;
1919 initialize_stream(&video_str,disk_buf_start,disk_buf_len,0xe0);
1921 video_str.status = STREAM_PLAYING;
1923 if ((video_str.thread = rb->create_thread(video_thread,
1924 (uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo"
1925 IF_PRIO(,PRIORITY_PLAYBACK)
1926 IF_COP(, COP, true))) == NULL)
1928 rb->splash(HZ, "Cannot create video thread!");
1930 else
1932 while (video_str.status != STREAM_TERMINATED)
1933 rb->yield();
1936 if ( video_str.curr_packet_end == video_str.curr_packet)
1937 rb->splash(0, "frame not available");
1940 int find_length( int in_file )
1942 uint8_t *p;
1943 size_t read_length = 60*1024;
1944 size_t disk_buf_len;
1946 play_time = 0;
1948 /* temporary read buffer size cannot exceed buffer size */
1949 if ( read_length > disk_buf_size )
1950 read_length = disk_buf_size;
1952 /* read tail of file */
1953 rb->lseek( in_file, -1*read_length, SEEK_END );
1954 disk_buf_len = rb->read( in_file, disk_buf_start, read_length );
1955 disk_buf_tail = disk_buf_start + disk_buf_len;
1957 /* sync reader to this segment of the stream */
1958 p=disk_buf_start;
1959 if (sync_data_stream(&p))
1961 DEBUGF("Could not sync stream\n");
1962 return PLUGIN_ERROR;
1965 /* find last PTS in audio stream; will movie always have audio? if
1966 the play time can not be determined, set play_time to 0 */
1967 audio_sync_start = 0;
1968 audio_sync_time = 0;
1969 video_sync_start = 0;
1971 Stream tmp;
1972 initialize_stream(&tmp,p,disk_buf_len-(disk_buf_start-p),0xc0);
1976 get_next_data(&tmp, 2);
1977 if (tmp.tagged == 1)
1978 /* 10 sec less to insure the video frame exist */
1979 play_time = (int)((tmp.curr_pts/45000-10)/30);
1981 while (tmp.curr_packet_end != NULL);
1983 return 0;
1986 ssize_t seek_PTS( int in_file, int start_time, int accept_button )
1988 static ssize_t last_seek_pos = 0;
1989 static int last_start_time = 0;
1990 ssize_t seek_pos;
1991 size_t disk_buf_len;
1992 uint8_t *p;
1993 size_t read_length = 60*1024;
1995 /* temporary read buffer size cannot exceed buffer size */
1996 if ( read_length > disk_buf_size )
1997 read_length = disk_buf_size;
1999 if ( start_time == last_start_time )
2001 seek_pos = last_seek_pos;
2002 rb->lseek(in_file,seek_pos,SEEK_SET);
2004 else if ( start_time != 0 )
2006 seek_pos = rb->filesize(in_file)*start_time/play_time;
2007 int seek_pos_sec_inc = rb->filesize(in_file)/play_time/30;
2009 if (seek_pos<0)
2010 seek_pos=0;
2011 if ((size_t)seek_pos > rb->filesize(in_file) - read_length)
2012 seek_pos = rb->filesize(in_file) - read_length;
2013 rb->lseek( in_file, seek_pos, SEEK_SET );
2014 disk_buf_len = rb->read( in_file, disk_buf_start, read_length );
2015 disk_buf_tail = disk_buf_start + disk_buf_len;
2017 /* sync reader to this segment of the stream */
2018 p=disk_buf_start;
2019 if (sync_data_stream(&p))
2021 DEBUGF("Could not sync stream\n");
2022 return PLUGIN_ERROR;
2025 /* find PTS >= start_time */
2026 audio_sync_start = 0;
2027 audio_sync_time = 0;
2028 video_sync_start = 0;
2030 Stream tmp;
2031 initialize_stream(&tmp,p,disk_buf_len-(disk_buf_start-p),0xc0);
2032 int cont_seek_loop = 1;
2033 int coarse_seek = 1;
2036 if ( accept_button )
2038 rb->yield();
2039 if (rb->button_queue_count())
2040 return -101;
2043 while ( get_next_data(&tmp, 1) == 1 )
2045 if ( tmp.curr_packet_end == disk_buf_start )
2046 seek_pos += disk_buf_tail - disk_buf_start;
2047 else
2048 seek_pos += tmp.curr_packet_end - disk_buf_start;
2049 if ((size_t)seek_pos > rb->filesize(in_file) - read_length)
2050 seek_pos = rb->filesize(in_file) - read_length;
2051 rb->lseek( in_file, seek_pos, SEEK_SET );
2052 disk_buf_len = rb->read ( in_file, disk_buf_start, read_length );
2053 disk_buf_tail = disk_buf_start + disk_buf_len;
2055 /* sync reader to this segment of the stream */
2056 p=disk_buf_start;
2057 initialize_stream(&tmp,p,disk_buf_len,0xc0);
2060 /* are we after start_time in the stream? */
2061 if ( coarse_seek && (int)(tmp.curr_pts/45000) >= start_time*30 )
2063 int time_to_backup = (int)(tmp.curr_pts/45000) - start_time*30;
2064 if (time_to_backup == 0)
2065 time_to_backup++;
2066 seek_pos -= seek_pos_sec_inc * time_to_backup;
2067 seek_pos_sec_inc -= seek_pos_sec_inc/20; /* for stability */
2068 if (seek_pos<0)
2069 seek_pos=0;
2070 if ((size_t)seek_pos > rb->filesize(in_file) - read_length)
2071 seek_pos = rb->filesize(in_file) - read_length;
2072 rb->lseek( in_file, seek_pos, SEEK_SET );
2073 disk_buf_len = rb->read( in_file, disk_buf_start, read_length );
2074 disk_buf_tail = disk_buf_start + disk_buf_len;
2076 /* sync reader to this segment of the stream */
2077 p=disk_buf_start;
2078 if (sync_data_stream(&p))
2080 DEBUGF("Could not sync stream\n");
2081 return PLUGIN_ERROR;
2083 initialize_stream(&tmp,p,disk_buf_len-(disk_buf_start-p),0xc0);
2084 continue;
2087 /* are we well before start_time in the stream? */
2088 if ( coarse_seek && start_time*30 - (int)(tmp.curr_pts/45000) > 2 )
2090 int time_to_advance = start_time*30 - (int)(tmp.curr_pts/45000) - 2;
2091 if (time_to_advance <= 0)
2092 time_to_advance = 1;
2093 seek_pos += seek_pos_sec_inc * time_to_advance;
2094 if (seek_pos<0)
2095 seek_pos=0;
2096 if ((size_t)seek_pos > rb->filesize(in_file) - read_length)
2097 seek_pos = rb->filesize(in_file) - read_length;
2098 rb->lseek( in_file, seek_pos, SEEK_SET );
2099 disk_buf_len = rb->read ( in_file, disk_buf_start, read_length );
2100 disk_buf_tail = disk_buf_start + disk_buf_len;
2102 /* sync reader to this segment of the stream */
2103 p=disk_buf_start;
2104 if (sync_data_stream(&p))
2106 DEBUGF("Could not sync stream\n");
2107 return PLUGIN_ERROR;
2109 initialize_stream(&tmp,p,disk_buf_len-(disk_buf_start-p),0xc0);
2110 continue;
2113 coarse_seek = 0;
2115 /* are we at start_time in the stream? */
2116 if ( (int)(tmp.curr_pts/45000) >= start_time*30 )
2117 cont_seek_loop = 0;
2120 while ( cont_seek_loop );
2123 DEBUGF("start diff: %u %u\n",(unsigned int)(tmp.curr_pts/45000),start_time*30);
2124 seek_pos+=tmp.curr_packet_end-disk_buf_start;
2126 last_seek_pos = seek_pos;
2127 last_start_time = start_time;
2129 rb->lseek(in_file,seek_pos,SEEK_SET);
2132 else
2134 seek_pos = 0;
2135 rb->lseek(in_file,0,SEEK_SET);
2136 last_seek_pos = seek_pos;
2137 last_start_time = start_time;
2139 return seek_pos;
2142 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
2144 int status = PLUGIN_ERROR; /* assume failure */
2145 int start_time=-1;
2146 void* audiobuf;
2147 ssize_t audiosize;
2148 int in_file;
2149 size_t disk_buf_len;
2150 ssize_t seek_pos;
2151 #ifndef HAVE_LCD_COLOR
2152 long graysize;
2153 int grayscales;
2154 #endif
2156 audio_sync_start = 0;
2157 audio_sync_time = 0;
2158 video_sync_start = 0;
2160 if (parameter == NULL)
2162 api->splash(HZ*2, "No File");
2163 return PLUGIN_ERROR;
2166 /* Initialize IRAM - stops audio and voice as well */
2167 PLUGIN_IRAM_INIT(api)
2169 rb = api;
2170 rb->splash(0, "loading ...");
2172 /* sets audiosize and returns buffer pointer */
2173 audiobuf = rb->plugin_get_audio_buffer(&audiosize);
2175 #if INPUT_SRC_CAPS != 0
2176 /* Select playback */
2177 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2178 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
2179 #endif
2181 rb->pcm_set_frequency(SAMPR_44);
2183 #ifndef HAVE_LCD_COLOR
2184 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */
2185 grayscales = gray_init(rb, audiobuf, audiosize, false, LCD_WIDTH, LCD_HEIGHT,
2186 32, 2<<8, &graysize) + 1;
2187 audiobuf += graysize;
2188 audiosize -= graysize;
2189 if (grayscales < 33 || audiosize <= 0)
2191 rb->splash(HZ, "gray buf error");
2192 return PLUGIN_ERROR;
2194 #endif
2196 /* Initialise our malloc buffer */
2197 audiosize = mpeg_alloc_init(audiobuf,audiosize, LIBMPEG2BUFFER_SIZE);
2198 if (audiosize == 0)
2199 return PLUGIN_ERROR;
2201 /* Set disk pointers to NULL */
2202 disk_buf_end = disk_buf_start = NULL;
2204 /* Grab most of the buffer for the compressed video - leave some for
2205 PCM audio data and some for libmpeg2 malloc use. */
2206 disk_buf_size = audiosize - (PCMBUFFER_SIZE+PCMBUFFER_GUARD_SIZE+
2207 MPABUF_SIZE);
2209 DEBUGF("audiosize=%ld, disk_buf_size=%ld\n",audiosize,disk_buf_size);
2210 disk_buf_start = mpeg_malloc(disk_buf_size,-1);
2212 if (disk_buf_start == NULL)
2213 return PLUGIN_ERROR;
2215 if (!init_mpabuf())
2216 return PLUGIN_ERROR;
2218 if (!init_pcmbuf())
2219 return PLUGIN_ERROR;
2221 /* The remaining buffer is for use by libmpeg2 */
2223 /* Open the video file */
2224 in_file = rb->open((char*)parameter,O_RDONLY);
2226 if (in_file < 0){
2227 DEBUGF("Could not open %s\n",(char*)parameter);
2228 return PLUGIN_ERROR;
2230 filename = (char*)parameter;
2232 #ifdef HAVE_LCD_COLOR
2233 rb->lcd_set_backdrop(NULL);
2234 rb->lcd_set_foreground(LCD_WHITE);
2235 rb->lcd_set_background(LCD_BLACK);
2236 #endif
2237 rb->lcd_clear_display();
2238 rb->lcd_update();
2240 /* Turn off backlight timeout */
2241 backlight_force_on(rb); /* backlight control in lib/helper.c */
2242 rb->talk_disable_menus();
2244 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
2245 rb->cpu_boost(true);
2246 #endif
2248 /* From this point on we've altered settings, colors, cpu_boost, etc. and
2249 cannot just return PLUGIN_ERROR - instead drop though to cleanup code
2252 init_settings((char*)parameter);
2254 /* Initialise libmad */
2255 rb->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
2256 init_mad(mad_frame_overlap);
2258 disk_buf_end = disk_buf_start + disk_buf_size-MPEG_GUARDBUF_SIZE;
2260 /* initalize play_time with the length (in half minutes) of the movie
2261 zero if the time could not be determined */
2262 find_length( in_file );
2264 /* start menu */
2265 start_time = mpeg_start_menu(play_time, in_file);
2266 if ( start_time == -1 )
2267 return 0;
2268 else if ( start_time < 0 )
2269 start_time = 0;
2270 else if ( start_time > play_time )
2271 start_time = play_time;
2273 rb->splash(0, "loading ...");
2275 /* seek start time */
2276 seek_pos = seek_PTS( in_file, start_time, 0 );
2278 rb->lseek(in_file,seek_pos,SEEK_SET);
2279 video_thumb_print = 0;
2280 audio_sync_start = 0;
2281 audio_sync_time = 0;
2282 video_sync_start = 0;
2284 /* Read some stream data */
2285 disk_buf_len = rb->read (in_file, disk_buf_start, disk_buf_size - MPEG_GUARDBUF_SIZE);
2287 disk_buf_tail = disk_buf_start + disk_buf_len;
2288 file_remaining = rb->filesize(in_file);
2289 file_remaining -= disk_buf_len + seek_pos;
2291 initialize_stream( &video_str, disk_buf_start, disk_buf_len, 0xe0 );
2292 initialize_stream( &audio_str, disk_buf_start, disk_buf_len, 0xc0 );
2294 rb->spinlock_init(&audio_str.msg_lock);
2295 rb->spinlock_init(&video_str.msg_lock);
2297 audio_str.status = STREAM_BUFFERING;
2298 video_str.status = STREAM_PLAYING;
2300 #ifndef HAVE_LCD_COLOR
2301 gray_show(true);
2302 #endif
2304 init_stream_lock();
2306 #if NUM_CORES > 1
2307 flush_icache();
2308 #endif
2310 /* We put the video thread on the second processor for multi-core targets. */
2311 if ((video_str.thread = rb->create_thread(video_thread,
2312 (uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK)
2313 IF_COP(, COP, true))) == NULL)
2315 rb->splash(HZ, "Cannot create video thread!");
2317 else if ((audio_str.thread = rb->create_thread(audio_thread,
2318 (uint8_t*)audio_stack,AUDIO_STACKSIZE,"mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK)
2319 IF_COP(, CPU, false))) == NULL)
2321 rb->splash(HZ, "Cannot create audio thread!");
2323 else
2325 rb->lcd_setfont(FONT_SYSFIXED);
2327 /* Wait until both threads have finished their work */
2328 while ((audio_str.status >= 0) || (video_str.status >= 0))
2330 size_t audio_remaining = audio_str.buffer_remaining;
2331 size_t video_remaining = video_str.buffer_remaining;
2333 if (MIN(audio_remaining,video_remaining) < MPEG_LOW_WATERMARK)
2336 size_t bytes_to_read = disk_buf_size - MPEG_GUARDBUF_SIZE -
2337 MAX(audio_remaining,video_remaining);
2339 bytes_to_read = MIN(bytes_to_read,(size_t)(disk_buf_end-disk_buf_tail));
2341 while (( bytes_to_read > 0) && (file_remaining > 0) &&
2342 ((audio_str.status != STREAM_DONE) || (video_str.status != STREAM_DONE)))
2345 size_t n;
2346 if ( video_sync_start != 0 )
2347 n = rb->read(in_file, disk_buf_tail, MIN(32*1024,bytes_to_read));
2348 else
2350 n = rb->read(in_file, disk_buf_tail,bytes_to_read);
2351 if (n==0)
2352 rb->splash(30,"buffer fill error");
2356 bytes_to_read -= n;
2357 file_remaining -= n;
2359 lock_stream();
2360 audio_str.buffer_remaining += n;
2361 video_str.buffer_remaining += n;
2362 unlock_stream();
2364 disk_buf_tail += n;
2366 rb->yield();
2369 if (disk_buf_tail == disk_buf_end)
2370 disk_buf_tail = disk_buf_start;
2373 rb->sleep(HZ/10);
2376 rb->lcd_setfont(FONT_UI);
2377 status = PLUGIN_OK;
2380 /* Stop the threads and wait for them to terminate */
2381 if (video_str.thread != NULL)
2382 str_send_msg(&video_str, STREAM_QUIT, 0);
2384 if (audio_str.thread != NULL)
2385 str_send_msg(&audio_str, STREAM_QUIT, 0);
2387 rb->sleep(HZ/10);
2389 #if NUM_CORES > 1
2390 invalidate_icache();
2391 #endif
2393 vo_cleanup();
2395 #ifndef HAVE_LCD_COLOR
2396 gray_release();
2397 #endif
2399 rb->lcd_clear_display();
2400 rb->lcd_update();
2402 mpeg2_close (mpeg2dec);
2404 rb->close (in_file);
2406 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
2407 rb->cpu_boost(false);
2408 #endif
2410 save_settings(); /* Save settings (if they have changed) */
2412 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
2414 /* Turn on backlight timeout (revert to settings) */
2415 backlight_use_settings(rb); /* backlight control in lib/helper.c */
2416 rb->talk_enable_menus();
2418 return status;