2 * mpegplayer.c - based on :
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
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
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
81 In libmpeg2, info->sequence->frame_period contains the frame_period.
83 Working with Rockbox's 100Hz tick, the common frame rates would need
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"
110 #include "mpeg_settings.h"
111 #include "video_out.h"
112 #include "../../codecs/libmad/mad.h"
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
164 #error MPEGPLAYER: Unsupported keypad
167 struct plugin_api
* rb
;
169 static mpeg2dec_t
* mpeg2dec
;
170 static int total_offset
= 0;
171 static int num_drawn
= 0;
172 static int count_start
= 0;
177 struct thread_entry
*thread
; /* Stream's thread */
178 int status
; /* Current stream status */
179 struct event ev
; /* Event sent to steam */
180 int have_msg
; /* 1=event pending */
181 int replied
; /* 1=replied to last event */
182 int reply
; /* reply value */
183 struct mutex msg_lock
; /* serialization for event senders */
184 uint8_t* curr_packet
; /* Current stream packet beginning */
185 uint8_t* curr_packet_end
; /* Current stream packet end */
187 uint8_t* prev_packet
; /* Previous stream packet beginning */
188 uint8_t* next_packet
; /* Next stream packet beginning */
190 size_t guard_bytes
; /* Number of bytes in guardbuf used */
191 size_t buffer_remaining
; /* How much data is left in the buffer */
192 uint32_t curr_pts
; /* Current presentation timestamp */
193 uint32_t curr_time
; /* Current time in samples */
194 uint32_t tagged
; /* curr_pts is valid */
199 static Stream audio_str IBSS_ATTR
;
200 static Stream video_str IBSS_ATTR
;
215 STREAM_TERMINATED
= -2,
222 /* Returns true if a message is waiting */
223 static inline bool str_have_msg(Stream
*str
)
225 return str
->have_msg
!= 0;
228 /* Waits until a message is sent */
229 static void str_wait_msg(Stream
*str
)
233 while (str
->have_msg
== 0)
235 if (spin_count
< 100)
246 /* Returns a message waiting or blocks until one is available - removes the
248 static void str_get_msg(Stream
*str
, struct event
*ev
)
252 ev
->data
= str
->ev
.data
;
256 /* Peeks at the current message without blocking, returns the data but
257 does not remove the event */
258 static bool str_look_msg(Stream
*str
, struct event
*ev
)
260 if (!str_have_msg(str
))
264 ev
->data
= str
->ev
.data
;
268 /* Replies to the last message pulled - has no effect if last message has not
269 been pulled or already replied */
270 static void str_reply_msg(Stream
*str
, int reply
)
272 if (str
->replied
== 1 || str
->have_msg
!= 0)
279 /* Sends a message to a stream and waits for a reply */
280 static intptr_t str_send_msg(Stream
*str
, int id
, intptr_t data
)
286 if (str
->thread
== rb
->thread_get_current())
287 return str
->dispatch_fn(str
, msg
);
290 /* Only one thread at a time, please */
291 rb
->spinlock_lock(&str
->msg_lock
);
299 while (str
->replied
== 0 && str
->status
!= STREAM_TERMINATED
)
301 if (spin_count
< 100)
313 rb
->spinlock_unlock(&str
->msg_lock
);
318 /* NOTE: Putting the following variables in IRAM cause audio corruption
319 on the ipod (reason unknown)
321 static uint8_t *disk_buf IBSS_ATTR
;
322 static uint8_t *disk_buf_end IBSS_ATTR
;
323 static uint8_t *disk_buf_tail IBSS_ATTR
;
324 static size_t buffer_size IBSS_ATTR
;
326 /* Some stream variables are shared between cores */
327 struct mutex stream_lock IBSS_ATTR
;
328 static inline void init_stream_lock(void)
329 { rb
->spinlock_init(&stream_lock
); }
330 static inline void lock_stream(void)
331 { rb
->spinlock_lock(&stream_lock
); }
332 static inline void unlock_stream(void)
333 { rb
->spinlock_unlock(&stream_lock
); }
335 /* No RMW issue here */
336 static inline void init_stream_lock(void)
338 static inline void lock_stream(void)
340 static inline void unlock_stream(void)
345 static struct event_queue msg_queue IBSS_ATTR
;
347 #define MSG_BUFFER_NEARLY_EMPTY 1
348 #define MSG_EXIT_REQUESTED 2
350 /* Various buffers */
351 /* TODO: Can we reduce the PCM buffer size? */
352 #define PCMBUFFER_SIZE ((512*1024)-PCMBUFFER_GUARD_SIZE)
353 #define PCMBUFFER_GUARD_SIZE (1152*4 + sizeof (struct pcm_frame_header))
354 #define MPA_MAX_FRAME_SIZE 1729 /* Largest frame - MPEG1, Layer II, 384kbps, 32kHz, pad */
355 #define MPABUF_SIZE (64*1024 + ALIGN_UP(MPA_MAX_FRAME_SIZE + 2*MAD_BUFFER_GUARD, 4))
356 #define LIBMPEG2BUFFER_SIZE (2*1024*1024)
358 /* 65536+6 is required since each PES has a 6 byte header with a 16 bit packet length field */
359 #define MPEG_GUARDBUF_SIZE (64*1024+1024) /* Keep a bit extra - excessive for now */
360 #define MPEG_LOW_WATERMARK (1024*1024)
362 static void pcm_playback_play_pause(bool play
);
364 /* libmad related functions/definitions */
365 #define INPUT_CHUNK_SIZE 8192
367 struct mad_stream stream IBSS_ATTR
;
368 struct mad_frame frame IBSS_ATTR
;
369 struct mad_synth synth IBSS_ATTR
;
371 unsigned char mad_main_data
[MAD_BUFFER_MDLEN
]; /* 2567 bytes */
373 /* There isn't enough room for this in IRAM on PortalPlayer, but there
377 static mad_fixed_t mad_frame_overlap
[2][32][18] IBSS_ATTR
; /* 4608 bytes */
379 static mad_fixed_t mad_frame_overlap
[2][32][18]; /* 4608 bytes */
382 static void init_mad(void* mad_frame_overlap
)
384 rb
->memset(&stream
, 0, sizeof(struct mad_stream
));
385 rb
->memset(&frame
, 0, sizeof(struct mad_frame
));
386 rb
->memset(&synth
, 0, sizeof(struct mad_synth
));
388 mad_stream_init(&stream
);
389 mad_frame_init(&frame
);
391 /* We do this so libmad doesn't try to call codec_calloc() */
392 frame
.overlap
= mad_frame_overlap
;
394 rb
->memset(mad_main_data
, 0, sizeof(mad_main_data
));
395 stream
.main_data
= &mad_main_data
;
398 /* MPEG related headers */
400 /* Macros for comparing memory bytes to a series of constant bytes in an
401 efficient manner - evaluate to true if corresponding bytes match */
402 #if defined (CPU_ARM)
403 /* ARM must load 32-bit values at addres % 4 == 0 offsets but this data
404 isn't aligned nescessarily, so just byte compare */
405 #define CMP_3_CONST(_a, _b) \
409 "ldrb %[x], [%[a], #0] \r\n" \
410 "eors %[x], %[x], %[b0] \r\n" \
411 "ldreqb %[x], [%[a], #1] \r\n" \
412 "eoreqs %[x], %[x], %[b1] \r\n" \
413 "ldreqb %[x], [%[a], #2] \r\n" \
414 "eoreqs %[x], %[x], %[b2] \r\n" \
417 [b0]"i"((_b) >> 24), \
418 [b1]"i"((_b) << 8 >> 24), \
419 [b2]"i"((_b) << 16 >> 24) \
423 #define CMP_4_CONST(_a, _b) \
427 "ldrb %[x], [%[a], #0] \r\n" \
428 "eors %[x], %[x], %[b0] \r\n" \
429 "ldreqb %[x], [%[a], #1] \r\n" \
430 "eoreqs %[x], %[x], %[b1] \r\n" \
431 "ldreqb %[x], [%[a], #2] \r\n" \
432 "eoreqs %[x], %[x], %[b2] \r\n" \
433 "ldreqb %[x], [%[a], #3] \r\n" \
434 "eoreqs %[x], %[x], %[b3] \r\n" \
437 [b0]"i"((_b) >> 24), \
438 [b1]"i"((_b) << 8 >> 24), \
439 [b2]"i"((_b) << 16 >> 24), \
440 [b3]"i"((_b) << 24 >> 24) \
444 #elif defined (CPU_COLDFIRE)
445 /* Coldfire can just load a 32 bit value at any offset but ASM is not the best way
446 to integrate this with the C code */
447 #define CMP_3_CONST(a, b) \
448 (((*(uint32_t *)(a) >> 8) ^ ((uint32_t)(b) >> 8)) == 0)
449 #define CMP_4_CONST(a, b) \
450 ((*(uint32_t *)(a) ^ (b)) == 0)
452 /* Don't know what this is - use bytewise comparisons */
453 #define CMP_3_CONST(a, b) \
454 (( ((a)[0] ^ ((b) >> 24)) | \
455 ((a)[1] ^ ((b) << 8 >> 24)) | \
456 ((a)[2] ^ ((b) << 16 >> 24)) ) == 0)
457 #define CMP_4_CONST(a, b) \
458 (( ((a)[0] ^ ((b) >> 24)) | \
459 ((a)[1] ^ ((b) << 8 >> 24)) | \
460 ((a)[2] ^ ((b) << 16 >> 24)) | \
461 ((a)[3] ^ ((b) << 24 >> 24)) ) == 0)
464 /* Codes for various header byte sequences - MSB represents lowest memory
466 #define PACKET_START_CODE_PREFIX 0x00000100ul
467 #define END_CODE 0x000001b9ul
468 #define PACK_START_CODE 0x000001baul
469 #define SYSTEM_HEADER_START_CODE 0x000001bbul
471 /* p = base pointer, b0 - b4 = byte offsets from p */
472 /* We only care about the MS 32 bits of the 33 and so the ticks are 45kHz */
473 #define TS_FROM_HEADER(p, b0, b1, b2, b3, b4) \
474 ((uint32_t)(((p)[b0] >> 1 << 29) | \
476 ((p)[b2] >> 1 << 14) | \
480 /* This function demuxes the streams and gives the next stream data pointer */
481 static void get_next_data( Stream
* str
)
487 static int mpeg1_skip_table
[16] =
488 { 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
490 if (str
->curr_packet_end
== NULL
)
492 /* What does this do? */
493 while ((p
= disk_buf
) == NULL
)
495 rb
->lcd_putsxy(0,LCD_HEIGHT
-10,"FREEZE!");
502 p
= str
->curr_packet_end
;
509 if (p
>= disk_buf_end
)
511 p
= disk_buf
+ (p
- disk_buf_end
);
514 /* Pack header, skip it */
515 if (CMP_4_CONST(p
, PACK_START_CODE
))
517 if ((p
[4] & 0xc0) == 0x40) /* mpeg-2 */
519 p
+= 14 + (p
[13] & 7);
521 else if ((p
[4] & 0xf0) == 0x20) /* mpeg-1 */
527 rb
->splash( 30, "Weird Pack header!" );
530 /*rb->splash( 30, "Pack header" );*/
533 /* System header, parse and skip it - four bytes */
534 if (CMP_4_CONST(p
, SYSTEM_HEADER_START_CODE
))
538 p
+= 4; /*skip start code*/
539 header_length
= *p
++ << 8;
540 header_length
+= *p
++;
544 if (p
>= disk_buf_end
)
546 p
= disk_buf
+ (p
- disk_buf_end
);
548 /*rb->splash( 30, "System header" );*/
551 /* Packet header, parse it */
552 if (!CMP_3_CONST(p
, PACKET_START_CODE_PREFIX
))
555 //rb->splash( HZ*3, "missing packet start code prefix : %X%X at %X", *p, *(p+2), p-disk_buf );
556 str
->curr_packet_end
= str
->curr_packet
= NULL
;
562 /* We retrieve basic infos */
564 length
= (p
[4] << 8) | p
[5];
566 /*rb->splash( 100, "Stream : %X", stream );*/
567 if (stream
!= str
->id
)
569 /* End of stream ? */
572 str
->curr_packet_end
= str
->curr_packet
= NULL
;
576 /* It's not the packet we're looking for, skip it */
581 /* Ok, it's our packet */
582 str
->curr_packet_end
= p
+ length
+6;
585 if ((header
[6] & 0xc0) == 0x80) /* mpeg2 */
587 length
= 9 + header
[8];
589 /* header points to the mpeg2 pes header */
590 if (header
[7] & 0x80)
592 /* header has a pts */
593 uint32_t pts
= TS_FROM_HEADER(header
, 9, 10, 11, 12, 13);
597 /* video stream - header may have a dts as well */
598 uint32_t dts
= (header
[7] & 0x40) == 0 ?
599 pts
: TS_FROM_HEADER(header
, 14, 15, 16, 17, 18);
601 mpeg2_tag_picture (mpeg2dec
, pts
, dts
);
617 while (header
[length
- 1] == 0xff)
622 rb
->splash( 30, "Too much stuffing" );
623 DEBUGF("Too much stuffing" );
628 if ((header
[length
- 1] & 0xc0) == 0x40)
634 length
+= mpeg1_skip_table
[header
[length
- 1] >> 4];
636 /* header points to the mpeg1 pes header */
637 ptsbuf
= header
+ len_skip
;
639 if ((ptsbuf
[-1] & 0xe0) == 0x20)
641 /* header has a pts */
642 uint32_t pts
= TS_FROM_HEADER(ptsbuf
, -1, 0, 1, 2, 3);
646 /* video stream - header may have a dts as well */
647 uint32_t dts
= (ptsbuf
[-1] & 0xf0) != 0x30 ?
648 pts
: TS_FROM_HEADER(ptsbuf
, 4, 5, 6, 7, 18);
650 mpeg2_tag_picture (mpeg2dec
, pts
, dts
);
661 bytes
= 6 + (header
[4] << 8) + header
[5] - length
;
665 str
->curr_packet_end
= p
+ bytes
;
666 //DEBUGF("prev = %d, curr = %d\n",str->prev_packet,str->curr_packet);
668 if (str
->curr_packet
!= NULL
)
672 if (str
->curr_packet
< str
->prev_packet
)
674 str
->buffer_remaining
-= (disk_buf_end
- str
->prev_packet
) +
675 (str
->curr_packet
- disk_buf
);
676 str
->buffer_remaining
-= str
->guard_bytes
;
677 str
->guard_bytes
= 0;
681 str
->buffer_remaining
-= (str
->curr_packet
- str
->prev_packet
);
686 str
->prev_packet
= str
->curr_packet
;
689 str
->curr_packet
= p
;
691 if (str
->curr_packet_end
> disk_buf_end
)
693 str
->guard_bytes
= str
->curr_packet_end
- disk_buf_end
;
694 rb
->memcpy(disk_buf_end
, disk_buf
, str
->guard_bytes
);
702 /* Our clock rate in ticks/second - this won't be a constant for long */
703 #define CLOCK_RATE 44100
705 /* For simple lowpass filtering of sync variables */
706 #define AVERAGE(var, x, count) (((var) * (count-1) + (x)) / (count))
707 /* Convert 45kHz PTS/DTS ticks to our clock ticks */
708 #define TS_TO_TICKS(pts) ((uint64_t)CLOCK_RATE*(pts) / 45000)
709 /* Convert 27MHz ticks to our clock ticks */
710 #define TIME_TO_TICKS(stamp) ((uint64_t)CLOCK_RATE*(stamp) / 27000000)
712 /** MPEG audio stream buffer */
715 static bool init_mpabuf(void)
717 mpa_buffer
= mpeg2_malloc(MPABUF_SIZE
,-2);
718 return mpa_buffer
!= NULL
;
721 #define PTS_QUEUE_LEN (1 << 5) /* 32 should be way more than sufficient -
722 if not, the case is handled */
723 #define PTS_QUEUE_MASK (PTS_QUEUE_LEN-1)
724 struct pts_queue_slot
726 uint32_t pts
; /* Time stamp for packet */
727 ssize_t size
; /* Number of bytes left in packet */
728 } pts_queue
[PTS_QUEUE_LEN
];
730 /* This starts out wr == rd but will never be emptied to zero during
731 streaming again in order to support initializing the first packet's
732 pts value without a special case */
733 static unsigned pts_queue_rd
;
734 static unsigned pts_queue_wr
;
736 /* Increments the queue head postion - should be used to preincrement */
737 static bool pts_queue_add_head(void)
739 if (pts_queue_wr
- pts_queue_rd
>= PTS_QUEUE_LEN
-1)
746 /* Increments the queue tail position - leaves one slot as current */
747 static bool pts_queue_remove_tail(void)
749 if (pts_queue_wr
- pts_queue_rd
<= 1u)
756 /* Returns the "head" at the index just behind the write index */
757 static struct pts_queue_slot
* pts_queue_head(void)
759 return &pts_queue
[(pts_queue_wr
- 1) & PTS_QUEUE_MASK
];
762 /* Returns a pointer to the current tail */
763 static struct pts_queue_slot
* pts_queue_tail(void)
765 return &pts_queue
[pts_queue_rd
& PTS_QUEUE_MASK
];
768 /* Resets the pts queue - call when starting and seeking */
769 static void pts_queue_reset(void)
771 struct pts_queue_slot
*pts
;
772 pts_queue_rd
= pts_queue_wr
;
773 pts
= pts_queue_tail();
778 struct pcm_frame_header
/* Header added to pcm data every time a decoded
779 mpa frame is sent out */
781 uint32_t size
; /* size of this frame - including header */
782 uint32_t time
; /* timestamp for this frame - derived from PTS */
783 unsigned char data
[]; /* open array of audio data */
786 #define PCMBUF_PLAY_ALL 1l /* Forces buffer to play back all data */
787 #define PCMBUF_PLAY_NONE LONG_MAX /* Keeps buffer from playing any data */
788 static volatile uint64_t pcmbuf_read IBSS_ATTR
;
789 static volatile uint64_t pcmbuf_written IBSS_ATTR
;
790 static volatile ssize_t pcmbuf_threshold IBSS_ATTR
;
791 static struct pcm_frame_header
*pcm_buffer IBSS_ATTR
;
792 static struct pcm_frame_header
*pcmbuf_end IBSS_ATTR
;
793 static struct pcm_frame_header
* volatile pcmbuf_head IBSS_ATTR
;
794 static struct pcm_frame_header
* volatile pcmbuf_tail IBSS_ATTR
;
796 static volatile uint32_t samplesplayed IBSS_ATTR
; /* Our base clock */
797 static volatile uint32_t samplestart IBSS_ATTR
; /* Clock at playback start */
798 static volatile int32_t sampleadjust IBSS_ATTR
; /* Clock drift adjustment */
800 static ssize_t
pcmbuf_used(void)
802 return (ssize_t
)(pcmbuf_written
- pcmbuf_read
);
805 static bool init_pcmbuf(void)
807 pcm_buffer
= mpeg2_malloc(PCMBUFFER_SIZE
+ PCMBUFFER_GUARD_SIZE
, -2);
809 if (pcm_buffer
== NULL
)
812 pcmbuf_head
= pcm_buffer
;
813 pcmbuf_tail
= pcm_buffer
;
814 pcmbuf_end
= SKIPBYTES(pcm_buffer
, PCMBUFFER_SIZE
);
821 /* Advance a PCM buffer pointer by size bytes circularly */
822 static inline void pcm_advance_buffer(struct pcm_frame_header
* volatile *p
,
825 *p
= SKIPBYTES(*p
, size
);
826 if (*p
>= pcmbuf_end
)
830 static void get_more(unsigned char** start
, size_t* size
)
833 static unsigned char silence
[4412] __attribute__((aligned (4))) = { 0 };
836 if (pcmbuf_used() >= pcmbuf_threshold
)
838 uint32_t time
= pcmbuf_tail
->time
;
839 sz
= pcmbuf_tail
->size
;
841 *start
= (unsigned char *)pcmbuf_tail
->data
;
843 pcm_advance_buffer(&pcmbuf_tail
, sz
);
847 sz
-= sizeof (*pcmbuf_tail
);
851 /* Drift the clock towards the audio timestamp values */
852 sampleadjust
= AVERAGE(sampleadjust
, (int32_t)(time
- samplesplayed
), 8);
854 /* Update master clock */
855 samplesplayed
+= sz
>> 2;
859 /* Keep clock going at all times */
860 sz
= sizeof (silence
);
864 samplesplayed
+= sz
>> 2;
866 if (pcmbuf_read
> pcmbuf_written
)
867 pcmbuf_read
= pcmbuf_written
;
870 /* Flushes the buffer - clock keeps counting */
871 static void pcm_playback_flush(void)
873 bool was_playing
= rb
->pcm_is_playing();
880 pcmbuf_head
= pcmbuf_tail
;
883 rb
->pcm_play_data(get_more
, NULL
, 0);
886 /* Seek the reference clock to the specified time - next audio data ready to
887 go to DMA should be on the buffer with the same time index or else the PCM
888 buffer should be empty */
889 static void pcm_playback_seek_time(uint32_t time
)
891 bool was_playing
= rb
->pcm_is_playing();
896 samplesplayed
= time
;
901 rb
->pcm_play_data(get_more
, NULL
, 0);
904 /* Start pcm playback with the reference clock set to the specified time */
905 static void pcm_playback_play(uint32_t time
)
907 pcm_playback_seek_time(time
);
909 if (!rb
->pcm_is_playing())
910 rb
->pcm_play_data(get_more
, NULL
, 0);
913 /* Pauses playback - and the clock */
914 static void pcm_playback_play_pause(bool play
)
916 rb
->pcm_play_pause(play
);
919 /* Stops all playback and resets the clock */
920 static void pcm_playback_stop(void)
922 if (rb
->pcm_is_playing())
925 pcm_playback_flush();
932 static uint32_t get_stream_time(void)
934 return samplesplayed
+ sampleadjust
- (rb
->pcm_get_bytes_waiting() >> 2);
937 static uint32_t get_playback_time(void)
939 return samplesplayed
+ sampleadjust
-
940 samplestart
- (rb
->pcm_get_bytes_waiting() >> 2);
943 static inline int32_t clip_sample(int32_t sample
)
945 if ((int16_t)sample
!= sample
)
946 sample
= 0x7fff ^ (sample
>> 31);
951 static int button_loop(void)
954 int vol
, minvol
, maxvol
;
957 if (str_have_msg(&audio_str
))
960 str_get_msg(&audio_str
, &ev
);
962 if (ev
.id
== STREAM_QUIT
)
964 audio_str
.status
= STREAM_STOPPED
;
969 str_reply_msg(&audio_str
, 0);
973 button
= rb
->button_get(false);
978 case MPEG_VOLUP
|BUTTON_REPEAT
:
981 case MPEG_VOLUP2
|BUTTON_REPEAT
:
983 vol
= rb
->global_settings
->volume
;
984 maxvol
= rb
->sound_max(SOUND_VOLUME
);
988 rb
->sound_set(SOUND_VOLUME
, vol
);
989 rb
->global_settings
->volume
= vol
;
994 case MPEG_VOLDOWN
|BUTTON_REPEAT
:
997 case MPEG_VOLDOWN2
|BUTTON_REPEAT
:
999 vol
= rb
->global_settings
->volume
;
1000 minvol
= rb
->sound_min(SOUND_VOLUME
);
1004 rb
->sound_set(SOUND_VOLUME
, vol
);
1005 rb
->global_settings
->volume
= vol
;
1010 pcm_playback_play_pause(false);
1011 audio_str
.status
= STREAM_PAUSED
;
1012 str_send_msg(&video_str
, STREAM_PAUSE
, 0);
1013 #ifndef HAVE_LCD_COLOR
1016 result
= mpeg_menu();
1017 count_start
= get_playback_time();
1020 #ifndef HAVE_LCD_COLOR
1024 /* The menu can change the font, so restore */
1025 rb
->lcd_setfont(FONT_SYSFIXED
);
1028 str_send_msg(&video_str
, STREAM_QUIT
, 0);
1029 audio_str
.status
= STREAM_STOPPED
;
1031 audio_str
.status
= STREAM_PLAYING
;
1032 str_send_msg(&video_str
, STREAM_PLAY
, 0);
1033 pcm_playback_play_pause(true);
1038 str_send_msg(&video_str
, STREAM_QUIT
, 0);
1039 audio_str
.status
= STREAM_STOPPED
;
1043 str_send_msg(&video_str
, STREAM_PAUSE
, 0);
1044 audio_str
.status
= STREAM_PAUSED
;
1045 pcm_playback_play_pause(false);
1047 button
= BUTTON_NONE
;
1048 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1049 rb
->cpu_boost(false);
1052 button
= rb
->button_get(true);
1053 if (button
== MPEG_STOP
) {
1054 str_send_msg(&video_str
, STREAM_QUIT
, 0);
1055 audio_str
.status
= STREAM_STOPPED
;
1058 } while (button
!= MPEG_PAUSE
);
1060 str_send_msg(&video_str
, STREAM_PLAY
, 0);
1061 audio_str
.status
= STREAM_PLAYING
;
1062 pcm_playback_play_pause(true);
1063 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1064 rb
->cpu_boost(true);
1069 if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
) {
1070 str_send_msg(&video_str
, STREAM_QUIT
, 0);
1071 audio_str
.status
= STREAM_STOPPED
;
1076 return audio_str
.status
;
1079 static void audio_thread(void)
1081 uint8_t *mpabuf
= mpa_buffer
;
1082 ssize_t mpabuf_used
= 0;
1083 int mad_errors
= 0; /* A count of the errors in each frame */
1084 struct pts_queue_slot
*pts
;
1086 /* We need this here to init the EMAC for Coldfire targets */
1087 mad_synth_init(&synth
);
1089 /* Init pts queue */
1091 pts
= pts_queue_tail();
1093 /* Keep buffer from playing */
1094 pcmbuf_threshold
= PCMBUF_PLAY_NONE
;
1097 pcm_playback_play(0);
1099 /* Get first packet */
1100 get_next_data(&audio_str
);
1102 if (audio_str
.curr_packet
== NULL
)
1105 /* This is the decoding loop. */
1111 if (button_loop() == STREAM_STOPPED
)
1112 goto audio_thread_quit
;
1116 /* Carry any overshoot to the next size since we're technically
1117 -pts->size bytes into it already. If size is negative an audio
1118 frame was split accross packets. Old has to be saved before
1120 if (pts_queue_remove_tail())
1122 struct pts_queue_slot
*old
= pts
;
1123 pts
= pts_queue_tail();
1124 pts
->size
+= old
->size
;
1130 if (mpabuf_used
>= MPA_MAX_FRAME_SIZE
+ MAD_BUFFER_GUARD
)
1132 /* Above low watermark - do nothing */
1134 else if (audio_str
.curr_packet
!= NULL
)
1138 /* Get data from next audio packet */
1139 len
= audio_str
.curr_packet_end
- audio_str
.curr_packet
;
1141 if (audio_str
.tagged
)
1143 struct pts_queue_slot
*stamp
= pts
;
1145 if (pts_queue_add_head())
1147 stamp
= pts_queue_head();
1148 stamp
->pts
= TS_TO_TICKS(audio_str
.curr_pts
);
1149 /* pts->size should have been zeroed when slot was
1152 /* else queue full - just count up from the last to make
1153 it look like more data in the same packet */
1155 audio_str
.tagged
= 0;
1159 /* Add to the one just behind the head - this may be the
1160 tail or the previouly added head - whether or not we'll
1161 ever reach this is quite in question since audio always
1162 seems to have every packet timestamped */
1163 pts_queue_head()->size
+= len
;
1166 /* Slide any remainder over to beginning - avoid function
1167 call overhead if no data remaining as well */
1168 if (mpabuf
> mpa_buffer
&& mpabuf_used
> 0)
1169 rb
->memmove(mpa_buffer
, mpabuf
, mpabuf_used
);
1171 /* Splice this packet onto any remainder */
1172 rb
->memcpy(mpa_buffer
+ mpabuf_used
, audio_str
.curr_packet
,
1176 mpabuf
= mpa_buffer
;
1178 /* Get data from next audio packet */
1179 get_next_data(&audio_str
);
1181 while (audio_str
.curr_packet
!= NULL
&&
1182 mpabuf_used
< MPA_MAX_FRAME_SIZE
+ MAD_BUFFER_GUARD
);
1184 else if (mpabuf_used
<= 0)
1186 /* Used up remainder of mpa buffer so quit */
1191 mad_stream_buffer(&stream
, mpabuf
, mpabuf_used
);
1193 mad_stat
= mad_frame_decode(&frame
, &stream
);
1195 if (stream
.next_frame
== NULL
)
1197 /* What to do here? (This really is fatal) */
1198 DEBUGF("/* What to do here? */\n");
1202 /* Next mad stream buffer is the next frame postion */
1203 mpabuf
= (uint8_t *)stream
.next_frame
;
1205 /* Adjust sizes by the frame size */
1206 len
= stream
.next_frame
- stream
.this_frame
;
1212 DEBUGF("Audio stream error - %d\n", stream
.error
);
1214 if (stream
.error
== MAD_FLAG_INCOMPLETE
1215 || stream
.error
== MAD_ERROR_BUFLEN
)
1217 /* This makes the codec support partially corrupted files */
1218 if (++mad_errors
> 30)
1222 rb
->priority_yield();
1225 else if (MAD_RECOVERABLE(stream
.error
))
1228 rb
->priority_yield();
1233 /* Some other unrecoverable error */
1234 DEBUGF("Unrecoverable error\n");
1240 mad_errors
= 0; /* Clear errors */
1242 /* Generate the pcm samples */
1243 mad_synth_frame(&synth
, &frame
);
1247 /* TODO: Output through core dsp. We'll still use our own PCM buffer
1248 since the core pcm buffer has no timestamping or clock facilities */
1250 /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */
1251 if (synth
.pcm
.length
> 0)
1253 int16_t *audio_data
= (int16_t *)pcmbuf_head
->data
;
1254 size_t size
= sizeof (*pcmbuf_head
) + synth
.pcm
.length
*4;
1255 size_t wait_for
= size
+ 32*1024;
1257 /* Leave at least 32KB free (this will be the currently
1259 while (pcmbuf_used() + wait_for
> PCMBUFFER_SIZE
)
1261 if (str_have_msg(&audio_str
))
1264 str_look_msg(&audio_str
, &ev
);
1266 if (ev
.id
== STREAM_QUIT
)
1267 goto audio_thread_quit
;
1270 rb
->priority_yield();
1273 /* TODO: This part will be replaced with dsp calls soon */
1274 if (MAD_NCHANNELS(&frame
.header
) == 2)
1276 int32_t *left
= &synth
.pcm
.samples
[0][0];
1277 int32_t *right
= &synth
.pcm
.samples
[1][0];
1278 int i
= synth
.pcm
.length
;
1282 /* libmad outputs s3.28 */
1283 *audio_data
++ = clip_sample(*left
++ >> 13);
1284 *audio_data
++ = clip_sample(*right
++ >> 13);
1290 int32_t *mono
= &synth
.pcm
.samples
[0][0];
1291 int i
= synth
.pcm
.length
;
1295 int32_t s
= clip_sample(*mono
++ >> 13);
1303 pcmbuf_head
->time
= pts
->pts
;
1304 pcmbuf_head
->size
= size
;
1306 /* As long as we're on this timestamp, the time is just incremented
1307 by the number of samples */
1308 pts
->pts
+= synth
.pcm
.length
;
1310 pcm_advance_buffer(&pcmbuf_head
, size
);
1312 if (pcmbuf_threshold
!= PCMBUF_PLAY_ALL
&& pcmbuf_used() >= 64*1024)
1314 /* We've reached our size treshold so start playing back the
1315 audio in the buffer and set the buffer to play all data */
1316 audio_str
.status
= STREAM_PLAYING
;
1317 pcmbuf_threshold
= PCMBUF_PLAY_ALL
;
1318 pcm_playback_seek_time(pcmbuf_tail
->time
);
1321 /* Make this data available to DMA */
1322 pcmbuf_written
+= size
;
1326 } /* end decoding loop */
1329 if (audio_str
.status
== STREAM_STOPPED
)
1330 goto audio_thread_quit
;
1332 /* Force any residue to play if audio ended before reaching the
1334 if (pcmbuf_threshold
!= PCMBUF_PLAY_ALL
&& pcmbuf_used() > 0)
1336 pcm_playback_play(pcmbuf_tail
->time
);
1337 pcmbuf_threshold
= PCMBUF_PLAY_ALL
;
1340 if (rb
->pcm_is_playing() && !rb
->pcm_is_paused())
1342 /* Wait for audio to finish */
1343 while (pcmbuf_used() > 0)
1345 if (button_loop() == STREAM_STOPPED
)
1346 goto audio_thread_quit
;
1351 audio_str
.status
= STREAM_DONE
;
1353 /* Process events until finished */
1354 while (button_loop() != STREAM_STOPPED
)
1358 pcm_playback_stop();
1360 audio_str
.status
= STREAM_TERMINATED
;
1361 rb
->remove_thread(NULL
);
1364 /* End of libmad stuff */
1366 /* TODO: Running in the main thread, libmad needs 8.25KB of stack.
1367 The codec thread uses a 9KB stack. So we can probable reduce this a
1368 little, but leave at 9KB for now to be safe. */
1369 #define AUDIO_STACKSIZE (9*1024)
1370 uint32_t audio_stack
[AUDIO_STACKSIZE
/ sizeof(uint32_t)] IBSS_ATTR
;
1372 /* TODO: Check if 4KB is appropriate - it works for my test streams,
1373 so maybe we can reduce it. */
1374 #define VIDEO_STACKSIZE (4*1024)
1375 static uint32_t video_stack
[VIDEO_STACKSIZE
/ sizeof(uint32_t)] IBSS_ATTR
;
1377 static void video_thread(void)
1380 const mpeg2_info_t
* info
;
1381 mpeg2_state_t state
;
1383 uint32_t curr_time
= 0;
1384 uint32_t period
= 0; /* Frame period in clock ticks */
1385 uint32_t eta_audio
= UINT_MAX
, eta_video
= 0;
1386 int32_t eta_early
= 0, eta_late
= 0;
1387 int frame_drop_level
= 0;
1389 int num_skipped
= 0;
1390 /* Used to decide when to display FPS */
1391 unsigned long last_showfps
= *rb
->current_tick
- HZ
;
1392 /* Used to decide whether or not to force a frame update */
1393 unsigned long last_render
= last_showfps
;
1395 mpeg2dec
= mpeg2_init();
1396 if (mpeg2dec
== NULL
)
1398 rb
->splash(0, "mpeg2_init failed");
1399 /* Commit suicide */
1400 video_str
.status
= STREAM_TERMINATED
;
1401 rb
->remove_thread(NULL
);
1404 /* Clear the display - this is mainly just to indicate that the
1405 video thread has started successfully. */
1406 rb
->lcd_clear_display();
1409 /* Request the first packet data */
1410 get_next_data( &video_str
);
1412 if (video_str
.curr_packet
== NULL
)
1415 mpeg2_buffer (mpeg2dec
, video_str
.curr_packet
, video_str
.curr_packet_end
);
1416 total_offset
+= video_str
.curr_packet_end
- video_str
.curr_packet
;
1418 info
= mpeg2_info (mpeg2dec
);
1420 /* Wait if the audio thread is buffering - i.e. before
1421 the first frames are decoded */
1422 while (audio_str
.status
== STREAM_BUFFERING
)
1423 rb
->priority_yield();
1427 /* quickly check mailbox first */
1428 if (str_have_msg(&video_str
))
1432 str_get_msg(&video_str
, &ev
);
1437 video_str
.status
= STREAM_STOPPED
;
1438 goto video_thread_quit
;
1441 video_str
.status
= STREAM_PAUSED
;
1442 str_reply_msg(&video_str
, 1);
1449 video_str
.status
= STREAM_PLAYING
;
1450 str_reply_msg(&video_str
, 1);
1453 state
= mpeg2_parse (mpeg2dec
);
1456 /* Prevent idle poweroff */
1457 rb
->reset_poweroff_timer();
1462 /* Request next packet data */
1463 get_next_data( &video_str
);
1464 mpeg2_buffer (mpeg2dec
, video_str
.curr_packet
, video_str
.curr_packet_end
);
1465 total_offset
+= video_str
.curr_packet_end
- video_str
.curr_packet
;
1466 info
= mpeg2_info (mpeg2dec
);
1468 if (video_str
.curr_packet
== NULL
)
1475 case STATE_SEQUENCE
:
1476 /* New GOP, inform output of any changes */
1477 vo_setup(info
->sequence
);
1482 int skip
= 0; /* Assume no skip */
1484 if (frame_drop_level
>= 1 || skip_level
> 0)
1486 /* A frame will be dropped in the decoder */
1488 /* Frame type: I/P/B/D */
1489 int type
= info
->current_picture
->flags
& PIC_MASK_CODING_TYPE
;
1493 case PIC_FLAG_CODING_TYPE_I
:
1494 case PIC_FLAG_CODING_TYPE_D
:
1495 /* Level 5: Things are extremely late and all frames will be
1496 dropped until the next key frame */
1497 if (frame_drop_level
>= 1)
1498 frame_drop_level
= 0; /* Key frame - reset drop level */
1499 if (skip_level
>= 5)
1501 frame_drop_level
= 1;
1502 skip_level
= 0; /* reset */
1505 case PIC_FLAG_CODING_TYPE_P
:
1506 /* Level 4: Things are very late and all frames will be
1507 dropped until the next key frame */
1508 if (skip_level
>= 4)
1510 frame_drop_level
= 1;
1511 skip_level
= 0; /* reset */
1514 case PIC_FLAG_CODING_TYPE_B
:
1515 /* We want to drop something, so this B frame won't even
1516 be decoded. Drawing can happen on the next frame if so
1517 desired. Bring the level down as skips are done. */
1523 skip
|= frame_drop_level
;
1526 mpeg2_skip(mpeg2dec
, skip
);
1532 case STATE_INVALID_END
:
1534 int32_t offset
; /* Tick adjustment to keep sync */
1536 /* draw current picture */
1537 if (!info
->display_fbuf
)
1540 /* No limiting => no dropping - draw this frame */
1541 if (!settings
.limitfps
)
1544 /* Get presentation times in audio samples - quite accurate
1545 enough - add previous frame duration if not stamped */
1546 curr_time
= (info
->display_picture
->flags
& PIC_FLAG_TAGS
) ?
1547 TS_TO_TICKS(info
->display_picture
->tag
) : (curr_time
+ period
);
1549 period
= TIME_TO_TICKS(info
->sequence
->frame_period
);
1551 eta_video
= curr_time
;
1552 eta_audio
= get_stream_time();
1554 /* How early/late are we? > 0 = late, < 0 early */
1555 offset
= eta_audio
- eta_video
;
1557 if (!settings
.skipframes
)
1559 /* Make no effort to determine whether this frame should be
1560 drawn or not since no action can be taken to correct the
1561 situation. We'll just wait if we're early and correct for
1562 lateness as much as possible. */
1566 eta_late
= AVERAGE(eta_late
, offset
, 4);
1569 if ((uint32_t)offset
> eta_video
)
1572 eta_video
-= offset
;
1576 /** Possibly skip this frame **/
1578 /* Frameskipping has the following order of preference:
1580 * Frame Type Who Notes/Rationale
1581 * B decoder arbitrarily drop - no decode or draw
1582 * Any renderer arbitrarily drop - will be I/D/P
1583 * P decoder must wait for I/D-frame - choppy
1584 * I/D decoder must wait for I/D-frame - choppy
1586 * If a frame can be drawn and it has been at least 1/2 second,
1587 * the image will be updated no matter how late it is just to
1588 * avoid looking stuck.
1591 /* If we're late, set the eta to play the frame early so
1592 we may catch up. If early, especially because of a drop,
1593 mitigate a "snap" by moving back gradually. */
1594 if (offset
>= 0) /* late or on time */
1596 eta_early
= 0; /* Not early now :( */
1598 eta_late
= AVERAGE(eta_late
, offset
, 4);
1601 if ((uint32_t)offset
> eta_video
)
1604 eta_video
-= offset
;
1608 eta_late
= 0; /* Not late now :) */
1610 if (offset
> eta_early
)
1612 /* Just dropped a frame and we're now early or we're
1613 coming back from being early */
1615 if ((uint32_t)-offset
> eta_video
)
1616 offset
= -eta_video
;
1618 eta_video
+= offset
;
1622 /* Just early with an offset, do exponential drift back */
1625 eta_early
= AVERAGE(eta_early
, 0, 8);
1626 eta_video
= ((uint32_t)-eta_early
> eta_video
) ?
1627 0 : (eta_video
+ eta_early
);
1634 if (info
->display_picture
->flags
& PIC_FLAG_SKIP
)
1636 /* This frame was set to skip so skip it after having updated
1637 timing information */
1639 eta_early
= INT32_MIN
;
1643 if (skip_level
== 3 && TIME_BEFORE(*rb
->current_tick
, last_render
+ HZ
/2))
1645 /* Render drop was set previously but nothing was dropped in the
1646 decoder or it's been to long since drawing the last frame. */
1649 eta_early
= INT32_MIN
;
1653 /* At this point a frame _will_ be drawn - a skip may happen on
1657 if (offset
> CLOCK_RATE
*110/1000)
1659 /* Decide which skip level is needed in order to catch up */
1661 /* TODO: Calculate this rather than if...else - this is rather
1662 exponential though */
1663 if (offset
> CLOCK_RATE
*367/1000)
1664 skip_level
= 5; /* Decoder skip: I/D */
1665 if (offset
> CLOCK_RATE
*233/1000)
1666 skip_level
= 4; /* Decoder skip: P */
1667 else if (offset
> CLOCK_RATE
*167/1000)
1668 skip_level
= 3; /* Render skip */
1669 else if (offset
> CLOCK_RATE
*133/1000)
1670 skip_level
= 2; /* Decoder skip: B */
1672 skip_level
= 1; /* Decoder skip: B */
1676 /* Wait until audio catches up */
1677 while (eta_video
> eta_audio
)
1679 rb
->priority_yield();
1681 /* Make sure not to get stuck waiting here forever */
1682 if (str_have_msg(&video_str
))
1684 str_look_msg(&video_str
, &ev
);
1686 /* If not to play, process up top */
1687 if (ev
.id
!= STREAM_PLAY
)
1688 goto rendering_finished
;
1690 /* Told to play but already playing */
1691 str_get_msg(&video_str
, &ev
);
1692 str_reply_msg(&video_str
, 1);
1695 eta_audio
= get_stream_time();
1699 /* Record last frame time */
1700 last_render
= *rb
->current_tick
;
1702 vo_draw_frame(info
->display_fbuf
->buf
);
1706 if (!settings
.showfps
)
1709 /* Calculate and display fps */
1710 if (TIME_AFTER(*rb
->current_tick
, last_showfps
+ HZ
))
1712 uint32_t clock_ticks
= get_playback_time() - count_start
;
1715 if (clock_ticks
!= 0)
1716 fps
= num_drawn
*CLOCK_RATE
*10ll / clock_ticks
;
1718 rb
->snprintf(str
, sizeof(str
), "%d.%d %d %d ",
1719 fps
/ 10, fps
% 10, num_skipped
,
1720 info
->display_picture
->temporal_reference
);
1721 rb
->lcd_putsxy(0, 0, str
);
1722 rb
->lcd_update_rect(0, 0, LCD_WIDTH
, 8);
1724 last_showfps
= *rb
->current_tick
;
1740 video_str
.status
= STREAM_DONE
;
1744 str_get_msg(&video_str
, &ev
);
1746 if (ev
.id
== STREAM_QUIT
)
1749 str_reply_msg(&video_str
, 0);
1755 /* Commit suicide */
1756 video_str
.status
= STREAM_TERMINATED
;
1757 rb
->remove_thread(NULL
);
1760 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
1762 int status
= PLUGIN_ERROR
; /* assume failure */
1767 size_t file_remaining
;
1768 size_t disk_buf_len
;
1769 #ifndef HAVE_LCD_COLOR
1774 if (parameter
== NULL
)
1776 api
->splash(HZ
*2, "No File");
1777 return PLUGIN_ERROR
;
1780 /* Initialize IRAM - stops audio and voice as well */
1781 PLUGIN_IRAM_INIT(api
)
1785 audiobuf
= rb
->plugin_get_audio_buffer(&audiosize
);
1787 #if INPUT_SRC_CAPS != 0
1788 /* Select playback */
1789 rb
->audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1790 rb
->audio_set_output_source(AUDIO_SRC_PLAYBACK
);
1793 rb
->pcm_set_frequency(SAMPR_44
);
1795 /* Set disk pointers to NULL */
1796 disk_buf_end
= disk_buf
= NULL
;
1798 /* Stream construction */
1799 /* We take the first stream of each (audio and video) */
1800 /* TODO : Search for these in the file first */
1801 audio_str
.curr_packet_end
= audio_str
.curr_packet
= audio_str
.next_packet
= NULL
;
1802 video_str
= audio_str
;
1803 video_str
.id
= 0xe0;
1804 audio_str
.id
= 0xc0;
1806 /* Initialise our malloc buffer */
1807 mpeg2_alloc_init(audiobuf
,audiosize
);
1809 /* Grab most of the buffer for the compressed video - leave some for
1810 PCM audio data and some for libmpeg2 malloc use. */
1811 buffer_size
= audiosize
- (PCMBUFFER_SIZE
+PCMBUFFER_GUARD_SIZE
+
1812 MPABUF_SIZE
+LIBMPEG2BUFFER_SIZE
);
1814 DEBUGF("audiosize=%ld, buffer_size=%ld\n",audiosize
,buffer_size
);
1815 buffer
= mpeg2_malloc(buffer_size
,-1);
1818 return PLUGIN_ERROR
;
1820 #ifndef HAVE_LCD_COLOR
1821 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */
1822 grayscales
= gray_init(rb
, buffer
, buffer_size
, false, LCD_WIDTH
, LCD_HEIGHT
,
1823 32, 2<<8, &graysize
) + 1;
1825 buffer_size
-= graysize
;
1826 if (grayscales
< 33 || buffer_size
<= 0)
1828 rb
->splash(HZ
, "gray buf error");
1829 return PLUGIN_ERROR
;
1833 buffer_size
&= ~(0x7ff); /* Round buffer down to nearest 2KB */
1834 DEBUGF("audiosize=%ld, buffer_size=%ld\n",audiosize
,buffer_size
);
1837 return PLUGIN_ERROR
;
1840 return PLUGIN_ERROR
;
1842 /* The remaining buffer is for use by libmpeg2 */
1844 /* Open the video file */
1845 in_file
= rb
->open((char*)parameter
,O_RDONLY
);
1848 //fprintf(stderr,"Could not open %s\n",argv[1]);
1849 return PLUGIN_ERROR
;
1852 #ifdef HAVE_LCD_COLOR
1853 rb
->lcd_set_backdrop(NULL
);
1854 rb
->lcd_set_foreground(LCD_WHITE
);
1855 rb
->lcd_set_background(LCD_BLACK
);
1857 rb
->lcd_clear_display();
1860 /* Turn off backlight timeout */
1861 backlight_force_on(); /* backlight control in lib/helper.c */
1863 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1864 rb
->cpu_boost(true);
1867 /* From this point on we've altered settings, colors, cpu_boost, etc. and
1868 cannot just return PLUGIN_ERROR - instead drop though to cleanup code
1873 /* Msg queue init - no need for queue_remove since it's not a registered
1875 rb
->queue_init( &msg_queue
, false );
1877 /* Initialise libmad */
1878 rb
->memset(mad_frame_overlap
, 0, sizeof(mad_frame_overlap
));
1879 init_mad(mad_frame_overlap
);
1881 file_remaining
= rb
->filesize(in_file
);
1882 disk_buf_end
= buffer
+ buffer_size
-MPEG_GUARDBUF_SIZE
;
1884 /* Read some stream data */
1885 disk_buf_len
= rb
->read (in_file
, buffer
, MPEG_LOW_WATERMARK
);
1887 DEBUGF("Initial Buffering - %d bytes\n",(int)disk_buf_len
);
1889 disk_buf_tail
= buffer
+disk_buf_len
;
1890 file_remaining
-= disk_buf_len
;
1892 video_str
.guard_bytes
= audio_str
.guard_bytes
= 0;
1893 video_str
.prev_packet
= disk_buf
;
1894 audio_str
.prev_packet
= disk_buf
;
1895 video_str
.buffer_remaining
= disk_buf_len
;
1896 audio_str
.buffer_remaining
= disk_buf_len
;
1898 rb
->spinlock_init(&audio_str
.msg_lock
);
1899 rb
->spinlock_init(&video_str
.msg_lock
);
1900 audio_str
.status
= STREAM_BUFFERING
;
1901 video_str
.status
= STREAM_PLAYING
;
1903 #ifndef HAVE_LCD_COLOR
1911 /* We put the video thread on the second processor for multi-core targets. */
1912 if ((video_str
.thread
= rb
->create_thread(video_thread
,
1913 (uint8_t*)video_stack
,VIDEO_STACKSIZE
,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK
)
1914 IF_COP(, COP
, true))) == NULL
)
1916 rb
->splash(HZ
, "Cannot create video thread!");
1918 else if ((audio_str
.thread
= rb
->create_thread(audio_thread
,
1919 (uint8_t*)audio_stack
,AUDIO_STACKSIZE
,"mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK
)
1920 IF_COP(, CPU
, false))) == NULL
)
1922 rb
->splash(HZ
, "Cannot create audio thread!");
1926 //DEBUGF("START: video = %d, audio = %d\n",audio_str.buffer_remaining,video_str.buffer_remaining);
1927 rb
->lcd_setfont(FONT_SYSFIXED
);
1929 /* Wait until both threads have finished their work */
1930 while ((audio_str
.status
>= 0) || (video_str
.status
>= 0))
1932 size_t audio_remaining
= audio_str
.buffer_remaining
;
1933 size_t video_remaining
= video_str
.buffer_remaining
;
1935 if (MIN(audio_remaining
,video_remaining
) < MPEG_LOW_WATERMARK
) {
1937 size_t bytes_to_read
= buffer_size
- MPEG_GUARDBUF_SIZE
-
1938 MAX(audio_remaining
,video_remaining
);
1940 bytes_to_read
= MIN(bytes_to_read
,(size_t)(disk_buf_end
-disk_buf_tail
));
1942 while (( bytes_to_read
> 0) && (file_remaining
> 0) &&
1943 ((audio_str
.status
>= 0) || (video_str
.status
>= 0))) {
1944 size_t n
= rb
->read(in_file
, disk_buf_tail
, MIN(32*1024,bytes_to_read
));
1947 file_remaining
-= n
;
1950 audio_str
.buffer_remaining
+= n
;
1951 video_str
.buffer_remaining
+= n
;
1959 if (disk_buf_tail
== disk_buf_end
)
1960 disk_buf_tail
= buffer
;
1966 rb
->lcd_setfont(FONT_UI
);
1970 /* Stop the threads and wait for them to terminate */
1971 if (video_str
.thread
!= NULL
)
1972 str_send_msg(&video_str
, STREAM_QUIT
, 0);
1974 if (audio_str
.thread
!= NULL
)
1975 str_send_msg(&audio_str
, STREAM_QUIT
, 0);
1979 #ifndef HAVE_LCD_COLOR
1983 rb
->lcd_clear_display();
1986 mpeg2_close (mpeg2dec
);
1988 rb
->close (in_file
);
1990 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1991 rb
->cpu_boost(false);
1994 save_settings(); /* Save settings (if they have changed) */
1996 rb
->pcm_set_frequency(HW_SAMPR_DEFAULT
);
1998 /* Turn on backlight timeout (revert to settings) */
1999 backlight_use_settings(); /* backlight control in lib/helper.c */