just pass the struct to vo_setup instead of multiple arguments
[Rockbox.git] / apps / plugins / mpegplayer / mpegplayer.c
bloba2e22ed2bd36fe7b8cceca1036939ef1c917fa82
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>
8 *
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"
108 #include "mpeg2.h"
109 #include "mpeg_settings.h"
110 #include "video_out.h"
111 #include "../../codecs/libmad/mad.h"
113 PLUGIN_HEADER
114 PLUGIN_IRAM_DECLARE
116 /* button definitions */
117 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
118 #define MPEG_MENU BUTTON_MODE
119 #define MPEG_STOP BUTTON_OFF
120 #define MPEG_PAUSE BUTTON_ON
121 #define MPEG_VOLDOWN BUTTON_DOWN
122 #define MPEG_VOLUP BUTTON_UP
124 #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
125 #define MPEG_MENU BUTTON_MENU
126 #define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL)
127 #define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT)
128 #define MPEG_VOLDOWN BUTTON_SCROLL_BACK
129 #define MPEG_VOLUP BUTTON_SCROLL_FWD
131 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
132 #define MPEG_MENU (BUTTON_REC | BUTTON_REL)
133 #define MPEG_STOP BUTTON_POWER
134 #define MPEG_PAUSE BUTTON_PLAY
135 #define MPEG_VOLDOWN BUTTON_DOWN
136 #define MPEG_VOLUP BUTTON_UP
138 #elif CONFIG_KEYPAD == GIGABEAT_PAD
139 #define MPEG_MENU BUTTON_MENU
140 #define MPEG_STOP BUTTON_A
141 #define MPEG_PAUSE BUTTON_SELECT
142 #define MPEG_VOLDOWN BUTTON_LEFT
143 #define MPEG_VOLUP BUTTON_RIGHT
144 #define MPEG_VOLDOWN2 BUTTON_VOL_DOWN
145 #define MPEG_VOLUP2 BUTTON_VOL_UP
147 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
148 #define MPEG_MENU (BUTTON_REW | BUTTON_REL)
149 #define MPEG_STOP BUTTON_POWER
150 #define MPEG_PAUSE BUTTON_PLAY
151 #define MPEG_VOLDOWN BUTTON_SCROLL_DOWN
152 #define MPEG_VOLUP BUTTON_SCROLL_UP
154 #elif CONFIG_KEYPAD == SANSA_E200_PAD
155 #define MPEG_MENU BUTTON_SELECT
156 #define MPEG_STOP BUTTON_POWER
157 #define MPEG_PAUSE BUTTON_UP
158 #define MPEG_VOLDOWN BUTTON_SCROLL_UP
159 #define MPEG_VOLUP BUTTON_SCROLL_DOWN
161 #else
162 #error MPEGPLAYER: Unsupported keypad
163 #endif
165 struct plugin_api* rb;
167 static mpeg2dec_t * mpeg2dec;
168 static int total_offset = 0;
170 /* Streams */
171 typedef struct
173 uint8_t* curr_packet; /* Current stream packet beginning */
174 uint8_t* curr_packet_end; /* Current stream packet end */
176 uint8_t* prev_packet; /* Previous stream packet beginning */
177 uint8_t* next_packet; /* Next stream packet beginning */
179 size_t guard_bytes; /* Number of bytes in guardbuf used */
180 size_t buffer_remaining; /* How much data is left in the buffer */
181 uint32_t first_pts;
182 uint32_t curr_pts;
183 int id;
184 } Stream;
186 static Stream audio_str IBSS_ATTR;
187 static Stream video_str IBSS_ATTR;
189 /* NOTE: Putting the following variables in IRAM cause audio corruption
190 on the ipod (reason unknown)
192 static uint8_t *disk_buf, *disk_buf_end;
193 static uint8_t *disk_buf_tail IBSS_ATTR;
194 static size_t buffer_size IBSS_ATTR;
196 /* Events */
197 static struct event_queue msg_queue IBSS_ATTR;
199 #define MSG_BUFFER_NEARLY_EMPTY 1
200 #define MSG_EXIT_REQUESTED 2
202 /* Threads */
203 static struct thread_entry* audiothread_id;
204 static struct thread_entry* videothread_id;
206 /* Status */
207 #define STREAM_PLAYING 0
208 #define STREAM_DONE 1
209 #define STREAM_PAUSING 2
210 #define STREAM_BUFFERING 3
211 #define STREAM_ERROR 4
212 #define PLEASE_STOP 5
213 #define PLEASE_PAUSE 6
215 int audiostatus IBSS_ATTR;
216 int videostatus IBSS_ATTR;
218 /* Various buffers */
219 /* TODO: Can we reduce the PCM buffer size? */
220 #define PCMBUFFER_SIZE (512*1024)
221 #define AUDIOBUFFER_SIZE (32*1024)
222 #define LIBMPEG2BUFFER_SIZE (2*1024*1024)
224 /* TODO: Is 32KB enough? */
225 #define MPEG_GUARDBUF_SIZE (32*1024)
226 #define MPEG_LOW_WATERMARK (1024*1024)
228 static void button_loop(void)
230 bool result;
231 int vol, minvol, maxvol;
232 int button = rb->button_get(false);
234 switch (button)
236 case MPEG_VOLUP:
237 case MPEG_VOLUP|BUTTON_REPEAT:
238 #ifdef MPEG_VOLUP2
239 case MPEG_VOLUP2:
240 case MPEG_VOLUP2|BUTTON_REPEAT:
241 #endif
242 vol = rb->global_settings->volume;
243 maxvol = rb->sound_max(SOUND_VOLUME);
245 if (vol < maxvol) {
246 vol++;
247 rb->sound_set(SOUND_VOLUME, vol);
248 rb->global_settings->volume = vol;
250 break;
252 case MPEG_VOLDOWN:
253 case MPEG_VOLDOWN|BUTTON_REPEAT:
254 #ifdef MPEG_VOLDOWN2
255 case MPEG_VOLDOWN2:
256 case MPEG_VOLDOWN2|BUTTON_REPEAT:
257 #endif
258 vol = rb->global_settings->volume;
259 minvol = rb->sound_min(SOUND_VOLUME);
261 if (vol > minvol) {
262 vol--;
263 rb->sound_set(SOUND_VOLUME, vol);
264 rb->global_settings->volume = vol;
266 break;
268 case MPEG_MENU:
269 rb->pcm_play_pause(false);
270 if (videostatus != STREAM_DONE) {
271 videostatus=PLEASE_PAUSE;
273 /* Wait for video thread to stop */
274 while (videostatus == PLEASE_PAUSE) { rb->sleep(HZ/25); }
277 #ifndef HAVE_LCD_COLOR
278 gray_show(false);
279 #endif
280 result = mpeg_menu();
282 #ifndef HAVE_LCD_COLOR
283 gray_show(true);
284 #endif
286 /* The menu can change the font, so restore */
287 rb->lcd_setfont(FONT_SYSFIXED);
289 if (result) {
290 audiostatus = PLEASE_STOP;
291 if (videostatus != STREAM_DONE) videostatus = PLEASE_STOP;
292 } else {
293 if (videostatus != STREAM_DONE) videostatus = STREAM_PLAYING;
294 rb->pcm_play_pause(true);
296 break;
298 case MPEG_STOP:
299 audiostatus = PLEASE_STOP;
300 if (videostatus != STREAM_DONE) videostatus = PLEASE_STOP;
301 break;
303 case MPEG_PAUSE:
304 if (videostatus != STREAM_DONE) videostatus=PLEASE_PAUSE;
305 rb->pcm_play_pause(false);
307 button = BUTTON_NONE;
308 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
309 rb->cpu_boost(false);
310 #endif
311 do {
312 button = rb->button_get(true);
313 if (button == MPEG_STOP) {
314 audiostatus = PLEASE_STOP;
315 if (videostatus != STREAM_DONE) videostatus = PLEASE_STOP;
316 return;
318 } while (button != MPEG_PAUSE);
320 if (videostatus != STREAM_DONE) videostatus = STREAM_PLAYING;
321 rb->pcm_play_pause(true);
322 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
323 rb->cpu_boost(true);
324 #endif
325 break;
327 default:
328 if(rb->default_event_handler(button) == SYS_USB_CONNECTED) {
329 audiostatus = PLEASE_STOP;
330 if (videostatus != STREAM_DONE) videostatus = PLEASE_STOP;
335 /* libmad related functions/definitions */
336 #define INPUT_CHUNK_SIZE 8192
338 struct mad_stream stream IBSS_ATTR;
339 struct mad_frame frame IBSS_ATTR;
340 struct mad_synth synth IBSS_ATTR;
342 unsigned char mad_main_data[MAD_BUFFER_MDLEN]; /* 2567 bytes */
344 static void init_mad(void* mad_frame_overlap)
346 rb->memset(&stream, 0, sizeof(struct mad_stream));
347 rb->memset(&frame, 0, sizeof(struct mad_frame));
348 rb->memset(&synth, 0, sizeof(struct mad_synth));
350 mad_stream_init(&stream);
351 mad_frame_init(&frame);
353 /* We do this so libmad doesn't try to call codec_calloc() */
354 frame.overlap = mad_frame_overlap;
356 rb->memset(mad_main_data, 0, sizeof(mad_main_data));
357 stream.main_data = &mad_main_data;
360 /* MPEG related headers */
361 uint8_t packet_start_code_prefix [3] = { 0x00, 0x00, 0x01 };
362 uint8_t end_code [4] = { 0x00, 0x00, 0x01, 0xb9 };
363 uint8_t pack_start_code [4] = { 0x00, 0x00, 0x01, 0xba };
364 uint8_t system_header_start_code [4] = { 0x00, 0x00, 0x01, 0xbb };
366 /* This function demux the streams and give the next stream data pointer */
367 static void get_next_data( Stream* str )
369 uint8_t *p;
370 uint8_t *header;
371 int stream;
373 static int mpeg1_skip_table[16] = {
374 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
377 if (str->curr_packet_end == NULL) {
378 /* What does this do? */
379 while( (p = disk_buf) == NULL )
381 rb->lcd_putsxy(0,LCD_HEIGHT-10,"FREEZE!");
382 rb->lcd_update();
383 rb->sleep(100);
385 } else {
386 p = str->curr_packet_end;
389 for( ;; )
391 int length, bytes;
393 if( p >= disk_buf_end )
395 p = disk_buf + (p - disk_buf_end);
398 /* Pack header, skip it */
399 if( rb->memcmp (p, pack_start_code, sizeof (pack_start_code)) == 0 )
401 if ((p[4] & 0xc0) == 0x40) { /* mpeg-2 */
402 p += 14 + (p[13] & 7);
403 } else if ((p[4] & 0xf0) == 0x20) { /* mpeg-1 */
404 p += 12;
405 } else {
406 rb->splash( 30, "Weird Pack header!" );
407 p += 5;
409 /*rb->splash( 30, "Pack header" );*/
412 /* System header, parse and skip it */
413 if( rb->memcmp (p, system_header_start_code, sizeof (system_header_start_code)) == 0 )
415 int header_length;
417 p += 4; /*skip start code*/
418 header_length = (*(p++)) << 8;
419 header_length += *(p++);
421 p += header_length;
422 /*rb->splash( 30, "System header" );*/
425 /* Packet header, parse it */
426 if( rb->memcmp (p, packet_start_code_prefix, sizeof (packet_start_code_prefix)) != 0 )
428 /* Problem */
429 //rb->splash( HZ*3, "missing packet start code prefix : %X%X at %X", *p, *(p+2), p-disk_buf );
430 str->curr_packet_end = str->curr_packet = NULL;
431 return;
432 //++p;
433 break;
436 /* We retrieve basic infos */
437 stream = *(p+3);
438 length = (*(p+4)) << 8;
439 length += *(p+5);
441 /*rb->splash( 100, "Stream : %X", stream );*/
442 if (stream != str->id)
444 /* End of stream ? */
445 if( stream == 0xB9 )
447 str->curr_packet_end = str->curr_packet = NULL;
448 return;
451 /* It's not the packet we're looking for, skip it */
452 p += length+6;
453 continue;
456 /* Ok, it's our packet */
457 str->curr_packet_end = p + length+6;
458 header = p;
459 if ((header[6] & 0xc0) == 0x80) { /* mpeg2 */
461 length = 9 + header[8];
462 /* header points to the mpeg2 pes header */
463 if (header[7] & 0x80) {
464 uint32_t pts, dts;
466 pts = (((header[9] >> 1) << 30) |
467 (header[10] << 22) | ((header[11] >> 1) << 15) |
468 (header[12] << 7) | (header[13] >> 1));
470 if (str->first_pts==0)
471 str->first_pts = pts;
473 str->curr_pts = pts;
475 dts = (!(header[7] & 0x40) ? pts :
476 ((uint32_t)(((header[14] >> 1) << 30) |
477 (header[15] << 22) |
478 ((header[16] >> 1) << 15) |
479 (header[17] << 7) | (header[18] >> 1))));
481 if( stream >= 0xe0 )
482 mpeg2_tag_picture (mpeg2dec, pts, dts);
484 } else { /* mpeg1 */
485 int len_skip;
486 uint8_t * ptsbuf;
488 length = 7;
489 while (header[length - 1] == 0xff)
491 length++;
492 if (length > 23)
494 rb->splash( 30, "Too much stuffing" );
495 DEBUGF("Too much stuffing" );
496 break;
499 if ((header[length - 1] & 0xc0) == 0x40)
501 length += 2;
503 len_skip = length;
504 length += mpeg1_skip_table[header[length - 1] >> 4];
506 /* header points to the mpeg1 pes header */
507 ptsbuf = header + len_skip;
508 if ((ptsbuf[-1] & 0xe0) == 0x20)
510 uint32_t pts, dts;
512 pts = (((ptsbuf[-1] >> 1) << 30) |
513 (ptsbuf[0] << 22) | ((ptsbuf[1] >> 1) << 15) |
514 (ptsbuf[2] << 7) | (ptsbuf[3] >> 1));
516 if (str->first_pts==0)
517 str->first_pts = pts;
519 str->curr_pts = pts;
521 dts = (((ptsbuf[-1] & 0xf0) != 0x30) ? pts :
522 ((uint32_t)(((ptsbuf[4] >> 1) << 30) |
523 (ptsbuf[5] << 22) | ((ptsbuf[6] >> 1) << 15) |
524 (ptsbuf[7] << 7) | (ptsbuf[18] >> 1))));
526 if( stream >= 0xe0 )
527 mpeg2_tag_picture (mpeg2dec, pts, dts);
531 p += length;
532 bytes = 6 + (header[4] << 8) + header[5] - length;
533 if (bytes > 0) {
534 str->curr_packet_end = p+bytes;
535 //DEBUGF("prev = %d, curr = %d\n",str->prev_packet,str->curr_packet);
537 if (str->curr_packet != NULL) {
538 if (str->curr_packet < str->prev_packet) {
539 str->buffer_remaining -= (disk_buf_end - str->prev_packet) + (str->curr_packet - disk_buf);
540 str->buffer_remaining -= str->guard_bytes;
541 str->guard_bytes = 0;
542 } else {
543 str->buffer_remaining -= (str->curr_packet - str->prev_packet);
546 str->prev_packet = str->curr_packet;
549 str->curr_packet = p;
551 if( str->curr_packet_end > disk_buf_end )
553 str->guard_bytes = str->curr_packet_end-disk_buf_end;
554 rb->memcpy(disk_buf_end,disk_buf,str->guard_bytes);
556 return ;
559 break;
563 uint8_t* mpa_buffer;
564 size_t mpa_buffer_size;
566 static volatile int madpcm_playing IBSS_ATTR;
567 static volatile int16_t* pcm_buffer IBSS_ATTR;
568 static volatile size_t pcm_buffer_size IBSS_ATTR;
570 static volatile size_t pcmbuf_len IBSS_ATTR;
571 static volatile int16_t* pcmbuf_end IBSS_ATTR;
572 static volatile int16_t* pcmbuf_head IBSS_ATTR;
573 static volatile int16_t* pcmbuf_tail IBSS_ATTR;
575 static volatile uint32_t samplesplayed IBSS_ATTR;
576 static volatile int delay IBSS_ATTR;
578 static void init_pcmbuf(void)
580 pcmbuf_head = pcm_buffer;
581 pcmbuf_len = 0;
582 pcmbuf_tail = pcm_buffer;
583 pcmbuf_end = pcm_buffer + pcm_buffer_size / sizeof(int16_t);
584 madpcm_playing = 0;
587 static void get_more(unsigned char** start, size_t* size)
589 if (pcmbuf_len < 32*1024) {
590 *start = NULL;
591 *size = 0;
592 madpcm_playing = 0;
593 pcmbuf_len = 0;
594 } else {
595 *start = (unsigned char*)(pcmbuf_tail);
596 *size = 32*1024;
597 pcmbuf_tail += (32*1024)/sizeof(int16_t);
598 pcmbuf_len -= 32*1024;
599 if (pcmbuf_tail >= pcmbuf_end) { pcmbuf_tail = pcm_buffer; }
601 /* Update master clock */
602 samplesplayed += (32*1024)/4;
606 int line;
608 static void audio_thread(void)
610 int32_t* left;
611 int32_t* right;
612 int32_t sample;
613 int i;
614 size_t n = 0;
615 size_t len;
616 int file_end = 0; /* A count of the errors in each frame */
617 int framelength;
618 int found_avdelay = 0;
619 int avdelay = 0; /* Number of audio samples difference between first audio and video PTS values. */
620 int64_t apts_samples;
621 uint32_t samplesdecoded = 0;
623 /* We need this here to init the EMAC for Coldfire targets */
624 mad_synth_init(&synth);
626 init_pcmbuf();
628 /* This is the decoding loop. */
629 for (;;) {
630 button_loop();
632 if (!found_avdelay) {
633 if ((audio_str.first_pts != 0) && (video_str.first_pts != 0)) {
634 avdelay = audio_str.first_pts - video_str.first_pts;
635 avdelay *= 44100;
636 avdelay /= 90000;
637 found_avdelay = 1;
638 DEBUGF("First Audio PTS = %u, First Video PTS=%u, A-V=%d samples\n",(unsigned int)audio_str.first_pts,(unsigned int)video_str.first_pts,avdelay);
642 if (audiostatus == PLEASE_STOP) {
643 goto done;
646 if (n < 1500) { /* TODO: What is the maximum size of an MPEG audio frame? */
647 get_next_data( &audio_str );
648 if (audio_str.curr_packet == NULL) {
649 /* Wait for audio to finish */
650 while (pcmbuf_len > 0) { rb->sleep(HZ/10); }
651 goto done;
654 len = audio_str.curr_packet_end - audio_str.curr_packet;
655 if (n + len > mpa_buffer_size) {
656 rb->splash( 30, "Audio buffer overflow" );
657 DEBUGF("Audio buffer overflow" );
658 audiostatus=STREAM_DONE;
659 /* Wait to be killed */
660 for (;;) { rb->sleep(HZ); }
662 rb->memcpy(mpa_buffer+n,audio_str.curr_packet,len);
663 n += len;
666 /* Lock buffers */
667 if (stream.error == 0) {
668 mad_stream_buffer(&stream, mpa_buffer, n);
671 if (mad_frame_decode(&frame, &stream)) {
672 DEBUGF("Audio stream error - %d\n",stream.error);
673 if (stream.error == MAD_FLAG_INCOMPLETE
674 || stream.error == MAD_ERROR_BUFLEN) {
675 /* This makes the codec support partially corrupted files */
676 if (file_end == 30)
677 break;
679 #if 0
680 /* The mpa.c version: */
681 if (stream.next_frame)
682 inputbuffer = stream.next_frame;
683 else
684 inputbuffer++;
685 #endif
687 stream.error = 0;
688 file_end++;
689 continue;
690 } else if (MAD_RECOVERABLE(stream.error)) {
691 continue;
692 } else {
693 /* Some other unrecoverable error */
694 DEBUGF("Unrecoverable error\n");
695 break;
697 break;
700 file_end = 0;
702 mad_synth_frame(&synth, &frame);
704 /* TODO: Don't memmove so much... */
705 if (stream.next_frame) {
706 len = stream.next_frame - mpa_buffer;
707 rb->memmove(mpa_buffer,stream.next_frame,n-len);
708 n -= len;
709 } else {
710 /* What to do here? */
711 DEBUGF("/* What to do here? */\n");
712 goto done;
714 #if 0
715 /* The mpa.c version: */
716 if (stream.next_frame)
717 inputbuffer = stream.next_frame;
718 else
719 inputbuffer = inputbuffer_end;
720 #endif
722 framelength = synth.pcm.length;
723 samplesdecoded += framelength;
725 if (found_avdelay) {
726 apts_samples = (audio_str.curr_pts-audio_str.first_pts);
727 apts_samples *= 44100;
728 apts_samples /= 90000;
729 delay = (int)(avdelay+apts_samples-samplesdecoded);
730 //DEBUGF("delay=%d\n",delay);
733 if (framelength > 0) {
734 /* Leave at least 32KB free (this will be the currently playing chunk) */
735 while (pcmbuf_len + framelength*4 + 32*1024 > pcm_buffer_size) { rb->yield(); }
737 if (MAD_NCHANNELS(&frame.header) == 2) {
738 left = &synth.pcm.samples[0][0];
739 right = &synth.pcm.samples[1][0];
740 for (i = 0 ; i < framelength; i++) {
741 /* libmad outputs s3.28 */
742 sample = *(left++) >> 13;
743 if (sample > 32767)
744 sample = 32767;
745 else if (sample < -32768)
746 sample = -32768;
747 *(pcmbuf_head++) = sample;
749 sample = *(right++) >> 13;
750 if (sample > 32767)
751 sample = 32767;
752 else if (sample < -32768)
753 sample = -32768;
754 *(pcmbuf_head++) = sample;
756 if (pcmbuf_head >= pcmbuf_end) { pcmbuf_head = pcm_buffer; }
758 } else { /* mono */
759 left = &synth.pcm.samples[0][0];
760 for (i = 0 ; i < framelength; i++) {
761 sample = *(left++) >> 13;
763 if (sample > 32767)
764 sample = 32767;
765 else if (sample < -32768)
766 sample = -32768;
768 *(pcmbuf_head++) = sample;
769 *(pcmbuf_head++) = sample;
770 if (pcmbuf_head >= pcmbuf_end) { pcmbuf_head = pcm_buffer; }
774 /* TODO: Disable interrupts for Coldfire? */
776 /* pcmbuf_len is also modified by the FIQ handler (in
777 get_more), so we disable the FIQ TODO: Add sempahore so we
778 don't change whilst get_more is running. */
780 #ifdef CPU_ARM
781 disable_fiq();
782 #endif
783 pcmbuf_len += framelength*4;
784 #ifdef CPU_ARM
785 enable_fiq();
786 #endif
787 if ((!madpcm_playing) && (pcmbuf_len > 64*1024)) {
788 madpcm_playing = 1;
789 rb->pcm_play_data(get_more,NULL,0);
790 audiostatus = STREAM_PLAYING;
793 rb->yield();
796 done:
797 rb->pcm_play_stop();
798 audiostatus=STREAM_DONE;
800 for (;;) {
801 button_loop();
802 rb->sleep(HZ/4);
806 /* End of libmad stuff */
808 static int64_t eta IBSS_ATTR;
810 /* TODO: Running in the main thread, libmad needs 8.25KB of stack.
811 The codec thread uses a 9KB stack. So we can probable reduce this a
812 little, but leave at 9KB for now to be safe. */
813 #define AUDIO_STACKSIZE (9*1024)
814 uint32_t audio_stack[AUDIO_STACKSIZE / sizeof(uint32_t)] IBSS_ATTR;
816 /* TODO: Check if 4KB is appropriate - it works for my test streams,
817 so maybe we can reduce it. */
818 #define VIDEO_STACKSIZE (4*1024)
819 static uint32_t video_stack[VIDEO_STACKSIZE / sizeof(uint32_t)] IBSS_ATTR;
821 static void video_thread(void)
823 const mpeg2_info_t * info;
824 mpeg2_state_t state;
825 char str[80];
826 int skipped = 0;
827 int skipcount = 0;
828 int frame = 0;
829 int lasttick;
830 int64_t eta2;
831 int64_t s;
832 int64_t fps;
834 rb->sleep(HZ/5);
835 mpeg2dec = mpeg2_init ();
837 if (mpeg2dec == NULL) {
838 videostatus = STREAM_ERROR;
839 rb->splash(0, "mpeg2_init failed");
840 /* Commit suicide */
841 rb->remove_thread(NULL);
844 /* Clear the display - this is mainly just to indicate that the
845 video thread has started successfully. */
846 rb->lcd_clear_display();
847 rb->lcd_update();
849 /* Used to decide when to display FPS */
850 lasttick = *rb->current_tick - HZ;
852 /* Request the first packet data */
853 get_next_data( &video_str );
854 mpeg2_buffer (mpeg2dec, video_str.curr_packet, video_str.curr_packet_end);
855 total_offset += video_str.curr_packet_end - video_str.curr_packet;
857 info = mpeg2_info (mpeg2dec);
858 while (1) {
859 if (videostatus == PLEASE_STOP) {
860 goto done;
861 } else if (videostatus == PLEASE_PAUSE) {
862 videostatus = STREAM_PAUSING;
863 while (videostatus == STREAM_PAUSING) { rb->sleep(HZ/10); }
865 state = mpeg2_parse (mpeg2dec);
866 rb->yield();
868 switch (state) {
869 case STATE_BUFFER:
870 /* Request next packet data */
871 get_next_data( &video_str );
872 mpeg2_buffer (mpeg2dec, video_str.curr_packet, video_str.curr_packet_end);
873 total_offset += video_str.curr_packet_end - video_str.curr_packet;
874 info = mpeg2_info (mpeg2dec);
875 if (video_str.curr_packet == NULL) {
876 /* No more data. */
877 goto done;
879 continue;
881 case STATE_SEQUENCE:
882 vo_setup(info->sequence);
883 mpeg2_skip (mpeg2dec, false);
885 break;
886 case STATE_PICTURE:
887 break;
888 case STATE_SLICE:
889 case STATE_END:
890 case STATE_INVALID_END:
891 /* draw current picture */
892 if (info->display_fbuf) {
893 /* Wait if the audio thread is buffering - i.e. before
894 the first frames are decoded */
895 while (audiostatus == STREAM_BUFFERING) {
896 rb->sleep(1);
898 eta += (info->sequence->frame_period);
900 /* Convert eta (in 27MHz ticks) into audio samples */
901 eta2 =(eta * 44100) / 27000000;
903 eta2 -= delay;
905 s = samplesplayed - (rb->pcm_get_bytes_waiting() >> 2);
906 if (settings.limitfps) {
907 if (eta2 > s) {
908 rb->sleep(4); //((eta2-s)*HZ)/44100);
912 /* If we are more than 3/20 second behind schedule (and
913 more than 3/20 second into the decoding), skip frame.
914 But don't skip more than 10 consecutive frames. */
915 if (settings.skipframes && (s > ((3*44100)/20)) &&
916 (eta2 < (s - ((3*44100)/20))) && (skipcount < 10)) {
917 skipped++;
918 skipcount++;
919 } else {
920 vo_draw_frame(info->display_fbuf->buf);
921 skipcount = 0;
924 /* Calculate fps */
925 frame++;
926 if (settings.showfps && (*rb->current_tick-lasttick>=HZ)) {
927 fps=frame;
928 fps*=441000;
929 fps/=s;
930 rb->snprintf(str,sizeof(str),"%d.%d %d %d",
931 (int)(fps/10),(int)(fps%10),skipped,delay);
932 rb->lcd_putsxy(0,0,str);
933 rb->lcd_update_rect(0,0,LCD_WIDTH,8);
935 lasttick = *rb->current_tick;
938 break;
939 default:
940 break;
943 rb->yield();
946 done:
947 videostatus = STREAM_DONE;
948 /* Commit suicide */
949 rb->remove_thread(NULL);
952 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
954 void* audiobuf;
955 int audiosize;
956 int in_file;
957 uint8_t* buffer;
958 size_t audio_remaining, video_remaining;
959 size_t bytes_to_read;
960 size_t file_remaining;
961 size_t n;
962 size_t disk_buf_len;
963 #ifndef HAVE_LCD_COLOR
964 long graysize;
965 int grayscales;
966 #endif
968 /* We define this here so it is on the main stack (in IRAM) */
969 mad_fixed_t mad_frame_overlap[2][32][18]; /* 4608 bytes */
971 /* This also stops audio playback - so we do it before using IRAM */
972 audiobuf = api->plugin_get_audio_buffer(&audiosize);
974 PLUGIN_IRAM_INIT(api)
975 rb = api;
977 /* Set disk pointers to NULL */
978 disk_buf_end = disk_buf = NULL;
980 /* Stream construction */
981 /* We take the first stream of each (audio and video) */
982 /* TODO : Search for these in the file first */
983 audio_str.curr_packet_end = audio_str.curr_packet = audio_str.next_packet = NULL;
984 video_str = audio_str;
985 video_str.id = 0xe0;
986 audio_str.id = 0xc0;
988 /* Initialise our malloc buffer */
989 mpeg2_alloc_init(audiobuf,audiosize);
991 /* Grab most of the buffer for the compressed video - leave some for
992 PCM audio data and some for libmpeg2 malloc use. */
993 buffer_size = audiosize - (PCMBUFFER_SIZE+AUDIOBUFFER_SIZE+LIBMPEG2BUFFER_SIZE);
995 DEBUGF("audiosize=%d, buffer_size=%ld\n",audiosize,buffer_size);
996 buffer = mpeg2_malloc(buffer_size,-1);
998 if (buffer == NULL)
999 return PLUGIN_ERROR;
1001 #ifndef HAVE_LCD_COLOR
1002 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */
1003 grayscales = gray_init(rb, buffer, buffer_size, false, LCD_WIDTH, LCD_HEIGHT,
1004 32, 2<<8, &graysize) + 1;
1005 buffer += graysize;
1006 buffer_size -= graysize;
1007 if (grayscales < 33 || buffer_size <= 0)
1009 rb->splash(HZ, "gray buf error");
1010 return PLUGIN_ERROR;
1012 #endif
1014 buffer_size &= ~(0x7ff); /* Round buffer down to nearest 2KB */
1015 DEBUGF("audiosize=%d, buffer_size=%ld\n",audiosize,buffer_size);
1017 mpa_buffer_size = AUDIOBUFFER_SIZE;
1018 mpa_buffer = mpeg2_malloc(mpa_buffer_size,-2);
1020 if (mpa_buffer == NULL)
1021 return PLUGIN_ERROR;
1023 pcm_buffer_size = PCMBUFFER_SIZE;
1024 pcm_buffer = mpeg2_malloc(pcm_buffer_size,-2);
1026 if (pcm_buffer == NULL)
1027 return PLUGIN_ERROR;
1029 /* The remaining buffer is for use by libmpeg2 */
1031 #ifdef HAVE_LCD_COLOR
1032 rb->lcd_set_backdrop(NULL);
1033 rb->lcd_set_foreground(LCD_WHITE);
1034 rb->lcd_set_background(LCD_BLACK);
1035 #endif
1036 rb->lcd_clear_display();
1037 rb->lcd_update();
1039 if (parameter == NULL) {
1040 return PLUGIN_ERROR;
1043 /* Open the video file */
1044 in_file = rb->open((char*)parameter,O_RDONLY);
1046 if (in_file < 0) {
1047 //fprintf(stderr,"Could not open %s\n",argv[1]);
1048 return PLUGIN_ERROR;
1051 init_settings();
1053 rb->queue_init( &msg_queue, false ); /* Msg queue init */
1055 /* make sure the backlight is always on when viewing video
1056 (actually it should also set the timeout when plugged in,
1057 but the function backlight_set_timeout_plugged is not
1058 available in plugins) */
1059 #if CONFIG_BACKLIGHT
1060 if (rb->global_settings->backlight_timeout > 0)
1061 rb->backlight_set_timeout(1);
1062 #endif
1064 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1065 rb->cpu_boost(true);
1066 #endif
1068 /* Initialise libmad */
1069 rb->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
1070 init_mad(mad_frame_overlap);
1072 eta = 0;
1074 file_remaining = rb->filesize(in_file);
1075 disk_buf_end = buffer + buffer_size-MPEG_GUARDBUF_SIZE;
1077 disk_buf_len = rb->read (in_file, buffer, MPEG_LOW_WATERMARK);
1079 DEBUGF("Initial Buffering - %d bytes\n",(int)disk_buf_len);
1080 disk_buf = buffer;
1081 disk_buf_tail = buffer+disk_buf_len;
1082 file_remaining -= disk_buf_len;
1084 video_str.guard_bytes = audio_str.guard_bytes = 0;
1085 video_str.first_pts = audio_str.first_pts = 0;
1086 video_str.prev_packet = disk_buf;
1087 audio_str.prev_packet = disk_buf;
1088 video_str.buffer_remaining = disk_buf_len;
1089 audio_str.buffer_remaining = disk_buf_len;
1091 //DEBUGF("START: video = %d, audio = %d\n",audio_str.buffer_remaining,video_str.buffer_remaining);
1092 rb->lcd_setfont(FONT_SYSFIXED);
1094 audiostatus = STREAM_BUFFERING;
1095 videostatus = STREAM_PLAYING;
1097 #ifndef HAVE_LCD_COLOR
1098 gray_show(true);
1099 #endif
1101 /* We put the video thread on the second processor for multi-core targets. */
1102 if ((videothread_id = rb->create_thread(video_thread,
1103 (uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK)
1104 IF_COP(, COP, true))) == NULL)
1106 rb->splash(HZ, "Cannot create video thread!");
1107 return PLUGIN_ERROR;
1109 if ((audiothread_id = rb->create_thread(audio_thread,
1110 (uint8_t*)audio_stack,AUDIO_STACKSIZE,"mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK)
1111 IF_COP(, CPU, false))) == NULL)
1113 rb->splash(HZ, "Cannot create audio thread!");
1114 /* To do: Handle this error correctly on dual-core targets */
1115 rb->remove_thread(videothread_id);
1116 return PLUGIN_ERROR;
1119 /* Wait until both threads have finished their work */
1120 while ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE)) {
1121 audio_remaining = audio_str.buffer_remaining;
1122 video_remaining = video_str.buffer_remaining;
1123 if (MIN(audio_remaining,video_remaining) < MPEG_LOW_WATERMARK) {
1125 // TODO: Add mutex when updating the A/V buffer_remaining variables.
1126 bytes_to_read = buffer_size - MPEG_GUARDBUF_SIZE - MAX(audio_remaining,video_remaining);
1128 bytes_to_read = MIN(bytes_to_read,(size_t)(disk_buf_end-disk_buf_tail));
1130 while (( bytes_to_read > 0) && (file_remaining > 0) &&
1131 ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE))) {
1132 n = rb->read(in_file, disk_buf_tail, MIN(32*1024,bytes_to_read));
1134 bytes_to_read -= n;
1135 file_remaining -= n;
1136 audio_str.buffer_remaining += n;
1137 video_str.buffer_remaining += n;
1138 disk_buf_tail += n;
1139 rb->yield();
1142 if (disk_buf_tail == disk_buf_end)
1143 disk_buf_tail = buffer;
1146 rb->sleep(HZ/10);
1149 #ifndef HAVE_LCD_COLOR
1150 gray_release();
1151 #endif
1153 rb->remove_thread(audiothread_id);
1154 rb->yield(); /* Is this needed? */
1156 rb->lcd_clear_display();
1157 rb->lcd_update();
1159 mpeg2_close (mpeg2dec);
1161 rb->queue_delete( &msg_queue );
1163 rb->close (in_file);
1165 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1166 rb->cpu_boost(false);
1167 #endif
1169 save_settings(); /* Save settings (if they have changed) */
1171 rb->lcd_setfont(FONT_UI);
1173 #if CONFIG_BACKLIGHT
1174 /* reset backlight settings */
1175 rb->backlight_set_timeout(rb->global_settings->backlight_timeout);
1176 #endif
1178 return PLUGIN_OK;