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"
109 #include "mpeg_settings.h"
110 #include "video_out.h"
111 #include "../../codecs/libmad/mad.h"
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_POWER
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
162 #error MPEGPLAYER: Unsupported keypad
165 struct plugin_api
* rb
;
167 static mpeg2dec_t
* mpeg2dec
;
168 static int total_offset
= 0;
169 static int num_drawn
= 0;
170 static int count_start
= 0;
175 struct thread_entry
*thread
; /* Stream's thread */
176 int status
; /* Current stream status */
177 struct event ev
; /* Event sent to steam */
178 int have_msg
; /* 1=event pending */
179 int replied
; /* 1=replied to last event */
180 int reply
; /* reply value */
181 struct mutex msg_lock
; /* serialization for event senders */
182 uint8_t* curr_packet
; /* Current stream packet beginning */
183 uint8_t* curr_packet_end
; /* Current stream packet end */
185 uint8_t* prev_packet
; /* Previous stream packet beginning */
186 uint8_t* next_packet
; /* Next stream packet beginning */
188 size_t guard_bytes
; /* Number of bytes in guardbuf used */
189 size_t buffer_remaining
; /* How much data is left in the buffer */
190 uint32_t curr_pts
; /* Current presentation timestamp */
191 uint32_t curr_time
; /* Current time in samples */
192 uint32_t tagged
; /* curr_pts is valid */
197 static Stream audio_str IBSS_ATTR
;
198 static Stream video_str IBSS_ATTR
;
213 STREAM_TERMINATED
= -2,
220 /* Returns true if a message is waiting */
221 static inline bool str_have_msg(Stream
*str
)
223 return str
->have_msg
!= 0;
226 /* Waits until a message is sent */
227 static void str_wait_msg(Stream
*str
)
229 /* NOTE: sleep(0) caused a prefectch abort at C0EDBABE on e200 -
230 will look into this oddness */
235 while (str
->have_msg
== 0)
238 if (spin_count
< 100)
251 /* Returns a message waiting or blocks until one is available - removes the
253 static bool str_get_msg(Stream
*str
, struct event
*ev
)
257 ev
->data
= str
->ev
.data
;
262 /* Peeks at the current message without blocking, returns the data but
263 does not remove the event */
264 static bool str_look_msg(Stream
*str
, struct event
*ev
)
266 if (!str_have_msg(str
))
270 ev
->data
= str
->ev
.data
;
274 /* Replies to the last message pulled - has no effect if last message has not
275 been pulled or already replied */
276 static void str_reply_msg(Stream
*str
, int reply
)
278 if (str
->replied
== 1 || str
->have_msg
!= 0)
285 /* Sends a message to a stream and waits for a reply */
286 static intptr_t str_send_msg(Stream
*str
, int id
, intptr_t data
)
288 /* NOTE: sleep(0) caused a prefectch abort at C0EDBABE on e200 -
289 will look into this oddness */
297 if (str
->thread
== rb
->thread_get_current())
298 return str
->dispatch_fn(str
, msg
);
301 /* Only one thread at a time, please */
302 rb
->spinlock_lock(&str
->msg_lock
);
310 while (str
->replied
== 0 && str
->status
!= STREAM_TERMINATED
)
313 if (spin_count
< 100)
327 rb
->spinlock_unlock(&str
->msg_lock
);
332 /* NOTE: Putting the following variables in IRAM cause audio corruption
333 on the ipod (reason unknown)
335 static uint8_t *disk_buf IBSS_ATTR
;
336 static uint8_t *disk_buf_end IBSS_ATTR
;
337 static uint8_t *disk_buf_tail IBSS_ATTR
;
338 static size_t buffer_size IBSS_ATTR
;
340 /* Some stream variables are shared between cores */
341 struct mutex stream_lock IBSS_ATTR
;
342 static inline void init_stream_lock(void)
343 { rb
->spinlock_init(&stream_lock
); }
344 static inline void lock_stream(void)
345 { rb
->spinlock_lock(&stream_lock
); }
346 static inline void unlock_stream(void)
347 { rb
->spinlock_unlock(&stream_lock
); }
349 /* No RMW issue here */
350 static inline void init_stream_lock(void)
352 static inline void lock_stream(void)
354 static inline void unlock_stream(void)
359 static struct event_queue msg_queue IBSS_ATTR
;
361 #define MSG_BUFFER_NEARLY_EMPTY 1
362 #define MSG_EXIT_REQUESTED 2
364 /* Various buffers */
365 /* TODO: Can we reduce the PCM buffer size? */
366 #define PCMBUFFER_SIZE ((512*1024)-PCMBUFFER_GUARD_SIZE)
367 #define PCMBUFFER_GUARD_SIZE (1152*4 + sizeof (struct pcm_frame_header))
368 #define MPA_MAX_FRAME_SIZE 1729 /* Largest frame - MPEG1, Layer II, 384kbps, 32kHz, pad */
369 #define MPABUF_SIZE (64*1024 + ALIGN_UP(MPA_MAX_FRAME_SIZE + 2*MAD_BUFFER_GUARD, 4))
370 #define LIBMPEG2BUFFER_SIZE (2*1024*1024)
372 /* 65536+6 is required since each PES has a 6 byte header with a 16 bit packet length field */
373 #define MPEG_GUARDBUF_SIZE (64*1024+1024) /* Keep a bit extra - excessive for now */
374 #define MPEG_LOW_WATERMARK (1024*1024)
376 static void pcm_playback_play_pause(bool play
);
378 /* libmad related functions/definitions */
379 #define INPUT_CHUNK_SIZE 8192
381 struct mad_stream stream IBSS_ATTR
;
382 struct mad_frame frame IBSS_ATTR
;
383 struct mad_synth synth IBSS_ATTR
;
385 unsigned char mad_main_data
[MAD_BUFFER_MDLEN
]; /* 2567 bytes */
387 static void init_mad(void* mad_frame_overlap
)
389 rb
->memset(&stream
, 0, sizeof(struct mad_stream
));
390 rb
->memset(&frame
, 0, sizeof(struct mad_frame
));
391 rb
->memset(&synth
, 0, sizeof(struct mad_synth
));
393 mad_stream_init(&stream
);
394 mad_frame_init(&frame
);
396 /* We do this so libmad doesn't try to call codec_calloc() */
397 frame
.overlap
= mad_frame_overlap
;
399 rb
->memset(mad_main_data
, 0, sizeof(mad_main_data
));
400 stream
.main_data
= &mad_main_data
;
403 /* MPEG related headers */
405 /* Macros for comparing memory bytes to a series of constant bytes in an
406 efficient manner - evaluate to true if corresponding bytes match */
407 #if defined (CPU_ARM)
408 /* ARM must load 32-bit values at addres % 4 == 0 offsets but this data
409 isn't aligned nescessarily, so just byte compare */
410 #define CMP_3_CONST(_a, _b) \
414 "ldrb %[x], [%[a], #0] \r\n" \
415 "eors %[x], %[x], %[b0] \r\n" \
416 "ldreqb %[x], [%[a], #1] \r\n" \
417 "eoreqs %[x], %[x], %[b1] \r\n" \
418 "ldreqb %[x], [%[a], #2] \r\n" \
419 "eoreqs %[x], %[x], %[b2] \r\n" \
422 [b0]"i"((_b) >> 24), \
423 [b1]"i"((_b) << 8 >> 24), \
424 [b2]"i"((_b) << 16 >> 24) \
428 #define CMP_4_CONST(_a, _b) \
432 "ldrb %[x], [%[a], #0] \r\n" \
433 "eors %[x], %[x], %[b0] \r\n" \
434 "ldreqb %[x], [%[a], #1] \r\n" \
435 "eoreqs %[x], %[x], %[b1] \r\n" \
436 "ldreqb %[x], [%[a], #2] \r\n" \
437 "eoreqs %[x], %[x], %[b2] \r\n" \
438 "ldreqb %[x], [%[a], #3] \r\n" \
439 "eoreqs %[x], %[x], %[b3] \r\n" \
442 [b0]"i"((_b) >> 24), \
443 [b1]"i"((_b) << 8 >> 24), \
444 [b2]"i"((_b) << 16 >> 24), \
445 [b3]"i"((_b) << 24 >> 24) \
449 #elif defined (CPU_COLDFIRE)
450 /* Coldfire can just load a 32 bit value at any offset but ASM is not the best way
451 to integrate this with the C code */
452 #define CMP_3_CONST(a, b) \
453 (((*(uint32_t *)(a) >> 8) ^ ((uint32_t)(b) >> 8)) == 0)
454 #define CMP_4_CONST(a, b) \
455 ((*(uint32_t *)(a) ^ (b)) == 0)
457 /* Don't know what this is - use bytewise comparisons */
458 #define CMP_3_CONST(a, b) \
459 (( ((a)[0] ^ ((b) >> 24)) | \
460 ((a)[1] ^ ((b) << 8 >> 24)) | \
461 ((a)[2] ^ ((b) << 16 >> 24)) ) == 0)
462 #define CMP_4_CONST(a, b) \
463 (( ((a)[0] ^ ((b) >> 24)) | \
464 ((a)[1] ^ ((b) << 8 >> 24)) | \
465 ((a)[2] ^ ((b) << 16 >> 24)) | \
466 ((a)[3] ^ ((b) << 24 >> 24)) ) == 0)
469 /* Codes for various header byte sequences - MSB represents lowest memory
471 #define PACKET_START_CODE_PREFIX 0x00000100ul
472 #define END_CODE 0x000001b9ul
473 #define PACK_START_CODE 0x000001baul
474 #define SYSTEM_HEADER_START_CODE 0x000001bbul
476 /* p = base pointer, b0 - b4 = byte offsets from p */
477 /* We only care about the MS 32 bits of the 33 and so the ticks are 45kHz */
478 #define TS_FROM_HEADER(p, b0, b1, b2, b3, b4) \
479 ((uint32_t)(((p)[b0] >> 1 << 29) | \
481 ((p)[b2] >> 1 << 14) | \
485 /* This function demuxes the streams and gives the next stream data pointer */
486 static void get_next_data( Stream
* str
)
492 static int mpeg1_skip_table
[16] =
493 { 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
495 if (str
->curr_packet_end
== NULL
)
497 /* What does this do? */
498 while ((p
= disk_buf
) == NULL
)
500 rb
->lcd_putsxy(0,LCD_HEIGHT
-10,"FREEZE!");
507 p
= str
->curr_packet_end
;
514 if (p
>= disk_buf_end
)
516 p
= disk_buf
+ (p
- disk_buf_end
);
519 /* Pack header, skip it */
520 if (CMP_4_CONST(p
, PACK_START_CODE
))
522 if ((p
[4] & 0xc0) == 0x40) /* mpeg-2 */
524 p
+= 14 + (p
[13] & 7);
526 else if ((p
[4] & 0xf0) == 0x20) /* mpeg-1 */
532 rb
->splash( 30, "Weird Pack header!" );
535 /*rb->splash( 30, "Pack header" );*/
538 /* System header, parse and skip it - four bytes */
539 if (CMP_4_CONST(p
, SYSTEM_HEADER_START_CODE
))
543 p
+= 4; /*skip start code*/
544 header_length
= *p
++ << 8;
545 header_length
+= *p
++;
549 if (p
>= disk_buf_end
)
551 p
= disk_buf
+ (p
- disk_buf_end
);
553 /*rb->splash( 30, "System header" );*/
556 /* Packet header, parse it */
557 if (!CMP_3_CONST(p
, PACKET_START_CODE_PREFIX
))
560 //rb->splash( HZ*3, "missing packet start code prefix : %X%X at %X", *p, *(p+2), p-disk_buf );
561 str
->curr_packet_end
= str
->curr_packet
= NULL
;
567 /* We retrieve basic infos */
569 length
= (p
[4] << 8) | p
[5];
571 /*rb->splash( 100, "Stream : %X", stream );*/
572 if (stream
!= str
->id
)
574 /* End of stream ? */
577 str
->curr_packet_end
= str
->curr_packet
= NULL
;
581 /* It's not the packet we're looking for, skip it */
586 /* Ok, it's our packet */
587 str
->curr_packet_end
= p
+ length
+6;
590 if ((header
[6] & 0xc0) == 0x80) /* mpeg2 */
592 length
= 9 + header
[8];
594 /* header points to the mpeg2 pes header */
595 if (header
[7] & 0x80)
597 /* header has a pts */
598 uint32_t pts
= TS_FROM_HEADER(header
, 9, 10, 11, 12, 13);
602 /* video stream - header may have a dts as well */
603 uint32_t dts
= (header
[7] & 0x40) == 0 ?
604 pts
: TS_FROM_HEADER(header
, 14, 15, 16, 17, 18);
606 mpeg2_tag_picture (mpeg2dec
, pts
, dts
);
622 while (header
[length
- 1] == 0xff)
627 rb
->splash( 30, "Too much stuffing" );
628 DEBUGF("Too much stuffing" );
633 if ((header
[length
- 1] & 0xc0) == 0x40)
639 length
+= mpeg1_skip_table
[header
[length
- 1] >> 4];
641 /* header points to the mpeg1 pes header */
642 ptsbuf
= header
+ len_skip
;
644 if ((ptsbuf
[-1] & 0xe0) == 0x20)
646 /* header has a pts */
647 uint32_t pts
= TS_FROM_HEADER(ptsbuf
, -1, 0, 1, 2, 3);
651 /* video stream - header may have a dts as well */
652 uint32_t dts
= (ptsbuf
[-1] & 0xf0) != 0x30 ?
653 pts
: TS_FROM_HEADER(ptsbuf
, 4, 5, 6, 7, 18);
655 mpeg2_tag_picture (mpeg2dec
, pts
, dts
);
666 bytes
= 6 + (header
[4] << 8) + header
[5] - length
;
670 str
->curr_packet_end
= p
+ bytes
;
671 //DEBUGF("prev = %d, curr = %d\n",str->prev_packet,str->curr_packet);
673 if (str
->curr_packet
!= NULL
)
677 if (str
->curr_packet
< str
->prev_packet
)
679 str
->buffer_remaining
-= (disk_buf_end
- str
->prev_packet
) +
680 (str
->curr_packet
- disk_buf
);
681 str
->buffer_remaining
-= str
->guard_bytes
;
682 str
->guard_bytes
= 0;
686 str
->buffer_remaining
-= (str
->curr_packet
- str
->prev_packet
);
691 str
->prev_packet
= str
->curr_packet
;
694 str
->curr_packet
= p
;
696 if (str
->curr_packet_end
> disk_buf_end
)
698 str
->guard_bytes
= str
->curr_packet_end
- disk_buf_end
;
699 rb
->memcpy(disk_buf_end
, disk_buf
, str
->guard_bytes
);
707 /* Our clock rate in ticks/second - this won't be a constant for long */
708 #define CLOCK_RATE 44100
710 /* For simple lowpass filtering of sync variables */
711 #define AVERAGE(var, x, count) (((var) * (count-1) + (x)) / (count))
712 /* Convert 45kHz PTS/DTS ticks to our clock ticks */
713 #define TS_TO_TICKS(pts) ((uint64_t)CLOCK_RATE*(pts) / 45000)
714 /* Convert 27MHz ticks to our clock ticks */
715 #define TIME_TO_TICKS(stamp) ((uint64_t)CLOCK_RATE*(stamp) / 27000000)
717 /** MPEG audio stream buffer */
720 static bool init_mpabuf(void)
722 mpa_buffer
= mpeg2_malloc(MPABUF_SIZE
,-2);
723 return mpa_buffer
!= NULL
;
726 #define PTS_QUEUE_LEN (1 << 5) /* 32 should be way more than sufficient -
727 if not, the case is handled */
728 #define PTS_QUEUE_MASK (PTS_QUEUE_LEN-1)
729 struct pts_queue_slot
731 uint32_t pts
; /* Time stamp for packet */
732 ssize_t size
; /* Number of bytes left in packet */
733 } pts_queue
[PTS_QUEUE_LEN
];
735 /* This starts out wr == rd but will never be emptied to zero during
736 streaming again in order to support initializing the first packet's
737 pts value without a special case */
738 static unsigned pts_queue_rd
;
739 static unsigned pts_queue_wr
;
741 /* Increments the queue head postion - should be used to preincrement */
742 static bool pts_queue_add_head(void)
744 if (pts_queue_wr
- pts_queue_rd
>= PTS_QUEUE_LEN
-1)
751 /* Increments the queue tail position - leaves one slot as current */
752 static bool pts_queue_remove_tail(void)
754 if (pts_queue_wr
- pts_queue_rd
<= 1u)
761 /* Returns the "head" at the index just behind the write index */
762 static struct pts_queue_slot
* pts_queue_head(void)
764 return &pts_queue
[(pts_queue_wr
- 1) & PTS_QUEUE_MASK
];
767 /* Returns a pointer to the current tail */
768 static struct pts_queue_slot
* pts_queue_tail(void)
770 return &pts_queue
[pts_queue_rd
& PTS_QUEUE_MASK
];
773 /* Resets the pts queue - call when starting and seeking */
774 static void pts_queue_reset(void)
776 struct pts_queue_slot
*pts
;
777 pts_queue_rd
= pts_queue_wr
;
778 pts
= pts_queue_tail();
783 struct pcm_frame_header
/* Header added to pcm data every time a decoded
784 mpa frame is sent out */
786 uint32_t size
; /* size of this frame - including header */
787 uint32_t time
; /* timestamp for this frame - derived from PTS */
788 unsigned char data
[]; /* open array of audio data */
791 #define PCMBUF_PLAY_ALL 1l /* Forces buffer to play back all data */
792 #define PCMBUF_PLAY_NONE LONG_MAX /* Keeps buffer from playing any data */
793 static volatile uint64_t pcmbuf_read IBSS_ATTR
;
794 static volatile uint64_t pcmbuf_written IBSS_ATTR
;
795 static volatile ssize_t pcmbuf_threshold IBSS_ATTR
;
796 static struct pcm_frame_header
*pcm_buffer IBSS_ATTR
;
797 static struct pcm_frame_header
*pcmbuf_end IBSS_ATTR
;
798 static struct pcm_frame_header
* volatile pcmbuf_head IBSS_ATTR
;
799 static struct pcm_frame_header
* volatile pcmbuf_tail IBSS_ATTR
;
801 static volatile uint32_t samplesplayed IBSS_ATTR
; /* Our base clock */
802 static volatile uint32_t samplestart IBSS_ATTR
; /* Clock at playback start */
803 static volatile int32_t sampleadjust IBSS_ATTR
; /* Clock drift adjustment */
805 static ssize_t
pcmbuf_used(void)
807 return (ssize_t
)(pcmbuf_written
- pcmbuf_read
);
810 static bool init_pcmbuf(void)
812 pcm_buffer
= mpeg2_malloc(PCMBUFFER_SIZE
+ PCMBUFFER_GUARD_SIZE
, -2);
814 if (pcm_buffer
== NULL
)
817 pcmbuf_head
= pcm_buffer
;
818 pcmbuf_tail
= pcm_buffer
;
819 pcmbuf_end
= SKIPBYTES(pcm_buffer
, PCMBUFFER_SIZE
);
826 /* Advance a PCM buffer pointer by size bytes circularly */
827 static inline void pcm_advance_buffer(struct pcm_frame_header
* volatile *p
,
830 *p
= SKIPBYTES(*p
, size
);
831 if (*p
>= pcmbuf_end
)
835 static void get_more(unsigned char** start
, size_t* size
)
838 static unsigned char silence
[4412] __attribute__((aligned (4))) = { 0 };
841 if (pcmbuf_used() >= pcmbuf_threshold
)
843 uint32_t time
= pcmbuf_tail
->time
;
844 sz
= pcmbuf_tail
->size
;
846 *start
= (unsigned char *)pcmbuf_tail
->data
;
848 pcm_advance_buffer(&pcmbuf_tail
, sz
);
852 sz
-= sizeof (*pcmbuf_tail
);
856 /* Drift the clock towards the audio timestamp values */
857 sampleadjust
= AVERAGE(sampleadjust
, (int32_t)(time
- samplesplayed
), 8);
859 /* Update master clock */
860 samplesplayed
+= sz
>> 2;
864 /* Keep clock going at all times */
865 sz
= sizeof (silence
);
869 samplesplayed
+= sz
>> 2;
871 if (pcmbuf_read
> pcmbuf_written
)
872 pcmbuf_read
= pcmbuf_written
;
875 /* Flushes the buffer - clock keeps counting */
876 static void pcm_playback_flush(void)
878 bool was_playing
= rb
->pcm_is_playing();
885 pcmbuf_head
= pcmbuf_tail
;
888 rb
->pcm_play_data(get_more
, NULL
, 0);
891 /* Seek the reference clock to the specified time - next audio data ready to
892 go to DMA should be on the buffer with the same time index or else the PCM
893 buffer should be empty */
894 static void pcm_playback_seek_time(uint32_t time
)
896 bool was_playing
= rb
->pcm_is_playing();
901 samplesplayed
= time
;
906 rb
->pcm_play_data(get_more
, NULL
, 0);
909 /* Start pcm playback with the reference clock set to the specified time */
910 static void pcm_playback_play(uint32_t time
)
912 pcm_playback_seek_time(time
);
914 if (!rb
->pcm_is_playing())
915 rb
->pcm_play_data(get_more
, NULL
, 0);
918 /* Pauses playback - and the clock */
919 static void pcm_playback_play_pause(bool play
)
921 rb
->pcm_play_pause(play
);
924 /* Stops all playback and resets the clock */
925 static void pcm_playback_stop(void)
927 if (rb
->pcm_is_playing())
930 pcm_playback_flush();
937 static uint32_t get_stream_time(void)
939 return samplesplayed
+ sampleadjust
- (rb
->pcm_get_bytes_waiting() >> 2);
942 static uint32_t get_playback_time(void)
944 return samplesplayed
+ sampleadjust
-
945 samplestart
- (rb
->pcm_get_bytes_waiting() >> 2);
948 static inline int32_t clip_sample(int32_t sample
)
950 if ((int16_t)sample
!= sample
)
951 sample
= 0x7fff ^ (sample
>> 31);
956 static int button_loop(void)
959 int vol
, minvol
, maxvol
;
962 if (str_have_msg(&audio_str
))
965 str_get_msg(&audio_str
, &ev
);
967 if (ev
.id
== STREAM_STOP
)
969 audio_str
.status
= STREAM_STOPPED
;
970 str_reply_msg(&audio_str
, 1);
975 str_reply_msg(&audio_str
, 0);
979 button
= rb
->button_get(false);
984 case MPEG_VOLUP
|BUTTON_REPEAT
:
987 case MPEG_VOLUP2
|BUTTON_REPEAT
:
989 vol
= rb
->global_settings
->volume
;
990 maxvol
= rb
->sound_max(SOUND_VOLUME
);
994 rb
->sound_set(SOUND_VOLUME
, vol
);
995 rb
->global_settings
->volume
= vol
;
1000 case MPEG_VOLDOWN
|BUTTON_REPEAT
:
1001 #ifdef MPEG_VOLDOWN2
1003 case MPEG_VOLDOWN2
|BUTTON_REPEAT
:
1005 vol
= rb
->global_settings
->volume
;
1006 minvol
= rb
->sound_min(SOUND_VOLUME
);
1010 rb
->sound_set(SOUND_VOLUME
, vol
);
1011 rb
->global_settings
->volume
= vol
;
1016 pcm_playback_play_pause(false);
1017 audio_str
.status
= STREAM_PAUSED
;
1018 str_send_msg(&video_str
, STREAM_PAUSE
, 0);
1019 #ifndef HAVE_LCD_COLOR
1022 result
= mpeg_menu();
1023 count_start
= get_playback_time();
1026 #ifndef HAVE_LCD_COLOR
1030 /* The menu can change the font, so restore */
1031 rb
->lcd_setfont(FONT_SYSFIXED
);
1034 str_send_msg(&video_str
, STREAM_STOP
, 0);
1035 audio_str
.status
= STREAM_STOPPED
;
1037 audio_str
.status
= STREAM_PLAYING
;
1038 str_send_msg(&video_str
, STREAM_PLAY
, 0);
1039 pcm_playback_play_pause(true);
1044 str_send_msg(&video_str
, STREAM_STOP
, 0);
1045 audio_str
.status
= STREAM_STOPPED
;
1049 str_send_msg(&video_str
, STREAM_PAUSE
, 0);
1050 audio_str
.status
= STREAM_PAUSED
;
1051 pcm_playback_play_pause(false);
1053 button
= BUTTON_NONE
;
1054 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1055 rb
->cpu_boost(false);
1058 button
= rb
->button_get(true);
1059 if (button
== MPEG_STOP
) {
1060 str_send_msg(&video_str
, STREAM_STOP
, 0);
1061 audio_str
.status
= STREAM_STOPPED
;
1064 } while (button
!= MPEG_PAUSE
);
1066 str_send_msg(&video_str
, STREAM_PLAY
, 0);
1067 audio_str
.status
= STREAM_PLAYING
;
1068 pcm_playback_play_pause(true);
1069 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1070 rb
->cpu_boost(true);
1075 if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
) {
1076 str_send_msg(&video_str
, STREAM_STOP
, 0);
1077 audio_str
.status
= STREAM_STOPPED
;
1082 return audio_str
.status
;
1085 static void audio_thread(void)
1087 uint8_t *mpabuf
= mpa_buffer
;
1088 ssize_t mpabuf_used
= 0;
1089 int mad_errors
= 0; /* A count of the errors in each frame */
1090 struct pts_queue_slot
*pts
;
1092 /* We need this here to init the EMAC for Coldfire targets */
1093 mad_synth_init(&synth
);
1095 /* Init pts queue */
1097 pts
= pts_queue_tail();
1099 /* Keep buffer from playing */
1100 pcmbuf_threshold
= PCMBUF_PLAY_NONE
;
1103 pcm_playback_play(0);
1105 /* Get first packet */
1106 get_next_data(&audio_str
);
1108 if (audio_str
.curr_packet
== NULL
)
1111 /* This is the decoding loop. */
1117 if (button_loop() < 0)
1122 /* Carry any overshoot to the next size since we're technically
1123 -pts->size bytes into it already. If size is negative an audio
1124 frame was split accross packets. Old has to be saved before
1126 if (pts_queue_remove_tail())
1128 struct pts_queue_slot
*old
= pts
;
1129 pts
= pts_queue_tail();
1130 pts
->size
+= old
->size
;
1136 if (mpabuf_used
>= MPA_MAX_FRAME_SIZE
+ MAD_BUFFER_GUARD
)
1138 /* Above low watermark - do nothing */
1140 else if (audio_str
.curr_packet
!= NULL
)
1144 /* Get data from next audio packet */
1145 len
= audio_str
.curr_packet_end
- audio_str
.curr_packet
;
1147 if (audio_str
.tagged
)
1149 struct pts_queue_slot
*stamp
= pts
;
1151 if (pts_queue_add_head())
1153 stamp
= pts_queue_head();
1154 stamp
->pts
= TS_TO_TICKS(audio_str
.curr_pts
);
1155 /* pts->size should have been zeroed when slot was
1158 /* else queue full - just count up from the last to make
1159 it look like more data in the same packet */
1161 audio_str
.tagged
= 0;
1165 /* Add to the one just behind the head - this may be the
1166 tail or the previouly added head - whether or not we'll
1167 ever reach this is quite in question since audio always
1168 seems to have every packet timestamped */
1169 pts_queue_head()->size
+= len
;
1172 /* Slide any remainder over to beginning - avoid function
1173 call overhead if no data remaining as well */
1174 if (mpabuf
> mpa_buffer
&& mpabuf_used
> 0)
1175 rb
->memmove(mpa_buffer
, mpabuf
, mpabuf_used
);
1177 /* Splice this packet onto any remainder */
1178 rb
->memcpy(mpa_buffer
+ mpabuf_used
, audio_str
.curr_packet
,
1182 mpabuf
= mpa_buffer
;
1184 /* Get data from next audio packet */
1185 get_next_data(&audio_str
);
1187 while (audio_str
.curr_packet
!= NULL
&&
1188 mpabuf_used
< MPA_MAX_FRAME_SIZE
+ MAD_BUFFER_GUARD
);
1190 else if (mpabuf_used
<= 0)
1192 /* Used up remainder of mpa buffer so quit */
1197 mad_stream_buffer(&stream
, mpabuf
, mpabuf_used
);
1199 mad_stat
= mad_frame_decode(&frame
, &stream
);
1201 if (stream
.next_frame
== NULL
)
1203 /* What to do here? (This really is fatal) */
1204 DEBUGF("/* What to do here? */\n");
1208 /* Next mad stream buffer is the next frame postion */
1209 mpabuf
= (uint8_t *)stream
.next_frame
;
1211 /* Adjust sizes by the frame size */
1212 len
= stream
.next_frame
- stream
.this_frame
;
1218 DEBUGF("Audio stream error - %d\n", stream
.error
);
1220 if (stream
.error
== MAD_FLAG_INCOMPLETE
1221 || stream
.error
== MAD_ERROR_BUFLEN
)
1223 /* This makes the codec support partially corrupted files */
1224 if (++mad_errors
> 30)
1228 rb
->priority_yield();
1231 else if (MAD_RECOVERABLE(stream
.error
))
1234 rb
->priority_yield();
1239 /* Some other unrecoverable error */
1240 DEBUGF("Unrecoverable error\n");
1246 mad_errors
= 0; /* Clear errors */
1248 /* Generate the pcm samples */
1249 mad_synth_frame(&synth
, &frame
);
1253 /* TODO: Output through core dsp. We'll still use our own PCM buffer
1254 since the core pcm buffer has no timestamping or clock facilities */
1256 /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */
1257 if (synth
.pcm
.length
> 0)
1259 int16_t *audio_data
= (int16_t *)pcmbuf_head
->data
;
1260 size_t size
= sizeof (*pcmbuf_head
) + synth
.pcm
.length
*4;
1261 size_t wait_for
= size
+ 32*1024;
1263 /* Leave at least 32KB free (this will be the currently
1265 while (pcmbuf_used() + wait_for
> PCMBUFFER_SIZE
)
1267 if (str_have_msg(&audio_str
))
1270 str_look_msg(&audio_str
, &ev
);
1272 if (ev
.id
== STREAM_STOP
)
1274 str_get_msg(&audio_str
, &ev
);
1275 str_reply_msg(&audio_str
, 1);
1280 rb
->priority_yield();
1283 /* TODO: This part will be replaced with dsp calls soon */
1284 if (MAD_NCHANNELS(&frame
.header
) == 2)
1286 int32_t *left
= &synth
.pcm
.samples
[0][0];
1287 int32_t *right
= &synth
.pcm
.samples
[1][0];
1288 int i
= synth
.pcm
.length
;
1292 /* libmad outputs s3.28 */
1293 *audio_data
++ = clip_sample(*left
++ >> 13);
1294 *audio_data
++ = clip_sample(*right
++ >> 13);
1300 int32_t *mono
= &synth
.pcm
.samples
[0][0];
1301 int i
= synth
.pcm
.length
;
1305 int32_t s
= clip_sample(*mono
++ >> 13);
1313 pcmbuf_head
->time
= pts
->pts
;
1314 pcmbuf_head
->size
= size
;
1316 /* As long as we're on this timestamp, the time is just incremented
1317 by the number of samples */
1318 pts
->pts
+= synth
.pcm
.length
;
1320 pcm_advance_buffer(&pcmbuf_head
, size
);
1322 if (pcmbuf_threshold
!= PCMBUF_PLAY_ALL
&& pcmbuf_used() >= 64*1024)
1324 /* We've reached our size treshold so start playing back the
1325 audio in the buffer and set the buffer to play all data */
1326 audio_str
.status
= STREAM_PLAYING
;
1327 pcmbuf_threshold
= PCMBUF_PLAY_ALL
;
1328 pcm_playback_seek_time(pcmbuf_tail
->time
);
1331 /* Make this data available to DMA */
1332 pcmbuf_written
+= size
;
1336 } /* end decoding loop */
1339 if (audio_str
.status
== STREAM_STOPPED
)
1342 /* Force any residue to play if audio ended before reaching the
1344 if (pcmbuf_threshold
!= PCMBUF_PLAY_ALL
&& pcmbuf_used() > 0)
1346 pcm_playback_play(pcmbuf_tail
->time
);
1347 pcmbuf_threshold
= PCMBUF_PLAY_ALL
;
1350 if (rb
->pcm_is_playing() && !rb
->pcm_is_paused())
1352 /* Wait for audio to finish */
1353 while (pcmbuf_used() > 0)
1355 if (button_loop() == STREAM_STOPPED
)
1363 audio_str
.status
= STREAM_DONE
;
1365 /* Process events until finished */
1366 while (button_loop() != STREAM_STOPPED
)
1369 pcm_playback_stop();
1371 audio_str
.status
= STREAM_TERMINATED
;
1372 rb
->remove_thread(NULL
);
1375 /* End of libmad stuff */
1377 /* TODO: Running in the main thread, libmad needs 8.25KB of stack.
1378 The codec thread uses a 9KB stack. So we can probable reduce this a
1379 little, but leave at 9KB for now to be safe. */
1380 #define AUDIO_STACKSIZE (9*1024)
1381 uint32_t audio_stack
[AUDIO_STACKSIZE
/ sizeof(uint32_t)] IBSS_ATTR
;
1383 /* TODO: Check if 4KB is appropriate - it works for my test streams,
1384 so maybe we can reduce it. */
1385 #define VIDEO_STACKSIZE (4*1024)
1386 static uint32_t video_stack
[VIDEO_STACKSIZE
/ sizeof(uint32_t)] IBSS_ATTR
;
1388 static void video_thread(void)
1391 const mpeg2_info_t
* info
;
1392 mpeg2_state_t state
;
1394 uint32_t curr_time
= 0;
1395 uint32_t period
= 0; /* Frame period in clock ticks */
1396 uint32_t eta_audio
= UINT_MAX
, eta_video
= 0;
1397 int32_t eta_early
= 0, eta_late
= 0;
1398 int frame_drop_level
= 0;
1400 int num_skipped
= 0;
1401 /* Used to decide when to display FPS */
1402 unsigned long last_showfps
= *rb
->current_tick
- HZ
;
1403 /* Used to decide whether or not to force a frame update */
1404 unsigned long last_render
= last_showfps
;
1406 mpeg2dec
= mpeg2_init();
1407 if (mpeg2dec
== NULL
)
1409 rb
->splash(0, "mpeg2_init failed");
1410 /* Commit suicide */
1411 video_str
.status
= STREAM_TERMINATED
;
1412 rb
->remove_thread(NULL
);
1415 /* Clear the display - this is mainly just to indicate that the
1416 video thread has started successfully. */
1417 rb
->lcd_clear_display();
1420 /* Request the first packet data */
1421 get_next_data( &video_str
);
1423 if (video_str
.curr_packet
== NULL
)
1426 mpeg2_buffer (mpeg2dec
, video_str
.curr_packet
, video_str
.curr_packet_end
);
1427 total_offset
+= video_str
.curr_packet_end
- video_str
.curr_packet
;
1429 info
= mpeg2_info (mpeg2dec
);
1431 /* Wait if the audio thread is buffering - i.e. before
1432 the first frames are decoded */
1433 while (audio_str
.status
== STREAM_BUFFERING
)
1434 rb
->priority_yield();
1438 /* quickly check mailbox first */
1439 if (str_have_msg(&video_str
))
1443 str_get_msg(&video_str
, &ev
);
1448 video_str
.status
= STREAM_STOPPED
;
1449 str_reply_msg(&video_str
, 1);
1453 video_str
.status
= STREAM_PAUSED
;
1454 str_reply_msg(&video_str
, 1);
1461 video_str
.status
= STREAM_PLAYING
;
1462 str_reply_msg(&video_str
, 1);
1465 state
= mpeg2_parse (mpeg2dec
);
1468 /* Prevent idle poweroff */
1469 rb
->reset_poweroff_timer();
1474 /* Request next packet data */
1475 get_next_data( &video_str
);
1476 mpeg2_buffer (mpeg2dec
, video_str
.curr_packet
, video_str
.curr_packet_end
);
1477 total_offset
+= video_str
.curr_packet_end
- video_str
.curr_packet
;
1478 info
= mpeg2_info (mpeg2dec
);
1480 if (video_str
.curr_packet
== NULL
)
1487 case STATE_SEQUENCE
:
1488 /* New GOP, inform output of any changes */
1489 vo_setup(info
->sequence
);
1494 int skip
= 0; /* Assume no skip */
1496 if (frame_drop_level
>= 1 || skip_level
> 0)
1498 /* A frame will be dropped in the decoder */
1500 /* Frame type: I/P/B/D */
1501 int type
= info
->current_picture
->flags
& PIC_MASK_CODING_TYPE
;
1505 case PIC_FLAG_CODING_TYPE_I
:
1506 case PIC_FLAG_CODING_TYPE_D
:
1507 /* Level 5: Things are extremely late and all frames will be
1508 dropped until the next key frame */
1509 if (frame_drop_level
>= 1)
1510 frame_drop_level
= 0; /* Key frame - reset drop level */
1511 if (skip_level
>= 5)
1513 frame_drop_level
= 1;
1514 skip_level
= 0; /* reset */
1517 case PIC_FLAG_CODING_TYPE_P
:
1518 /* Level 4: Things are very late and all frames will be
1519 dropped until the next key frame */
1520 if (skip_level
>= 4)
1522 frame_drop_level
= 1;
1523 skip_level
= 0; /* reset */
1526 case PIC_FLAG_CODING_TYPE_B
:
1527 /* We want to drop something, so this B frame won't even
1528 be decoded. Drawing can happen on the next frame if so
1529 desired. Bring the level down as skips are done. */
1535 skip
|= frame_drop_level
;
1538 mpeg2_skip(mpeg2dec
, skip
);
1544 case STATE_INVALID_END
:
1546 int32_t offset
; /* Tick adjustment to keep sync */
1548 /* draw current picture */
1549 if (!info
->display_fbuf
)
1552 /* No limiting => no dropping - draw this frame */
1553 if (!settings
.limitfps
)
1556 /* Get presentation times in audio samples - quite accurate
1557 enough - add previous frame duration if not stamped */
1558 curr_time
= (info
->display_picture
->flags
& PIC_FLAG_TAGS
) ?
1559 TS_TO_TICKS(info
->display_picture
->tag
) : (curr_time
+ period
);
1561 period
= TIME_TO_TICKS(info
->sequence
->frame_period
);
1563 eta_video
= curr_time
;
1564 eta_audio
= get_stream_time();
1566 /* How early/late are we? > 0 = late, < 0 early */
1567 offset
= eta_audio
- eta_video
;
1569 if (!settings
.skipframes
)
1571 /* Make no effort to determine whether this frame should be
1572 drawn or not since no action can be taken to correct the
1573 situation. We'll just wait if we're early and correct for
1574 lateness as much as possible. */
1578 eta_late
= AVERAGE(eta_late
, offset
, 4);
1581 if ((uint32_t)offset
> eta_video
)
1584 eta_video
-= offset
;
1588 /** Possibly skip this frame **/
1590 /* Frameskipping has the following order of preference:
1592 * Frame Type Who Notes/Rationale
1593 * B decoder arbitrarily drop - no decode or draw
1594 * Any renderer arbitrarily drop - will be I/D/P
1595 * P decoder must wait for I/D-frame - choppy
1596 * I/D decoder must wait for I/D-frame - choppy
1598 * If a frame can be drawn and it has been at least 1/2 second,
1599 * the image will be updated no matter how late it is just to
1600 * avoid looking stuck.
1603 /* If we're late, set the eta to play the frame early so
1604 we may catch up. If early, especially because of a drop,
1605 mitigate a "snap" by moving back gradually. */
1606 if (offset
>= 0) /* late or on time */
1608 eta_early
= 0; /* Not early now :( */
1610 eta_late
= AVERAGE(eta_late
, offset
, 4);
1613 if ((uint32_t)offset
> eta_video
)
1616 eta_video
-= offset
;
1620 eta_late
= 0; /* Not late now :) */
1622 if (offset
> eta_early
)
1624 /* Just dropped a frame and we're now early or we're
1625 coming back from being early */
1627 if ((uint32_t)-offset
> eta_video
)
1628 offset
= -eta_video
;
1630 eta_video
+= offset
;
1634 /* Just early with an offset, do exponential drift back */
1637 eta_early
= AVERAGE(eta_early
, 0, 8);
1638 eta_video
= ((uint32_t)-eta_early
> eta_video
) ?
1639 0 : (eta_video
+ eta_early
);
1646 if (info
->display_picture
->flags
& PIC_FLAG_SKIP
)
1648 /* This frame was set to skip so skip it after having updated
1649 timing information */
1651 eta_early
= INT32_MIN
;
1655 if (skip_level
== 3 && TIME_BEFORE(*rb
->current_tick
, last_render
+ HZ
/2))
1657 /* Render drop was set previously but nothing was dropped in the
1658 decoder or it's been to long since drawing the last frame. */
1661 eta_early
= INT32_MIN
;
1665 /* At this point a frame _will_ be drawn - a skip may happen on
1669 if (offset
> CLOCK_RATE
*110/1000)
1671 /* Decide which skip level is needed in order to catch up */
1673 /* TODO: Calculate this rather than if...else - this is rather
1674 exponential though */
1675 if (offset
> CLOCK_RATE
*367/1000)
1676 skip_level
= 5; /* Decoder skip: I/D */
1677 if (offset
> CLOCK_RATE
*233/1000)
1678 skip_level
= 4; /* Decoder skip: P */
1679 else if (offset
> CLOCK_RATE
*167/1000)
1680 skip_level
= 3; /* Render skip */
1681 else if (offset
> CLOCK_RATE
*133/1000)
1682 skip_level
= 2; /* Decoder skip: B */
1684 skip_level
= 1; /* Decoder skip: B */
1688 /* Wait until audio catches up */
1689 while (eta_video
> eta_audio
)
1691 rb
->priority_yield();
1693 /* Make sure not to get stuck waiting here forever */
1694 if (str_have_msg(&video_str
))
1696 str_look_msg(&video_str
, &ev
);
1698 if (ev
.id
!= STREAM_PLAY
)
1699 goto rendering_finished
;
1701 str_get_msg(&video_str
, &ev
);
1702 str_reply_msg(&video_str
, 1);
1705 eta_audio
= get_stream_time();
1709 /* Record last frame time */
1710 last_render
= *rb
->current_tick
;
1712 vo_draw_frame(info
->display_fbuf
->buf
);
1716 if (!settings
.showfps
)
1719 /* Calculate and display fps */
1720 if (TIME_AFTER(*rb
->current_tick
, last_showfps
+ HZ
))
1722 uint32_t clock_ticks
= get_playback_time() - count_start
;
1725 if (clock_ticks
!= 0)
1726 fps
= num_drawn
*CLOCK_RATE
*10ll / clock_ticks
;
1728 rb
->snprintf(str
, sizeof(str
), "%d.%d %d %d ",
1729 fps
/ 10, fps
% 10, num_skipped
,
1730 info
->display_picture
->temporal_reference
);
1731 rb
->lcd_putsxy(0, 0, str
);
1732 rb
->lcd_update_rect(0, 0, LCD_WIDTH
, 8);
1734 last_showfps
= *rb
->current_tick
;
1750 video_str
.status
= STREAM_DONE
;
1754 str_get_msg(&video_str
, &ev
);
1756 if (ev
.id
== STREAM_STOP
)
1759 str_reply_msg(&video_str
, 0);
1762 /* Commit suicide */
1763 str_reply_msg(&video_str
, 1);
1764 video_str
.status
= STREAM_TERMINATED
;
1765 rb
->remove_thread(NULL
);
1768 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
1770 int status
= PLUGIN_ERROR
; /* assume failure */
1775 size_t file_remaining
;
1776 size_t disk_buf_len
;
1777 #ifndef HAVE_LCD_COLOR
1782 /* We define this here so it is on the main stack (in IRAM) */
1783 mad_fixed_t mad_frame_overlap
[2][32][18]; /* 4608 bytes */
1785 if (parameter
== NULL
)
1787 api
->splash(HZ
*2, "No File");
1788 return PLUGIN_ERROR
;
1791 /* Initialize IRAM - stops audio and voice as well */
1792 PLUGIN_IRAM_INIT(api
)
1796 audiobuf
= rb
->plugin_get_audio_buffer(&audiosize
);
1798 #if INPUT_SRC_CAPS != 0
1799 /* Select playback */
1800 rb
->audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1801 rb
->audio_set_output_source(AUDIO_SRC_PLAYBACK
);
1804 rb
->pcm_set_frequency(SAMPR_44
);
1806 /* Set disk pointers to NULL */
1807 disk_buf_end
= disk_buf
= NULL
;
1809 /* Stream construction */
1810 /* We take the first stream of each (audio and video) */
1811 /* TODO : Search for these in the file first */
1812 audio_str
.curr_packet_end
= audio_str
.curr_packet
= audio_str
.next_packet
= NULL
;
1813 video_str
= audio_str
;
1814 video_str
.id
= 0xe0;
1815 audio_str
.id
= 0xc0;
1817 /* Initialise our malloc buffer */
1818 mpeg2_alloc_init(audiobuf
,audiosize
);
1820 /* Grab most of the buffer for the compressed video - leave some for
1821 PCM audio data and some for libmpeg2 malloc use. */
1822 buffer_size
= audiosize
- (PCMBUFFER_SIZE
+PCMBUFFER_GUARD_SIZE
+
1823 MPABUF_SIZE
+LIBMPEG2BUFFER_SIZE
);
1825 DEBUGF("audiosize=%ld, buffer_size=%ld\n",audiosize
,buffer_size
);
1826 buffer
= mpeg2_malloc(buffer_size
,-1);
1829 return PLUGIN_ERROR
;
1831 #ifndef HAVE_LCD_COLOR
1832 /* initialize the grayscale buffer: 32 bitplanes for 33 shades of gray. */
1833 grayscales
= gray_init(rb
, buffer
, buffer_size
, false, LCD_WIDTH
, LCD_HEIGHT
,
1834 32, 2<<8, &graysize
) + 1;
1836 buffer_size
-= graysize
;
1837 if (grayscales
< 33 || buffer_size
<= 0)
1839 rb
->splash(HZ
, "gray buf error");
1840 return PLUGIN_ERROR
;
1844 buffer_size
&= ~(0x7ff); /* Round buffer down to nearest 2KB */
1845 DEBUGF("audiosize=%ld, buffer_size=%ld\n",audiosize
,buffer_size
);
1848 return PLUGIN_ERROR
;
1851 return PLUGIN_ERROR
;
1853 /* The remaining buffer is for use by libmpeg2 */
1855 /* Open the video file */
1856 in_file
= rb
->open((char*)parameter
,O_RDONLY
);
1859 //fprintf(stderr,"Could not open %s\n",argv[1]);
1860 return PLUGIN_ERROR
;
1863 #ifdef HAVE_LCD_COLOR
1864 rb
->lcd_set_backdrop(NULL
);
1865 rb
->lcd_set_foreground(LCD_WHITE
);
1866 rb
->lcd_set_background(LCD_BLACK
);
1868 rb
->lcd_clear_display();
1871 /* make sure the backlight is always on when viewing video
1872 (actually it should also set the timeout when plugged in,
1873 but the function backlight_set_timeout_plugged is not
1874 available in plugins) */
1875 #ifdef HAVE_BACKLIGHT
1876 if (rb
->global_settings
->backlight_timeout
> 0)
1877 rb
->backlight_set_timeout(1);
1880 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
1881 rb
->cpu_boost(true);
1884 /* From this point on we've altered settings, colors, cpu_boost, etc. and
1885 cannot just return PLUGIN_ERROR - instead drop though to cleanup code
1890 /* Msg queue init - no need for queue_remove since it's not a registered
1892 rb
->queue_init( &msg_queue
, false );
1894 /* Initialise libmad */
1895 rb
->memset(mad_frame_overlap
, 0, sizeof(mad_frame_overlap
));
1896 init_mad(mad_frame_overlap
);
1898 file_remaining
= rb
->filesize(in_file
);
1899 disk_buf_end
= buffer
+ buffer_size
-MPEG_GUARDBUF_SIZE
;
1901 /* Read some stream data */
1902 disk_buf_len
= rb
->read (in_file
, buffer
, MPEG_LOW_WATERMARK
);
1904 DEBUGF("Initial Buffering - %d bytes\n",(int)disk_buf_len
);
1906 disk_buf_tail
= buffer
+disk_buf_len
;
1907 file_remaining
-= disk_buf_len
;
1909 video_str
.guard_bytes
= audio_str
.guard_bytes
= 0;
1910 video_str
.prev_packet
= disk_buf
;
1911 audio_str
.prev_packet
= disk_buf
;
1912 video_str
.buffer_remaining
= disk_buf_len
;
1913 audio_str
.buffer_remaining
= disk_buf_len
;
1915 rb
->spinlock_init(&audio_str
.msg_lock
);
1916 rb
->spinlock_init(&video_str
.msg_lock
);
1917 audio_str
.status
= STREAM_BUFFERING
;
1918 video_str
.status
= STREAM_PLAYING
;
1920 #ifndef HAVE_LCD_COLOR
1926 /* We put the video thread on the second processor for multi-core targets. */
1927 if ((video_str
.thread
= rb
->create_thread(video_thread
,
1928 (uint8_t*)video_stack
,VIDEO_STACKSIZE
,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK
)
1929 IF_COP(, COP
, true))) == NULL
)
1931 rb
->splash(HZ
, "Cannot create video thread!");
1933 else if ((audio_str
.thread
= rb
->create_thread(audio_thread
,
1934 (uint8_t*)audio_stack
,AUDIO_STACKSIZE
,"mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK
)
1935 IF_COP(, CPU
, false))) == NULL
)
1937 rb
->splash(HZ
, "Cannot create audio thread!");
1941 //DEBUGF("START: video = %d, audio = %d\n",audio_str.buffer_remaining,video_str.buffer_remaining);
1942 rb
->lcd_setfont(FONT_SYSFIXED
);
1944 /* Wait until both threads have finished their work */
1945 while ((audio_str
.status
>= 0) || (video_str
.status
>= 0))
1947 size_t audio_remaining
= audio_str
.buffer_remaining
;
1948 size_t video_remaining
= video_str
.buffer_remaining
;
1950 if (MIN(audio_remaining
,video_remaining
) < MPEG_LOW_WATERMARK
) {
1952 size_t bytes_to_read
= buffer_size
- MPEG_GUARDBUF_SIZE
-
1953 MAX(audio_remaining
,video_remaining
);
1955 bytes_to_read
= MIN(bytes_to_read
,(size_t)(disk_buf_end
-disk_buf_tail
));
1957 while (( bytes_to_read
> 0) && (file_remaining
> 0) &&
1958 ((audio_str
.status
>= 0) || (video_str
.status
>= 0))) {
1959 size_t n
= rb
->read(in_file
, disk_buf_tail
, MIN(32*1024,bytes_to_read
));
1962 file_remaining
-= n
;
1965 audio_str
.buffer_remaining
+= n
;
1966 video_str
.buffer_remaining
+= n
;
1974 if (disk_buf_tail
== disk_buf_end
)
1975 disk_buf_tail
= buffer
;
1981 rb
->lcd_setfont(FONT_UI
);
1985 /* Stop the threads and wait for them to terminate */
1986 if (video_str
.thread
!= NULL
)
1987 str_send_msg(&video_str
, STREAM_STOP
, 0);
1989 if (audio_str
.thread
!= NULL
)
1990 str_send_msg(&audio_str
, STREAM_STOP
, 0);
1994 #ifndef HAVE_LCD_COLOR
1998 rb
->lcd_clear_display();
2001 mpeg2_close (mpeg2dec
);
2003 rb
->close (in_file
);
2005 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
2006 rb
->cpu_boost(false);
2009 save_settings(); /* Save settings (if they have changed) */
2011 rb
->pcm_set_frequency(HW_SAMPR_DEFAULT
);
2013 #ifdef HAVE_BACKLIGHT
2014 /* reset backlight settings */
2015 rb
->backlight_set_timeout(rb
->global_settings
->backlight_timeout
);