From d25d24812e8120c0eb133a412287ac030eb185c9 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Wed, 4 Aug 2021 09:49:56 -0400 Subject: [PATCH] RFC: Get rid of mpegplayer plugin It might have made sense once upon a time, but in today's world... Change-Id: I5d638e6f7a2308c50ab12bd901338f02cf426aae --- apps/lang/english.lang | 291 +- apps/plugins/CATEGORIES | 1 - apps/plugins/SUBDIRS | 4 - apps/plugins/bitmaps/mono/SOURCES | 5 - .../mono/mpegplayer_status_icons_12x12x1.bmp | Bin 158 -> 0 bytes .../mono/mpegplayer_status_icons_16x16x1.bmp | Bin 254 -> 0 bytes .../mono/mpegplayer_status_icons_8x8x1.bmp | Bin 126 -> 0 bytes apps/plugins/mpegplayer/SOURCES | 35 - apps/plugins/mpegplayer/alloc.c | 233 -- apps/plugins/mpegplayer/audio_thread.c | 721 ---- apps/plugins/mpegplayer/disk_buf.c | 989 ------ apps/plugins/mpegplayer/disk_buf.h | 152 - apps/plugins/mpegplayer/libmpeg2/AUTHORS | 33 - apps/plugins/mpegplayer/libmpeg2/README | 204 -- .../mpegplayer/libmpeg2/README.rockbox | 44 - apps/plugins/mpegplayer/libmpeg2/attributes.h | 42 - apps/plugins/mpegplayer/libmpeg2/decode.c | 527 --- apps/plugins/mpegplayer/libmpeg2/header.c | 1287 -------- apps/plugins/mpegplayer/libmpeg2/idct.c | 274 -- apps/plugins/mpegplayer/libmpeg2/idct_arm.S | 443 --- apps/plugins/mpegplayer/libmpeg2/idct_armv6.S | 297 -- .../mpegplayer/libmpeg2/idct_coldfire.S | 575 ---- .../plugins/mpegplayer/libmpeg2/motion_comp.c | 66 - .../plugins/mpegplayer/libmpeg2/motion_comp.h | 86 - .../mpegplayer/libmpeg2/motion_comp_arm_c.c | 39 - .../mpegplayer/libmpeg2/motion_comp_arm_s.S | 342 -- .../mpegplayer/libmpeg2/motion_comp_c.c | 40 - .../libmpeg2/motion_comp_coldfire_c.c | 38 - .../libmpeg2/motion_comp_coldfire_s.S | 436 --- apps/plugins/mpegplayer/libmpeg2/mpeg2.h | 223 -- .../mpegplayer/libmpeg2/mpeg2_internal.h | 274 -- .../mpegplayer/libmpeg2/mpeg2dec_config.h | 15 - apps/plugins/mpegplayer/libmpeg2/slice.c | 2898 ----------------- apps/plugins/mpegplayer/libmpeg2/vlc.h | 433 --- apps/plugins/mpegplayer/mpeg_alloc.h | 32 - apps/plugins/mpegplayer/mpeg_misc.c | 227 -- apps/plugins/mpegplayer/mpeg_misc.h | 258 -- apps/plugins/mpegplayer/mpeg_parser.c | 1203 ------- apps/plugins/mpegplayer/mpeg_settings.c | 1454 --------- apps/plugins/mpegplayer/mpeg_settings.h | 110 - apps/plugins/mpegplayer/mpeg_stream.h | 122 - apps/plugins/mpegplayer/mpegplayer.c | 2638 --------------- apps/plugins/mpegplayer/mpegplayer.h | 95 - apps/plugins/mpegplayer/mpegplayer.make | 32 - apps/plugins/mpegplayer/parser.h | 103 - apps/plugins/mpegplayer/pcm_output.c | 396 --- apps/plugins/mpegplayer/pcm_output.h | 48 - apps/plugins/mpegplayer/stream_mgr.c | 1163 ------- apps/plugins/mpegplayer/stream_mgr.h | 168 - apps/plugins/mpegplayer/stream_thread.h | 201 -- apps/plugins/mpegplayer/video_out.h | 102 - apps/plugins/mpegplayer/video_out_rockbox.c | 576 ---- apps/plugins/mpegplayer/video_thread.c | 1059 ------ apps/plugins/viewers.config | 4 - docs/MAINTAINERS | 1 - lib/rbcodec/codecs/libmad/libmad.make | 25 - lib/rbcodec/codecs/libmad/mad_iram.h | 7 +- lib/rbcodec/codecs/mpa.c | 2 +- manual/plugins/main.tex | 2 - manual/plugins/mpegplayer.tex | 119 - 60 files changed, 5 insertions(+), 21189 deletions(-) delete mode 100644 apps/plugins/bitmaps/mono/mpegplayer_status_icons_12x12x1.bmp delete mode 100644 apps/plugins/bitmaps/mono/mpegplayer_status_icons_16x16x1.bmp delete mode 100644 apps/plugins/bitmaps/mono/mpegplayer_status_icons_8x8x1.bmp delete mode 100644 apps/plugins/mpegplayer/SOURCES delete mode 100644 apps/plugins/mpegplayer/alloc.c delete mode 100644 apps/plugins/mpegplayer/audio_thread.c delete mode 100644 apps/plugins/mpegplayer/disk_buf.c delete mode 100644 apps/plugins/mpegplayer/disk_buf.h delete mode 100644 apps/plugins/mpegplayer/libmpeg2/AUTHORS delete mode 100644 apps/plugins/mpegplayer/libmpeg2/README delete mode 100644 apps/plugins/mpegplayer/libmpeg2/README.rockbox delete mode 100644 apps/plugins/mpegplayer/libmpeg2/attributes.h delete mode 100644 apps/plugins/mpegplayer/libmpeg2/decode.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/header.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/idct.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/idct_arm.S delete mode 100644 apps/plugins/mpegplayer/libmpeg2/idct_armv6.S delete mode 100644 apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S delete mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp.h delete mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S delete mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S delete mode 100644 apps/plugins/mpegplayer/libmpeg2/mpeg2.h delete mode 100644 apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h delete mode 100644 apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h delete mode 100644 apps/plugins/mpegplayer/libmpeg2/slice.c delete mode 100644 apps/plugins/mpegplayer/libmpeg2/vlc.h delete mode 100644 apps/plugins/mpegplayer/mpeg_alloc.h delete mode 100644 apps/plugins/mpegplayer/mpeg_misc.c delete mode 100644 apps/plugins/mpegplayer/mpeg_misc.h delete mode 100644 apps/plugins/mpegplayer/mpeg_parser.c delete mode 100644 apps/plugins/mpegplayer/mpeg_settings.c delete mode 100644 apps/plugins/mpegplayer/mpeg_settings.h delete mode 100644 apps/plugins/mpegplayer/mpeg_stream.h delete mode 100644 apps/plugins/mpegplayer/mpegplayer.c delete mode 100644 apps/plugins/mpegplayer/mpegplayer.h delete mode 100644 apps/plugins/mpegplayer/mpegplayer.make delete mode 100644 apps/plugins/mpegplayer/parser.h delete mode 100644 apps/plugins/mpegplayer/pcm_output.c delete mode 100644 apps/plugins/mpegplayer/pcm_output.h delete mode 100644 apps/plugins/mpegplayer/stream_mgr.c delete mode 100644 apps/plugins/mpegplayer/stream_mgr.h delete mode 100644 apps/plugins/mpegplayer/stream_thread.h delete mode 100644 apps/plugins/mpegplayer/video_out.h delete mode 100644 apps/plugins/mpegplayer/video_out_rockbox.c delete mode 100644 apps/plugins/mpegplayer/video_thread.c delete mode 100644 manual/plugins/mpegplayer.tex diff --git a/apps/lang/english.lang b/apps/lang/english.lang index e8d646b258..990bc9fbcd 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -14263,128 +14263,9 @@ *: "View Played Games" - - id: LANG_MENU_AUDIO_OPTIONS - desc: in mpegplayer menus - user: core - - *: "Audio Options" - lowmem: none - - - *: "Audio Options" - lowmem: none - - - *: "Audio Options" - lowmem: none - - - - id: LANG_MENU_RESUME_OPTIONS - desc: in mpegplayer menus - user: core - - *: "Resume Options" - lowmem: none - - - *: "Resume Options" - lowmem: none - - - *: "Resume Options" - lowmem: none - - - - id: LANG_MENU_PLAY_MODE - desc: in mpegplayer menus - user: core - - *: "Play Mode" - lowmem: none - - - *: "Play Mode" - lowmem: none - - - *: "Play Mode" - lowmem: none - - - - id: LANG_SINGLE - desc: in mpegplayer menus - user: core - - *: "Single" - lowmem: none - - - *: "Single" - lowmem: none - - - *: "Single" - lowmem: none - - - - id: LANG_USE_SOUND_SETTING - desc: in mpegplayer menus - user: core - - *: "Use sound setting" - lowmem: none - - - *: "Use sound setting" - lowmem: none - - - *: "Use sound setting" - lowmem: none - - - - id: LANG_RESTART_PLAYBACK - desc: in the mpegplayer settings menu - user: core - - *: "Play from beginning" - lowmem: none - - - *: "Play from beginning" - lowmem: none - - - *: "Play from beginning" - lowmem: none - - - - id: LANG_SET_RESUME_TIME - desc: in the mpegplayer settings menu - user: core - - *: "Set resume time (min)" - lowmem: none - - - *: "Set resume time (min)" - lowmem: none - - - *: "Set resume time" - lowmem: none - - id: LANG_DISPLAY_FPS - desc: in the mpegplayer and pictureflow settings menus + desc: in the pictureflow settings menus user: core *: "Display FPS" @@ -14396,176 +14277,6 @@ *: "Display FPS" - - id: LANG_LIMIT_FPS - desc: in the mpegplayer settings menu - user: core - - *: "Limit FPS" - lowmem: none - - - *: "Limit FPS" - lowmem: none - - - *: "Limit FPS" - lowmem: none - - - - id: LANG_SKIP_FRAMES - desc: in the mpegplayer settings menu - user: core - - *: "Skip frames" - lowmem: none - - - *: "Skip frames" - lowmem: none - - - *: "Skip frames" - lowmem: none - - - - id: LANG_BACKLIGHT_BRIGHTNESS - desc: in the mpegplayer settings menu - user: core - - *: "Backlight brightness" - lowmem: none - - - *: "Backlight brightness" - lowmem: none - - - *: "Backlight brightness" - lowmem: none - - - - id: LANG_USE_COMMON_SETTING - desc: in the mpegplayer settings menu - user: core - - *: "Use common setting" - lowmem: none - - - *: "Use common setting" - lowmem: none - - - *: "Use common setting" - lowmem: none - - - - id: LANG_TONE_CONTROLS - desc: in the mpegplayer settings menu - user: core - - *: "Tone controls" - lowmem: none - - - *: "Tone controls" - lowmem: none - - - *: "Tone controls" - lowmem: none - - - - id: LANG_FORCE_START_MENU - desc: in mpegplayer menus - user: core - - *: "Start menu" - lowmem: none - - - *: "Start menu" - lowmem: none - - - *: "Start menu" - lowmem: none - - - - id: LANG_CONDITIONAL_START_MENU - desc: in mpegplayer menus - user: core - - *: "Start menu if not completed" - lowmem: none - - - *: "Start menu if not completed" - lowmem: none - - - *: "Start menu if not completed" - lowmem: none - - - - id: LANG_AUTO_RESUME - desc: in mpegplayer menus - user: core - - *: "Resume automatically" - lowmem: none - - - *: "Resume automatically" - lowmem: none - - - *: "Resume automatically" - lowmem: none - - - - id: LANG_CLEAR_ALL_RESUMES - desc: in the mpegplayer settings menu - user: core - - *: "Clear all resumes" - lowmem: none - - - *: "Clear all resumes" - lowmem: none - - - *: "Clear all resumes" - lowmem: none - - - - id: LANG_UNAVAILABLE - desc: in mpegplayer settings - user: core - - *: "Unavailable" - lowmem: none - - - *: "Unavailable" - lowmem: none - - - *: "Unavailable" - lowmem: none - - id: LANG_TOGGLE_ITEM desc: in main_menu_config diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index f2ab4843c2..13db81f004 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -68,7 +68,6 @@ mikmod,viewers minesweeper,games mosaique,demos mp3_encoder,apps -mpegplayer,viewers multiboot_select,apps nim,games open_plugins,viewers diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index 4cb57edb1b..23cd029ccc 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS @@ -78,10 +78,6 @@ mikmod pdbox #endif -#if !defined(RB_PROFILE) && MEMORYSIZE > 2 /* mpegplayer allocates at least 2MB of RAM */ -mpegplayer -#endif - /* Lua needs at least 160 KB to work in */ #if PLUGIN_BUFFER_SIZE >= 0x80000 lua diff --git a/apps/plugins/bitmaps/mono/SOURCES b/apps/plugins/bitmaps/mono/SOURCES index eb00bd9e8a..df8521dd0a 100644 --- a/apps/plugins/bitmaps/mono/SOURCES +++ b/apps/plugins/bitmaps/mono/SOURCES @@ -49,11 +49,6 @@ invadrox_fire.6x6x1.bmp #endif #endif -/* MPEGplayer */ -mpegplayer_status_icons_8x8x1.bmp -mpegplayer_status_icons_12x12x1.bmp -mpegplayer_status_icons_16x16x1.bmp - #if LCD_WIDTH == 160 && LCD_HEIGHT == 128 && LCD_DEPTH < 16 superdom_boarditems.160x128x1.bmp #endif diff --git a/apps/plugins/bitmaps/mono/mpegplayer_status_icons_12x12x1.bmp b/apps/plugins/bitmaps/mono/mpegplayer_status_icons_12x12x1.bmp deleted file mode 100644 index 61f6a52fbc40905d5439d9674bd5f29b93d2d074..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmZ?royPzHc0fu4h;4wF2Z$Mg5CjsyBqs6y|9=J`27wO@636d<-~ampkUsx;{^tom m`uNBG#{xk5@Q3z8Ao}13<^~Xb-~%HAG9M-nQxDS*HV*&>89EjK diff --git a/apps/plugins/bitmaps/mono/mpegplayer_status_icons_16x16x1.bmp b/apps/plugins/bitmaps/mono/mpegplayer_status_icons_16x16x1.bmp deleted file mode 100644 index 944bd5132efc422ba1d176f4ff1527f1db32ad31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 254 zcmZ?r{l@?Sc0fu4hy#FF0EiiZ5Cjf@NlfDZ|Njg?3ne|QLG*R%0II0$9iGqE3NgtFxsm>WRW1I_%v4|NKNjVz9= Q9@!iu^O5aEb`Q**0HQfufdBvi diff --git a/apps/plugins/bitmaps/mono/mpegplayer_status_icons_8x8x1.bmp b/apps/plugins/bitmaps/mono/mpegplayer_status_icons_8x8x1.bmp deleted file mode 100644 index d4b71fe1e02f45b2efe39523ee403d814b494b51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126 zcmZ?rtz&=yJ0PV2#T-DI5ePxR0Zd{N|NsAI0Ae5sR6BWp{#!6TU;QMQ?q_ZU)9s8P NQy3@1_%L~hdH{MF7wrH5 diff --git a/apps/plugins/mpegplayer/SOURCES b/apps/plugins/mpegplayer/SOURCES deleted file mode 100644 index 3fc079dfbd..0000000000 --- a/apps/plugins/mpegplayer/SOURCES +++ /dev/null @@ -1,35 +0,0 @@ -libmpeg2/decode.c -libmpeg2/header.c -libmpeg2/idct.c -libmpeg2/motion_comp.c -libmpeg2/slice.c - -#ifdef CPU_COLDFIRE -libmpeg2/idct_coldfire.S -libmpeg2/motion_comp_coldfire_c.c -libmpeg2/motion_comp_coldfire_s.S -#elif defined CPU_ARM -#if ARM_ARCH >= 6 -libmpeg2/idct_armv6.S -#else -libmpeg2/idct_arm.S -#endif -libmpeg2/motion_comp_arm_c.c -libmpeg2/motion_comp_arm_s.S -#else /* other CPU or SIM */ -libmpeg2/motion_comp_c.c -#endif /* CPU_* */ - - - -alloc.c -video_out_rockbox.c -video_thread.c -pcm_output.c -audio_thread.c -disk_buf.c -mpeg_settings.c -stream_mgr.c -mpegplayer.c -mpeg_parser.c -mpeg_misc.c diff --git a/apps/plugins/mpegplayer/alloc.c b/apps/plugins/mpegplayer/alloc.c deleted file mode 100644 index cbf930a7eb..0000000000 --- a/apps/plugins/mpegplayer/alloc.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * alloc.c - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.13 - */ - -#include "plugin.h" -#include "mpegplayer.h" -#include - -/* Main allocator */ -static off_t mem_ptr; -static size_t bufsize; -static unsigned char* mallocbuf; - -/* libmpeg2 allocator */ -static off_t mpeg2_mem_ptr SHAREDBSS_ATTR; -static size_t mpeg2_bufsize SHAREDBSS_ATTR; -static unsigned char *mpeg2_mallocbuf SHAREDBSS_ATTR; -static unsigned char *mpeg2_bufallocbuf SHAREDBSS_ATTR; - -#if defined(DEBUG) || defined(SIMULATOR) -const char * mpeg_get_reason_str(int reason) -{ - const char *str; - - switch (reason) - { - case MPEG2_ALLOC_MPEG2DEC: - str = "MPEG2_ALLOC_MPEG2DEC"; - break; - case MPEG2_ALLOC_CHUNK: - str = "MPEG2_ALLOC_CHUNK"; - break; - case MPEG2_ALLOC_YUV: - str = "MPEG2_ALLOC_YUV"; - break; - case MPEG2_ALLOC_CONVERT_ID: - str = "MPEG2_ALLOC_CONVERT_ID"; - break; - case MPEG2_ALLOC_CONVERTED: - str = "MPEG2_ALLOC_CONVERTED"; - break; - case MPEG_ALLOC_MPEG2_BUFFER: - str = "MPEG_ALLOC_MPEG2_BUFFER"; - break; - case MPEG_ALLOC_AUDIOBUF: - str = "MPEG_ALLOC_AUDIOBUF"; - break; - case MPEG_ALLOC_PCMOUT: - str = "MPEG_ALLOC_PCMOUT"; - break; - case MPEG_ALLOC_DISKBUF: - str = "MPEG_ALLOC_DISKBUF"; - break; - case MPEG_ALLOC_CODEC_MALLOC: - str = "MPEG_ALLOC_CODEC_MALLOC"; - break; - case MPEG_ALLOC_CODEC_CALLOC: - str = "MPEG_ALLOC_CODEC_CALLOC"; - break; - default: - str = "Unknown"; - } - - return str; -} -#endif - -static void * mpeg_malloc_internal (unsigned char *mallocbuf, - off_t *mem_ptr, - size_t bufsize, - unsigned size, - int reason) -{ - void *x; - - DEBUGF("mpeg_alloc_internal: bs:%lu s:%u reason:%s (%d)\n", - (unsigned long)bufsize, size, mpeg_get_reason_str(reason), reason); - - if ((size_t) (*mem_ptr + size) > bufsize) - { - DEBUGF("OUT OF MEMORY\n"); - return NULL; - } - - x = &mallocbuf[*mem_ptr]; - *mem_ptr += (size + 3) & ~3; /* Keep memory 32-bit aligned */ - - return x; - (void)reason; -} - -void *mpeg_malloc(size_t size, mpeg2_alloc_t reason) -{ - return mpeg_malloc_internal(mallocbuf, &mem_ptr, bufsize, size, - reason); -} - -void *mpeg_malloc_all(size_t *size_out, mpeg2_alloc_t reason) -{ - /* Can steal all but MIN_MEMMARGIN */ - if (bufsize - mem_ptr < MIN_MEMMARGIN) - return NULL; - - *size_out = bufsize - mem_ptr - MIN_MEMMARGIN; - return mpeg_malloc(*size_out, reason); -} - -bool mpeg_alloc_init(unsigned char *buf, size_t mallocsize) -{ - mem_ptr = 0; - /* Cache-align buffer or 4-byte align */ - mallocbuf = buf; - bufsize = mallocsize; - ALIGN_BUFFER(mallocbuf, bufsize, CACHEALIGN_UP(4)); - - /* Separate allocator for video */ - mpeg2_mem_ptr = 0; - mpeg2_mallocbuf = mallocbuf; - mpeg2_bufallocbuf = mallocbuf; - mpeg2_bufsize = CACHEALIGN_UP(LIBMPEG2_ALLOC_SIZE); - - if (mpeg_malloc_internal(mallocbuf, &mem_ptr, - bufsize, mpeg2_bufsize, - MPEG_ALLOC_MPEG2_BUFFER) == NULL) - { - return false; - } - - IF_COP(rb->commit_discard_dcache()); - return true; -} - -/* allocate non-dedicated buffer space which mpeg2_mem_reset will free */ -void * mpeg2_malloc(unsigned size, mpeg2_alloc_t reason) -{ - void *ptr = mpeg_malloc_internal(mpeg2_mallocbuf, &mpeg2_mem_ptr, - mpeg2_bufsize, size, reason); - /* libmpeg2 expects zero-initialized allocations */ - if (ptr) - rb->memset(ptr, 0, size); - - return ptr; -} - -/* allocate dedicated buffer - memory behind buffer pointer becomes dedicated - so order is important */ -void * mpeg2_bufalloc(unsigned size, mpeg2_alloc_t reason) -{ - void *buf = mpeg2_malloc(size, reason); - - if (buf == NULL) - return NULL; - - mpeg2_bufallocbuf = &mpeg2_mallocbuf[mpeg2_mem_ptr]; - return buf; -} - -/* return unused buffer portion and size */ -void * mpeg2_get_buf(size_t *size) -{ - if ((size_t)mpeg2_mem_ptr + 32 >= mpeg2_bufsize) - return NULL; - - *size = mpeg2_bufsize - mpeg2_mem_ptr; - return &mpeg2_mallocbuf[mpeg2_mem_ptr]; -} - -/* de-allocate all non-dedicated buffer space */ -void mpeg2_mem_reset(void) -{ - DEBUGF("mpeg2_mem_reset\n"); - mpeg2_mem_ptr = mpeg2_bufallocbuf - mpeg2_mallocbuf; -} - -/* The following are expected by libmad */ -void * codec_malloc(size_t size) -{ - void* ptr; - - ptr = mpeg_malloc_internal(mallocbuf, &mem_ptr, - bufsize, size, MPEG_ALLOC_CODEC_MALLOC); - - if (ptr) - rb->memset(ptr,0,size); - - return ptr; -} - -void * codec_calloc(size_t nmemb, size_t size) -{ - void* ptr; - - ptr = mpeg_malloc_internal(mallocbuf, &mem_ptr, - bufsize, nmemb*size, - MPEG_ALLOC_CODEC_CALLOC); - - if (ptr) - rb->memset(ptr,0,size); - - return ptr; -} - -void codec_free(void* ptr) -{ - DEBUGF("codec_free - %p\n", ptr); -#if 0 - mem_ptr = (void *)ptr - (void *)mallocbuf; -#endif - (void)ptr; -} diff --git a/apps/plugins/mpegplayer/audio_thread.c b/apps/plugins/mpegplayer/audio_thread.c deleted file mode 100644 index 764ad111f2..0000000000 --- a/apps/plugins/mpegplayer/audio_thread.c +++ /dev/null @@ -1,721 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * mpegplayer audio thread implementation - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" -#include "codecs/libmad/bit.h" -#include "codecs/libmad/mad.h" - -/** Audio stream and thread **/ -struct pts_queue_slot; -struct audio_thread_data -{ - struct queue_event ev; /* Our event queue to receive commands */ - int state; /* Thread state */ - int status; /* Media status (STREAM_PLAYING, etc.) */ - int mad_errors; /* A count of the errors in each frame */ - unsigned samplerate; /* Current stream sample rate */ - int nchannels; /* Number of audio channels */ - struct dsp_config *dsp; /* The DSP we're using */ - struct dsp_buffer src; /* Current audio data for DSP processing */ -}; - -/* The audio thread is stolen from the core codec thread */ -static struct event_queue audio_str_queue SHAREDBSS_ATTR; -static struct queue_sender_list audio_str_queue_send SHAREDBSS_ATTR; -struct stream audio_str IBSS_ATTR; - -/* libmad related definitions */ -static struct mad_stream stream IBSS_ATTR; -static struct mad_frame frame IBSS_ATTR; -static struct mad_synth synth IBSS_ATTR; - -/*sbsample buffer for mad_frame*/ -mad_fixed_t sbsample[2][36][32]; - -/* 2567 bytes */ -static unsigned char mad_main_data[MAD_BUFFER_MDLEN]; - -/* There isn't enough room for this in IRAM on PortalPlayer, but there - is for Coldfire. */ - -/* 4608 bytes */ -#if defined(CPU_COLDFIRE) || defined(CPU_S5L870X) -static mad_fixed_t mad_frame_overlap[2][32][18] IBSS_ATTR; -#else -static mad_fixed_t mad_frame_overlap[2][32][18]; -#endif - -/** A queue for saving needed information about MPEG audio packets **/ -#define AUDIODESC_QUEUE_LEN (1 << 5) /* 32 should be way more than sufficient - - if not, the case is handled */ -#define AUDIODESC_QUEUE_MASK (AUDIODESC_QUEUE_LEN-1) -struct audio_frame_desc -{ - uint32_t time; /* Time stamp for packet in audio ticks */ - ssize_t size; /* Number of unprocessed bytes left in packet */ -}; - - /* This starts out wr == rd but will never be emptied to zero during - streaming again in order to support initializing the first packet's - timestamp without a special case */ -struct -{ - /* Compressed audio data */ - uint8_t *start; /* Start of encoded audio buffer */ - uint8_t *ptr; /* Pointer to next encoded audio data */ - ssize_t used; /* Number of bytes in MPEG audio buffer */ - /* Compressed audio data descriptors */ - unsigned read, write; - struct audio_frame_desc *curr; /* Current slot */ - struct audio_frame_desc descs[AUDIODESC_QUEUE_LEN]; -} audio_queue; - -static inline int audiodesc_queue_count(void) -{ - return audio_queue.write - audio_queue.read; -} - -static inline bool audiodesc_queue_full(void) -{ - return audio_queue.used >= MPA_MAX_FRAME_SIZE + MAD_BUFFER_GUARD || - audiodesc_queue_count() >= AUDIODESC_QUEUE_LEN; -} - -/* Increments the queue tail postion - should be used to preincrement */ -static inline void audiodesc_queue_add_tail(void) -{ - if (audiodesc_queue_full()) - { - DEBUGF("audiodesc_queue_add_tail: audiodesc queue full!\n"); - return; - } - - audio_queue.write++; -} - -/* Increments the queue head position - leaves one slot as current */ -static inline bool audiodesc_queue_remove_head(void) -{ - if (audio_queue.write == audio_queue.read) - return false; - - audio_queue.read++; - return true; -} - -/* Returns the "tail" at the index just behind the write index */ -static inline struct audio_frame_desc * audiodesc_queue_tail(void) -{ - return &audio_queue.descs[(audio_queue.write - 1) & AUDIODESC_QUEUE_MASK]; -} - -/* Returns a pointer to the current head */ -static inline struct audio_frame_desc * audiodesc_queue_head(void) -{ - return &audio_queue.descs[audio_queue.read & AUDIODESC_QUEUE_MASK]; -} - -/* Resets the pts queue - call when starting and seeking */ -static void audio_queue_reset(void) -{ - audio_queue.ptr = audio_queue.start; - audio_queue.used = 0; - audio_queue.read = 0; - audio_queue.write = 0; - rb->memset(audio_queue.descs, 0, sizeof (audio_queue.descs)); - audio_queue.curr = audiodesc_queue_head(); -} - -static void audio_queue_advance_pos(ssize_t len) -{ - audio_queue.ptr += len; - audio_queue.used -= len; - audio_queue.curr->size -= len; -} - -static int audio_buffer(struct stream *str, enum stream_parse_mode type) -{ - int ret = STREAM_OK; - - /* Carry any overshoot to the next size since we're technically - -size bytes into it already. If size is negative an audio - frame was split across packets. Old has to be saved before - moving the head. */ - if (audio_queue.curr->size <= 0 && audiodesc_queue_remove_head()) - { - struct audio_frame_desc *old = audio_queue.curr; - audio_queue.curr = audiodesc_queue_head(); - audio_queue.curr->size += old->size; - old->size = 0; - } - - /* Add packets to compressed audio buffer until it's full or the - * timestamp queue is full - whichever happens first */ - while (!audiodesc_queue_full()) - { - ret = parser_get_next_data(str, type); - struct audio_frame_desc *curr; - ssize_t len; - - if (ret != STREAM_OK) - break; - - /* Get data from next audio packet */ - len = str->curr_packet_end - str->curr_packet; - - if (str->pkt_flags & PKT_HAS_TS) - { - audiodesc_queue_add_tail(); - curr = audiodesc_queue_tail(); - curr->time = TS_TO_TICKS(str->pts); - /* pts->size should have been zeroed when slot was - freed */ - } - else - { - /* Add to the one just behind the tail - this may be - * the head or the previouly added tail - whether or - * not we'll ever reach this is quite in question - * since audio always seems to have every packet - * timestamped */ - curr = audiodesc_queue_tail(); - } - - curr->size += len; - - /* Slide any remainder over to beginning */ - if (audio_queue.ptr > audio_queue.start && audio_queue.used > 0) - { - rb->memmove(audio_queue.start, audio_queue.ptr, - audio_queue.used); - } - - /* Splice this packet onto any remainder */ - rb->memcpy(audio_queue.start + audio_queue.used, - str->curr_packet, len); - - audio_queue.used += len; - audio_queue.ptr = audio_queue.start; - - rb->yield(); - } - - return ret; -} - -/* Initialise libmad */ -static void init_mad(void) -{ - /* init the sbsample buffer */ - frame.sbsample_prev = &sbsample; - frame.sbsample = &sbsample; - - /* We do this so libmad doesn't try to call codec_calloc(). This needs to - * be called before mad_stream_init(), mad_frame_inti() and - * mad_synth_init(). */ - frame.overlap = &mad_frame_overlap; - stream.main_data = &mad_main_data; - - /* Call mad initialization. Those will zero the arrays frame.overlap, - * frame.sbsample and frame.sbsample_prev. Therefore there is no need to - * zero them here. */ - mad_stream_init(&stream); - mad_frame_init(&frame); - mad_synth_init(&synth); -} - -/* Sync audio stream to a particular frame - see main decoder loop for - * detailed remarks */ -static int audio_sync(struct audio_thread_data *td, - struct str_sync_data *sd) -{ - int retval = STREAM_MATCH; - uint32_t sdtime = TS_TO_TICKS(clip_time(&audio_str, sd->time)); - uint32_t time; - uint32_t duration = 0; - struct stream *str; - struct stream tmp_str; - struct mad_header header; - struct mad_stream stream; - - if (td->ev.id == STREAM_SYNC) - { - /* Actually syncing for playback - use real stream */ - time = 0; - str = &audio_str; - } - else - { - /* Probing - use temp stream */ - time = INVALID_TIMESTAMP; - str = &tmp_str; - str->id = audio_str.id; - } - - str->hdr.pos = sd->sk.pos; - str->hdr.limit = sd->sk.pos + sd->sk.len; - - mad_stream_init(&stream); - mad_header_init(&header); - - while (1) - { - if (audio_buffer(str, STREAM_PM_RANDOM_ACCESS) == STREAM_DATA_END) - { - DEBUGF("audio_sync:STR_DATA_END\n aqu:%ld swl:%ld swr:%ld\n", - (long)audio_queue.used, str->hdr.win_left, str->hdr.win_right); - if (audio_queue.used <= MAD_BUFFER_GUARD) - goto sync_data_end; - } - - stream.error = 0; - mad_stream_buffer(&stream, audio_queue.ptr, audio_queue.used); - - if (stream.sync && mad_stream_sync(&stream) < 0) - { - DEBUGF(" audio: mad_stream_sync failed\n"); - audio_queue_advance_pos(MAX(audio_queue.curr->size - 1, 1)); - continue; - } - - stream.sync = 0; - - if (mad_header_decode(&header, &stream) < 0) - { - DEBUGF(" audio: mad_header_decode failed:%s\n", - mad_stream_errorstr(&stream)); - audio_queue_advance_pos(1); - continue; - } - - duration = 32*MAD_NSBSAMPLES(&header); - time = audio_queue.curr->time; - - DEBUGF(" audio: ft:%u t:%u fe:%u nsamp:%u sampr:%u\n", - (unsigned)TICKS_TO_TS(time), (unsigned)sd->time, - (unsigned)TICKS_TO_TS(time + duration), - (unsigned)duration, header.samplerate); - - audio_queue_advance_pos(stream.this_frame - audio_queue.ptr); - - if (time <= sdtime && sdtime < time + duration) - { - DEBUGF(" audio: ft<=t sdtime) - { - DEBUGF(" audio: ft>t\n"); - break; - } - - audio_queue_advance_pos(stream.next_frame - audio_queue.ptr); - audio_queue.curr->time += duration; - - rb->yield(); - } - -sync_data_end: - if (td->ev.id == STREAM_FIND_END_TIME) - { - if (time != INVALID_TIMESTAMP) - { - time = TICKS_TO_TS(time); - duration = TICKS_TO_TS(duration); - sd->time = time + duration; - retval = STREAM_PERFECT_MATCH; - } - else - { - retval = STREAM_NOT_FOUND; - } - } - - DEBUGF(" audio header: 0x%02X%02X%02X%02X\n", - (unsigned)audio_queue.ptr[0], (unsigned)audio_queue.ptr[1], - (unsigned)audio_queue.ptr[2], (unsigned)audio_queue.ptr[3]); - - return retval; - (void)td; -} - -static void audio_thread_msg(struct audio_thread_data *td) -{ - while (1) - { - intptr_t reply = 0; - - switch (td->ev.id) - { - case STREAM_PLAY: - td->status = STREAM_PLAYING; - - switch (td->state) - { - case TSTATE_INIT: - td->state = TSTATE_DECODE; - case TSTATE_DECODE: - case TSTATE_RENDER_WAIT: - break; - - case TSTATE_EOS: - /* At end of stream - no playback possible so fire the - * completion event */ - stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0); - break; - } - - break; - - case STREAM_PAUSE: - td->status = STREAM_PAUSED; - reply = td->state != TSTATE_EOS; - break; - - case STREAM_STOP: - if (td->state == TSTATE_DATA) - stream_clear_notify(&audio_str, DISK_BUF_DATA_NOTIFY); - - td->status = STREAM_STOPPED; - td->state = TSTATE_EOS; - - reply = true; - break; - - case STREAM_RESET: - if (td->state == TSTATE_DATA) - stream_clear_notify(&audio_str, DISK_BUF_DATA_NOTIFY); - - td->status = STREAM_STOPPED; - td->state = TSTATE_INIT; - td->samplerate = 0; - td->nchannels = 0; - - init_mad(); - td->mad_errors = 0; - - audio_queue_reset(); - - reply = true; - break; - - case STREAM_NEEDS_SYNC: - reply = true; /* Audio always needs to */ - break; - - case STREAM_SYNC: - case STREAM_FIND_END_TIME: - if (td->state != TSTATE_INIT) - break; - - reply = audio_sync(td, (struct str_sync_data *)td->ev.data); - break; - - case DISK_BUF_DATA_NOTIFY: - /* Our bun is done */ - if (td->state != TSTATE_DATA) - break; - - td->state = TSTATE_DECODE; - str_data_notify_received(&audio_str); - break; - - case STREAM_QUIT: - /* Time to go - make thread exit */ - td->state = TSTATE_EOS; - return; - } - - str_reply_msg(&audio_str, reply); - - if (td->status == STREAM_PLAYING) - { - switch (td->state) - { - case TSTATE_DECODE: - case TSTATE_RENDER_WAIT: - /* These return when in playing state */ - return; - } - } - - str_get_msg(&audio_str, &td->ev); - } -} - -static void audio_thread(void) -{ - struct audio_thread_data td; -#ifdef HAVE_PRIORITY_SCHEDULING - /* Up the priority since the core DSP over-yields internally */ - int old_priority = rb->thread_set_priority(rb->thread_self(), - PRIORITY_PLAYBACK-4); -#endif - - rb->memset(&td, 0, sizeof (td)); - td.status = STREAM_STOPPED; - td.state = TSTATE_EOS; - - /* We need this here to init the EMAC for Coldfire targets */ - init_mad(); - - td.dsp = rb->dsp_get_config(CODEC_IDX_AUDIO); - rb->dsp_configure(td.dsp, DSP_SET_OUT_FREQUENCY, CLOCK_RATE); -#ifdef HAVE_PITCHCONTROL - rb->sound_set_pitch(PITCH_SPEED_100); - rb->dsp_set_timestretch(PITCH_SPEED_100); -#endif - rb->dsp_configure(td.dsp, DSP_RESET, 0); - rb->dsp_configure(td.dsp, DSP_FLUSH, 0); - rb->dsp_configure(td.dsp, DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); - - goto message_wait; - - /* This is the decoding loop. */ - while (1) - { - td.state = TSTATE_DECODE; - - /* Check for any pending messages and process them */ - if (str_have_msg(&audio_str)) - { - message_wait: - /* Wait for a message to be queued */ - str_get_msg(&audio_str, &td.ev); - - message_process: - /* Process a message already dequeued */ - audio_thread_msg(&td); - - switch (td.state) - { - /* These states are the only ones that should return */ - case TSTATE_DECODE: goto audio_decode; - case TSTATE_RENDER_WAIT: goto render_wait; - /* Anything else is interpreted as an exit */ - default: - { -#ifdef HAVE_PRIORITY_SCHEDULING - rb->thread_set_priority(rb->thread_self(), old_priority); -#endif - return; - } - } - } - - audio_decode: - - /** Buffering **/ - switch (audio_buffer(&audio_str, STREAM_PM_STREAMING)) - { - case STREAM_DATA_NOT_READY: - { - td.state = TSTATE_DATA; - goto message_wait; - } /* STREAM_DATA_NOT_READY: */ - - case STREAM_DATA_END: - { - if (audio_queue.used > MAD_BUFFER_GUARD) - break; /* Still have frames to decode */ - - /* Used up remainder of compressed audio buffer. Wait for - * samples on PCM buffer to finish playing. */ - audio_queue_reset(); - - while (1) - { - if (pcm_output_empty()) - { - td.state = TSTATE_EOS; - stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0); - break; - } - - pcm_output_drain(); - str_get_msg_w_tmo(&audio_str, &td.ev, 1); - - if (td.ev.id != SYS_TIMEOUT) - break; - } - - goto message_wait; - } /* STREAM_DATA_END: */ - } - - /** Decoding **/ - mad_stream_buffer(&stream, audio_queue.ptr, audio_queue.used); - - int mad_stat = mad_frame_decode(&frame, &stream); - - ssize_t len = stream.next_frame - audio_queue.ptr; - - if (mad_stat != 0) - { - DEBUGF("audio: Stream error: %s\n", - mad_stream_errorstr(&stream)); - - /* If something's goofed - try to perform resync by moving - * at least one byte at a time */ - audio_queue_advance_pos(MAX(len, 1)); - - if (stream.error == MAD_ERROR_BUFLEN) - { - /* This makes the codec support partially corrupted files */ - if (++td.mad_errors <= MPA_MAX_FRAME_SIZE) - { - stream.error = 0; - rb->yield(); - continue; - } - DEBUGF("audio: Too many errors\n"); - } - else if (MAD_RECOVERABLE(stream.error)) - { - /* libmad says it can recover - just keep on decoding */ - rb->yield(); - continue; - } - else - { - /* Some other unrecoverable error */ - DEBUGF("audio: Unrecoverable error\n"); - } - - /* This is too hard - bail out */ - td.state = TSTATE_EOS; - td.status = STREAM_ERROR; - stream_generate_event(&audio_str, STREAM_EV_COMPLETE, 0); - - goto message_wait; - } - - /* Adjust sizes by the frame size */ - audio_queue_advance_pos(len); - td.mad_errors = 0; /* Clear errors */ - - /* Generate the pcm samples */ - mad_synth_frame(&synth, &frame); - - /** Output **/ - if (frame.header.samplerate != td.samplerate) - { - td.samplerate = frame.header.samplerate; - rb->dsp_configure(td.dsp, DSP_SET_FREQUENCY, - td.samplerate); - } - - if (MAD_NCHANNELS(&frame.header) != td.nchannels) - { - td.nchannels = MAD_NCHANNELS(&frame.header); - rb->dsp_configure(td.dsp, DSP_SET_STEREO_MODE, - td.nchannels == 1 ? - STEREO_MONO : STEREO_NONINTERLEAVED); - } - - td.src.remcount = synth.pcm.length; - td.src.pin[0] = synth.pcm.samples[0]; - td.src.pin[1] = synth.pcm.samples[1]; - td.src.proc_mask = 0; - - td.state = TSTATE_RENDER_WAIT; - - /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */ - render_wait: - rb->yield(); - - while (1) - { - struct dsp_buffer dst; - dst.remcount = 0; - dst.bufcount = MAX(td.src.remcount, 1024); - - ssize_t size = dst.bufcount * 2 * sizeof(int16_t); - - /* Wait for required amount of free buffer space */ - while ((dst.p16out = pcm_output_get_buffer(&size)) == NULL) - { - /* Wait one frame */ - int timeout = dst.bufcount*HZ / td.samplerate; - str_get_msg_w_tmo(&audio_str, &td.ev, MAX(timeout, 1)); - if (td.ev.id != SYS_TIMEOUT) - goto message_process; - } - - dst.bufcount = size / (2 * sizeof (int16_t)); - rb->dsp_process(td.dsp, &td.src, &dst); - - if (dst.remcount > 0) - { - /* Make this data available to DMA */ - pcm_output_commit_data(dst.remcount * 2 * sizeof(int16_t), - audio_queue.curr->time); - - /* As long as we're on this timestamp, the time is just - incremented by the number of samples */ - audio_queue.curr->time += dst.remcount; - } - else if (td.src.remcount <= 0) - { - break; - } - } - } /* end decoding loop */ -} - -/* Initializes the audio thread resources and starts the thread */ -bool audio_thread_init(void) -{ - /* Initialise the encoded audio buffer and its descriptors */ - audio_queue.start = mpeg_malloc(AUDIOBUF_ALLOC_SIZE, - MPEG_ALLOC_AUDIOBUF); - if (audio_queue.start == NULL) - return false; - - /* Start the audio thread */ - audio_str.hdr.q = &audio_str_queue; - rb->queue_init(audio_str.hdr.q, false); - - /* We steal the codec thread for audio */ - rb->codec_thread_do_callback(audio_thread, &audio_str.thread); - - rb->queue_enable_queue_send(audio_str.hdr.q, &audio_str_queue_send, - audio_str.thread); - - /* Wait for thread to initialize */ - str_send_msg(&audio_str, STREAM_NULL, 0); - - return true; -} - -/* Stops the audio thread */ -void audio_thread_exit(void) -{ - if (audio_str.thread != 0) - { - str_post_msg(&audio_str, STREAM_QUIT, 0); - rb->codec_thread_do_callback(NULL, NULL); - audio_str.thread = 0; - } -} diff --git a/apps/plugins/mpegplayer/disk_buf.c b/apps/plugins/mpegplayer/disk_buf.c deleted file mode 100644 index 50c4222192..0000000000 --- a/apps/plugins/mpegplayer/disk_buf.c +++ /dev/null @@ -1,989 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * mpegplayer buffering routines - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" -#include - -static struct mutex disk_buf_mtx SHAREDBSS_ATTR; -static struct event_queue disk_buf_queue SHAREDBSS_ATTR; -static struct queue_sender_list disk_buf_queue_send SHAREDBSS_ATTR; -static uint32_t disk_buf_stack[DEFAULT_STACK_SIZE*2/sizeof(uint32_t)]; - -struct disk_buf disk_buf SHAREDBSS_ATTR; -static void *nf_list[MPEGPLAYER_MAX_STREAMS+1]; - -static inline void disk_buf_lock(void) -{ - rb->mutex_lock(&disk_buf_mtx); -} - -static inline void disk_buf_unlock(void) -{ - rb->mutex_unlock(&disk_buf_mtx); -} - -static inline void disk_buf_on_clear_data_notify(struct stream_hdr *sh) -{ - DEBUGF("DISK_BUF_CLEAR_DATA_NOTIFY: 0x%02X (cleared)\n", - STR_FROM_HDR(sh)->id); - list_remove_item(nf_list, sh); -} - -inline bool disk_buf_is_data_ready(struct stream_hdr *sh, - ssize_t margin) -{ - /* Data window available? */ - off_t right = sh->win_right; - - /* Margins past end-of-file can still return true */ - if (right > disk_buf.filesize - margin) - right = disk_buf.filesize - margin; - - return sh->win_left >= disk_buf.win_left && - right + margin <= disk_buf.win_right; -} - -void dbuf_l2_init(struct dbuf_l2_cache *l2_p) -{ - l2_p->addr = OFF_T_MAX; /* Mark as invalid */ -} - -static int disk_buf_on_data_notify(struct stream_hdr *sh) -{ - DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X ", STR_FROM_HDR(sh)->id); - - if (sh->win_left <= sh->win_right) - { - /* Check if the data is already ready already */ - if (disk_buf_is_data_ready(sh, 0)) - { - /* It was - don't register */ - DEBUGF("(was ready)\n" - " swl:%lu swr:%lu\n" - " dwl:%lu dwr:%lu\n", - sh->win_left, sh->win_right, - disk_buf.win_left, disk_buf.win_right); - /* Be sure it's not listed though if multiple requests were made */ - list_remove_item(nf_list, sh); - return DISK_BUF_NOTIFY_OK; - } - - switch (disk_buf.state) - { - case TSTATE_DATA: - case TSTATE_BUFFERING: - case TSTATE_INIT: - disk_buf.state = TSTATE_BUFFERING; - list_add_item(nf_list, sh); - DEBUGF("(registered)\n" - " swl:%lu swr:%lu\n" - " dwl:%lu dwr:%lu\n", - sh->win_left, sh->win_right, - disk_buf.win_left, disk_buf.win_right); - return DISK_BUF_NOTIFY_REGISTERED; - } - } - - DEBUGF("(error)\n"); - return DISK_BUF_NOTIFY_ERROR; -} - -static bool check_data_notifies_callback(struct stream_hdr *sh, void *data) -{ - if (disk_buf_is_data_ready(sh, 0)) - { - /* Remove from list then post notification - post because send - * could result in a wait for each thread to finish resulting - * in deadlock */ - list_remove_item(nf_list, sh); - str_post_msg(STR_FROM_HDR(sh), DISK_BUF_DATA_NOTIFY, 0); - DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X (notified)\n", - STR_FROM_HDR(sh)->id); - } - - return true; - (void)data; -} - -/* Check registered streams and notify them if their data is available */ -static inline void check_data_notifies(void) -{ - list_enum_items(nf_list, - (list_enum_callback_t)check_data_notifies_callback, - NULL); -} - -/* Clear all registered notifications - do not post them */ -static inline void clear_data_notifies(void) -{ - list_clear_all(nf_list); -} - -/* Background buffering when streaming */ -static inline void disk_buf_buffer(void) -{ - struct stream_window sw; - - switch (disk_buf.state) - { - default: - { - size_t wm; - uint32_t time; - - /* Get remaining minimum data based upon the stream closest to the - * right edge of the window */ - if (!stream_get_window(&sw)) - break; - - time = stream_get_ticks(NULL); - wm = muldiv_uint32(5*CLOCK_RATE, sw.right - disk_buf.pos_last, - time - disk_buf.time_last); - wm = MIN(wm, (size_t)disk_buf.size); - wm = MAX(wm, DISK_BUF_LOW_WATERMARK); - - disk_buf.time_last = time; - disk_buf.pos_last = sw.right; - - /* Fast attack, slow decay */ - disk_buf.low_wm = (wm > (size_t)disk_buf.low_wm) ? - wm : AVERAGE(disk_buf.low_wm, wm, 16); - -#if 0 - rb->splashf(0, "*%10ld %10ld", disk_buf.low_wm, - disk_buf.win_right - sw.right); -#endif - - if (disk_buf.win_right - sw.right > disk_buf.low_wm) - break; - - disk_buf.state = TSTATE_BUFFERING; - } /* default: */ - - /* Fall-through */ - case TSTATE_BUFFERING: - { - ssize_t len, n; - uint32_t tag, *tag_p; - - /* Limit buffering up to the stream with the least progress */ - if (!stream_get_window(&sw)) - { - disk_buf.state = TSTATE_DATA; - rb->storage_sleep(); - break; - } - - /* Wrap pointer */ - if (disk_buf.tail >= disk_buf.end) - disk_buf.tail = disk_buf.start; - - len = disk_buf.size - disk_buf.win_right + sw.left; - - if (len < DISK_BUF_PAGE_SIZE) - { - /* Free space is less than one page */ - disk_buf.state = TSTATE_DATA; - disk_buf.low_wm = DISK_BUF_LOW_WATERMARK; - rb->storage_sleep(); - break; - } - - len = disk_buf.tail - disk_buf.start; - tag = MAP_OFFSET_TO_TAG(disk_buf.win_right); - tag_p = &disk_buf.cache[len >> DISK_BUF_PAGE_SHIFT]; - - if (*tag_p != tag) - { - if (disk_buf.need_seek) - { - rb->lseek(disk_buf.in_file, disk_buf.win_right, SEEK_SET); - disk_buf.need_seek = false; - } - - n = rb->read(disk_buf.in_file, disk_buf.tail, DISK_BUF_PAGE_SIZE); - - if (n <= 0) - { - /* Error or end of stream */ - disk_buf.state = TSTATE_EOS; - rb->storage_sleep(); - break; - } - - if (len < DISK_GUARDBUF_SIZE) - { - /* Autoguard guard-o-rama - maintain guardbuffer coherency */ - rb->memcpy(disk_buf.end + len, disk_buf.tail, - MIN(DISK_GUARDBUF_SIZE - len, n)); - } - - /* Update the cache entry for this page */ - *tag_p = tag; - } - else - { - /* Skipping a read */ - n = MIN(DISK_BUF_PAGE_SIZE, - disk_buf.filesize - disk_buf.win_right); - disk_buf.need_seek = true; - } - - disk_buf.tail += DISK_BUF_PAGE_SIZE; - - /* Keep left edge moving forward */ - - /* Advance right edge in temp variable first, then move - * left edge if overflow would occur. This avoids a stream - * thinking its data might be available when it actually - * may not end up that way after a slide of the window. */ - len = disk_buf.win_right + n; - - if (len - disk_buf.win_left > disk_buf.size) - disk_buf.win_left += n; - - disk_buf.win_right = len; - - /* Continue buffering until filled or file end */ - rb->yield(); - } /* TSTATE_BUFFERING: */ - - case TSTATE_EOS: - break; - } /* end switch */ -} - -static void disk_buf_on_reset(ssize_t pos) -{ - int page; - uint32_t tag; - off_t anchor; - - disk_buf.state = TSTATE_INIT; - disk_buf.status = STREAM_STOPPED; - clear_data_notifies(); - - if (pos >= disk_buf.filesize) - { - /* Anchor on page immediately following the one containing final - * data */ - anchor = disk_buf.file_pages * DISK_BUF_PAGE_SIZE; - disk_buf.win_left = disk_buf.filesize; - } - else - { - anchor = pos & ~DISK_BUF_PAGE_MASK; - disk_buf.win_left = anchor; - } - - /* Collect all valid data already buffered that is contiguous with the - * current position - probe to left, then to right */ - if (anchor > 0) - { - page = MAP_OFFSET_TO_PAGE(anchor); - tag = MAP_OFFSET_TO_TAG(anchor); - - do - { - if (--tag, --page < 0) - page = disk_buf.pgcount - 1; - - if (disk_buf.cache[page] != tag) - break; - - disk_buf.win_left = tag << DISK_BUF_PAGE_SHIFT; - } - while (tag > 0); - } - - if (anchor < disk_buf.filesize) - { - page = MAP_OFFSET_TO_PAGE(anchor); - tag = MAP_OFFSET_TO_TAG(anchor); - - do - { - if (disk_buf.cache[page] != tag) - break; - - if (++tag, ++page >= disk_buf.pgcount) - page = 0; - - anchor += DISK_BUF_PAGE_SIZE; - } - while (anchor < disk_buf.filesize); - } - - if (anchor >= disk_buf.filesize) - { - disk_buf.win_right = disk_buf.filesize; - disk_buf.state = TSTATE_EOS; - } - else - { - disk_buf.win_right = anchor; - } - - disk_buf.tail = disk_buf.start + MAP_OFFSET_TO_BUFFER(anchor); - - DEBUGF("disk buf reset\n" - " dwl:%ld dwr:%ld\n", - disk_buf.win_left, disk_buf.win_right); - - /* Next read position is at right edge */ - rb->lseek(disk_buf.in_file, disk_buf.win_right, SEEK_SET); - disk_buf.need_seek = false; - - disk_buf_reply_msg(disk_buf.win_right - disk_buf.win_left); -} - -static void disk_buf_on_stop(void) -{ - bool was_buffering = disk_buf.state == TSTATE_BUFFERING; - - disk_buf.state = TSTATE_EOS; - disk_buf.status = STREAM_STOPPED; - clear_data_notifies(); - - disk_buf_reply_msg(was_buffering); -} - -static void disk_buf_on_play_pause(bool play, bool forcefill) -{ - struct stream_window sw; - - if (disk_buf.state != TSTATE_EOS) - { - if (forcefill) - { - /* Force buffer filling to top */ - disk_buf.state = TSTATE_BUFFERING; - } - else if (disk_buf.state != TSTATE_BUFFERING) - { - /* If not filling already, simply monitor */ - disk_buf.state = TSTATE_DATA; - } - } - /* else end of stream - no buffering to do */ - - disk_buf.pos_last = stream_get_window(&sw) ? sw.right : 0; - disk_buf.time_last = stream_get_ticks(NULL); - - disk_buf.status = play ? STREAM_PLAYING : STREAM_PAUSED; -} - -static int disk_buf_on_load_range(struct dbuf_range *rng) -{ - uint32_t tag = rng->tag_start; - uint32_t tag_end = rng->tag_end; - int page = rng->pg_start; - - /* Check if a seek is required */ - bool need_seek = rb->lseek(disk_buf.in_file, 0, SEEK_CUR) - != (off_t)(tag << DISK_BUF_PAGE_SHIFT); - - do - { - uint32_t *tag_p = &disk_buf.cache[page]; - - if (*tag_p != tag) - { - /* Page not cached - load it */ - ssize_t o, n; - - if (need_seek) - { - rb->lseek(disk_buf.in_file, tag << DISK_BUF_PAGE_SHIFT, - SEEK_SET); - need_seek = false; - } - - o = page << DISK_BUF_PAGE_SHIFT; - n = rb->read(disk_buf.in_file, disk_buf.start + o, - DISK_BUF_PAGE_SIZE); - - if (n < 0) - { - /* Read error */ - return DISK_BUF_NOTIFY_ERROR; - } - - if (n == 0) - { - /* End of file */ - break; - } - - if (o < DISK_GUARDBUF_SIZE) - { - /* Autoguard guard-o-rama - maintain guardbuffer coherency */ - rb->memcpy(disk_buf.end + o, disk_buf.start + o, - MIN(DISK_GUARDBUF_SIZE - o, n)); - } - - /* Update the cache entry */ - *tag_p = tag; - } - else - { - /* Skipping a disk read - must seek on next one */ - need_seek = true; - } - - if (++page >= disk_buf.pgcount) - page = 0; - } - while (++tag <= tag_end); - - return DISK_BUF_NOTIFY_OK; -} - -static void disk_buf_thread(void) -{ - struct queue_event ev; - - disk_buf.state = TSTATE_EOS; - disk_buf.status = STREAM_STOPPED; - - while (1) - { - if (disk_buf.state != TSTATE_EOS) - { - /* Poll buffer status and messages */ - rb->queue_wait_w_tmo(disk_buf.q, &ev, - disk_buf.state == TSTATE_BUFFERING ? - 0 : HZ/5); - } - else - { - /* Sit idle and wait for commands */ - rb->queue_wait(disk_buf.q, &ev); - } - - switch (ev.id) - { - case SYS_TIMEOUT: - if (disk_buf.state == TSTATE_EOS) - break; - - disk_buf_buffer(); - - /* Check for any due notifications if any are pending */ - if (*nf_list != NULL) - check_data_notifies(); - - /* Still more data left? */ - if (disk_buf.state != TSTATE_EOS) - continue; - - /* Nope - end of stream */ - break; - - case DISK_BUF_CACHE_RANGE: - disk_buf_reply_msg(disk_buf_on_load_range( - (struct dbuf_range *)ev.data)); - break; - - case STREAM_RESET: - disk_buf_on_reset(ev.data); - break; - - case STREAM_STOP: - disk_buf_on_stop(); - break; - - case STREAM_PAUSE: - case STREAM_PLAY: - disk_buf_on_play_pause(ev.id == STREAM_PLAY, ev.data != 0); - disk_buf_reply_msg(1); - break; - - case STREAM_QUIT: - disk_buf.state = TSTATE_EOS; - return; - - case DISK_BUF_DATA_NOTIFY: - disk_buf_reply_msg(disk_buf_on_data_notify( - (struct stream_hdr *)ev.data)); - break; - - case DISK_BUF_CLEAR_DATA_NOTIFY: - disk_buf_on_clear_data_notify((struct stream_hdr *)ev.data); - disk_buf_reply_msg(1); - break; - } - } -} - -/* Caches some data from the current file */ -static ssize_t disk_buf_probe(off_t start, size_t length, void **p) -{ - off_t end; - uint32_t tag, tag_end; - int page; - - /* Can't read past end of file */ - if (length > (size_t)(disk_buf.filesize - start)) - { - length = disk_buf.filesize - start; - } - - /* Can't cache more than the whole buffer size */ - if (length > (size_t)disk_buf.size) - { - length = disk_buf.size; - } - /* Zero-length probes permitted */ - - end = start + length; - - /* Prepare the range probe */ - tag = MAP_OFFSET_TO_TAG(start); - tag_end = MAP_OFFSET_TO_TAG(end); - page = MAP_OFFSET_TO_PAGE(start); - - /* If the end is on a page boundary, check one less or an extra - * one will be probed */ - if (tag_end > tag && (end & DISK_BUF_PAGE_MASK) == 0) - { - tag_end--; - } - - if (p != NULL) - { - *p = disk_buf.start + (page << DISK_BUF_PAGE_SHIFT) - + (start & DISK_BUF_PAGE_MASK); - } - - /* Obtain initial load point. If all data was cached, no message is sent - * otherwise begin on the first page that is not cached. Since we have to - * send the message anyway, the buffering thread will determine what else - * requires loading on its end in order to cache the specified range. */ - do - { - if (disk_buf.cache[page] != tag) - { - static struct dbuf_range rng IBSS_ATTR; - intptr_t result; - - DEBUGF("disk_buf: cache miss\n"); - rng.tag_start = tag; - rng.tag_end = tag_end; - rng.pg_start = page; - - result = rb->queue_send(disk_buf.q, DISK_BUF_CACHE_RANGE, - (intptr_t)&rng); - - return result == DISK_BUF_NOTIFY_OK ? (ssize_t)length : -1; - } - - if (++page >= disk_buf.pgcount) - page = 0; - } - while (++tag <= tag_end); - - return length; -} - -/* Attempt to get a pointer to size bytes on the buffer. Returns real amount of - * data available as well as the size of non-wrapped data after *p. */ -ssize_t _disk_buf_getbuffer(size_t size, void **pp, void **pwrap, - size_t *sizewrap) -{ - disk_buf_lock(); - - size = disk_buf_probe(disk_buf.offset, size, pp); - - if (size != (size_t)-1 && pwrap && sizewrap) - { - uint8_t *p = (uint8_t *)*pp; - - if (p + size > disk_buf.end + DISK_GUARDBUF_SIZE) - { - /* Return pointer to wraparound and the size of same */ - size_t nowrap = (disk_buf.end + DISK_GUARDBUF_SIZE) - p; - *pwrap = disk_buf.start + DISK_GUARDBUF_SIZE; - *sizewrap = size - nowrap; - } - else - { - *pwrap = NULL; - *sizewrap = 0; - } - } - - disk_buf_unlock(); - - return size; -} - -ssize_t _disk_buf_getbuffer_l2(struct dbuf_l2_cache *l2, - size_t size, void **pp) -{ - off_t offs; - off_t l2_addr; - size_t l2_size; - void *l2_p; - - if (l2 == NULL) - { - /* Shouldn't have to check this normally */ - DEBUGF("disk_buf_getbuffer_l2: l2 = NULL!\n"); - } - - if (size > DISK_BUF_L2_CACHE_SIZE) - { - /* Asking for too much; just go through L1 */ - return disk_buf_getbuffer(size, pp, NULL, NULL); - } - - offs = disk_buf.offset; /* Other calls keep this within bounds */ - l2_addr = l2->addr; - - if (offs >= l2_addr && offs < l2_addr + DISK_BUF_L2_CACHE_SIZE) - { - /* Data is in the local buffer */ - offs &= DISK_BUF_L2_CACHE_MASK; - - *pp = l2->data + offs; - if (offs + size > l2->size) - size = l2->size - offs; /* Keep size within file limits */ - - return size; - } - - /* Have to probe main buffer */ - l2_addr = offs & ~DISK_BUF_L2_CACHE_MASK; - l2_size = DISK_BUF_L2_CACHE_SIZE*2; /* 2nd half is a guard buffer */ - - disk_buf_lock(); - - l2_size = disk_buf_probe(l2_addr, l2_size, &l2_p); - - if (l2_size != (size_t)-1) - { - rb->memcpy(l2->data, l2_p, l2_size); - - l2->addr = l2_addr; - l2->size = l2_size; - offs -= l2_addr; - - *pp = l2->data + offs; - if (offs + size > l2->size) - size = l2->size - offs; /* Keep size within file limits */ - } - else - { - size = -1; - } - - disk_buf_unlock(); - - return size; -} - - -/* Read size bytes of data into a buffer - advances the buffer pointer - * and returns the real size read. */ -ssize_t disk_buf_read(void *buffer, size_t size) -{ - uint8_t *p; - - disk_buf_lock(); - - size = disk_buf_probe(disk_buf.offset, size, PUN_PTR(void **, &p)); - - if (size != (size_t)-1) - { - if (p + size > disk_buf.end + DISK_GUARDBUF_SIZE) - { - /* Read wraps */ - size_t nowrap = (disk_buf.end + DISK_GUARDBUF_SIZE) - p; - rb->memcpy(buffer, p, nowrap); - rb->memcpy(buffer + nowrap, disk_buf.start + DISK_GUARDBUF_SIZE, - size - nowrap); - } - else - { - /* Read wasn't wrapped or guardbuffer holds it */ - rb->memcpy(buffer, p, size); - } - - disk_buf.offset += size; - } - - disk_buf_unlock(); - - return size; -} - -ssize_t disk_buf_lseek(off_t offset, int whence) -{ - disk_buf_lock(); - - /* The offset returned is the result of the current thread's action and - * may be invalidated so a local result is returned and not the value - * of disk_buf.offset directly */ - switch (whence) - { - case SEEK_SET: - /* offset is just the offset */ - break; - case SEEK_CUR: - offset += disk_buf.offset; - break; - case SEEK_END: - offset = disk_buf.filesize + offset; - break; - default: - disk_buf_unlock(); - return -2; /* Invalid request */ - } - - if (offset < 0 || offset > disk_buf.filesize) - { - offset = -3; - } - else - { - disk_buf.offset = offset; - } - - disk_buf_unlock(); - - return offset; -} - -/* Prepare the buffer to enter the streaming state. Evaluates the available - * streaming window. */ -ssize_t disk_buf_prepare_streaming(off_t pos, size_t len) -{ - disk_buf_lock(); - - if (pos < 0) - pos = 0; - else if (pos > disk_buf.filesize) - pos = disk_buf.filesize; - - DEBUGF("prepare streaming:\n pos:%ld len:%lu\n", pos, (unsigned long)len); - - pos = disk_buf_lseek(pos, SEEK_SET); - len = disk_buf_probe(pos, len, NULL); - - DEBUGF(" probe done: pos:%ld len:%lu\n", pos, (unsigned long)len); - - len = disk_buf_send_msg(STREAM_RESET, pos); - - disk_buf_unlock(); - - return len; -} - -/* Set the streaming window to an arbitrary position within the file. Makes no - * probes to validate data. Use after calling another function to cause data - * to be cached and correct values are known. */ -ssize_t disk_buf_set_streaming_window(off_t left, off_t right) -{ - ssize_t len; - - disk_buf_lock(); - - if (left < 0) - left = 0; - else if (left > disk_buf.filesize) - left = disk_buf.filesize; - - if (left > right) - right = left; - - if (right > disk_buf.filesize) - right = disk_buf.filesize; - - disk_buf.win_left = left; - disk_buf.win_right = right; - disk_buf.tail = disk_buf.start + ((right + DISK_BUF_PAGE_SIZE-1) & - ~DISK_BUF_PAGE_MASK) % disk_buf.size; - - len = disk_buf.win_right - disk_buf.win_left; - - disk_buf_unlock(); - - return len; -} - -void * disk_buf_offset2ptr(off_t offset) -{ - if (offset < 0) - offset = 0; - else if (offset > disk_buf.filesize) - offset = disk_buf.filesize; - - return disk_buf.start + (offset % disk_buf.size); -} - -void disk_buf_close(void) -{ - disk_buf_lock(); - - if (disk_buf.in_file >= 0) - { - rb->close(disk_buf.in_file); - disk_buf.in_file = -1; - - /* Invalidate entire cache */ - rb->memset(disk_buf.cache, 0xff, - disk_buf.pgcount*sizeof (*disk_buf.cache)); - disk_buf.file_pages = 0; - disk_buf.filesize = 0; - disk_buf.offset = 0; - } - - disk_buf_unlock(); -} - -int disk_buf_open(const char *filename) -{ - int fd; - - disk_buf_lock(); - - disk_buf_close(); - - fd = rb->open(filename, O_RDONLY); - - if (fd >= 0) - { - ssize_t filesize = rb->filesize(fd); - - if (filesize <= 0) - { - rb->close(disk_buf.in_file); - } - else - { - disk_buf.filesize = filesize; - /* Number of file pages rounded up toward +inf */ - disk_buf.file_pages = ((size_t)filesize + DISK_BUF_PAGE_SIZE-1) - / DISK_BUF_PAGE_SIZE; - disk_buf.in_file = fd; - } - } - - disk_buf_unlock(); - - return fd; -} - -intptr_t disk_buf_send_msg(long id, intptr_t data) -{ - return rb->queue_send(disk_buf.q, id, data); -} - -void disk_buf_post_msg(long id, intptr_t data) -{ - rb->queue_post(disk_buf.q, id, data); -} - -void disk_buf_reply_msg(intptr_t retval) -{ - rb->queue_reply(disk_buf.q, retval); -} - -bool disk_buf_init(void) -{ - disk_buf.thread = 0; - - rb->mutex_init(&disk_buf_mtx); - - disk_buf.q = &disk_buf_queue; - rb->queue_init(disk_buf.q, false); - - disk_buf.state = TSTATE_EOS; - disk_buf.status = STREAM_STOPPED; - - disk_buf.in_file = -1; - disk_buf.filesize = 0; - disk_buf.win_left = 0; - disk_buf.win_right = 0; - disk_buf.time_last = 0; - disk_buf.pos_last = 0; - disk_buf.low_wm = DISK_BUF_LOW_WATERMARK; - - disk_buf.start = mpeg_malloc_all((size_t*)&disk_buf.size, MPEG_ALLOC_DISKBUF); - if (disk_buf.start == NULL) - return false; - -#if NUM_CORES > 1 - CACHEALIGN_BUFFER(disk_buf.start, disk_buf.size); - disk_buf.start = UNCACHED_ADDR(disk_buf.start); -#endif - disk_buf.size -= DISK_GUARDBUF_SIZE; - disk_buf.pgcount = disk_buf.size / DISK_BUF_PAGE_SIZE; - - /* Fit it as tightly as possible */ - while (disk_buf.pgcount*(sizeof (*disk_buf.cache) + DISK_BUF_PAGE_SIZE) - > (size_t)disk_buf.size) - { - disk_buf.pgcount--; - } - - disk_buf.cache = (typeof (disk_buf.cache))disk_buf.start; - disk_buf.start += sizeof (*disk_buf.cache)*disk_buf.pgcount; - disk_buf.size = disk_buf.pgcount*DISK_BUF_PAGE_SIZE; - disk_buf.end = disk_buf.start + disk_buf.size; - disk_buf.tail = disk_buf.start; - - DEBUGF("disk_buf info:\n" - " page count: %d\n" - " size: %ld\n", - disk_buf.pgcount, (long)disk_buf.size); - - rb->memset(disk_buf.cache, 0xff, - disk_buf.pgcount*sizeof (*disk_buf.cache)); - - disk_buf.thread = rb->create_thread( - disk_buf_thread, disk_buf_stack, sizeof(disk_buf_stack), 0, - "mpgbuffer" IF_PRIO(, PRIORITY_BUFFERING) IF_COP(, CPU)); - - rb->queue_enable_queue_send(disk_buf.q, &disk_buf_queue_send, - disk_buf.thread); - - if (disk_buf.thread == 0) - return false; - - /* Wait for thread to initialize */ - disk_buf_send_msg(STREAM_NULL, 0); - - return true; -} - -void disk_buf_exit(void) -{ - if (disk_buf.thread != 0) - { - rb->queue_post(disk_buf.q, STREAM_QUIT, 0); - rb->thread_wait(disk_buf.thread); - disk_buf.thread = 0; - } -} diff --git a/apps/plugins/mpegplayer/disk_buf.h b/apps/plugins/mpegplayer/disk_buf.h deleted file mode 100644 index bc76ab6dc3..0000000000 --- a/apps/plugins/mpegplayer/disk_buf.h +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * AV disk buffer declarations - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef DISK_BUF_H -#define DISK_BUF_H - -#ifndef OFF_T_MAX -#define OFF_T_MAX (~((off_t)1 << (sizeof (off_t)*8 - 1))) -#endif - -#ifndef OFF_T_MIN -#define OFF_T_MIN ((off_t)1 << (sizeof (off_t)*8 - 1)) -#endif - -#define DISK_BUF_PAGE_SHIFT 15 /* 32KB cache lines */ -#define DISK_BUF_PAGE_SIZE (1 << DISK_BUF_PAGE_SHIFT) -#define DISK_BUF_PAGE_MASK (DISK_BUF_PAGE_SIZE-1) - -enum -{ - DISK_BUF_NOTIFY_ERROR = -1, - DISK_BUF_NOTIFY_NULL = 0, - DISK_BUF_NOTIFY_OK, - DISK_BUF_NOTIFY_TIMEDOUT, - DISK_BUF_NOTIFY_PROCESS_EVENT, - DISK_BUF_NOTIFY_REGISTERED, -}; - -/** Macros to map file offsets to cached data **/ - -/* Returns a cache tag given a file offset */ -#define MAP_OFFSET_TO_TAG(o) \ - ((o) >> DISK_BUF_PAGE_SHIFT) - -/* Returns the cache page number given a file offset */ -#define MAP_OFFSET_TO_PAGE(o) \ - (MAP_OFFSET_TO_TAG(o) % disk_buf.pgcount) - -/* Returns the buffer offset given a file offset */ -#define MAP_OFFSET_TO_BUFFER(o) \ - (MAP_OFFSET_TO_PAGE(o) * DISK_BUF_PAGE_SIZE) - -struct dbuf_range -{ - uint32_t tag_start; - uint32_t tag_end; - int pg_start; -}; - -#define DISK_BUF_L2_CACHE_SHIFT 6 -#define DISK_BUF_L2_CACHE_SIZE (1 << DISK_BUF_L2_CACHE_SHIFT) -#define DISK_BUF_L2_CACHE_MASK (DISK_BUF_L2_CACHE_SIZE-1) - -struct dbuf_l2_cache -{ - off_t addr; /* L2 file offset */ - size_t size; /* Real size */ - uint8_t data[DISK_BUF_L2_CACHE_SIZE*2]; /* Local data and guard */ -}; - -void dbuf_l2_init(struct dbuf_l2_cache *l2_p); - -/* This object is an extension of the stream manager and handles some - * playback events as well as buffering */ -struct disk_buf -{ - unsigned int thread; - struct event_queue *q; - uint8_t *start; /* Start pointer */ - uint8_t *end; /* End of buffer pointer less MPEG_GUARDBUF_SIZE. The - guard space is used to wrap data at the buffer start to - pass continuous data packets */ - uint8_t *tail; /* Location of last data + 1 filled into the buffer */ - ssize_t size; /* The buffer length _not_ including the guard space (end-start) */ - int pgcount; /* Total number of available cached pages */ - uint32_t *cache; /* Pointer to cache structure - allocated on buffer */ - int in_file; /* File being read */ - ssize_t filesize; /* Size of file in_file in bytes */ - int file_pages; /* Number of pages in file (rounded up) */ - off_t offset; /* Current position (random access) */ - off_t win_left; /* Left edge of buffer window (streaming) */ - off_t win_right; /* Right edge of buffer window (streaming) */ - uint32_t time_last; /* Last time watermark was checked */ - off_t pos_last; /* Last position at watermark check time */ - ssize_t low_wm; /* The low watermark for automatic rebuffering */ - int status; /* Status as stream */ - int state; /* Current thread state */ - bool need_seek; /* Need to seek because a read was not contiguous */ -}; - -extern struct disk_buf disk_buf SHAREDBSS_ATTR; - -struct stream_hdr; -bool disk_buf_is_data_ready(struct stream_hdr *sh, ssize_t margin); - -bool disk_buf_init(void); -void disk_buf_exit(void); - -static inline int disk_buf_status(void) - { return disk_buf.status; } - -int disk_buf_open(const char *filename); -void disk_buf_close(void); -ssize_t _disk_buf_getbuffer(size_t size, void **pp, void **pwrap, - size_t *sizewrap); -#define disk_buf_getbuffer(size, pp, pwrap, sizewrap) \ - _disk_buf_getbuffer((size), PUN_PTR(void **, (pp)), \ - PUN_PTR(void **, (pwrap)), (sizewrap)) - -ssize_t _disk_buf_getbuffer_l2(struct dbuf_l2_cache *l2, - size_t size, void **pp); -#define disk_buf_getbuffer_l2(l2, size, pp) \ - _disk_buf_getbuffer_l2((l2), (size), PUN_PTR(void **, (pp))) - -ssize_t disk_buf_read(void *buffer, size_t size); -ssize_t disk_buf_lseek(off_t offset, int whence); - -static inline off_t disk_buf_ftell(void) - { return disk_buf.offset; } - -static inline ssize_t disk_buf_filesize(void) - { return disk_buf.filesize; } - -ssize_t disk_buf_prepare_streaming(off_t pos, size_t len); -ssize_t disk_buf_set_streaming_window(off_t left, off_t right); -void * disk_buf_offset2ptr(off_t offset); -int disk_buf_check_streaming_window(off_t left, off_t right); - -intptr_t disk_buf_send_msg(long id, intptr_t data); -void disk_buf_post_msg(long id, intptr_t data); -void disk_buf_reply_msg(intptr_t retval); - -#endif /* DISK_BUF_H */ diff --git a/apps/plugins/mpegplayer/libmpeg2/AUTHORS b/apps/plugins/mpegplayer/libmpeg2/AUTHORS deleted file mode 100644 index 4722897c97..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/AUTHORS +++ /dev/null @@ -1,33 +0,0 @@ -Aaron Holtzman started the project and -made the initial working implementation. - -Michel Lespinasse did major changes for speed and -mpeg conformance and is the current maintainer. Most of the current -code was (re)written by him. - -Other contributors include: - Bruno Barreyra - build fixes - Gildas Bazin - mingw32 port - Alexander W. Chin - progressive_seq fix - Stephen Crowley - build fixes - Didier Gautheron - bug fixes - Ryan C. Gordon - SDL support - Peter Gubanov - MMX IDCT scheduling - HÃ¥kan Hjort - Solaris fixes, mlib code - Nicolas Joly - assorted bug fixes - Gerd Knorr - Xv support - David I. Lehn - motion_comp mmx code - Olie Lho - MMX yuv2rgb routine - David S. Miller - sparc VIS optimizations - Rick Niles - build fixes - Real Ouellet - g200 fixes - Bajusz Peter - motion comp fixes - Franck Sicard - x11 fixes - Brion Vibber - x11 fixes - Martin Vogt - reentrancy fixes - Fredrik Vraalsen - general hackage and stuff - -(let me know if I forgot anyone) - -Thanks to David Schleef for creating me an account on his ppc g4 -machine and making it possible for me to work on the altivec code. diff --git a/apps/plugins/mpegplayer/libmpeg2/README b/apps/plugins/mpegplayer/libmpeg2/README deleted file mode 100644 index 2a58846772..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/README +++ /dev/null @@ -1,204 +0,0 @@ - - -ABOUT LIBMPEG2 - -libmpeg2 is a free library for decoding mpeg-2 and mpeg-1 video -streams. It is released under the terms of the GPL license. - -The main goals in libmpeg2 development are: - - * Conformance - libmpeg2 is able to decode all mpeg streams that - conform to certain restrictions: "constrained parameters" for - mpeg-1, and "main profile" for mpeg-2. In practice, this is - what most people are using. For streams that follow these - restrictions, we believe libmpeg2 is 100% conformant to the - mpeg standards - and we have a pretty extensive test suite to - check this. - - * Speed - there has been huge efforts there, and we believe - libmpeg2 is the fastest library around for what it - does. Please tell us if you find a faster one ! With typical - video streams as found on DVD's, and doing only decoding with - no display, you should be able to get about 110 fps on a - PIII/666, or 150 fps on an Athlon/950. This is less than 20 - cycles per output pixel. In a real player program, the display - routines will probably take as much time as the actual - decoding ! - - * Portability - most of the code is written in C, and when we - use platform-specific optimizations (typically assembly - routines, currently used for the motion compensation and the - inverse cosine transform stages) we always have a generic C - routine to fall back on. This should be portable to all - architectures - at least we have heard reports from people - running this code on x86, ppc, sparc, arm and - sh4. Assembly-optimized implementations are available on x86 - (MMX) and ppc (altivec) architectures. Ultrasparc (VIS) is - probably the next on the list - we'll see. - - * Reuseability - we do not want libmpeg2 to include any - project-specific code, but it should still include enough - features to be used by very diverse projects. We are only - starting to get there - the best way to help here is to give - us some feedback ! - -The project homepage is at http://libmpeg2.sourceforge.net/ - - -MPEG2DEC - -mpeg2dec is a test program for libmpeg2. It decodes mpeg-1 and mpeg-2 -video streams, and also includes a demultiplexer for mpeg-1 and mpeg-2 -program streams. It is purposely kept simple : it does not include -features like reading files from a DVD, CSS, fullscreen output, -navigation, etc... The main purpose of mpeg2dec is to have a simple -test bed for libmpeg2. - -The libmpeg2 source code is always distributed in the mpeg2dec -package, to make it easier for people to test it. - -The basic usage is to just type "mpeg2dec file" where file is a -demultiplexed mpeg video file. - -The "-s" option must be used for multiplexed (audio and video) mpeg -files using the "program stream" format. These files are usualy found -on the internet or on unencrypted DVDs. - -The "-t" option must be used for multiplexed (audio and video) mpeg -files using the "transport stream" format. These files are usualy -found in digital TV applications. - -The "-o" option is used to select a given output module - for example -to redirect the output to a file. This is also used for performance -testing and conformance testing. - -The "-c" option is used to disable all optimizations. - - -OTHER PROJECTS USING LIBMPEG2 - -libmpeg2 is being used by various other projects, including: - - * xine (http://xine.sourceforge.net/) - started as a simple - mpeg-2 audio and video decoder, but it since became a - full-featured DVD and video media player. - - * VideoLAN (http://www.videolan.org/) - video streaming over an - ethernet network, can also be used as a standalone player. - - * MPlayer (http://www.MPlayerHQ.hu) - another good player, it is - also very robust against damaged streams. - - * movietime (http://movietime.sourceforge.net/) - still quite - young, but it looks very promising ! - - * mpeg2decX (http://homepage1.nifty.com/~toku/software_en.html) - - a graphical interface for mpeg2dec for macintosh osX. - - * TCVP (http://tcvp.sf.net) - video and music player for unix. - - * drip (http://drip.sourceforge.net/) - a DVD to DIVX transcoder. - - * PoMP - (http://www.dmclab.hanyang.ac.kr/research/project/PoDS/PoDS_sw.htm) - - a research player optimized to minimize disk power consumption. - - * OMS (http://www.linuxvideo.org/oms/) - - * XMPS (http://xmps.sourceforge.net/) - - * GStreamer (http://www.gstreamer.net/) - a framework for - streaming media; it has an mpeg2 decoding plugin based on - libmpeg2. - - * mpeglib (http://mpeglib.sourceforge.net/) - a video decoding - library that usess libmpeg2 when decoding mpeg streams. - - * daphne (http://daphne.rulecity.com/) - a laserdisc arcade game - simulator. - - * GOPchop (http://outflux.net/unix/software/GOPchop/) - a - GOP-accurate editor for MPEG2 streams. - -If you use libmpeg2 in another project, let us know ! - - -TASKS - -There are several places where we could easily use some help: - - * Documentation: libmpeg2 still has no documentation. Every - project using it has had to figure things out by looking at - the header files, at the mpeg2dec sample application, and by - asking questions. Writing down a nice documentation would make - the code more easily reuseable. - - * Testing: If you find any stream that does not decode right - with libmpeg2, let us know ! The best thing would be to mail - to the libmpeg2-devel mailing list. Also, it would be nice to - build a stress test so we can make sure libmpeg2 never crashes - on bad streams. - - * Coding: There is a small TODO list in the mpeg2dec package, - you can have a look there ! Most items are pretty terse - though. - - * Porting: If you're porting to a new architecture, you might - want to experiment with the compile flags defined in - configure.in . When you figure out whats fastest on your - platform, send us a patch ! - - * Assembly optimizations: We only have x86 and altivec - optimizations yet, it would be worthwhile writing routines for - other architectures, especially those that have SIMD - instruction set extensions ! Also the yuv2rgb x86 routines - could probably be optimized a lot. - - -CVS SNAPSHOTS - -A daily snapshot is created using "make distcheck" every night and -uploaded to http://libmpeg2.sourceforge.net/files/mpeg2dec-snapshot.tar.gz . -It is easier to use than the CVS repository, because you do not need -to have the right versions of automake, autoconf and libtool -installed. It might be convenient when working on a libmpeg2 port for -example. - - -CVS REPOSITORY - -The latest libmpeg2 and mpeg2dec source code can always be found by -anonymous CVS: - -# export CVSROOT=:pserver:anonymous@cvs.libmpeg2.sourceforge.net:/cvsroot/libmpeg2 -# cvs login (Just press Return when prompted for a password) -# cvs checkout mpeg2dec - -You can also browse the latest changes online at -http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/libmpeg2/mpeg2dec/ - -The other CVS modules are mpeg2dec-streams for the test suite, and -mpeg2dec-livid for the CVS history of the project while it was still -hosted on the linuxvideo.org servers. - - -MAILING LISTS - -See the subscription information at http://libmpeg2.sourceforge.net/lists.html - -libmpeg2-devel - -This is the main mailing list for technical discussion about -libmpeg2. Anyone wanting to work on libmpeg2, or maybe just stay -informed about the development process, should probably subscribe to -this list. - -libmpeg2-checkins - -All libmpeg2 checkins are announced there. This is a good way to keep -track of what goes into CVS. - -libmpeg2-announce - -This is a very low traffic mailing list, only for announcements of new -versions of libmpeg2. Only project administrators can post there. diff --git a/apps/plugins/mpegplayer/libmpeg2/README.rockbox b/apps/plugins/mpegplayer/libmpeg2/README.rockbox deleted file mode 100644 index 95f5a3d4b5..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/README.rockbox +++ /dev/null @@ -1,44 +0,0 @@ -Library: libmpeg2 from mpeg2dec-0.4.0b (Released 2004-01-21) -Imported: 2006-08-06 by Dave Chapman - - -This directory contains a local version of libmpeg2 imported into -Rockbox for MPEG video decoding. - - -LICENSING INFORMATION - -mpeg2dec and libmpeg2 are licensed under Version 2 of the GNU General -Public License. - - -IMPORT DETAILS - -The following files were imported from the mpeg2dec-0.4.0b -distribution. Minor changes were made to enable compilation in -Rockbox and TABs were replaced by spaces to comply with the Rockbox -coding guidelines. - -AUTHORS -README -SOURCES -attributes.h -cpu_accel.c -cpu_state.c -decode.c -header.c -idct.c -motion_comp.c -mpeg2.h -mpeg2_internal.h -slice.c -video_out.h -vlc.h - -The following files are new, but based on code in mpeg2dec. - -Makefile -mpegplayer.c -video_out_rockbox.c -mpeg2dec_config.h -alloc.c diff --git a/apps/plugins/mpegplayer/libmpeg2/attributes.h b/apps/plugins/mpegplayer/libmpeg2/attributes.h deleted file mode 100644 index 24b069223b..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/attributes.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * attributes.h - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.5 - */ - -/* use gcc attribs to align critical data structures */ -#ifdef ATTRIBUTE_ALIGNED_MAX -#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align))) -#else -#define ATTR_ALIGN(align) -#endif - -#if defined(LIKELY) && defined (UNLIKELY) -#define likely(x) LIKELY(x) -#define unlikely(x) UNLIKELY(x) -#else -#define likely(x) (x) -#define unlikely(x) (x) -#endif - diff --git a/apps/plugins/mpegplayer/libmpeg2/decode.c b/apps/plugins/mpegplayer/libmpeg2/decode.c deleted file mode 100644 index 9c8081efbe..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/decode.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * decode.c - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.114 - */ - -#include "plugin.h" - -#include "mpeg2dec_config.h" - -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" - -#define BUFFER_SIZE (1194 * 1024) - -#if defined(CPU_COLDFIRE) || (defined(CPU_ARM) && ARM_ARCH >= 6) -/* twice as large as on other targets because coldfire uses - * a secondary, transposed buffer for optimisation */ -static int16_t static_dct_block[128] IBSS_ATTR ATTR_ALIGN(16); -#define DCT_BLOCKSIZE (128 * sizeof (int16_t)) -#else -static int16_t static_dct_block[64] IBSS_ATTR ATTR_ALIGN(16); -#define DCT_BLOCKSIZE (64 * sizeof (int16_t)) -#endif - -const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec) -{ - return &mpeg2dec->info; -} - -static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes) -{ - uint8_t * current; - uint32_t shift; - uint8_t * limit; - uint8_t byte; - - if (!bytes) - return 0; - - current = mpeg2dec->buf_start; - shift = mpeg2dec->shift; - limit = current + bytes; - - do - { - byte = *current++; - - if (shift == 0x00000100) - { - int skipped; - - mpeg2dec->shift = 0xffffff00; - skipped = current - mpeg2dec->buf_start; - mpeg2dec->buf_start = current; - - return skipped; - } - - shift = (shift | byte) << 8; - } - while (current < limit); - - mpeg2dec->shift = shift; - mpeg2dec->buf_start = current; - - return 0; -} - -static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes) -{ - uint8_t * current; - uint32_t shift; - uint8_t * chunk_ptr; - uint8_t * limit; - uint8_t byte; - - if (!bytes) - return 0; - - current = mpeg2dec->buf_start; - shift = mpeg2dec->shift; - chunk_ptr = mpeg2dec->chunk_ptr; - limit = current + bytes; - - do - { - byte = *current++; - - if (shift == 0x00000100) - { - int copied; - - mpeg2dec->shift = 0xffffff00; - mpeg2dec->chunk_ptr = chunk_ptr + 1; - copied = current - mpeg2dec->buf_start; - mpeg2dec->buf_start = current; - return copied; - } - - shift = (shift | byte) << 8; - *chunk_ptr++ = byte; - } - while (current < limit); - - mpeg2dec->shift = shift; - mpeg2dec->buf_start = current; - return 0; -} - -void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end) -{ - mpeg2dec->buf_start = start; - mpeg2dec->buf_end = end; -} - -int mpeg2_getpos (mpeg2dec_t * mpeg2dec) -{ - return mpeg2dec->buf_end - mpeg2dec->buf_start; -} - -static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec) -{ - int size, skipped; - - size = mpeg2dec->buf_end - mpeg2dec->buf_start; - skipped = skip_chunk (mpeg2dec, size); - - if (!skipped) - { - mpeg2dec->bytes_since_tag += size; - return STATE_BUFFER; - } - - mpeg2dec->bytes_since_tag += skipped; - mpeg2dec->code = mpeg2dec->buf_start[-1]; - - return STATE_INTERNAL_NORETURN; -} - -mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec) -{ - while (!(mpeg2dec->code == 0xb3 || - ((mpeg2dec->code == 0xb7 || mpeg2dec->code == 0xb8 || - !mpeg2dec->code) && mpeg2dec->sequence.width != (unsigned)-1))) - { - if (seek_chunk (mpeg2dec) == STATE_BUFFER) - return STATE_BUFFER; - } - - mpeg2dec->chunk_start = - mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; - - mpeg2dec->user_data_len = 0; - - return ((mpeg2dec->code == 0xb7) ? - mpeg2_header_end(mpeg2dec) : mpeg2_parse_header(mpeg2dec)); -} - -#define RECEIVED(code,state) (((state) << 8) + (code)) - -mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec) -{ - int size_buffer, size_chunk, copied; - - if (mpeg2dec->action) - { - mpeg2_state_t state; - - state = mpeg2dec->action (mpeg2dec); - - if (state > STATE_INTERNAL_NORETURN) - return state; - } - - while (1) - { - while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) < - mpeg2dec->nb_decode_slices) - { - size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; - size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE - - mpeg2dec->chunk_ptr; - - if (size_buffer <= size_chunk) - { - copied = copy_chunk (mpeg2dec, size_buffer); - - if (!copied) - { - mpeg2dec->bytes_since_tag += size_buffer; - mpeg2dec->chunk_ptr += size_buffer; - return STATE_BUFFER; - } - } - else - { - copied = copy_chunk (mpeg2dec, size_chunk); - - if (!copied) - { - /* filled the chunk buffer without finding a start code */ - mpeg2dec->bytes_since_tag += size_chunk; - mpeg2dec->action = seek_chunk; - return STATE_INVALID; - } - } - - mpeg2dec->bytes_since_tag += copied; - - mpeg2_slice (&mpeg2dec->decoder, mpeg2dec->code, - mpeg2dec->chunk_start); - mpeg2dec->code = mpeg2dec->buf_start[-1]; - mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; - } - - if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1) - break; - - if (seek_chunk (mpeg2dec) == STATE_BUFFER) - return STATE_BUFFER; - } - - mpeg2dec->action = mpeg2_seek_header; - - switch (mpeg2dec->code) - { - case 0x00: - return mpeg2dec->state; - case 0xb3: - case 0xb7: - case 0xb8: - return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID; - default: - mpeg2dec->action = seek_chunk; - return STATE_INVALID; - } -} - -mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec) -{ - static int (* const process_header[9]) (mpeg2dec_t *) = - { - mpeg2_header_picture, - mpeg2_header_extension, - mpeg2_header_user_data, - mpeg2_header_sequence, - NULL, - NULL, - NULL, - NULL, - mpeg2_header_gop - }; - - int size_buffer, size_chunk, copied; - - mpeg2dec->action = mpeg2_parse_header; - mpeg2dec->info.user_data = NULL; - mpeg2dec->info.user_data_len = 0; - - while (1) - { - size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; - size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE - - mpeg2dec->chunk_ptr; - - if (size_buffer <= size_chunk) - { - copied = copy_chunk (mpeg2dec, size_buffer); - - if (!copied) - { - mpeg2dec->bytes_since_tag += size_buffer; - mpeg2dec->chunk_ptr += size_buffer; - return STATE_BUFFER; - } - } - else - { - copied = copy_chunk (mpeg2dec, size_chunk); - - if (!copied) - { - /* filled the chunk buffer without finding a start code */ - mpeg2dec->bytes_since_tag += size_chunk; - mpeg2dec->code = 0xb4; - mpeg2dec->action = mpeg2_seek_header; - return STATE_INVALID; - } - } - - mpeg2dec->bytes_since_tag += copied; - - if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) - { - mpeg2dec->code = mpeg2dec->buf_start[-1]; - mpeg2dec->action = mpeg2_seek_header; - return STATE_INVALID; - } - - mpeg2dec->code = mpeg2dec->buf_start[-1]; - - switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) - { - /* state transition after a sequence header */ - case RECEIVED (0x00, STATE_SEQUENCE): - case RECEIVED (0xb8, STATE_SEQUENCE): - mpeg2_header_sequence_finalize (mpeg2dec); - break; - - /* other legal state transitions */ - case RECEIVED (0x00, STATE_GOP): - mpeg2_header_gop_finalize (mpeg2dec); - break; - case RECEIVED (0x01, STATE_PICTURE): - case RECEIVED (0x01, STATE_PICTURE_2ND): - mpeg2_header_picture_finalize (mpeg2dec); - mpeg2dec->action = mpeg2_header_slice_start; - break; - - /* legal headers within a given state */ - case RECEIVED (0xb2, STATE_SEQUENCE): - case RECEIVED (0xb2, STATE_GOP): - case RECEIVED (0xb2, STATE_PICTURE): - case RECEIVED (0xb2, STATE_PICTURE_2ND): - case RECEIVED (0xb5, STATE_SEQUENCE): - case RECEIVED (0xb5, STATE_PICTURE): - case RECEIVED (0xb5, STATE_PICTURE_2ND): - mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; - continue; - - default: - mpeg2dec->action = mpeg2_seek_header; - return STATE_INVALID; - } - - mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; - mpeg2dec->user_data_len = 0; - - return mpeg2dec->state; - } -} - -int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg) -{ - mpeg2_convert_init_t convert_init; - int error; - - error = convert (MPEG2_CONVERT_SET, NULL, &mpeg2dec->sequence, 0, - arg, &convert_init); - - if (!error) - { - mpeg2dec->convert = convert; - mpeg2dec->convert_arg = arg; - mpeg2dec->convert_id_size = convert_init.id_size; - mpeg2dec->convert_stride = 0; - } - - return error; -} - -int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride) -{ - if (!mpeg2dec->convert) - { - if (stride < (int) mpeg2dec->sequence.width) - stride = mpeg2dec->sequence.width; - - mpeg2dec->decoder.stride_frame = stride; - } - else - { - mpeg2_convert_init_t convert_init; - - stride = mpeg2dec->convert(MPEG2_CONVERT_STRIDE, NULL, - &mpeg2dec->sequence, stride, - mpeg2dec->convert_arg, - &convert_init); - - mpeg2dec->convert_id_size = convert_init.id_size; - mpeg2dec->convert_stride = stride; - } - - return stride; -} - -void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[MPEG2_COMPONENTS], void * id) -{ - mpeg2_fbuf_t * fbuf; - - if (mpeg2dec->custom_fbuf) - { - if (mpeg2dec->state == STATE_SEQUENCE) - { - mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; - mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; - } - - mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type == - PIC_FLAG_CODING_TYPE_B)); - - fbuf = mpeg2dec->fbuf[0]; - } - else - { - fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf; - mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index; - } - - fbuf->buf[0] = buf[0]; -#if MPEG2_COLOR - fbuf->buf[1] = buf[1]; - fbuf->buf[2] = buf[2]; -#endif - - fbuf->id = id; -} - -void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf) -{ - mpeg2dec->custom_fbuf = custom_fbuf; -} - -void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip) -{ - mpeg2dec->first_decode_slice = 1; - mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1); -} - -void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end) -{ - start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start; - end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end; - mpeg2dec->first_decode_slice = start; - mpeg2dec->nb_decode_slices = end - start; -} - -void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2) -{ - mpeg2dec->tag_previous = mpeg2dec->tag_current; - mpeg2dec->tag2_previous = mpeg2dec->tag2_current; - mpeg2dec->tag_current = tag; - mpeg2dec->tag2_current = tag2; - mpeg2dec->num_tags++; - mpeg2dec->bytes_since_tag = 0; -} - -void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset) -{ - mpeg2dec->buf_start = mpeg2dec->buf_end = NULL; - mpeg2dec->num_tags = 0; - mpeg2dec->shift = 0xffffff00; - mpeg2dec->code = 0xb4; - mpeg2dec->action = mpeg2_seek_header; - mpeg2dec->state = STATE_INVALID; - mpeg2dec->first = 1; - - mpeg2_reset_info(&mpeg2dec->info); - mpeg2dec->info.gop = NULL; - mpeg2dec->info.user_data = NULL; - mpeg2dec->info.user_data_len = 0; - - if (full_reset) - { - mpeg2dec->info.sequence = NULL; - mpeg2_header_state_init (mpeg2dec); - } -} - -mpeg2dec_t * mpeg2_init (void) -{ - mpeg2dec_t * mpeg2dec; - - mpeg2_idct_init (); - - mpeg2dec = (mpeg2dec_t *)mpeg2_bufalloc(sizeof (mpeg2dec_t), - MPEG2_ALLOC_MPEG2DEC); - if (mpeg2dec == NULL) - return NULL; - - mpeg2dec->decoder.DCTblock = static_dct_block; - - rb->memset (mpeg2dec->decoder.DCTblock, 0, DCT_BLOCKSIZE); - - DEBUGF("DCTblock: %p\n", mpeg2dec->decoder.DCTblock); - - mpeg2dec->chunk_buffer = (uint8_t *)mpeg2_bufalloc(BUFFER_SIZE + 4, - MPEG2_ALLOC_CHUNK); - - mpeg2dec->sequence.width = (unsigned)-1; - mpeg2_reset (mpeg2dec, 1); - - return mpeg2dec; -} - -void mpeg2_close (mpeg2dec_t * mpeg2dec) -{ - mpeg2_header_state_init (mpeg2dec); -#if 0 - /* These are dedicated buffers in rockbox */ - mpeg2_free (mpeg2dec->chunk_buffer); - mpeg2_free (mpeg2dec); -#endif -} diff --git a/apps/plugins/mpegplayer/libmpeg2/header.c b/apps/plugins/mpegplayer/libmpeg2/header.c deleted file mode 100644 index b40193a338..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/header.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* - * header.c - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 2003 Regis Duchesne - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.101 - */ - -#include "plugin.h" - -#include "mpeg2dec_config.h" - -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" - -#define SEQ_EXT 2 -#define SEQ_DISPLAY_EXT 4 -#define QUANT_MATRIX_EXT 8 -#define COPYRIGHT_EXT 0x10 -#define PIC_DISPLAY_EXT 0x80 -#define PIC_CODING_EXT 0x100 - -/* default intra quant matrix, in zig-zag order */ -static const uint8_t default_intra_quantizer_matrix[64] = -{ - 8, - 16, 16, - 19, 16, 19, - 22, 22, 22, 22, - 22, 22, 26, 24, 26, - 27, 27, 27, 26, 26, 26, - 26, 27, 27, 27, 29, 29, 29, - 34, 34, 34, 29, 29, 29, 27, 27, - 29, 29, 32, 32, 34, 34, 37, - 38, 37, 35, 35, 34, 35, - 38, 38, 40, 40, 40, - 48, 48, 46, 46, - 56, 56, 58, - 69, 69, - 83 -}; - -const uint8_t default_mpeg2_scan_norm[64] = -{ - /* Zig-Zag scan pattern */ - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -}; - -const uint8_t default_mpeg2_scan_alt[64] = -{ - /* Alternate scan pattern */ - 0, 8, 16, 24, 1, 9, 2, 10, - 17, 25, 32, 40, 48, 56, 57, 49, - 41, 33, 26, 18, 3, 11, 4, 12, - 19, 27, 34, 42, 50, 58, 35, 43, - 51, 59, 20, 28, 5, 13, 6, 14, - 21, 29, 36, 44, 52, 60, 37, 45, - 53, 61, 22, 30, 7, 15, 23, 31, - 38, 46, 54, 62, 39, 47, 55, 63 -}; - -uint8_t mpeg2_scan_norm[64] IDATA_ATTR; -uint8_t mpeg2_scan_alt[64] IDATA_ATTR; - -void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec) -{ - if (mpeg2dec->sequence.width != (unsigned)-1) - { - mpeg2dec->sequence.width = (unsigned)-1; - mpeg2_mem_reset(); /* Clean the memory slate */ -#if 0 - if (!mpeg2dec->custom_fbuf) - { - int i; - for (i = mpeg2dec->alloc_index_user; - i < mpeg2dec->alloc_index; i++) - { - mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[0]); -#if MPEG2_COLOR - mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[1]); - mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[2]); -#endif - } - } - - if (mpeg2dec->convert_start) - { - int i; - for (i = 0; i < 3; i++) - { - mpeg2_free(mpeg2dec->yuv_buf[i][0]); -#if MPEG2_COLOR - mpeg2_free(mpeg2dec->yuv_buf[i][1]); - mpeg2_free(mpeg2dec->yuv_buf[i][2]); -#endif - } - } - - if (mpeg2dec->decoder.convert_id) - { - mpeg2_free(mpeg2dec->decoder.convert_id); - } -#endif - } - - mpeg2dec->decoder.coding_type = I_TYPE; - mpeg2dec->decoder.convert = NULL; - mpeg2dec->decoder.convert_id = NULL; - - mpeg2dec->picture = mpeg2dec->pictures; - - mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[0].fbuf; - mpeg2dec->fbuf[1] = &mpeg2dec->fbuf_alloc[1].fbuf; - mpeg2dec->fbuf[2] = &mpeg2dec->fbuf_alloc[2].fbuf; - - mpeg2dec->first = 1; - mpeg2dec->alloc_index = 0; - mpeg2dec->alloc_index_user = 0; - mpeg2dec->first_decode_slice = 1; - mpeg2dec->nb_decode_slices = 0xb0 - 1; - mpeg2dec->convert = NULL; - mpeg2dec->convert_start = NULL; - mpeg2dec->custom_fbuf = 0; - mpeg2dec->yuv_index = 0; -} - -void mpeg2_reset_info (mpeg2_info_t * info) -{ - info->current_picture = - info->current_picture_2nd = NULL; - - info->display_picture = - info->display_picture_2nd = NULL; - - info->current_fbuf = - info->display_fbuf = - info->discard_fbuf = NULL; -} - -static void info_user_data (mpeg2dec_t * mpeg2dec) -{ - if (mpeg2dec->user_data_len) - { - mpeg2dec->info.user_data = mpeg2dec->chunk_buffer; - mpeg2dec->info.user_data_len = mpeg2dec->user_data_len - 3; - } -} - -int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec) -{ - static const unsigned int frame_period[16] = - { - 0, 1126125, 1125000, 1080000, 900900, 900000, 540000, 450450, 450000, - /* unofficial: xing 15 fps */ - 1800000, - /* unofficial: libmpeg3 "Unofficial economy rates" 5/10/12/15 fps */ - 5400000, 2700000, 2250000, 1800000, 0, 0 - }; - - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; - int i; - - if ((buffer[6] & 0x20) != 0x20) /* missing marker_bit */ - return 1; - - i = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; - - if (!(sequence->display_width = sequence->picture_width = i >> 12)) - return 1; - - if (!(sequence->display_height = sequence->picture_height = i & 0xfff)) - return 1; - - sequence->width = (sequence->picture_width + 15) & ~15; - sequence->height = (sequence->picture_height + 15) & ~15; - sequence->chroma_width = sequence->width >> 1; - sequence->chroma_height = sequence->height >> 1; - - sequence->flags = SEQ_FLAG_PROGRESSIVE_SEQUENCE | - SEQ_VIDEO_FORMAT_UNSPECIFIED; - - sequence->pixel_width = buffer[3] >> 4; /* aspect ratio */ - sequence->frame_period = frame_period[buffer[3] & 15]; - - sequence->byte_rate = (buffer[4]<<10) | (buffer[5]<<2) | (buffer[6]>>6); - - sequence->vbv_buffer_size = ((buffer[6]<<16) | (buffer[7]<<8)) & 0x1ff800; - - if (buffer[7] & 4) - sequence->flags |= SEQ_FLAG_CONSTRAINED_PARAMETERS; - - mpeg2dec->copy_matrix = 3; - - if (buffer[7] & 2) - { - for (i = 0; i < 64; i++) - { - mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] = - (buffer[i+7] << 7) | (buffer[i+8] >> 1); - } - - buffer += 64; - } - else - { - for (i = 0; i < 64; i++) - { - mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] = - default_intra_quantizer_matrix[i]; - } - } - - if (buffer[7] & 1) - { - for (i = 0; i < 64; i++) - { - mpeg2dec->new_quantizer_matrix[1][mpeg2_scan_norm[i]] = - buffer[i+8]; - } - } - else - { - rb->memset (mpeg2dec->new_quantizer_matrix[1], 16, 64); - } - - sequence->profile_level_id = 0x80; - sequence->colour_primaries = 0; - sequence->transfer_characteristics = 0; - sequence->matrix_coefficients = 0; - - mpeg2dec->ext_state = SEQ_EXT; - mpeg2dec->state = STATE_SEQUENCE; - - mpeg2dec->display_offset_x = - mpeg2dec->display_offset_y = 0; - - return 0; -} - -static int sequence_ext (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; - uint32_t flags; - - if (!(buffer[3] & 1)) - return 1; - - sequence->profile_level_id = (buffer[0] << 4) | (buffer[1] >> 4); - - sequence->picture_width += ((buffer[1] << 13) | (buffer[2] << 5)) & 0x3000; - sequence->display_width = sequence->picture_width; - - sequence->picture_height += (buffer[2] << 7) & 0x3000; - sequence->display_height = sequence->picture_height; - - sequence->width = (sequence->picture_width + 15) & ~15; - sequence->height = (sequence->picture_height + 15) & ~15; - - flags = sequence->flags | SEQ_FLAG_MPEG2; - - if (!(buffer[1] & 8)) - { - flags &= ~SEQ_FLAG_PROGRESSIVE_SEQUENCE; - sequence->height = (sequence->height + 31) & ~31; - } - - if (buffer[5] & 0x80) - flags |= SEQ_FLAG_LOW_DELAY; - - sequence->flags = flags; - sequence->chroma_width = sequence->width; - sequence->chroma_height = sequence->height; - - switch (buffer[1] & 6) - { - case 0: /* invalid */ - return 1; - case 2: /* 4:2:0 */ - sequence->chroma_height >>= 1; - /* fallthrough */ - case 4: /* 4:2:2 */ - sequence->chroma_width >>= 1; - } - - sequence->byte_rate += ((buffer[2]<<25) | (buffer[3]<<17)) & 0x3ffc0000; - - sequence->vbv_buffer_size |= buffer[4] << 21; - - sequence->frame_period = - sequence->frame_period * ((buffer[5]&31)+1) / (((buffer[5]>>2)&3)+1); - - mpeg2dec->ext_state = SEQ_DISPLAY_EXT; - - return 0; -} - -static int sequence_display_ext (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; - int x; - - sequence->flags = (sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) | - ((buffer[0] << 4) & SEQ_MASK_VIDEO_FORMAT); - - if (buffer[0] & 1) - { - sequence->flags |= SEQ_FLAG_COLOUR_DESCRIPTION; - sequence->colour_primaries = buffer[1]; - sequence->transfer_characteristics = buffer[2]; - sequence->matrix_coefficients = buffer[3]; - buffer += 3; - } - - if (!(buffer[2] & 2)) /* missing marker_bit */ - return 1; - - x = (buffer[1] << 6) | (buffer[2] >> 2); - if (x) - sequence->display_width = x; - - x = ((buffer[2] & 1) << 13) | (buffer[3] << 5) | (buffer[4] >> 3); - if (x) - sequence->display_height = x; - - return 0; -} - -static inline void simplify (unsigned int * u, unsigned int * v) -{ - unsigned int a, b, tmp; - - a = *u; - b = *v; - - /* find greatest common divisor */ - while (a) - { - tmp = a; - a = b % tmp; - b = tmp; - } - - *u /= b; - *v /= b; -} - -static inline void finalize_sequence (mpeg2_sequence_t * sequence) -{ - int width; - int height; - - sequence->byte_rate *= 50; - - if (sequence->flags & SEQ_FLAG_MPEG2) - { - switch (sequence->pixel_width) - { - case 1: /* square pixels */ - sequence->pixel_width = - sequence->pixel_height = 1; - return; - case 2: /* 4:3 aspect ratio */ - width = 4; - height = 3; - break; - case 3: /* 16:9 aspect ratio */ - width = 16; - height = 9; - break; - case 4: /* 2.21:1 aspect ratio */ - width = 221; - height = 100; - break; - default: /* illegal */ - sequence->pixel_width = - sequence->pixel_height = 0; - return; - } - - width *= sequence->display_height; - height *= sequence->display_width; - } - else - { - if (sequence->byte_rate == 50 * 0x3ffff) - sequence->byte_rate = 0; /* mpeg-1 VBR */ - - switch (sequence->pixel_width) - { - case 0: - case 15: /* illegal */ - sequence->pixel_width = - sequence->pixel_height = 0; - return; - case 1: /* square pixels */ - sequence->pixel_width = - sequence->pixel_height = 1; - return; - case 3: /* 720x576 16:9 */ - sequence->pixel_width = 64; - sequence->pixel_height = 45; - return; - case 6: /* 720x480 16:9 */ - sequence->pixel_width = 32; - sequence->pixel_height = 27; - return; - case 8: /* BT.601 625 lines 4:3 */ - sequence->pixel_width = 59; - sequence->pixel_height = 54; - return; - case 12: /* BT.601 525 lines 4:3 */ - sequence->pixel_width = 10; - sequence->pixel_height = 11; - return; - default: - height = 88 * sequence->pixel_width + 1171; - width = 2000; - } - } - - sequence->pixel_width = width; - sequence->pixel_height = height; - - simplify(&sequence->pixel_width, &sequence->pixel_height); -} - -int mpeg2_guess_aspect (const mpeg2_sequence_t * sequence, - unsigned int * pixel_width, - unsigned int * pixel_height) -{ - static const struct - { - unsigned int width, height; - } video_modes[] = - { - {720, 576}, /* 625 lines, 13.5 MHz (D1, DV, DVB, DVD) */ - {704, 576}, /* 625 lines, 13.5 MHz (1/1 D1, DVB, DVD, 4CIF) */ - {544, 576}, /* 625 lines, 10.125 MHz (DVB, laserdisc) */ - {528, 576}, /* 625 lines, 10.125 MHz (3/4 D1, DVB, laserdisc) */ - {480, 576}, /* 625 lines, 9 MHz (2/3 D1, DVB, SVCD) */ - {352, 576}, /* 625 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVB, DVD) */ - {352, 288}, /* 625 lines, 6.75 MHz, 1 field (D4, VCD, DVB, DVD, CIF) */ - {176, 144}, /* 625 lines, 3.375 MHz, half field (QCIF) */ - {720, 486}, /* 525 lines, 13.5 MHz (D1) */ - {704, 486}, /* 525 lines, 13.5 MHz */ - {720, 480}, /* 525 lines, 13.5 MHz (DV, DSS, DVD) */ - {704, 480}, /* 525 lines, 13.5 MHz (1/1 D1, ATSC, DVD) */ - {544, 480}, /* 525 lines. 10.125 MHz (DSS, laserdisc) */ - {528, 480}, /* 525 lines. 10.125 MHz (3/4 D1, laserdisc) */ - {480, 480}, /* 525 lines, 9 MHz (2/3 D1, SVCD) */ - {352, 480}, /* 525 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVD) */ - {352, 240} /* 525 lines. 6.75 MHz, 1 field (D4, VCD, DSS, DVD) */ - }; - unsigned int width, height, pix_width, pix_height, i, DAR_16_9; - - *pixel_width = sequence->pixel_width; - *pixel_height = sequence->pixel_height; - width = sequence->picture_width; - height = sequence->picture_height; - - for (i = 0; i < sizeof (video_modes) / sizeof (video_modes[0]); i++) - { - if (width == video_modes[i].width && height == video_modes[i].height) - break; - } - - if (i == ARRAYLEN(video_modes) || - (sequence->pixel_width == 1 && sequence->pixel_height == 1) || - width != sequence->display_width || height != sequence->display_height) - { - return 0; - } - - for (pix_height = 1; height * pix_height < 480; pix_height <<= 1); - height *= pix_height; - - for (pix_width = 1; width * pix_width <= 352; pix_width <<= 1); - width *= pix_width; - - if (!(sequence->flags & SEQ_FLAG_MPEG2)) - { - static unsigned int mpeg1_check[2][2] = {{11, 54}, {27, 45}}; - DAR_16_9 = (sequence->pixel_height == 27 || - sequence->pixel_height == 45); - if (width < 704 || - sequence->pixel_height != mpeg1_check[DAR_16_9][height == 576]) - return 0; - } - else - { - DAR_16_9 = (3 * sequence->picture_width * sequence->pixel_width > - 4 * sequence->picture_height * sequence->pixel_height); - switch (width) - { - case 528: - case 544: - pix_width *= 4; - pix_height *= 3; - break; - case 480: - pix_width *= 3; - pix_height *= 2; - break; - } - } - - if (DAR_16_9) - { - pix_width *= 4; - pix_height *= 3; - } - - if (height == 576) - { - pix_width *= 59; - pix_height *= 54; - } - else - { - pix_width *= 10; - pix_height *= 11; - } - - *pixel_width = pix_width; - *pixel_height = pix_height; - - simplify (pixel_width, pixel_height); - - return (height == 576) ? 1 : 2; -} - -static void copy_matrix (mpeg2dec_t * mpeg2dec, int index) -{ - if (rb->memcmp (mpeg2dec->quantizer_matrix[index], - mpeg2dec->new_quantizer_matrix[index], 64)) - { - rb->memcpy (mpeg2dec->quantizer_matrix[index], - mpeg2dec->new_quantizer_matrix[index], 64); - - mpeg2dec->scaled[index] = -1; - } -} - -static void finalize_matrix (mpeg2dec_t * mpeg2dec) -{ - mpeg2_decoder_t *decoder = &mpeg2dec->decoder; - int i; - - for (i = 0; i < 2; i++) - { - if (mpeg2dec->copy_matrix & (1 << i)) - copy_matrix (mpeg2dec, i); - - if ((mpeg2dec->copy_matrix & (4 << i)) && - rb->memcmp(mpeg2dec->quantizer_matrix[i], - mpeg2dec->new_quantizer_matrix[i+2], 64)) - { - copy_matrix (mpeg2dec, i + 2); - decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i+2]; - } - else if (mpeg2dec->copy_matrix & (5 << i)) - { - decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i]; - } - } -} - -static mpeg2_state_t invalid_end_action (mpeg2dec_t * mpeg2dec) -{ - mpeg2_reset_info (&mpeg2dec->info); - - mpeg2dec->info.gop = NULL; - - info_user_data (mpeg2dec); - - mpeg2_header_state_init (mpeg2dec); - - mpeg2dec->sequence = mpeg2dec->new_sequence; - mpeg2dec->action = mpeg2_seek_header; - mpeg2dec->state = STATE_SEQUENCE; - - return STATE_SEQUENCE; -} - -void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec) -{ - mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; - mpeg2_decoder_t * decoder = &mpeg2dec->decoder; - - finalize_sequence(sequence); - finalize_matrix(mpeg2dec); - - decoder->mpeg1 = !(sequence->flags & SEQ_FLAG_MPEG2); - decoder->width = sequence->width; - decoder->height = sequence->height; - decoder->vertical_position_extension = sequence->picture_height > 2800; - decoder->chroma_format = (sequence->chroma_width == sequence->width) + - (sequence->chroma_height == sequence->height); - - if (mpeg2dec->sequence.width != (unsigned)-1) - { - /* - * According to 6.1.1.6, repeat sequence headers should be - * identical to the original. However some encoders don't - * respect that and change various fields (including bitrate - * and aspect ratio) in the repeat sequence headers. So we - * choose to be as conservative as possible and only restart - * the decoder if the width, height, chroma_width, - * chroma_height or low_delay flag are modified. - */ - if (sequence->width != mpeg2dec->sequence.width || - sequence->height != mpeg2dec->sequence.height || - sequence->chroma_width != mpeg2dec->sequence.chroma_width || - sequence->chroma_height != mpeg2dec->sequence.chroma_height || - ((sequence->flags ^ mpeg2dec->sequence.flags) & - SEQ_FLAG_LOW_DELAY)) - { - decoder->stride_frame = sequence->width; - mpeg2_header_end (mpeg2dec); - mpeg2dec->action = invalid_end_action; - mpeg2dec->state = STATE_INVALID_END; - return; - } - - mpeg2dec->state = rb->memcmp(&mpeg2dec->sequence, sequence, - sizeof (mpeg2_sequence_t)) ? - STATE_SEQUENCE_MODIFIED : - STATE_SEQUENCE_REPEATED; - } - else - { - decoder->stride_frame = sequence->width; - } - - mpeg2dec->sequence = *sequence; - mpeg2_reset_info(&mpeg2dec->info); - mpeg2dec->info.sequence = &mpeg2dec->sequence; - mpeg2dec->info.gop = NULL; - - info_user_data (mpeg2dec); -} - -int mpeg2_header_gop (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_gop_t * gop = &mpeg2dec->new_gop; - - if (!(buffer[1] & 8)) - return 1; - - gop->hours = (buffer[0] >> 2) & 31; - gop->minutes = ((buffer[0] << 4) | (buffer[1] >> 4)) & 63; - gop->seconds = ((buffer[1] << 3) | (buffer[2] >> 5)) & 63; - gop->pictures = ((buffer[2] << 1) | (buffer[3] >> 7)) & 63; - gop->flags = (buffer[0] >> 7) | ((buffer[3] >> 4) & 6); - - mpeg2dec->state = STATE_GOP; - return 0; -} - -void mpeg2_header_gop_finalize (mpeg2dec_t * mpeg2dec) -{ - mpeg2dec->gop = mpeg2dec->new_gop; - mpeg2_reset_info (&mpeg2dec->info); - mpeg2dec->info.gop = &mpeg2dec->gop; - info_user_data (mpeg2dec); -} - -void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type) -{ - int i; - - for (i = 0; i < 3; i++) - { - if (mpeg2dec->fbuf[1] != &mpeg2dec->fbuf_alloc[i].fbuf && - mpeg2dec->fbuf[2] != &mpeg2dec->fbuf_alloc[i].fbuf) - { - mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[i].fbuf; - mpeg2dec->info.current_fbuf = mpeg2dec->fbuf[0]; - - if (b_type || (mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY)) - { - if (b_type || mpeg2dec->convert) - mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[0]; - - mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[0]; - } - - break; - } - } -} - -int mpeg2_header_picture (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_picture_t * picture = &mpeg2dec->new_picture; - mpeg2_decoder_t * decoder = &mpeg2dec->decoder; - int type; - - mpeg2dec->state = (mpeg2dec->state != STATE_SLICE_1ST) ? - STATE_PICTURE : STATE_PICTURE_2ND; - mpeg2dec->ext_state = PIC_CODING_EXT; - - picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6); - - type = (buffer [1] >> 3) & 7; - - if (type == PIC_FLAG_CODING_TYPE_P || type == PIC_FLAG_CODING_TYPE_B) - { - /* forward_f_code and backward_f_code - used in mpeg1 only */ - decoder->f_motion.f_code[1] = (buffer[3] >> 2) & 1; - decoder->f_motion.f_code[0] = - (((buffer[3] << 1) | (buffer[4] >> 7)) & 7) - 1; - decoder->b_motion.f_code[1] = (buffer[4] >> 6) & 1; - decoder->b_motion.f_code[0] = ((buffer[4] >> 3) & 7) - 1; - } - - picture->flags = PIC_FLAG_PROGRESSIVE_FRAME | type; - picture->tag = picture->tag2 = 0; - - if (mpeg2dec->num_tags) - { - if (mpeg2dec->bytes_since_tag >= mpeg2dec->chunk_ptr - buffer + 4) - { - mpeg2dec->num_tags = 0; - picture->tag = mpeg2dec->tag_current; - picture->tag2 = mpeg2dec->tag2_current; - picture->flags |= PIC_FLAG_TAGS; - } - else if (mpeg2dec->num_tags > 1) - { - mpeg2dec->num_tags = 1; - picture->tag = mpeg2dec->tag_previous; - picture->tag2 = mpeg2dec->tag2_previous; - picture->flags |= PIC_FLAG_TAGS; - } - } - - picture->nb_fields = 2; - picture->display_offset[0].x = picture->display_offset[1].x = - picture->display_offset[2].x = mpeg2dec->display_offset_x; - - picture->display_offset[0].y = picture->display_offset[1].y = - picture->display_offset[2].y = mpeg2dec->display_offset_y; - - /* XXXXXX decode extra_information_picture as well */ - - mpeg2dec->q_scale_type = 0; - decoder->intra_dc_precision = 7; - decoder->frame_pred_frame_dct = 1; - decoder->concealment_motion_vectors = 0; - decoder->scan = mpeg2_scan_norm; - decoder->picture_structure = FRAME_PICTURE; - mpeg2dec->copy_matrix = 0; - - return 0; -} - -static int picture_coding_ext (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_picture_t * picture = &mpeg2dec->new_picture; - mpeg2_decoder_t * decoder = &mpeg2dec->decoder; - uint32_t flags; - - /* pre subtract 1 for use later in compute_motion_vector */ - decoder->f_motion.f_code[0] = (buffer[0] & 15) - 1; - decoder->f_motion.f_code[1] = (buffer[1] >> 4) - 1; - decoder->b_motion.f_code[0] = (buffer[1] & 15) - 1; - decoder->b_motion.f_code[1] = (buffer[2] >> 4) - 1; - - flags = picture->flags; - - decoder->intra_dc_precision = 7 - ((buffer[2] >> 2) & 3); - decoder->picture_structure = buffer[2] & 3; - - switch (decoder->picture_structure) - { - case TOP_FIELD: - flags |= PIC_FLAG_TOP_FIELD_FIRST; - case BOTTOM_FIELD: - picture->nb_fields = 1; - break; - case FRAME_PICTURE: - if (!(mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE)) - { - picture->nb_fields = (buffer[3] & 2) ? 3 : 2; - flags |= (buffer[3] & 128) ? PIC_FLAG_TOP_FIELD_FIRST : 0; - } - else - { - picture->nb_fields = (buffer[3]&2) ? ((buffer[3]&128) ? 6 : 4) : 2; - } - break; - default: - return 1; - } - - decoder->top_field_first = buffer[3] >> 7; - decoder->frame_pred_frame_dct = (buffer[3] >> 6) & 1; - decoder->concealment_motion_vectors = (buffer[3] >> 5) & 1; - mpeg2dec->q_scale_type = buffer[3] & 16; - decoder->intra_vlc_format = (buffer[3] >> 3) & 1; - decoder->scan = (buffer[3] & 4) ? mpeg2_scan_alt : mpeg2_scan_norm; - - if (!(buffer[4] & 0x80)) - flags &= ~PIC_FLAG_PROGRESSIVE_FRAME; - - if (buffer[4] & 0x40) - { - flags |= (((buffer[4]<<26) | (buffer[5]<<18) | (buffer[6]<<10)) & - PIC_MASK_COMPOSITE_DISPLAY) | PIC_FLAG_COMPOSITE_DISPLAY; - } - - picture->flags = flags; - - mpeg2dec->ext_state = PIC_DISPLAY_EXT | COPYRIGHT_EXT | QUANT_MATRIX_EXT; - - return 0; -} - -static int picture_display_ext (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - mpeg2_picture_t * picture = &mpeg2dec->new_picture; - int i, nb_pos; - - nb_pos = picture->nb_fields; - - if (mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE) - nb_pos >>= 1; - - for (i = 0; i < nb_pos; i++) - { - int x, y; - - x = ((buffer[4*i] << 24) | (buffer[4*i+1] << 16) | - (buffer[4*i+2] << 8) | buffer[4*i+3]) >> (11-2*i); - - y = ((buffer[4*i+2] << 24) | (buffer[4*i+3] << 16) | - (buffer[4*i+4] << 8) | buffer[4*i+5]) >> (10-2*i); - - if (! (x & y & 1)) - return 1; - - picture->display_offset[i].x = mpeg2dec->display_offset_x = x >> 1; - picture->display_offset[i].y = mpeg2dec->display_offset_y = y >> 1; - } - - for (; i < 3; i++) - { - picture->display_offset[i].x = mpeg2dec->display_offset_x; - picture->display_offset[i].y = mpeg2dec->display_offset_y; - } - - return 0; -} - -void mpeg2_header_picture_finalize (mpeg2dec_t * mpeg2dec) -{ - mpeg2_decoder_t * decoder = &mpeg2dec->decoder; - int old_type_b = decoder->coding_type == B_TYPE; - int low_delay = mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY; - - finalize_matrix (mpeg2dec); - decoder->coding_type = mpeg2dec->new_picture.flags & PIC_MASK_CODING_TYPE; - - if (mpeg2dec->state == STATE_PICTURE) - { - mpeg2_picture_t * picture; - mpeg2_picture_t * other; - - decoder->second_field = 0; - - picture = other = mpeg2dec->pictures; - - if (old_type_b ^ (mpeg2dec->picture < mpeg2dec->pictures + 2)) - picture += 2; - else - other += 2; - - mpeg2dec->picture = picture; - *picture = mpeg2dec->new_picture; - - if (!old_type_b) - { - mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; - mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; - } - - mpeg2dec->fbuf[0] = NULL; - mpeg2_reset_info (&mpeg2dec->info); - mpeg2dec->info.current_picture = picture; - mpeg2dec->info.display_picture = picture; - - if (decoder->coding_type != B_TYPE) - { - if (!low_delay) - { - if (mpeg2dec->first) - { - mpeg2dec->info.display_picture = NULL; - mpeg2dec->first = 0; - } - else - { - mpeg2dec->info.display_picture = other; - - if (other->nb_fields == 1) - mpeg2dec->info.display_picture_2nd = other + 1; - - mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[1]; - } - } - - if (!low_delay + !mpeg2dec->convert) - { - mpeg2dec->info.discard_fbuf = - mpeg2dec->fbuf[!low_delay + !mpeg2dec->convert]; - } - } - - if (mpeg2dec->convert) - { - mpeg2_convert_init_t convert_init; - - if (!mpeg2dec->convert_start) - { - mpeg2dec->decoder.convert_id = - mpeg2_malloc (mpeg2dec->convert_id_size, - MPEG2_ALLOC_CONVERT_ID); - - mpeg2dec->convert (MPEG2_CONVERT_START, - mpeg2dec->decoder.convert_id, - &mpeg2dec->sequence, - mpeg2dec->convert_stride, - mpeg2dec->convert_arg, &convert_init); - - mpeg2dec->convert_start = convert_init.start; - mpeg2dec->decoder.convert = convert_init.copy; - - int y_size = decoder->stride_frame * mpeg2dec->sequence.height; - - mpeg2dec->yuv_buf[0][0] = - (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV); -#if MPEG2_COLOR - int uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format); - - mpeg2dec->yuv_buf[0][1] = - (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); - mpeg2dec->yuv_buf[0][2] = - (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); -#endif - - mpeg2dec->yuv_buf[1][0] = - (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV); -#if MPEG2_COLOR - mpeg2dec->yuv_buf[1][1] = - (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); - mpeg2dec->yuv_buf[1][2] = - (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); -#endif - y_size = decoder->stride_frame * 32; - - mpeg2dec->yuv_buf[2][0] = - (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV); -#if MPEG2_COLOR - uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format); - - mpeg2dec->yuv_buf[2][1] = - (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); - mpeg2dec->yuv_buf[2][2] = - (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); -#endif - } - - if (!mpeg2dec->custom_fbuf) - { - while (mpeg2dec->alloc_index < 3) - { - mpeg2_fbuf_t * fbuf; - - fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf; - fbuf->id = NULL; - - fbuf->buf[0] = - (uint8_t *) mpeg2_malloc (convert_init.buf_size[0], - MPEG2_ALLOC_CONVERTED); -#if MPEG2_COLOR - fbuf->buf[1] = - (uint8_t *) mpeg2_malloc (convert_init.buf_size[1], - MPEG2_ALLOC_CONVERTED); - fbuf->buf[2] = - (uint8_t *) mpeg2_malloc (convert_init.buf_size[2], - MPEG2_ALLOC_CONVERTED); -#endif - } - - mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE)); - } - } - else if (!mpeg2dec->custom_fbuf) - { - while (mpeg2dec->alloc_index < 3) - { - mpeg2_fbuf_t * fbuf; - - fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf; - - fbuf->id = NULL; - - int y_size = decoder->stride_frame * mpeg2dec->sequence.height; - - fbuf->buf[0] = (uint8_t *) mpeg2_malloc (y_size, - MPEG2_ALLOC_YUV); -#if MPEG2_COLOR - int uv_size = y_size >> (2 - decoder->chroma_format); - - fbuf->buf[1] = (uint8_t *) mpeg2_malloc (uv_size, - MPEG2_ALLOC_YUV); - fbuf->buf[2] = (uint8_t *) mpeg2_malloc (uv_size, - MPEG2_ALLOC_YUV); -#endif - } - - mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE)); - } - } - else - { - decoder->second_field = 1; - mpeg2dec->picture++; /* second field picture */ - - *(mpeg2dec->picture) = mpeg2dec->new_picture; - - mpeg2dec->info.current_picture_2nd = mpeg2dec->picture; - - if (low_delay || decoder->coding_type == B_TYPE) - mpeg2dec->info.display_picture_2nd = mpeg2dec->picture; - } - - info_user_data (mpeg2dec); -} - -static int copyright_ext (mpeg2dec_t * mpeg2dec) -{ - (void)mpeg2dec; - return 0; -} - -static int quant_matrix_ext (mpeg2dec_t * mpeg2dec) -{ - uint8_t * buffer = mpeg2dec->chunk_start; - int i, j; - - for (i = 0; i < 4; i++) - { - if (buffer[0] & (8 >> i)) - { - for (j = 0; j < 64; j++) - { - mpeg2dec->new_quantizer_matrix[i][mpeg2_scan_norm[j]] = - (buffer[j] << (i+5)) | (buffer[j+1] >> (3-i)); - } - - mpeg2dec->copy_matrix |= 1 << i; - buffer += 64; - } - } - - return 0; -} - -int mpeg2_header_extension (mpeg2dec_t * mpeg2dec) -{ - static int (* const parser[9]) (mpeg2dec_t *) = - { - NULL, - sequence_ext, - sequence_display_ext, - quant_matrix_ext, - copyright_ext, - NULL, - NULL, - picture_display_ext, - picture_coding_ext - }; - - int ext, ext_bit; - - ext = mpeg2dec->chunk_start[0] >> 4; - ext_bit = 1 << ext; - - if (!(mpeg2dec->ext_state & ext_bit)) - return 0; /* ignore illegal extensions */ - - mpeg2dec->ext_state &= ~ext_bit; - - return parser[ext] (mpeg2dec); -} - -int mpeg2_header_user_data (mpeg2dec_t * mpeg2dec) -{ - mpeg2dec->user_data_len += mpeg2dec->chunk_ptr - 1 - mpeg2dec->chunk_start; - mpeg2dec->chunk_start = mpeg2dec->chunk_ptr - 1; - - return 0; -} - -static void prescale (mpeg2dec_t * mpeg2dec, int index) -{ - static const int non_linear_scale[32] = - { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 10, 12, 14, 16, 18, 20, 22, - 24, 28, 32, 36, 40, 44, 48, 52, - 56, 64, 72, 80, 88, 96, 104, 112 - }; - - int i, j, k; - mpeg2_decoder_t * decoder = &mpeg2dec->decoder; - - if (mpeg2dec->scaled[index] != mpeg2dec->q_scale_type) - { - mpeg2dec->scaled[index] = mpeg2dec->q_scale_type; - - for (i = 0; i < 32; i++) - { - k = mpeg2dec->q_scale_type ? non_linear_scale[i] : (i << 1); - - for (j = 0; j < 64; j++) - { - decoder->quantizer_prescale[index][i][j] = - k * mpeg2dec->quantizer_matrix[index][j]; - } - } - } -} - -mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec) -{ - mpeg2_decoder_t * decoder = &mpeg2dec->decoder; - - mpeg2dec->info.user_data = NULL; - mpeg2dec->info.user_data_len = 0; - mpeg2dec->state = (mpeg2dec->picture->nb_fields > 1 || - mpeg2dec->state == STATE_PICTURE_2ND) ? - STATE_SLICE : STATE_SLICE_1ST; - - if (mpeg2dec->decoder.coding_type != D_TYPE) - { - prescale (mpeg2dec, 0); - - if (decoder->chroma_quantizer[0] == decoder->quantizer_prescale[2]) - prescale (mpeg2dec, 2); - - if (mpeg2dec->decoder.coding_type != I_TYPE) - { - prescale (mpeg2dec, 1); - - if (decoder->chroma_quantizer[1] == decoder->quantizer_prescale[3]) - prescale (mpeg2dec, 3); - } - } - - if (!(mpeg2dec->nb_decode_slices)) - { - mpeg2dec->picture->flags |= PIC_FLAG_SKIP; - } - else if (mpeg2dec->convert_start) - { - mpeg2dec->convert_start (decoder->convert_id, mpeg2dec->fbuf[0], - mpeg2dec->picture, mpeg2dec->info.gop); - - if (mpeg2dec->decoder.coding_type == B_TYPE) - { - mpeg2_init_fbuf (&mpeg2dec->decoder, mpeg2dec->yuv_buf[2], - mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1], - mpeg2dec->yuv_buf[mpeg2dec->yuv_index]); - } - else - { - mpeg2_init_fbuf (&mpeg2dec->decoder, - mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1], - mpeg2dec->yuv_buf[mpeg2dec->yuv_index], - mpeg2dec->yuv_buf[mpeg2dec->yuv_index]); - - if (mpeg2dec->state == STATE_SLICE) - mpeg2dec->yuv_index ^= 1; - } - } - else - { - int b_type; - - b_type = (mpeg2dec->decoder.coding_type == B_TYPE); - - mpeg2_init_fbuf (&mpeg2dec->decoder, mpeg2dec->fbuf[0]->buf, - mpeg2dec->fbuf[b_type + 1]->buf, - mpeg2dec->fbuf[b_type]->buf); - } - - mpeg2dec->action = NULL; - - return STATE_INTERNAL_NORETURN; -} - -static mpeg2_state_t seek_sequence (mpeg2dec_t * mpeg2dec) -{ - mpeg2_reset_info (&mpeg2dec->info); - - mpeg2dec->info.sequence = NULL; - mpeg2dec->info.gop = NULL; - - mpeg2_header_state_init (mpeg2dec); - - mpeg2dec->action = mpeg2_seek_header; - - return mpeg2_seek_header (mpeg2dec); -} - -mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec) -{ - mpeg2_picture_t * picture; - int b_type; - - b_type = (mpeg2dec->decoder.coding_type == B_TYPE); - picture = mpeg2dec->pictures; - - if ((mpeg2dec->picture >= picture + 2) ^ b_type) - picture = mpeg2dec->pictures + 2; - - mpeg2_reset_info (&mpeg2dec->info); - - if (!(mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY)) - { - mpeg2dec->info.display_picture = picture; - - if (picture->nb_fields == 1) - mpeg2dec->info.display_picture_2nd = picture + 1; - - mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[b_type]; - - if (!mpeg2dec->convert) - mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type + 1]; - } - else if (!mpeg2dec->convert) - { - mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type]; - } - - mpeg2dec->action = seek_sequence; - - return STATE_END; -} diff --git a/apps/plugins/mpegplayer/libmpeg2/idct.c b/apps/plugins/mpegplayer/libmpeg2/idct.c deleted file mode 100644 index 7f0b9a3c12..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/idct.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * idct.c - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.36 - */ - -#include "plugin.h" - -#include "mpeg2dec_config.h" - -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" - -#if defined(CPU_COLDFIRE) || defined (CPU_ARM) -#define IDCT_ASM -#endif - -#ifndef IDCT_ASM - -#define W1 2841 /* 2048 * sqrt (2) * cos (1 * pi / 16) */ -#define W2 2676 /* 2048 * sqrt (2) * cos (2 * pi / 16) */ -#define W3 2408 /* 2048 * sqrt (2) * cos (3 * pi / 16) */ -#define W5 1609 /* 2048 * sqrt (2) * cos (5 * pi / 16) */ -#define W6 1108 /* 2048 * sqrt (2) * cos (6 * pi / 16) */ -#define W7 565 /* 2048 * sqrt (2) * cos (7 * pi / 16) */ - -/* - * In legal streams, the IDCT output should be between -384 and +384. - * In corrupted streams, it is possible to force the IDCT output to go - * to +-3826 - this is the worst case for a column IDCT where the - * column inputs are 16-bit values. - */ -#define CLIP(i) \ - ({ typeof (i) _i = (i); \ - if ((_i & 0xff) != _i) \ - _i = ~(_i >> (8*sizeof(_i) - 1)); \ - _i; }) - -#if 0 -#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ - do { \ - t0 = W0 * d0 + W1 * d1; \ - t1 = W0 * d1 - W1 * d0; \ - } while (0) -#else -#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ - do { \ - int tmp = W0 * (d0 + d1); \ - t0 = tmp + (W1 - W0) * d1; \ - t1 = tmp - (W1 + W0) * d0; \ - } while (0) -#endif - -static inline void idct_row (int16_t * const block) -{ - int d0, d1, d2, d3; - int a0, a1, a2, a3, b0, b1, b2, b3; - int t0, t1, t2, t3; - - /* shortcut */ - if (likely (!(block[1] | ((int32_t *)block)[1] | ((int32_t *)block)[2] | - ((int32_t *)block)[3]))) - { - uint32_t tmp = (uint16_t) (block[0] >> 1); - tmp |= tmp << 16; - ((int32_t *)block)[0] = tmp; - ((int32_t *)block)[1] = tmp; - ((int32_t *)block)[2] = tmp; - ((int32_t *)block)[3] = tmp; - return; - } - - d0 = (block[0] << 11) + 2048; - d1 = block[1]; - d2 = block[2] << 11; - d3 = block[3]; - t0 = d0 + d2; - t1 = d0 - d2; - BUTTERFLY (t2, t3, W6, W2, d3, d1); - a0 = t0 + t2; - a1 = t1 + t3; - a2 = t1 - t3; - a3 = t0 - t2; - - d0 = block[4]; - d1 = block[5]; - d2 = block[6]; - d3 = block[7]; - BUTTERFLY (t0, t1, W7, W1, d3, d0); - BUTTERFLY (t2, t3, W3, W5, d1, d2); - b0 = t0 + t2; - b3 = t1 + t3; - t0 -= t2; - t1 -= t3; - b1 = ((t0 + t1) >> 8) * 181; - b2 = ((t0 - t1) >> 8) * 181; - - block[0] = (a0 + b0) >> 12; - block[1] = (a1 + b1) >> 12; - block[2] = (a2 + b2) >> 12; - block[3] = (a3 + b3) >> 12; - block[4] = (a3 - b3) >> 12; - block[5] = (a2 - b2) >> 12; - block[6] = (a1 - b1) >> 12; - block[7] = (a0 - b0) >> 12; -} - -static inline void idct_col (int16_t * const block) -{ - int d0, d1, d2, d3; - int a0, a1, a2, a3, b0, b1, b2, b3; - int t0, t1, t2, t3; - - d0 = (block[8*0] << 11) + 65536; - d1 = block[8*1]; - d2 = block[8*2] << 11; - d3 = block[8*3]; - t0 = d0 + d2; - t1 = d0 - d2; - BUTTERFLY (t2, t3, W6, W2, d3, d1); - a0 = t0 + t2; - a1 = t1 + t3; - a2 = t1 - t3; - a3 = t0 - t2; - - d0 = block[8*4]; - d1 = block[8*5]; - d2 = block[8*6]; - d3 = block[8*7]; - BUTTERFLY (t0, t1, W7, W1, d3, d0); - BUTTERFLY (t2, t3, W3, W5, d1, d2); - b0 = t0 + t2; - b3 = t1 + t3; - t0 -= t2; - t1 -= t3; - b1 = ((t0 + t1) >> 8) * 181; - b2 = ((t0 - t1) >> 8) * 181; - - block[8*0] = (a0 + b0) >> 17; - block[8*1] = (a1 + b1) >> 17; - block[8*2] = (a2 + b2) >> 17; - block[8*3] = (a3 + b3) >> 17; - block[8*4] = (a3 - b3) >> 17; - block[8*5] = (a2 - b2) >> 17; - block[8*6] = (a1 - b1) >> 17; - block[8*7] = (a0 - b0) >> 17; -} - -void mpeg2_idct_copy (int16_t * block, uint8_t * dest, - const int stride) -{ - int i; - - for (i = 0; i < 8; i++) - idct_row (block + 8 * i); - - for (i = 0; i < 8; i++) - idct_col (block + i); - - do - { - dest[0] = CLIP (block[0]); - dest[1] = CLIP (block[1]); - dest[2] = CLIP (block[2]); - dest[3] = CLIP (block[3]); - dest[4] = CLIP (block[4]); - dest[5] = CLIP (block[5]); - dest[6] = CLIP (block[6]); - dest[7] = CLIP (block[7]); - - ((int32_t *)block)[0] = 0; - ((int32_t *)block)[1] = 0; - ((int32_t *)block)[2] = 0; - ((int32_t *)block)[3] = 0; - - dest += stride; - block += 8; - } - while (--i); -} - -void mpeg2_idct_add (const int last, int16_t * block, - uint8_t * dest, const int stride) -{ - int i; - - if (last != 129 || (block[0] & (7 << 4)) == (4 << 4)) - { - for (i = 0; i < 8; i++) - idct_row (block + 8 * i); - - for (i = 0; i < 8; i++) - idct_col (block + i); - - do - { - dest[0] = CLIP (block[0] + dest[0]); - dest[1] = CLIP (block[1] + dest[1]); - dest[2] = CLIP (block[2] + dest[2]); - dest[3] = CLIP (block[3] + dest[3]); - dest[4] = CLIP (block[4] + dest[4]); - dest[5] = CLIP (block[5] + dest[5]); - dest[6] = CLIP (block[6] + dest[6]); - dest[7] = CLIP (block[7] + dest[7]); - - ((int32_t *)block)[0] = 0; - ((int32_t *)block)[1] = 0; - ((int32_t *)block)[2] = 0; - ((int32_t *)block)[3] = 0; - - dest += stride; - block += 8; - } - while (--i); - } - else - { - int DC = (block[0] + 64) >> 7; - block[0] = block[63] = 0; - i = 8; - - do - { - dest[0] = CLIP (DC + dest[0]); - dest[1] = CLIP (DC + dest[1]); - dest[2] = CLIP (DC + dest[2]); - dest[3] = CLIP (DC + dest[3]); - dest[4] = CLIP (DC + dest[4]); - dest[5] = CLIP (DC + dest[5]); - dest[6] = CLIP (DC + dest[6]); - dest[7] = CLIP (DC + dest[7]); - dest += stride; - } - while (--i); - } -} - -#endif /* IDCT_ASM */ - -void mpeg2_idct_init (void) -{ - int i, j; - - for (i = 0; i < 64; i++) - { - j = default_mpeg2_scan_norm[i]; - mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); - - j = default_mpeg2_scan_alt[i]; - mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); - } -} diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_arm.S b/apps/plugins/mpegplayer/libmpeg2/idct_arm.S deleted file mode 100644 index 97a87a8b59..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/idct_arm.S +++ /dev/null @@ -1,443 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" - - .global mpeg2_idct_copy - .type mpeg2_idct_copy, %function - .global mpeg2_idct_add - .type mpeg2_idct_add, %function - - -/* Custom calling convention: - * r0 contains block pointer and is non-volatile - * all non-volatile c context saved and restored on its behalf - */ -.idct: - add r12, r0, #128 -1: - ldrsh r1, [r0, #0] /* d0 */ - ldrsh r2, [r0, #2] /* d1 */ - ldrsh r3, [r0, #4] /* d2 */ - ldrsh r4, [r0, #6] /* d3 */ - ldrsh r5, [r0, #8] /* d0 */ - ldrsh r6, [r0, #10] /* d1 */ - ldrsh r7, [r0, #12] /* d2 */ - ldrsh r8, [r0, #14] /* d3 */ - orrs r9, r2, r3 - orreqs r9, r4, r5 - orreqs r9, r6, r7 - cmpeq r8, #0 - bne 2f - mov r1, r1, asl #15 - bic r1, r1, #0x8000 - orr r1, r1, r1, lsr #16 - str r1, [r0], #4 - str r1, [r0], #4 - str r1, [r0], #4 - str r1, [r0], #4 - cmp r0, r12 - blo 1b - b 3f -2: - mov r1, r1, asl #11 /* r1 = d0 = (block[0] << 11) + 2048 */ - add r1, r1, #2048 - add r1, r1, r3, asl #11 /* r1 = t0 = d0 + (block[2] << 11) */ - sub r3, r1, r3, asl #12 /* r3 = t1 = d0 - (block[2] << 11) */ - - add r9, r2, r4 /* r9 = tmp = (d1+d3)*(1108/4) */ - add r10, r9, r9, asl #2 - add r10, r10, r9, asl #4 - add r9, r10, r9, asl #8 - - add r10, r2, r2, asl #4 /* r2 = t2 = tmp + (d1*(1568/32)*8) */ - add r2, r10, r2, asl #5 - add r2, r9, r2, asl #3 - - add r10, r4, r4, asl #2 /* r4 = t3 = tmp - (d3*(3784/8)*2) */ - rsb r10, r10, r4, asl #6 - add r4, r4, r10, asl #3 - sub r4, r9, r4, asl #1 - /* t2 & t3 are 1/4 final value here */ - add r1, r1, r2, asl #2 /* r1 = a0 = t0 + t2 */ - sub r2, r1, r2, asl #3 /* r2 = a3 = t0 - t2 */ - add r3, r3, r4, asl #2 /* r3 = a1 = t1 + t3 */ - sub r4, r3, r4, asl #3 /* r4 = a2 = t1 - t3 */ - - add r9, r8, r5 /* r9 = tmp = 565*(d3 + d0) */ - add r10, r9, r9, asl #4 - add r10, r10, r10, asl #5 - add r9, r10, r9, asl #2 - - add r10, r5, r5, asl #4 /* r5 = t0 = tmp + (((2276/4)*d0)*4) */ - add r10, r10, r10, asl #5 - add r5, r10, r5, asl #3 - add r5, r9, r5, asl #2 - - add r10, r8, r8, asl #2 /* r8 = t1 = tmp - (((3406/2)*d3)*2) */ - add r10, r10, r10, asl #4 - add r10, r10, r8, asl #7 - rsb r8, r8, r10, asl #3 - sub r8, r9, r8, asl #1 - - add r9, r6, r7 /* r9 = tmp = (2408/8)*(d1 + d2) */ - add r10, r9, r9, asl #3 - add r10, r10, r10, asl #5 - add r9, r10, r9, asl #2 - - add r10, r7, r7, asl #3 /* r7 = t2 = (tmp*8) - 799*d2 */ - add r10, r10, r7, asl #4 - rsb r7, r7, r10, asl #5 - rsb r7, r7, r9, asl #3 - - sub r10, r6, r6, asl #4 /* r6 = t3 = (tmp*8) - 4017*d1 */ - sub r10, r10, r6, asl #6 - add r10, r10, r6, asl #12 - add r6, r10, r6 - rsb r6, r6, r9, asl #3 - /* t0 = r5, t1 = r8, t2 = r7, t3 = r6*/ - add r9, r5, r7 /* r9 = b0 = t0 + t2 */ - add r10, r8, r6 /* r10 = b3 = t1 + t3 */ - sub r5, r5, r7 /* t0 -= t2 */ - sub r8, r8, r6 /* t1 -= t3 */ - add r6, r5, r8 /* r6 = t0 + t1 */ - sub r7, r5, r8 /* r7 = t0 - t1 */ - - add r11, r6, r6, asr #2 /* r6 = b1 = r6*(181/128) */ - add r11, r11, r11, asr #5 - add r6, r11, r6, asr #3 - add r11, r7, r7, asr #2 /* r7 = b2 = r7*(181/128) */ - add r11, r11, r11, asr #5 - add r7, r11, r7, asr #3 - /* r1 = a0, r3 = a1, r4 = a2, r2 = a3 */ - /* r9 = b0, r6 = b1*2, r7 = b2*2, r10 = b3 */ - add r5, r1, r9 /* block[0] = (a0 + b0) >> 12 */ - mov r5, r5, asr #12 - strh r5, [r0], #2 - add r8, r3, r6, asr #1 /* block[1] = (a1 + b1) >> 12 */ - mov r8, r8, asr #12 - strh r8, [r0], #2 - add r5, r4, r7, asr #1 /* block[2] = (a2 + b2) >> 12 */ - mov r5, r5, asr #12 - strh r5, [r0], #2 - add r8, r2, r10 /* block[3] = (a3 + b3) >> 12 */ - mov r8, r8, asr #12 - strh r8, [r0], #2 - sub r5, r2, r10 /* block[4] = (a3 - b3) >> 12 */ - mov r5, r5, asr #12 - strh r5, [r0], #2 - sub r8, r4, r7, asr #1 /* block[5] = (a2 - b2) >> 12 */ - mov r8, r8, asr #12 - strh r8, [r0], #2 - sub r5, r3, r6, asr #1 /* block[6] = (a1 - b1) >> 12 */ - mov r5, r5, asr #12 - strh r5, [r0], #2 - sub r8, r1, r9 /* block[7] = (a0 - b0) >> 12 */ - mov r8, r8, asr #12 - strh r8, [r0], #2 - cmp r0, r12 - blo 1b -3: - sub r0, r0, #128 - add r12, r0, #16 -4: - ldrsh r1, [r0, #0*8] /* d0 */ - ldrsh r2, [r0, #2*8] /* d1 */ - ldrsh r3, [r0, #4*8] /* d2 */ - ldrsh r4, [r0, #6*8] /* d3 */ - ldrsh r5, [r0, #8*8] /* d0 */ - ldrsh r6, [r0, #10*8] /* d1 */ - ldrsh r7, [r0, #12*8] /* d2 */ - ldrsh r8, [r0, #14*8] /* d3 */ - - mov r1, r1, asl #11 /* r1 = d0 = (block[0] << 11) + 2048 */ - add r1, r1, #65536 - add r1, r1, r3, asl #11 /* r1 = t0 = d0 + d2:(block[2] << 11) */ - sub r3, r1, r3, asl #12 /* r3 = t1 = d0 - d2:(block[2] << 11) */ - - add r9, r2, r4 /* r9 = tmp = (d1+d3)*(1108/4) */ - add r10, r9, r9, asl #2 - add r10, r10, r9, asl #4 - add r9, r10, r9, asl #8 - - add r11, r2, r2, asl #4 /* r2 = t2 = tmp + (d1*(1568/32)*8) */ - add r2, r11, r2, asl #5 - add r2, r9, r2, asl #3 - - add r10, r4, r4, asl #2 /* r4 = t3 = tmp - (d3*(3784/8)*2) */ - rsb r10, r10, r4, asl #6 - add r4, r4, r10, asl #3 - sub r4, r9, r4, asl #1 - /* t2 & t3 are 1/4 final value here */ - add r1, r1, r2, asl #2 /* r1 = a0 = t0 + t2 */ - sub r2, r1, r2, asl #3 /* r2 = a3 = t0 - t2 */ - add r3, r3, r4, asl #2 /* r3 = a1 = t1 + t3 */ - sub r4, r3, r4, asl #3 /* r4 = a2 = t1 - t3 */ - - add r9, r8, r5 /* r9 = tmp = 565*(d3 + d0) */ - add r10, r9, r9, asl #4 - add r10, r10, r10, asl #5 - add r9, r10, r9, asl #2 - - add r10, r5, r5, asl #4 /* r5 = t0 = tmp + (((2276/4)*d0)*4) */ - add r10, r10, r10, asl #5 - add r5, r10, r5, asl #3 - add r5, r9, r5, asl #2 - - add r10, r8, r8, asl #2 /* r8 = t1 = tmp - (((3406/2)*d3)*2) */ - add r10, r10, r10, asl #4 - add r10, r10, r8, asl #7 - rsb r8, r8, r10, asl #3 - sub r8, r9, r8, asl #1 - - add r9, r6, r7 /* r9 = tmp = (2408/8)*(d1 + d2) */ - add r10, r9, r9, asl #3 - add r10, r10, r10, asl #5 - add r9, r10, r9, asl #2 - - add r10, r7, r7, asl #3 /* r7 = t2 = (tmp*8) - 799*d2 */ - add r10, r10, r7, asl #4 - rsb r7, r7, r10, asl #5 - rsb r7, r7, r9, asl #3 - - sub r10, r6, r6, asl #4 /* r6 = t3 = (tmp*8) - 4017*d1 */ - sub r10, r10, r6, asl #6 - add r10, r10, r6, asl #12 - add r6, r10, r6 - rsb r6, r6, r9, asl #3 - /* t0=r5, t1=r8, t2=r7, t3=r6*/ - add r9, r5, r7 /* r9 = b0 = t0 + t2 */ - add r10, r8, r6 /* r10 = b3 = t1 + t3 */ - sub r5, r5, r7 /* t0 -= t2 */ - sub r8, r8, r6 /* t1 -= t3 */ - add r6, r5, r8 /* r6 = t0 + t1 */ - sub r7, r5, r8 /* r7 = t0 - t1 */ - - add r11, r6, r6, asr #2 /* r6 = b1 = r5*(181/128) */ - add r11, r11, r11, asr #5 - add r6, r11, r6, asr #3 - add r11, r7, r7, asr #2 /* r7 = b2 = r6*(181/128) */ - add r11, r11, r11, asr #5 - add r7, r11, r7, asr #3 - /* r1 = a0, r3 = a1, r4 = a2, r2 = a3 */ - /* r9 = b0, r6 = b1*2, r7 = b2*2, r10 = b3 */ - add r5, r1, r9 /* block[0] = (a0 + b0) >> 17 */ - mov r5, r5, asr #17 - strh r5, [r0, #0*8] - add r8, r3, r6, asr #1 /* block[1] = (a1 + b1) >> 17 */ - mov r8, r8, asr #17 - strh r8, [r0, #2*8] - add r5, r4, r7, asr #1 /* block[2] = (a2 + b2) >> 17 */ - mov r5, r5, asr #17 - strh r5, [r0, #4*8] - add r8, r2, r10 /* block[3] = (a3 + b3) >> 17 */ - mov r8, r8, asr #17 - strh r8, [r0, #6*8] - sub r5, r2, r10 /* block[4] = (a3 - b3) >> 17 */ - mov r5, r5, asr #17 - strh r5, [r0, #8*8] - sub r8, r4, r7, asr #1 /* block[5] = (a2 - b2) >> 17 */ - mov r8, r8, asr #17 - strh r8, [r0, #10*8] - sub r5, r3, r6, asr #1 /* block[6] = (a1 - b1) >> 17 */ - mov r5, r5, asr #17 - strh r5, [r0, #12*8] - sub r8, r1, r9 /* block[7] = (a0 - b0) >> 17 */ - mov r8, r8, asr #17 - strh r8, [r0, #14*8] - add r0, r0, #2 - cmp r0, r12 - blo 4b - sub r0, r0, #16 - bx lr - -mpeg2_idct_copy: - stmfd sp!, { r1-r2, r4-r11, lr } - bl .idct - ldmfd sp!, { r1-r2 } - mov r11, #0 - add r12, r0, #128 -1: - ldrsh r3, [r0, #0] - ldrsh r4, [r0, #2] - ldrsh r5, [r0, #4] - ldrsh r6, [r0, #6] - ldrsh r7, [r0, #8] - ldrsh r8, [r0, #10] - ldrsh r9, [r0, #12] - ldrsh r10, [r0, #14] - cmp r3, #255 - mvnhi r3, r3, asr #31 - strb r3, [r1, #0] - str r11, [r0], #4 - cmp r4, #255 - mvnhi r4, r4, asr #31 - strb r4, [r1, #1] - cmp r5, #255 - mvnhi r5, r5, asr #31 - strb r5, [r1, #2] - str r11, [r0], #4 - cmp r6, #255 - mvnhi r6, r6, asr #31 - strb r6, [r1, #3] - cmp r7, #255 - mvnhi r7, r7, asr #31 - strb r7, [r1, #4] - str r11, [r0], #4 - cmp r8, #255 - mvnhi r8, r8, asr #31 - strb r8, [r1, #5] - cmp r9, #255 - mvnhi r9, r9, asr #31 - strb r9, [r1, #6] - str r11, [r0], #4 - cmp r10, #255 - mvnhi r10, r10, asr #31 - strb r10, [r1, #7] - add r1, r1, r2 - cmp r0, r12 - blo 1b - ldmpc regs=r4-r11 - -mpeg2_idct_add: - cmp r0, #129 - mov r0, r1 - ldreqsh r1, [r0, #0] - bne 1f - and r1, r1, #0x70 - cmp r1, #0x40 - bne 3f -1: - stmfd sp!, { r2-r11, lr } - bl .idct - ldmfd sp!, { r1-r2 } - mov r11, #0 - add r12, r0, #128 -2: - ldrb r3, [r1, #0] - ldrb r4, [r1, #1] - ldrb r5, [r1, #2] - ldrb r6, [r1, #3] - ldrsh r7, [r0, #0] - ldrsh r8, [r0, #2] - ldrsh r9, [r0, #4] - ldrsh r10, [r0, #6] - add r7, r7, r3 - ldrb r3, [r1, #4] - cmp r7, #255 - mvnhi r7, r7, asr #31 - strb r7, [r1, #0] - ldrsh r7, [r0, #8] - add r8, r8, r4 - ldrb r4, [r1, #5] - cmp r8, #255 - mvnhi r8, r8, asr #31 - strb r8, [r1, #1] - ldrsh r8, [r0, #10] - add r9, r9, r5 - ldrb r5, [r1, #6] - cmp r9, #255 - mvnhi r9, r9, asr #31 - strb r9, [r1, #2] - ldrsh r9, [r0, #12] - add r10, r10, r6 - ldrb r6, [r1, #7] - cmp r10, #255 - mvnhi r10, r10, asr #31 - strb r10, [r1, #3] - ldrsh r10, [r0, #14] - str r11, [r0], #4 - add r7, r7, r3 - cmp r7, #255 - mvnhi r7, r7, asr #31 - strb r7, [r1, #4] - str r11, [r0], #4 - add r8, r8, r4 - cmp r8, #255 - mvnhi r8, r8, asr #31 - strb r8, [r1, #5] - str r11, [r0], #4 - add r9, r9, r5 - cmp r9, #255 - mvnhi r9, r9, asr #31 - strb r9, [r1, #6] - add r10, r10, r6 - cmp r10, #255 - mvnhi r10, r10, asr #31 - strb r10, [r1, #7] - str r11, [r0], #4 - add r1, r1, r2 - cmp r0, r12 - blo 2b - ldmpc regs=r4-r11 -3: - stmfd sp!, { r4-r5, lr } - ldrsh r1, [r0, #0] /* r1 = block[0] */ - mov r4, #0 - strh r4, [r0, #0] /* block[0] = 0 */ - strh r4, [r0, #126] /* block[63] = 0 */ - add r1, r1, #64 /* r1 = DC << 7 */ - add r0, r2, r3, asl #3 -4: - ldrb r4, [r2, #0] - ldrb r5, [r2, #1] - ldrb r12, [r2, #2] - ldrb lr, [r2, #3] - add r4, r4, r1, asr #7 - cmp r4, #255 - mvnhi r4, r4, asr #31 - strb r4, [r2, #0] - add r5, r5, r1, asr #7 - cmp r5, #255 - mvnhi r5, r5, asr #31 - strb r5, [r2, #1] - add r12, r12, r1, asr #7 - cmp r12, #255 - mvnhi r12, r12, asr #31 - strb r12, [r2, #2] - add lr, lr, r1, asr #7 - cmp lr, #255 - mvnhi lr, lr, asr #31 - strb lr, [r2, #3] - ldrb r4, [r2, #4] - ldrb r5, [r2, #5] - ldrb r12, [r2, #6] - ldrb lr, [r2, #7] - add r4, r4, r1, asr #7 - cmp r4, #255 - mvnhi r4, r4, asr #31 - strb r4, [r2, #4] - add r5, r5, r1, asr #7 - cmp r5, #255 - mvnhi r5, r5, asr #31 - strb r5, [r2, #5] - add r12, r12, r1, asr #7 - cmp r12, #255 - mvnhi r12, r12, asr #31 - strb r12, [r2, #6] - add lr, lr, r1, asr #7 - cmp lr, #255 - mvnhi lr, lr, asr #31 - strb lr, [r2, #7] - add r2, r2, r3 - cmp r2, r0 - blo 4b - ldmpc regs=r4-r5 diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S b/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S deleted file mode 100644 index dc53cbd7bd..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S +++ /dev/null @@ -1,297 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Jens Arnold - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - - - .global mpeg2_idct_copy - .type mpeg2_idct_copy, %function - .global mpeg2_idct_add - .type mpeg2_idct_add, %function - -/* Custom calling convention: - * r0 contains block pointer and is non-volatile - * all non-volatile c context saved and restored on its behalf - */ -.idct: - str lr, [sp, #-4]! @ lr is used - add r1, r0, #128 @ secondary, transposed temp buffer - mov r14, #8 @ loop counter - -.row_loop: - ldmia r0!, {r2, r3, r10, r11} @ fetch f0, f2, f4, f6, f1, f3, f5, f7 - ldrd r4, L_W1357 @ load W1, W3, W5, W7 - - smuad r6, r4, r10 @ b0 = W1 * f1 + W3 * f3 - smultt r7, r5, r10 @ -b1 = W7 * f3 - smulbt r8, r4, r10 @ -b2 = W1 * f3 - - smusdx r9, r10, r5 @ b3 = f1 * W7 - f3 * W5 - smlabb r7, r4, r11, r7 @ -b1 += W1 * f5 - rsb r8, r8, #0 @ b2 = -b2 - smlabb r8, r5, r10, r8 @ b2 += W5 * f1 - - smlad r6, r5, r11, r6 @ b0 += W5 * f5 + W7 * f7 - smlabt r7, r5, r11, r7 @ -b1 += W5 * f7 - smlatb r8, r5, r11, r8 @ b2 += W7 * f5 - - smlsdx r9, r11, r4, r9 @ b3 += f5 * W3 - f7 * W1 - rsb r7, r7, #0 @ b1 = -b1 - smlatb r7, r4, r10, r7 @ b1 += W3 * f1 - smlatt r8, r4, r11, r8 @ b2 += W3 * f7 - - ldrd r4, L_W0246 @ load W0, W2, W4, W6 - add r2, r2, #1 @ f0 += 1 - - smulbb r10, r5, r3 @ a0' = W4 * f4 - smultt r12, r5, r3 @ a3' = W6 * f6 - smultt r3, r4, r3 @ -a2' = W2 * f6 - - rsb r11, r10, #0 @ a1' = -W4 * f4 - smlabb r10, r4, r2, r10 @ a0' += W0 * f0 - smlabb r11, r4, r2, r11 @ a1' += W0 * f0 - smlatt r12, r4, r2, r12 @ a3' += W2 * f2 - rsb r3, r3, #0 @ a2' = -a2' - smlatt r3, r5, r2, r3 @ a2' += W6 * f2 - - add r10, r10, r12 @ a0 = a0' + a3' - sub r12, r10, r12, lsl #1 @ a3 = a0 - 2 * a3' - add r11, r11, r3 @ a1 = a1' + a2' - sub r3, r11, r3, lsl #1 @ a2 = a1 - 2 * a2' - - subs r14, r14, #1 @ decrease loop count - - @ Special store order for making the column pass calculate columns in - @ the order 0-2-1-3-4-6-5-7, allowing for uxtab16 use in later stages. - sub r2, r10, r6 @ block[7] = (a0 - b0) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1, #7*16] - sub r2, r11, r7 @ block[6] = (a1 - b1) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1, #5*16] - sub r2, r3, r8 @ block[5] = (a2 - b2) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1, #6*16] - sub r2, r12, r9 @ block[4] = (a3 - b3) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1, #4*16] - add r2, r12, r9 @ block[3] = (a3 + b3) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1, #3*16] - add r2, r3, r8 @ block[2] = (a2 + b2) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1, #1*16] - add r2, r11, r7 @ block[1] = (a1 + b1) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1, #2*16] - add r2, r10, r6 @ block[0] = (a0 + b0) - mov r2, r2, asr #12 @ >> 12 - strh r2, [r1], #2 @ advance to next temp column - - bne .row_loop - b .col_start - - @placed here because of ldrd's offset limit -L_W1357: - .short 2841 - .short 2408 - .short 1609 - .short 565 - -L_W0246: - .short 2048 - .short 2676 - .short 2048 - .short 1108 - -.col_start: - @ r0 now points to the temp buffer, where we need it. - sub r1, r1, #128+16 @ point r1 back to the input block - mov r14, #8 @ loop counter - -.col_loop: - ldmia r0!, {r2, r3, r10, r11} @ fetch f0, f2, f4, f6, f1, f3, f5, f7 - ldrd r4, L_W1357 @ load W1, W3, W5, W7 - - smuad r6, r4, r10 @ b0 = W1 * f1 + W3 * f3 - smultt r7, r5, r10 @ -b1 = W7 * f3 - smulbt r8, r4, r10 @ -b2 = W1 * f3 - - smusdx r9, r10, r5 @ b3 = f1 * W7 - f3 * W5 - smlabb r7, r4, r11, r7 @ -b1 += W1 * f5 - rsb r8, r8, #0 @ b2 = -b2 - smlabb r8, r5, r10, r8 @ b2 += W5 * f1 - - smlad r6, r5, r11, r6 @ b0 += W5 * f5 + W7 * f7 - smlabt r7, r5, r11, r7 @ -b1 += W5 * f7 - smlatb r8, r5, r11, r8 @ b2 += W7 * f5 - - smlsdx r9, r11, r4, r9 @ b3 += f5 * W3 - f7 * W1 - rsb r7, r7, #0 @ b1 = -b1 - smlatb r7, r4, r10, r7 @ b1 += W3 * f1 - smlatt r8, r4, r11, r8 @ b2 += W3 * f7 - - ldrd r4, L_W0246 @ load W0, W2, W4, W6 - add r2, r2, #32 @ DC offset: 0.5 - - smulbb r10, r5, r3 @ a0' = W4 * f4 - smultt r12, r5, r3 @ a3' = W6 * f6 - smultt r3, r4, r3 @ -a2' = W2 * f6 - - rsb r11, r10, #0 @ a1' = -W4 * f4 - smlabb r10, r4, r2, r10 @ a0' += W0 * f0 - smlabb r11, r4, r2, r11 @ a1' += W0 * f0 - smlatt r12, r4, r2, r12 @ a3' += W2 * f2 - rsb r3, r3, #0 @ a2' = -a2' - smlatt r3, r5, r2, r3 @ a2' += W6 * f2 - - add r10, r10, r12 @ a0 = a0' + a3' - sub r12, r10, r12, lsl #1 @ a3 = a0 - 2 * a3' - add r11, r11, r3 @ a1 = a1' + a2' - sub r3, r11, r3, lsl #1 @ a2 = a1 - 2 * a2' - - subs r14, r14, #1 @ decrease loop count - - sub r2, r10, r6 @ block[7] = (a0 - b0) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1, #7*16] - sub r2, r11, r7 @ block[6] = (a1 - b1) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1, #6*16] - sub r2, r3, r8 @ block[5] = (a2 - b2) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1, #5*16] - sub r2, r12, r9 @ block[4] = (a3 - b3) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1, #4*16] - add r2, r12, r9 @ block[3] = (a3 + b3) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1, #3*16] - add r2, r3, r8 @ block[2] = (a2 + b2) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1, #2*16] - add r2, r11, r7 @ block[1] = (a1 + b1) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1, #1*16] - add r2, r10, r6 @ block[0] = (a0 + b0) - mov r2, r2, asr #17 @ >> 17 - strh r2, [r1], #2 @ advance to next column - - bne .col_loop - - sub r0, r0, #256 @ point r0 back to the input block - ldr pc, [sp], #4 - - -mpeg2_idct_copy: - stmfd sp!, {r1-r2, r4-r11, lr} - bl .idct - ldmfd sp!, {r1-r2} - - add r3, r0, #128 - mov r8, #0 - mov r9, #0 - mov r10, #0 - mov r11, #0 -1: @ idct data is in order 0-2-1-3-4-6-5-7, - ldmia r0, {r4-r7} @ see above - stmia r0!, {r8-r11} - usat16 r4, #8, r4 - usat16 r5, #8, r5 - orr r4, r4, r5, lsl #8 - usat16 r6, #8, r6 - usat16 r7, #8, r7 - orr r5, r6, r7, lsl #8 - strd r4, [r1] @ r4, r5 - add r1, r1, r2 - cmp r0, r3 - blo 1b - - ldmfd sp!, {r4-r11, pc} - -mpeg2_idct_add: - cmp r0, #129 - mov r0, r1 - ldreqsh r1, [r0, #0] - bne 1f - and r1, r1, #0x70 - cmp r1, #0x40 - bne 3f -1: - stmfd sp!, {r2-r11, lr} - bl .idct - ldmfd sp!, {r1-r2} - - add r3, r0, #128 - mov r10, #0 - mov r11, #0 - mov r12, #0 - mov lr, #0 - ldrd r8, [r1] @ r8, r9 -2: @ idct data is in order 0-2-1-3-4-6-5-7, - ldmia r0, {r4-r7} @ see above - stmia r0!, {r10-r12, lr} - uxtab16 r4, r4, r8 - uxtab16 r5, r5, r8, ror #8 - usat16 r4, #8, r4 - usat16 r5, #8, r5 - orr r4, r4, r5, lsl #8 - uxtab16 r6, r6, r9 - uxtab16 r7, r7, r9, ror #8 - usat16 r6, #8, r6 - usat16 r7, #8, r7 - orr r5, r6, r7, lsl #8 - strd r4, [r1] @ r4, r5 - add r1, r1, r2 - cmp r0, r3 - ldrlod r8, [r1] @ r8, r9 - blo 2b - - ldmfd sp!, {r4-r11, pc} - -3: - stmfd sp!, {r4, lr} - ldrsh r4, [r0, #0] @ r4 = block[0] - mov r12, #0 - strh r12, [r0, #0] @ block[0] = 0 - strh r12, [r0, #126] @ block[63] = 0 - add r4, r4, #64 - mov r4, r4, asr #7 @ r4 = DC - mov r4, r4, lsl #16 @ spread to 2 halfwords - orr r4, r4, r4, lsr #16 - ldrd r0, [r2] @ r0, r1 - add r12, r2, r3, asl #3 -4: - uxtab16 lr, r4, r0, ror #8 - uxtab16 r0, r4, r0 - usat16 lr, #8, lr - usat16 r0, #8, r0 - orr r0, r0, lr, lsl #8 - uxtab16 lr, r4, r1, ror #8 - uxtab16 r1, r4, r1 - usat16 lr, #8, lr - usat16 r1, #8, r1 - orr r1, r1, lr, lsl #8 - strd r0, [r2] @ r0, r1 - add r2, r2, r3 - cmp r2, r12 - ldrlod r0, [r2] @ r0, r1 - blo 4b - - ldmfd sp!, {r4, pc} diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S b/apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S deleted file mode 100644 index abc54b16cb..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S +++ /dev/null @@ -1,575 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 Jens Arnold - * Based on the work of Karim Boucher and Rani Hod - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - - .global mpeg2_idct_copy - .type mpeg2_idct_copy, @function - .global mpeg2_idct_add - .type mpeg2_idct_add, @function - - /* The IDCT itself. - * Input: %a0: block pointer - * Caller must save all registers. */ - .align 2 -.idct: - move.l %a0, %a6 - - move.l #0, %macsr | signed integer mode - - move.l #((2048<<16)+2841), %a0 | W0, W1 - move.l #((2676<<16)+2408), %a1 | W2, W3 - move.l #((2048<<16)+1609), %a2 | W4, W5 - move.l #((1108<<16)+ 565), %a3 | W6, W7 - - lea.l (128,%a6), %a4 | secondary, transposed temp buffer - moveq.l #8, %d3 | loop counter - -.row_loop: - movem.l (%a6), %d0-%d2/%a5 | fetch (f0, f2, f4, f6, f1, f3, f5, f7) - - mac.w %a0l, %d2u, %acc0 | %acc0 = W1 * f1 - mac.w %a1l, %d2l, %acc0 | + W3 * f3 - mac.w %a2l, %a5u, %acc0 | + W5 * f5 - mac.w %a3l, %a5l, %acc0 | + W7 * f7 - - mac.w %a1l, %d2u, %acc1 | %acc1 = W3 * f1 - msac.w %a3l, %d2l, %acc1 | - W7 * f3 - msac.w %a0l, %a5u, %acc1 | - W1 * f5 - msac.w %a2l, %a5l, %acc1 | - W5 * f7 - - mac.w %a2l, %d2u, %acc2 | %acc2 = W5 * f1 - msac.w %a0l, %d2l, %acc2 | - W1 * f3 - mac.w %a3l, %a5u, %acc2 | + W7 * f5 - mac.w %a1l, %a5l, %acc2 | + W3 * f7 - - mac.w %a3l, %d2u, %acc3 | %acc3 = W7 * f1 - msac.w %a2l, %d2l, %acc3 | - W5 * f3 - mac.w %a1l, %a5u, %acc3 | + W3 * f5 - msac.w %a0l, %a5l, %acc3 | - W1 * f7 - - lea.l (16,%a6), %a6 | Advance to next row; put here to fill EMAC latency - add.l #(1<<16), %d0 | f0 += 1; - - movclr.l %acc0, %d4 | b0 - movclr.l %acc1, %d5 | b1 - movclr.l %acc2, %d6 | b2 - movclr.l %acc3, %d7 | b3 - - mac.w %a0u, %d0u, %acc0 | %acc0 = W0 * f0 - mac.w %a2u, %d1u, %acc0 | + W4 * f4 - move.l %acc0, %acc3 - mac.w %a1u, %d0l, %acc0 | + W2 * f2 - mac.w %a3u, %d1l, %acc0 | + W6 * f6 - - mac.w %a0u, %d0u, %acc1 | %acc1 = W0 * f0 - msac.w %a2u, %d1u, %acc1 | - W4 * f4 - move.l %acc1, %acc2 - mac.w %a3u, %d0l, %acc1 | + W6 * f2 - msac.w %a1u, %d1l, %acc1 | - W2 * f6 - - | ^ move.l %acc1, %acc2 %acc2 = W0 * f0 - W4 * f4 - msac.w %a3u, %d0l, %acc2 | - W6 * f2 - mac.w %a1u, %d1l, %acc2 | + W2 * f6 - - | ^ move.l %acc0, %acc3 %acc3 = W0 * f0 + W4 * f4 - msac.w %a1u, %d0l, %acc3 | - W2 * f2 - msac.w %a3u, %d1l, %acc3 | - W6 * f6 - - moveq.l #12, %d1 | shift amount - - move.l %acc0, %d0 | block[7] = (a0 - sub.l %d4,%d0 | - b0) - asr.l %d1, %d0 | >> 12 - move.w %d0, (7*16,%a4) - - move.l %acc1, %d0 | block[6] = (a1 - sub.l %d5,%d0 | - b1) - asr.l %d1, %d0 | >> 12 - move.w %d0, (6*16,%a4) - - move.l %acc2, %d0 | block[5] = (a2 - sub.l %d6,%d0 | - b2) - asr.l %d1, %d0 | >> 12 - move.w %d0, (5*16,%a4) - - move.l %acc3, %d0 | block[4] = (a3 - sub.l %d7,%d0 | - b3) - asr.l %d1, %d0 | >> 12 - move.w %d0, (4*16,%a4) - - movclr.l %acc3, %d0 | block[3] = (a3 - add.l %d7, %d0 | + b3) - asr.l %d1, %d0 | >> 12 - move.w %d0, (3*16,%a4) - - movclr.l %acc2, %d0 | block[2] = (a2 - add.l %d6, %d0 | + b2) - asr.l %d1, %d0 | >> 12 - move.w %d0, (2*16,%a4) - - movclr.l %acc1, %d0 | block[1] = (a1 - add.l %d5, %d0 | + b1) - asr.l %d1, %d0 | >> 12 - move.w %d0, (1*16,%a4) - - movclr.l %acc0, %d0 | block[0] = (a0 - add.l %d4, %d0 | + b0) - asr.l %d1, %d0 | >> 12 - move.w %d0, (%a4)+ | advance to next temp column - - subq.l #1, %d3 | loop 8 times - bne.w .row_loop - - | %a6 now points to the temp buffer, where we need it. - lea.l (-16-128,%a4), %a4 | point %a4 back to the input block - moveq.l #8, %d3 | loop counter - -.col_loop: - movem.l (%a6), %d0-%d2/%a5 | fetch (f0, f2, f4, f6, f1, f3, f5, f7) - - mac.w %a0l, %d2u, %acc0 | %acc0 = W1 * f1 - mac.w %a1l, %d2l, %acc0 | + W3 * f3 - mac.w %a2l, %a5u, %acc0 | + W5 * f5 - mac.w %a3l, %a5l, %acc0 | + W7 * f7 - - mac.w %a1l, %d2u, %acc1 | %acc1 = W3 * f1 - msac.w %a3l, %d2l, %acc1 | - W7 * f3 - msac.w %a0l, %a5u, %acc1 | - W1 * f5 - msac.w %a2l, %a5l, %acc1 | - W5 * f7 - - mac.w %a2l, %d2u, %acc2 | %acc2 = W5 * f1 - msac.w %a0l, %d2l, %acc2 | - W1 * f3 - mac.w %a3l, %a5u, %acc2 | + W7 * f5 - mac.w %a1l, %a5l, %acc2 | + W3 * f7 - - mac.w %a3l, %d2u, %acc3 | %acc3 = W7 * f1 - msac.w %a2l, %d2l, %acc3 | - W5 * f3 - mac.w %a1l, %a5u, %acc3 | + W3 * f5 - msac.w %a0l, %a5l, %acc3 | - W1 * f7 - - lea.l (16,%a6), %a6 | Advance to next row; put here to fill EMAC latency - add.l #(32<<16), %d0 | DC offset: 0.5 - - movclr.l %acc0, %d4 | b0 - movclr.l %acc1, %d5 | b1 - movclr.l %acc2, %d6 | b2 - movclr.l %acc3, %d7 | b3 - - mac.w %a0u, %d0u, %acc0 | %acc0 = W0 * f0 - mac.w %a2u, %d1u, %acc0 | + W4 * f4 - move.l %acc0, %acc3 - mac.w %a1u, %d0l, %acc0 | + W2 * f2 - mac.w %a3u, %d1l, %acc0 | + W6 * f6 - - mac.w %a0u, %d0u, %acc1 | %acc1 = W0 * f0 - msac.w %a2u, %d1u, %acc1 | - W4 * f4 - move.l %acc1, %acc2 - mac.w %a3u, %d0l, %acc1 | + W6 * f2 - msac.w %a1u, %d1l, %acc1 | - W2 * f6 - - | ^ move.l %acc1, %acc2 %acc2 = W0 * f0 - W4 * f4 - msac.w %a3u, %d0l, %acc2 | - W6 * f2 - mac.w %a1u, %d1l, %acc2 | + W2 * f6 - - | ^ move.l %acc0, %acc3 %acc3 = W0 * f0 + W4 * f4 - msac.w %a1u, %d0l, %acc3 | - W2 * f2 - msac.w %a3u, %d1l, %acc3 | - W6 * f6 - - moveq.l #17, %d1 | shift amount - - move.l %acc0, %d0 | block[7] = (a0 - sub.l %d4,%d0 | - b0) - asr.l %d1, %d0 | >> 17 - move.w %d0, (7*16,%a4) - - move.l %acc1, %d0 | block[6] = (a1 - sub.l %d5,%d0 | - b1) - asr.l %d1, %d0 | >> 17 - move.w %d0, (6*16,%a4) - - move.l %acc2, %d0 | block[5] = (a2 - sub.l %d6,%d0 | - b2) - asr.l %d1, %d0 | >> 17 - move.w %d0, (5*16,%a4) - - move.l %acc3, %d0 | block[4] = (a3 - sub.l %d7,%d0 | - b3) - asr.l %d1, %d0 | >> 17 - move.w %d0, (4*16,%a4) - - movclr.l %acc3, %d0 | block[3] = (a3 - add.l %d7, %d0 | + b3) - asr.l %d1, %d0 | >> 17 - move.w %d0, (3*16,%a4) - - movclr.l %acc2, %d0 | block[2] = (a2 - add.l %d6, %d0 | + b2) - asr.l %d1, %d0 | >> 17 - move.w %d0, (2*16,%a4) - - movclr.l %acc1, %d0 | block[1] = (a1 - add.l %d5, %d0 | + b1) - asr.l %d1, %d0 | >> 17 - move.w %d0, (1*16,%a4) - - movclr.l %acc0, %d0 | block[0] = (a0 - add.l %d4, %d0 | + b0) - asr.l %d1, %d0 | >> 17 - move.w %d0, (%a4)+ | advance to next column - - subq.l #1, %d3 | loop 8 times - bne.w .col_loop - - rts - - .align 2 - -mpeg2_idct_copy: - lea.l (-11*4,%sp), %sp - movem.l %d2-%d7/%a2-%a6, (%sp) | save some registers - move.l (11*4+4,%sp), %a0 | %a0 - block pointer for idct - - bsr.w .idct | apply idct to block - movem.l (11*4+4,%sp), %a0-%a2 | %a0 - block pointer - | %a1 - destination pointer - | %a2 - stride - - move.l #255, %d1 | preload constant for clipping - moveq.l #8, %d4 | loop counter - -.copy_clip_loop: - move.w (%a0), %d0 | load block[0] - ext.l %d0 | sign extend - cmp.l %d1, %d0 | overflow? - bls.b 1f - spl.b %d0 | yes: set appropriate limit value in low byte -1: - move.b %d0, %d2 | collect output bytes 0..3 in %d2 - lsl.l #8, %d2 - - move.w (2,%a0), %d0 | load block[1] - ext.l %d0 | sign extend - cmp.l %d1, %d0 | overflow? - bls.b 1f - spl.b %d0 | yes: set appropriate limit value in low byte -1: - move.b %d0, %d2 | collect output bytes 0..3 in %d2 - lsl.l #8, %d2 - clr.l (%a0)+ | clear block[0] and block[1], - | %a0 now pointing to block[2] - move.w (%a0), %d0 | do b2 and b3 - ext.l %d0 - cmp.l %d1, %d0 - bls.b 1f - spl.b %d0 -1: - move.b %d0, %d2 - lsl.l #8, %d2 - - move.w (2,%a0), %d0 - ext.l %d0 - cmp.l %d1, %d0 - bls.b 1f - spl.b %d0 -1: - move.b %d0, %d2 - clr.l (%a0)+ - - move.w (%a0), %d0 | do b4 and b5 - ext.l %d0 - cmp.l %d1, %d0 - bls.b 1f - spl.b %d0 -1: - move.b %d0, %d3 - lsl.l #8, %d3 - - move.w (2,%a0), %d0 - ext.l %d0 - cmp.l %d1, %d0 - bls.b 1f - spl.b %d0 -1: - move.b %d0, %d3 - lsl.l #8, %d3 - clr.l (%a0)+ - - move.w (%a0), %d0 | do b6 and b7 - ext.l %d0 - cmp.l %d1, %d0 - bls.b 1f - spl.b %d0 -1: - move.b %d0, %d3 - lsl.l #8, %d3 - - move.w (2,%a0), %d0 - ext.l %d0 - cmp.l %d1, %d0 - bls.b 1f - spl.b %d0 -1: - move.b %d0, %d3 - clr.l (%a0)+ - - movem.l %d2-%d3, (%a1) | write all 8 output bytes at once - add.l %a2, %a1 | advance output pointer - subq.l #1, %d4 | loop 8 times - bne.w .copy_clip_loop - - movem.l (%sp), %d2-%d7/%a2-%a6 - lea.l (11*4,%sp), %sp - rts - - .align 2 - -mpeg2_idct_add: - lea.l (-11*4,%sp), %sp - movem.l %d2-%d7/%a2-%a6, (%sp) - movem.l (11*4+4,%sp), %d0/%a0-%a2 | %d0 - last value - | %a0 - block pointer - | %a1 - destination pointer - | %a2 - stride - - cmp.l #129, %d0 | last == 129 ? - bne.b .idct_add | no: perform idct + addition - move.w (%a0), %d0 - ext.l %d0 | ((block[0] - asr.l #4, %d0 | >> 4) - and.l #7, %d0 | & 7) - subq.l #4, %d0 | - 4 == 0 ? - bne.w .dc_add | no: just perform addition - -.idct_add: - bsr.w .idct | apply idct - movem.l (11*4+8,%sp), %a0-%a2 | reload arguments %a0..%a2 - - move.l #255, %d2 | preload constant for clipping - clr.l %d3 | used for splitting input words into bytes - moveq.l #8, %d4 | loop counter - -.add_clip_loop: - movem.l (%a1), %d6-%d7 | fetch (b0 b1 b2 b3) (b4 b5 b6 b7) - swap %d6 | (b2 b3 b0 b1) - swap %d7 | (b6 b7 b4 b5) - - move.w (2,%a0), %d0 | load block[1] - ext.l %d0 | sign extend - move.b %d6, %d3 | copy b1 - lsr.l #8, %d6 | prepare 1st buffer for next byte - add.l %d3, %d0 | add b1 - cmp.l %d2, %d0 | overflow ? - bls.b 1f - spl.b %d0 | yes: set appropriate limit value in low byte -1: - move.w (%a0), %d1 | load block[0] - ext.l %d1 | sign extend - move.b %d6, %d3 | copy b0 - lsr.l #8, %d6 | prepare 1st buffer for next byte - add.l %d3, %d1 | add b0 - cmp.l %d2, %d1 | overflow ? - bls.b 1f - spl.b %d1 | yes: set appropriate limit value in low byte -1: - move.b %d1, %d5 | collect output bytes 0..3 in %d5 - lsl.l #8, %d5 - move.b %d0, %d5 - lsl.l #8, %d5 - clr.l (%a0)+ | clear block[0] and block[1] - | %a0 now pointing to block[2] - move.w (2,%a0), %d0 | do b3 and b2 - ext.l %d0 - move.b %d6, %d3 - lsr.l #8, %d6 - add.l %d3, %d0 - cmp.l %d2, %d0 - bls.b 1f - spl.b %d0 -1: - move.w (%a0), %d1 - ext.l %d1 - add.l %d6, %d1 - cmp.l %d2, %d1 - bls.b 1f - spl.b %d1 -1: - move.b %d1, %d5 - lsl.l #8, %d5 - move.b %d0, %d5 - clr.l (%a0)+ - - move.w (2,%a0), %d0 | do b5 and b4 - ext.l %d0 - move.b %d7, %d3 - lsr.l #8, %d7 - add.l %d3, %d0 - cmp.l %d2, %d0 - bls.b 1f - spl.b %d0 -1: - move.w (%a0), %d1 - ext.l %d1 - move.b %d7, %d3 - lsr.l #8, %d7 - add.l %d3, %d1 - cmp.l %d2, %d1 - bls.b 1f - spl.b %d1 -1: - move.b %d1, %d6 - lsl.l #8, %d6 - move.b %d0, %d6 - lsl.l #8, %d6 - clr.l (%a0)+ - - move.w (2,%a0), %d0 | do b7 and b6 - ext.l %d0 - move.b %d7, %d3 - lsr.l #8, %d7 - add.l %d3, %d0 - cmp.l %d2, %d0 - bls.b 1f - spl.b %d0 -1: - move.w (%a0), %d1 - ext.l %d1 - add.l %d7, %d1 - cmp.l %d2, %d1 - bls.b 1f - spl.b %d1 -1: - move.b %d1, %d6 - lsl.l #8, %d6 - move.b %d0, %d6 - clr.l (%a0)+ - - movem.l %d5-%d6, (%a1) | write all 8 output bytes at once - add.l %a2, %a1 | advance output pointer - subq.l #1, %d4 | loop 8 times - bne.w .add_clip_loop - - bra.w .idct_add_end - -.dc_add: - move.w (%a0), %d0 - ext.l %d0 | %d0 = (block[0] - add.l #64, %d0 | + 64) - asr.l #7, %d0 | >> 7 - clr.w (%a0) | clear block[0] - clr.w (63*2,%a0) | and block[63] - move.l %d0, %a0 | DC value in %a0 - - move.l #255, %d2 | preload constant for clipping - clr.l %d3 | for splitting input words into bytes - moveq.l #8, %d4 | loop counter - -.dc_clip_loop: - movem.l (%a1), %d6-%d7 | (b0 b1 b2 b3) (b4 b5 b6 b7) - swap %d6 | (b2 b3 b0 b1) - swap %d7 | (b6 b7 b4 b5) - - move.l %a0, %d0 | copy DC - move.b %d6, %d3 | copy b1 - lsr.l #8, %d6 | prepare 1st buffer for next byte - add.l %d3, %d0 | add b1 - cmp.l %d2, %d0 | overflow ? - bls.b 1f - spl.b %d0 | yes: set appropriate limit value in low byte -1: - move.l %a0, %d1 | copy DC - move.b %d6, %d3 | copy b0 - lsr.l #8, %d6 | prepare 1st buffer for next byte - add.l %d3, %d1 | add b0 - cmp.l %d2, %d1 | overflow ? - bls.b 1f - spl.b %d1 | yes: set appropriate limit value in low byte -1: - move.b %d1, %d5 | collect output bytes 0..3 in %d5 - lsl.l #8, %d5 - move.b %d0, %d5 - lsl.l #8, %d5 - - move.l %a0, %d0 | do b3 and b2 - move.b %d6, %d3 - lsr.l #8, %d6 - add.l %d3, %d0 - cmp.l %d2, %d0 - bls.b 1f - spl.b %d0 -1: - move.l %a0, %d1 - add.l %d6, %d1 - cmp.l %d2, %d1 - bls.b 1f - spl.b %d1 -1: - move.b %d1, %d5 - lsl.l #8, %d5 - move.b %d0, %d5 - - move.l %a0, %d0 | do b5 and b4 - move.b %d7, %d3 - lsr.l #8, %d7 - add.l %d3, %d0 - cmp.l %d2, %d0 - bls.b 1f - spl.b %d0 -1: - move.l %a0, %d1 - move.b %d7, %d3 - lsr.l #8, %d7 - add.l %d3, %d1 - cmp.l %d2, %d1 - bls.b 1f - spl.b %d1 -1: - move.b %d1, %d6 | do b7 and b6 - lsl.l #8, %d6 - move.b %d0, %d6 - lsl.l #8, %d6 - - move.l %a0, %d0 - move.b %d7, %d3 - lsr.l #8, %d7 - add.l %d3, %d0 - cmp.l %d2, %d0 - bls.b 1f - spl.b %d0 -1: - move.l %a0, %d1 - add.l %d7, %d1 - cmp.l %d2, %d1 - bls.b 1f - spl.b %d1 -1: - move.b %d1, %d6 - lsl.l #8, %d6 - move.b %d0, %d6 - - movem.l %d5-%d6, (%a1) | write all 8 output bytes at once - add.l %a2, %a1 | advance output pointer - subq.l #1, %d4 | loop 8 times - bne.w .dc_clip_loop - -.idct_add_end: - movem.l (%sp), %d2-%d7/%a2-%a6 - lea.l (11*4,%sp), %sp - rts diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp.c deleted file mode 100644 index d6968f68ce..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/motion_comp.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * motion_comp.c - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.17 - lost compatibility previously to - * provide simplified and CPU-optimized motion compensation. - */ - -#include "plugin.h" - -#include "mpeg2dec_config.h" - -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" - -/* These are defined in their respective target files - motion_comp_X.c */ -extern mpeg2_mc_fct MC_put_o_16; -extern mpeg2_mc_fct MC_put_o_8; -extern mpeg2_mc_fct MC_put_x_16; -extern mpeg2_mc_fct MC_put_x_8; -extern mpeg2_mc_fct MC_put_y_16; -extern mpeg2_mc_fct MC_put_y_8; -extern mpeg2_mc_fct MC_put_xy_16; -extern mpeg2_mc_fct MC_put_xy_8; - -extern mpeg2_mc_fct MC_avg_o_16; -extern mpeg2_mc_fct MC_avg_o_8; -extern mpeg2_mc_fct MC_avg_x_16; -extern mpeg2_mc_fct MC_avg_x_8; -extern mpeg2_mc_fct MC_avg_y_16; -extern mpeg2_mc_fct MC_avg_y_8; -extern mpeg2_mc_fct MC_avg_xy_16; -extern mpeg2_mc_fct MC_avg_xy_8; - -const mpeg2_mc_t mpeg2_mc = -{ - { - MC_put_o_16, MC_put_x_16, MC_put_y_16, MC_put_xy_16, - MC_put_o_8, MC_put_x_8, MC_put_y_8, MC_put_xy_8 - }, - { - MC_avg_o_16, MC_avg_x_16, MC_avg_y_16, MC_avg_xy_16, - MC_avg_o_8, MC_avg_x_8, MC_avg_y_8, MC_avg_xy_8 - } -}; diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp.h b/apps/plugins/mpegplayer/libmpeg2/motion_comp.h deleted file mode 100644 index 4737e72cab..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/motion_comp.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * motion_comp.h - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - - -#define avg2(a,b) ((a+b+1)>>1) -#define avg4(a,b,c,d) ((a+b+c+d+2)>>2) - -#define predict_o(i) (ref[i]) -#define predict_x(i) (avg2 (ref[i], ref[i+1])) -#define predict_y(i) (avg2 (ref[i], (ref+stride)[i])) -#define predict_xy(i) (avg4 (ref[i], ref[i+1], \ - (ref+stride)[i], (ref+stride)[i+1])) - -#define put(predictor,i) dest[i] = predictor (i) -#define avg(predictor,i) dest[i] = avg2 (predictor (i), dest[i]) - -/* mc function template */ -#define MC_FUNC(op, xy) \ - MC_FUNC_16(op, xy) \ - MC_FUNC_8(op, xy) - -#define MC_FUNC_16(op, xy) \ - void MC_##op##_##xy##_16 (uint8_t * dest, const uint8_t * ref, \ - const int stride, int height) \ - { \ - do { \ - op (predict_##xy, 0); \ - op (predict_##xy, 1); \ - op (predict_##xy, 2); \ - op (predict_##xy, 3); \ - op (predict_##xy, 4); \ - op (predict_##xy, 5); \ - op (predict_##xy, 6); \ - op (predict_##xy, 7); \ - op (predict_##xy, 8); \ - op (predict_##xy, 9); \ - op (predict_##xy, 10); \ - op (predict_##xy, 11); \ - op (predict_##xy, 12); \ - op (predict_##xy, 13); \ - op (predict_##xy, 14); \ - op (predict_##xy, 15); \ - ref += stride; \ - dest += stride; \ - } while (--height); \ - } - -#define MC_FUNC_8(op, xy) \ - void MC_##op##_##xy##_8 (uint8_t * dest, const uint8_t * ref, \ - const int stride, int height) \ - { \ - do { \ - op (predict_##xy, 0); \ - op (predict_##xy, 1); \ - op (predict_##xy, 2); \ - op (predict_##xy, 3); \ - op (predict_##xy, 4); \ - op (predict_##xy, 5); \ - op (predict_##xy, 6); \ - op (predict_##xy, 7); \ - ref += stride; \ - dest += stride; \ - } while (--height); \ - } diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c deleted file mode 100644 index dcf1df53e9..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * motion_comp_arm.c - * Copyright (C) 2004 AGAWA Koji - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ -#include -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" -#include "motion_comp.h" - -/* definitions of the actual mc functions */ - -/* MC_FUNC (put, o) <= ASM */ -MC_FUNC (avg, o) -/* MC_FUNC (put, x) <= ASM */ -MC_FUNC (avg, x) -MC_FUNC (put, y) -MC_FUNC (avg, y) -MC_FUNC (put, xy) -MC_FUNC (avg, xy) diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S deleted file mode 100644 index 1ec1b0686e..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S +++ /dev/null @@ -1,342 +0,0 @@ -@ motion_comp_arm_s.S -@ Copyright (C) 2004 AGAWA Koji -@ -@ This file is part of mpeg2dec, a free MPEG-2 video stream decoder. -@ See http://libmpeg2.sourceforge.net/ for updates. -@ -@ mpeg2dec is free software; you can redistribute it and/or modify -@ it under the terms of the GNU General Public License as published by -@ the Free Software Foundation; either version 2 of the License, or -@ (at your option) any later version. -@ -@ mpeg2dec is distributed in the hope that it will be useful, -@ but WITHOUT ANY WARRANTY; without even the implied warranty of -@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -@ GNU General Public License for more details. -@ -@ You should have received a copy of the GNU General Public License -@ along with this program; if not, write to the Free Software -@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -@ -@ $Id$ - -#include "config.h" /* Rockbox: ARM architecture version */ - - .text - -@ ---------------------------------------------------------------- - .align - .global MC_put_o_16 -MC_put_o_16: - @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) - @@ pld [r1] - stmfd sp!, {r4-r7, lr} @ R14 is also called LR - and r4, r1, #3 - ldr pc, [pc, r4, lsl #2] - .word 0 - .word MC_put_o_16_align0 - .word MC_put_o_16_align1 - .word MC_put_o_16_align2 - .word MC_put_o_16_align3 - -MC_put_o_16_align0: - ldmia r1, {r4-r7} - add r1, r1, r2 - @@ pld [r1] - stmia r0, {r4-r7} - subs r3, r3, #1 - add r0, r0, r2 - bne MC_put_o_16_align0 - ldmpc regs=r4-r7 @@ update PC with LR content. - -.macro ADJ_ALIGN_QW shift, R0, R1, R2, R3, R4 - mov \R0, \R0, lsr #(\shift) - orr \R0, \R0, \R1, lsl #(32 - \shift) - mov \R1, \R1, lsr #(\shift) - orr \R1, \R1, \R2, lsl #(32 - \shift) - mov \R2, \R2, lsr #(\shift) - orr \R2, \R2, \R3, lsl #(32 - \shift) - mov \R3, \R3, lsr #(\shift) - orr \R3, \R3, \R4, lsl #(32 - \shift) - mov \R4, \R4, lsr #(\shift) -.endm - -MC_put_o_16_align1: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4-r7, r12} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_QW 8, r4, r5, r6, r7, r12 - stmia r0, {r4-r7} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-r7 @@ update PC with LR content. - -MC_put_o_16_align2: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4-r7, r12} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_QW 16, r4, r5, r6, r7, r12 - stmia r0, {r4-r7} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-r7 @@ update PC with LR content. - -MC_put_o_16_align3: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4-r7, r12} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_QW 24, r4, r5, r6, r7, r12 - stmia r0, {r4-r7} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-r7 @@ update PC with LR content. - -@ ---------------------------------------------------------------- - .align - .global MC_put_o_8 -MC_put_o_8: - @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) - @@ pld [r1] - stmfd sp!, {r4, r5, lr} @ R14 is also called LR - and r4, r1, #3 - ldr pc, [pc, r4, lsl #2] - .word 0 - .word MC_put_o_8_align0 - .word MC_put_o_8_align1 - .word MC_put_o_8_align2 - .word MC_put_o_8_align3 - -MC_put_o_8_align0: - ldmia r1, {r4, r5} - add r1, r1, r2 - @@ pld [r1] - stmia r0, {r4, r5} - add r0, r0, r2 - subs r3, r3, #1 - bne MC_put_o_8_align0 - ldmpc regs=r4-r5 @@ update PC with LR content. - -.macro ADJ_ALIGN_DW shift, R0, R1, R2 - mov \R0, \R0, lsr #(\shift) - orr \R0, \R0, \R1, lsl #(32 - \shift) - mov \R1, \R1, lsr #(\shift) - orr \R1, \R1, \R2, lsl #(32 - \shift) - mov \R2, \R2, lsr #(\shift) -.endm - -MC_put_o_8_align1: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4, r5, r12} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_DW 8, r4, r5, r12 - stmia r0, {r4, r5} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-r5 @@ update PC with LR content. - -MC_put_o_8_align2: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4, r5, r12} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_DW 16, r4, r5, r12 - stmia r0, {r4, r5} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-r5 @@ update PC with LR content. - -MC_put_o_8_align3: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4, r5, r12} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_DW 24, r4, r5, r12 - stmia r0, {r4, r5} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-r5 @@ update PC with LR content. - -@ ---------------------------------------------------------------- -.macro AVG_PW rW1, rW2 - mov \rW2, \rW2, lsl #24 - orr \rW2, \rW2, \rW1, lsr #8 - eor r9, \rW1, \rW2 -#if ARM_ARCH >= 6 - uhadd8 \rW2, \rW1, \rW2 -#else - and \rW2, \rW1, \rW2 - and r10, r9, r11 - add \rW2, \rW2, r10, lsr #1 -#endif - and r9, r9, r12 - add \rW2, \rW2, r9 -.endm - -#if ARM_ARCH >= 6 -#define HIGHEST_REG r9 -#else -#define HIGHEST_REG r11 -#endif - - .align - .global MC_put_x_16 -MC_put_x_16: - @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) - @@ pld [r1] - stmfd sp!, {r4-HIGHEST_REG, lr} @ R14 is also called LR - and r4, r1, #3 - ldr r12, 2f -#if ARM_ARCH < 6 - mvn r11, r12 -#endif - ldr pc, [pc, r4, lsl #2] -2: .word 0x01010101 - .word MC_put_x_16_align0 - .word MC_put_x_16_align1 - .word MC_put_x_16_align2 - .word MC_put_x_16_align3 - -MC_put_x_16_align0: - ldmia r1, {r4-r8} - add r1, r1, r2 - @@ pld [r1] - AVG_PW r7, r8 - AVG_PW r6, r7 - AVG_PW r5, r6 - AVG_PW r4, r5 - stmia r0, {r5-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne MC_put_x_16_align0 - ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content. - -MC_put_x_16_align1: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4-r8} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_QW 8, r4, r5, r6, r7, r8 - AVG_PW r7, r8 - AVG_PW r6, r7 - AVG_PW r5, r6 - AVG_PW r4, r5 - stmia r0, {r5-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content. - -MC_put_x_16_align2: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4-r8} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_QW 16, r4, r5, r6, r7, r8 - AVG_PW r7, r8 - AVG_PW r6, r7 - AVG_PW r5, r6 - AVG_PW r4, r5 - stmia r0, {r5-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content. - -MC_put_x_16_align3: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r4-r8} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_QW 24, r4, r5, r6, r7, r8 - AVG_PW r7, r8 - AVG_PW r6, r7 - AVG_PW r5, r6 - AVG_PW r4, r5 - stmia r0, {r5-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content. - -@ ---------------------------------------------------------------- - .align - .global MC_put_x_8 -MC_put_x_8: - @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height) - @@ pld [r1] - stmfd sp!, {r6-HIGHEST_REG, lr} @ R14 is also called LR - and r6, r1, #3 - ldr r12, 2f -#if ARM_ARCH < 6 - mvn r11, r12 -#endif - ldr pc, [pc, r6, lsl #2] -2: .word 0x01010101 - .word MC_put_x_8_align0 - .word MC_put_x_8_align1 - .word MC_put_x_8_align2 - .word MC_put_x_8_align3 - -MC_put_x_8_align0: - ldmia r1, {r6-r8} - add r1, r1, r2 - @@ pld [r1] - AVG_PW r7, r8 - AVG_PW r6, r7 - stmia r0, {r7-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne MC_put_x_8_align0 - ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content. - -MC_put_x_8_align1: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r6-r8} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_DW 8, r6, r7, r8 - AVG_PW r7, r8 - AVG_PW r6, r7 - stmia r0, {r7-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content. - -MC_put_x_8_align2: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r6-r8} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_DW 16, r6, r7, r8 - AVG_PW r7, r8 - AVG_PW r6, r7 - stmia r0, {r7-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content. - -MC_put_x_8_align3: - and r1, r1, #0xFFFFFFFC -1: ldmia r1, {r6-r8} - add r1, r1, r2 - @@ pld [r1] - ADJ_ALIGN_DW 24, r6, r7, r8 - AVG_PW r7, r8 - AVG_PW r6, r7 - stmia r0, {r7-r8} - subs r3, r3, #1 - add r0, r0, r2 - bne 1b - ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content. diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c deleted file mode 100644 index 9a8640e7e6..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * motion_comp.c - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ -#include -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" -#include "motion_comp.h" - -/* definitions of the actual mc functions */ - -MC_FUNC (put, o) -MC_FUNC (avg, o) -MC_FUNC (put, x) -MC_FUNC (avg, x) -MC_FUNC (put, y) -MC_FUNC (avg, y) -MC_FUNC (put, xy) -MC_FUNC (avg, xy) diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c deleted file mode 100644 index b97e3510e7..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Based on: - * motion_comp_arm.c - * Copyright (C) 2004 AGAWA Koji - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" -#include "motion_comp.h" - -/* definitions of the actual mc functions */ - -/* MC_FUNC (put, o) <= ASM */ -MC_FUNC (avg, o) -/* MC_FUNC (put, x) <= ASM */ -MC_FUNC (avg, x) -MC_FUNC (put, y) -MC_FUNC (avg, y) -MC_FUNC (put, xy) -MC_FUNC (avg, xy) diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S deleted file mode 100644 index 55d87cb708..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S +++ /dev/null @@ -1,436 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 Jens Arnold - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -.macro LEFT8_PW dW1, dW2 | needs %d0 == 24, clobbers %d2 - lsl.l #8, \dW1 | changes dW1, keeps dW2 - move.l \dW2, %d2 - lsr.l %d0, %d2 - or.l %d2, \dW1 -.endm - -.macro LEFT24_PW dW1, dW2 | needs %d0 == 24, clobbers %d2 - lsl.l %d0, \dW1 | changes dW1, keeps dW2 - move.l \dW2, %d2 - lsr.l #8, %d2 - or.l %d2, \dW1 -.endm - -/*****************************************************************************/ - - .align 2 - .global MC_put_o_8 - .type MC_put_o_8, @function - -MC_put_o_8: - movem.l (4,%sp), %a0-%a1 | dest, source - move.l %a1, %d0 - and.l #3, %d0 - sub.l %d0, %a1 | align source - jmp.l (2, %pc, %d0.l*4) - bra.w .po8_0 - bra.w .po8_1 - bra.w .po8_2 - | last table entry coincides with target - -.po8_3: - lea.l (-5*4,%sp), %sp - movem.l %d2-%d5/%a2, (%sp) | save some registers - move.l (5*4+12,%sp), %a2 | stride - move.l (5*4+16,%sp), %d1 | height - moveq.l #24, %d0 | shift amount -1: - movem.l (%a1), %d3-%d5 - add.l %a2, %a1 - LEFT24_PW %d3, %d4 - lsl.l %d0, %d4 - lsr.l #8, %d5 - or.l %d5, %d4 - movem.l %d3-%d4, (%a0) - add.l %a2, %a0 - subq.l #1, %d1 - bne.s 1b - movem.l (%sp), %d2-%d5/%a2 - lea.l (5*4,%sp), %sp - rts - -.po8_2: - lea.l (-3*4,%sp), %sp - movem.l %d2-%d4, (%sp) | save some registers - movem.l (3*4+12,%sp), %d0-%d1 | stride, height -1: - movem.l (%a1), %d2-%d4 - add.l %d0, %a1 - swap %d2 - swap %d3 - move.w %d3, %d2 - swap %d4 - move.w %d4, %d3 - movem.l %d2-%d3, (%a0) - add.l %d0, %a0 - subq.l #1, %d1 - bne.s 1b - movem.l (%sp), %d2-%d4 - lea.l (3*4,%sp), %sp - rts - -.po8_1: - lea.l (-5*4,%sp), %sp - movem.l %d2-%d5/%a2, (%sp) | save some registers - move.l (5*4+12,%sp), %a2 | stride - move.l (5*4+16,%sp), %d1 | height - moveq.l #24, %d0 | shift amount -1: - movem.l (%a1), %d3-%d5 - add.l %a2, %a1 - LEFT8_PW %d3, %d4 - lsl.l #8, %d4 - lsr.l %d0, %d5 - or.l %d5, %d4 - movem.l %d3-%d4, (%a0) - add.l %a2, %a0 - subq.l #1, %d1 - bne.s 1b - movem.l (%sp), %d2-%d5/%a2 - lea.l (5*4,%sp), %sp - rts - -.po8_0: - movem.l (12,%sp), %d0-%d1 | stride, height - subq.l #4, %d0 | adjust for increment within the loop -1: - move.l (%a1)+, (%a0)+ - move.l (%a1), (%a0) - add.l %d0, %a0 - add.l %d0, %a1 - subq.l #1, %d1 - bne.s 1b - rts - -/*****************************************************************************/ - - .align 2 - .global MC_put_o_16 - .type MC_put_o_16, @function - -MC_put_o_16: - lea.l (-7*4,%sp), %sp - movem.l %d2-%d7/%a2, (%sp) | save some registers - movem.l (7*4+4,%sp), %a0-%a2| dest, source, stride - move.l (7*4+16,%sp), %d1 | height - move.l %a1, %d0 - and.l #3, %d0 - sub.l %d0, %a1 - jmp.l (2, %pc, %d0.l*4) - bra.w .po16_0 - bra.w .po16_1 - bra.w .po16_2 - | last table entry coincides with target - -.po16_3: - moveq.l #24, %d0 | shift amount -1: - movem.l (%a1), %d3-%d7 - add.l %a2, %a1 - LEFT24_PW %d3, %d4 - LEFT24_PW %d4, %d5 - LEFT24_PW %d5, %d6 - lsl.l %d0, %d6 - lsr.l #8, %d7 - or.l %d7, %d6 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %d1 - bne.s 1b - movem.l (%sp), %d2-%d7/%a2 - lea.l (7*4,%sp), %sp - rts - -.po16_2: -1: - movem.l (%a1), %d3-%d7 - add.l %a2, %a1 - swap %d3 - swap %d4 - move.w %d4, %d3 - swap %d5 - move.w %d5, %d4 - swap %d6 - move.w %d6, %d5 - swap %d7 - move.w %d7, %d6 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %d1 - bne.s 1b - movem.l (%sp), %d2-%d7/%a2 - lea.l (7*4,%sp), %sp - rts - -.po16_1: - moveq.l #24, %d0 | shift amount -1: - movem.l (%a1), %d3-%d7 - add.l %a2, %a1 - LEFT8_PW %d3, %d4 - LEFT8_PW %d4, %d5 - LEFT8_PW %d5, %d6 - lsl.l #8, %d6 - lsr.l %d0, %d7 - or.l %d7, %d6 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %d1 - bne.s 1b - movem.l (%sp), %d2-%d7/%a2 - lea.l (7*4,%sp), %sp - rts - -.po16_0: -1: - movem.l (%a1), %d3-%d6 - add.l %a2, %a1 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %d1 - bne.s 1b - movem.l (%sp), %d2-%d7/%a2 - lea.l (7*4,%sp), %sp - rts - -/*****************************************************************************/ - -.macro AVG_PW dW1, dW2 | needs %d0 == 24, clobbers %d1, %d2, - move.l \dW1, %d1 | changes dW1, keeps dW2 - lsl.l #8, \dW1 - move.l \dW2, %d2 - lsr.l %d0, %d2 - or.l %d2, \dW1 - move.l %d1, %d2 - eor.l \dW1, %d1 - and.l %d2, \dW1 - move.l #0xfefefefe, %d2 - and.l %d1, %d2 - eor.l %d2, %d1 - lsr.l #1, %d2 - add.l %d2, \dW1 - add.l %d1, \dW1 -.endm - -/*****************************************************************************/ - - .align 2 - .global MC_put_x_8 - .type MC_put_x_8, @function - -MC_put_x_8: - lea.l (-6*4,%sp), %sp - movem.l %d2-%d6/%a2, (%sp) | save some registers - movem.l (6*4+4,%sp), %a0-%a2| dest, source, stride - move.l (6*4+16,%sp), %d6 | height - move.l %a1, %d0 - and.l #3, %d0 - sub.l %d0, %a1 - jmp.l (2, %pc, %d0.l*4) - bra.w .px8_0 - bra.w .px8_1 - bra.w .px8_2 - | last table entry coincides with target - -.px8_3: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d5 - add.l %a2, %a1 - LEFT24_PW %d3, %d4 - LEFT24_PW %d4, %d5 - lsl.l %d0, %d5 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - movem.l %d3-%d4, (%a0) - add.l %a2, %a0 - subq.l #1, %d6 - bne.s 1b - movem.l (%sp), %d2-%d6/%a2 - lea.l (6*4,%sp), %sp - rts - -.px8_2: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d5 - add.l %a2, %a1 - swap %d3 - swap %d4 - move.w %d4, %d3 - swap %d5 - move.w %d5, %d4 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - movem.l %d3-%d4, (%a0) - add.l %a2, %a0 - subq.l #1, %d6 - bne.s 1b - movem.l (%sp), %d2-%d6/%a2 - lea.l (6*4,%sp), %sp - rts - -.px8_1: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d5 - add.l %a2, %a1 - LEFT8_PW %d3, %d4 - LEFT8_PW %d4, %d5 - lsl.l #8, %d5 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - movem.l %d3-%d4, (%a0) - add.l %a2, %a0 - subq.l #1, %d6 - bne.s 1b - movem.l (%sp), %d2-%d6/%a2 - lea.l (6*4,%sp), %sp - rts - -.px8_0: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d5 - add.l %a2, %a1 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - movem.l %d3-%d4, (%a0) - add.l %a2, %a0 - subq.l #1, %d6 - bne.s 1b - movem.l (%sp), %d2-%d6/%a2 - lea.l (6*4,%sp), %sp - rts - -/*****************************************************************************/ - - .align 2 - .global MC_put_x_16 - .type MC_put_x_16, @function - -MC_put_x_16: - lea.l (-8*4,%sp), %sp - movem.l %d2-%d7/%a2-%a3, (%sp) | save some registers - movem.l (8*4+4,%sp), %a0-%a3 | dest, source, stride, height - move.l %a1, %d0 - and.l #3, %d0 - sub.l %d0, %a1 - jmp.l (2, %pc, %d0.l*4) - bra.w .px16_0 - bra.w .px16_1 - bra.w .px16_2 - | last table entry coincides with target - -.px16_3: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d7 - add.l %a2, %a1 - LEFT24_PW %d3, %d4 - LEFT24_PW %d4, %d5 - LEFT24_PW %d5, %d6 - LEFT24_PW %d6, %d7 - lsl.l %d0, %d7 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - AVG_PW %d5, %d6 - AVG_PW %d6, %d7 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %a3 - tst.l %a3 - bne.w 1b - movem.l (%sp), %d2-%d7/%a2-%a3 - lea.l (8*4,%sp), %sp - rts - -.px16_2: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d7 - add.l %a2, %a1 - swap %d3 - swap %d4 - move.w %d4, %d3 - swap %d5 - move.w %d5, %d4 - swap %d6 - move.w %d6, %d5 - swap %d7 - move.w %d7, %d6 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - AVG_PW %d5, %d6 - AVG_PW %d6, %d7 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %a3 - tst.l %a3 - bne.w 1b - movem.l (%sp), %d2-%d7/%a2-%a3 - lea.l (8*4,%sp), %sp - rts - -.px16_1: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d7 - add.l %a2, %a1 - LEFT8_PW %d3, %d4 - LEFT8_PW %d4, %d5 - LEFT8_PW %d5, %d6 - LEFT8_PW %d6, %d7 - lsl.l #8, %d7 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - AVG_PW %d5, %d6 - AVG_PW %d6, %d7 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %a3 - tst.l %a3 - bne.w 1b - movem.l (%sp), %d2-%d7/%a2-%a3 - lea.l (8*4,%sp), %sp - rts - -.px16_0: - moveq.l #24, %d0 -1: - movem.l (%a1), %d3-%d7 - add.l %a2, %a1 - AVG_PW %d3, %d4 - AVG_PW %d4, %d5 - AVG_PW %d5, %d6 - AVG_PW %d6, %d7 - movem.l %d3-%d6, (%a0) - add.l %a2, %a0 - subq.l #1, %a3 - tst.l %a3 - bne.w 1b - movem.l (%sp), %d2-%d7/%a2-%a3 - lea.l (8*4,%sp), %sp - rts diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2.h deleted file mode 100644 index bd14ead96e..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/mpeg2.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * mpeg2.h - * Copyright (C) 2000-2004 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.67 - */ - -#ifndef MPEG2_H -#define MPEG2_H - -#include "mpeg2dec_config.h" - -#define MPEG2_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c)) -#define MPEG2_RELEASE MPEG2_VERSION (0, 5, 0) /* 0.5.0 */ - -#define SEQ_FLAG_MPEG2 1 -#define SEQ_FLAG_CONSTRAINED_PARAMETERS 2 -#define SEQ_FLAG_PROGRESSIVE_SEQUENCE 4 -#define SEQ_FLAG_LOW_DELAY 8 -#define SEQ_FLAG_COLOUR_DESCRIPTION 16 - -#define SEQ_MASK_VIDEO_FORMAT 0xe0 -#define SEQ_VIDEO_FORMAT_COMPONENT 0x00 -#define SEQ_VIDEO_FORMAT_PAL 0x20 -#define SEQ_VIDEO_FORMAT_NTSC 0x40 -#define SEQ_VIDEO_FORMAT_SECAM 0x60 -#define SEQ_VIDEO_FORMAT_MAC 0x80 -#define SEQ_VIDEO_FORMAT_UNSPECIFIED 0xa0 - -typedef struct mpeg2_sequence_s -{ - unsigned int width, height; - unsigned int chroma_width, chroma_height; - unsigned int byte_rate; - unsigned int vbv_buffer_size; - uint32_t flags; - - unsigned int picture_width, picture_height; - unsigned int display_width, display_height; - unsigned int pixel_width, pixel_height; - unsigned int frame_period; - - uint8_t profile_level_id; - uint8_t colour_primaries; - uint8_t transfer_characteristics; - uint8_t matrix_coefficients; -} mpeg2_sequence_t; - -#define GOP_FLAG_DROP_FRAME 1 -#define GOP_FLAG_BROKEN_LINK 2 -#define GOP_FLAG_CLOSED_GOP 4 - -typedef struct mpeg2_gop_s -{ - uint8_t hours; - uint8_t minutes; - uint8_t seconds; - uint8_t pictures; - uint32_t flags; -} mpeg2_gop_t; - -#define PIC_MASK_CODING_TYPE 7 -#define PIC_FLAG_CODING_TYPE_I 1 -#define PIC_FLAG_CODING_TYPE_P 2 -#define PIC_FLAG_CODING_TYPE_B 3 -#define PIC_FLAG_CODING_TYPE_D 4 - -#define PIC_FLAG_TOP_FIELD_FIRST 8 -#define PIC_FLAG_PROGRESSIVE_FRAME 16 -#define PIC_FLAG_COMPOSITE_DISPLAY 32 -#define PIC_FLAG_SKIP 64 -#define PIC_FLAG_TAGS 128 -#define PIC_MASK_COMPOSITE_DISPLAY 0xfffff000 - -typedef struct mpeg2_picture_s -{ - unsigned int temporal_reference; - unsigned int nb_fields; - uint32_t tag, tag2; - uint32_t flags; - struct - { - int x, y; - } display_offset[3]; -} mpeg2_picture_t; - -typedef struct mpeg2_fbuf_s -{ - uint8_t * buf[MPEG2_COMPONENTS]; - void * id; -} mpeg2_fbuf_t; - -typedef struct mpeg2_info_s -{ - const mpeg2_sequence_t * sequence; - const mpeg2_gop_t * gop; - const mpeg2_picture_t * current_picture; - const mpeg2_picture_t * current_picture_2nd; - const mpeg2_fbuf_t * current_fbuf; - const mpeg2_picture_t * display_picture; - const mpeg2_picture_t * display_picture_2nd; - const mpeg2_fbuf_t * display_fbuf; - const mpeg2_fbuf_t * discard_fbuf; - const uint8_t * user_data; - unsigned int user_data_len; -} mpeg2_info_t; - -typedef struct mpeg2dec_s mpeg2dec_t; -typedef struct mpeg2_decoder_s mpeg2_decoder_t; - -typedef enum -{ - STATE_INTERNAL_NORETURN = -1, - STATE_BUFFER = 0, - STATE_SEQUENCE = 1, - STATE_SEQUENCE_REPEATED = 2, - STATE_SEQUENCE_MODIFIED = 3, - STATE_GOP = 4, - STATE_PICTURE = 5, - STATE_SLICE_1ST = 6, - STATE_PICTURE_2ND = 7, - STATE_SLICE = 8, - STATE_END = 9, - STATE_INVALID = 10, - STATE_INVALID_END = 11, -} mpeg2_state_t; - -typedef struct mpeg2_convert_init_s -{ - unsigned int id_size; - unsigned int buf_size[MPEG2_COMPONENTS]; - void (* start)(void * id, const mpeg2_fbuf_t * fbuf, - const mpeg2_picture_t * picture, const mpeg2_gop_t * gop); - void (* copy)(void * id, uint8_t * const * src, unsigned int v_offset); -} mpeg2_convert_init_t; - -typedef enum -{ - MPEG2_CONVERT_SET = 0, - MPEG2_CONVERT_STRIDE = 1, - MPEG2_CONVERT_START = 2 -} mpeg2_convert_stage_t; - -typedef int mpeg2_convert_t (int stage, void * id, - const mpeg2_sequence_t * sequence, int stride, - void * arg, mpeg2_convert_init_t * result); -int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg); -int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride); -void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[MPEG2_COMPONENTS], - void * id); -void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf); - -mpeg2dec_t * mpeg2_init (void); -const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec); -void mpeg2_close (mpeg2dec_t * mpeg2dec); - -void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end); -int mpeg2_getpos (mpeg2dec_t * mpeg2dec); -mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec); - -void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset); -void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip); -void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end); - -void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2); - -void mpeg2_init_fbuf (mpeg2_decoder_t * decoder, - uint8_t * current_fbuf[MPEG2_COMPONENTS], - uint8_t * forward_fbuf[MPEG2_COMPONENTS], - uint8_t * backward_fbuf[MPEG2_COMPONENTS]); -void mpeg2_slice (mpeg2_decoder_t * decoder, int code, const uint8_t * buffer); - -int mpeg2_guess_aspect (const mpeg2_sequence_t * sequence, - unsigned int * pixel_width, - unsigned int * pixel_height); - -typedef enum -{ - MPEG2_ALLOC_MPEG2DEC = 0, - MPEG2_ALLOC_CHUNK = 1, - MPEG2_ALLOC_YUV = 2, - MPEG2_ALLOC_CONVERT_ID = 3, - MPEG2_ALLOC_CONVERTED = 4, - MPEG_ALLOC_CODEC_MALLOC, - MPEG_ALLOC_CODEC_CALLOC, - MPEG_ALLOC_MPEG2_BUFFER, - MPEG_ALLOC_AUDIOBUF, - MPEG_ALLOC_PCMOUT, - MPEG_ALLOC_DISKBUF, - __MPEG_ALLOC_FIRST = -256, -} mpeg2_alloc_t; - -void * mpeg2_malloc (unsigned size, mpeg2_alloc_t reason); -#if 0 -void mpeg2_free (void * buf); -#endif -/* allocates a dedicated buffer and locks all previous allocation in place */ -void * mpeg2_bufalloc(unsigned size, mpeg2_alloc_t reason); -/* clears all non-dedicated buffer space */ -void mpeg2_mem_reset(void); -void mpeg2_alloc_init(unsigned char* buf, int mallocsize); - -#endif /* MPEG2_H */ diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h deleted file mode 100644 index e04562e18d..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h +++ /dev/null @@ -1,274 +0,0 @@ -/* - * mpeg2_internal.h - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.89 - */ -#ifndef MPEG2_INTERNAL_H -#define MPEG2_INTERNAL_H - -#include "config.h" /* for Rockbox CPU_ #defines */ - -/* macroblock modes */ -#define MACROBLOCK_INTRA 1 -#define MACROBLOCK_PATTERN 2 -#define MACROBLOCK_MOTION_BACKWARD 4 -#define MACROBLOCK_MOTION_FORWARD 8 -#define MACROBLOCK_QUANT 16 -#define DCT_TYPE_INTERLACED 32 -/* motion_type */ -#define MOTION_TYPE_SHIFT 6 -#define MC_FIELD 1 -#define MC_FRAME 2 -#define MC_16X8 2 -#define MC_DMV 3 - -/* picture structure */ -#define TOP_FIELD 1 -#define BOTTOM_FIELD 2 -#define FRAME_PICTURE 3 - -/* picture coding type */ -#define I_TYPE 1 -#define P_TYPE 2 -#define B_TYPE 3 -#define D_TYPE 4 - -typedef void mpeg2_mc_fct (uint8_t *, const uint8_t *, int, int); - -typedef struct -{ - uint8_t * ref[2][MPEG2_COMPONENTS]; - uint8_t ** ref2[2]; - int pmv[2][2]; - int f_code[2]; -} motion_t; - -typedef void motion_parser_t(mpeg2_decoder_t * decoder, - motion_t * motion, - mpeg2_mc_fct * const * table); - -struct mpeg2_decoder_s -{ - /* first, state that carries information from one macroblock to the */ - /* next inside a slice, and is never used outside of mpeg2_slice() */ - - /* bit parsing stuff */ - uint32_t bitstream_buf; /* current 32 bit working set */ - int bitstream_bits; /* used bits in working set */ - const uint8_t * bitstream_ptr; /* buffer with stream data */ - - uint8_t * dest[MPEG2_COMPONENTS]; - - int offset; - int stride; - int uv_stride; - int slice_stride; - int slice_uv_stride; - int stride_frame; - unsigned int limit_x; - unsigned int limit_y_16; - unsigned int limit_y_8; - unsigned int limit_y; - - /* Motion vectors */ - /* The f_ and b_ correspond to the forward and backward motion */ - /* predictors */ - motion_t b_motion; - motion_t f_motion; - motion_parser_t * motion_parser[5]; - - /* predictor for DC coefficients in intra blocks */ - int16_t dc_dct_pred[MPEG2_COMPONENTS]; - - /* DCT coefficients */ - int16_t * DCTblock; /* put buffer separately to have it in IRAM */ - - uint8_t * picture_dest[MPEG2_COMPONENTS]; - void (* convert) (void * convert_id, uint8_t * const * src, - unsigned int v_offset); - void * convert_id; - - int dmv_offset; - unsigned int v_offset; - - /* now non-slice-specific information */ - - /* sequence header stuff */ - uint16_t * quantizer_matrix[4]; - uint16_t (* chroma_quantizer[2])[64]; - uint16_t quantizer_prescale[4][32][64]; - - /* The width and height of the picture snapped to macroblock units */ - int width; - int height; - int vertical_position_extension; - int chroma_format; - - /* picture header stuff */ - - /* what type of picture this is (I, P, B, D) */ - int coding_type; - - /* picture coding extension stuff */ - - /* quantization factor for intra dc coefficients */ - int intra_dc_precision; - /* top/bottom/both fields */ - int picture_structure; - /* bool to indicate all predictions are frame based */ - int frame_pred_frame_dct; - /* bool to indicate whether intra blocks have motion vectors */ - /* (for concealment) */ - int concealment_motion_vectors; - /* bool to use different vlc tables */ - int intra_vlc_format; - /* used for DMV MC */ - int top_field_first; - - /* stuff derived from bitstream */ - - /* pointer to the zigzag scan we're supposed to be using */ - const uint8_t * scan; - - int second_field; - - int mpeg1; -}; - -typedef struct -{ - mpeg2_fbuf_t fbuf; -} fbuf_alloc_t; - -struct mpeg2dec_s -{ - mpeg2_decoder_t decoder; - - mpeg2_info_t info; - - uint32_t shift; - int is_display_initialized; - mpeg2_state_t (* action) (struct mpeg2dec_s * mpeg2dec); - mpeg2_state_t state; - uint32_t ext_state; - - /* allocated in init - gcc has problems allocating such big structures */ - uint8_t * ATTR_ALIGN(4) chunk_buffer; - /* pointer to start of the current chunk */ - uint8_t * chunk_start; - /* pointer to current position in chunk_buffer */ - uint8_t * chunk_ptr; - /* last start code ? */ - uint8_t code; - - /* picture tags */ - uint32_t tag_current, tag2_current, tag_previous, tag2_previous; - int num_tags; - int bytes_since_tag; - - int first; - int alloc_index_user; - int alloc_index; - uint8_t first_decode_slice; - uint8_t nb_decode_slices; - - unsigned int user_data_len; - - mpeg2_sequence_t new_sequence; - mpeg2_sequence_t sequence; - mpeg2_gop_t new_gop; - mpeg2_gop_t gop; - mpeg2_picture_t new_picture; - mpeg2_picture_t pictures[4]; - mpeg2_picture_t * picture; - /*const*/ mpeg2_fbuf_t * fbuf[3]; /* 0: current fbuf, 1-2: prediction fbufs */ - - fbuf_alloc_t fbuf_alloc[3]; - int custom_fbuf; - - uint8_t * yuv_buf[3][MPEG2_COMPONENTS]; - int yuv_index; - mpeg2_convert_t * convert; - void * convert_arg; - unsigned int convert_id_size; - int convert_stride; - void (* convert_start) (void * id, const mpeg2_fbuf_t * fbuf, - const mpeg2_picture_t * picture, - const mpeg2_gop_t * gop); - - uint8_t * buf_start; - uint8_t * buf_end; - - int16_t display_offset_x, display_offset_y; - - int copy_matrix; - int8_t q_scale_type, scaled[4]; - uint8_t quantizer_matrix[4][64]; - uint8_t new_quantizer_matrix[4][64]; -}; - -/* decode.c */ -mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec); -mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec); - -/* header.c */ -void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec); -void mpeg2_reset_info (mpeg2_info_t * info); -int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec); -int mpeg2_header_gop (mpeg2dec_t * mpeg2dec); -int mpeg2_header_picture (mpeg2dec_t * mpeg2dec); -int mpeg2_header_extension (mpeg2dec_t * mpeg2dec); -int mpeg2_header_user_data (mpeg2dec_t * mpeg2dec); -void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec); -void mpeg2_header_gop_finalize (mpeg2dec_t * mpeg2dec); -void mpeg2_header_picture_finalize (mpeg2dec_t * mpeg2dec); -mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec); -mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec); -void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type); - -/* idct.c */ -void mpeg2_idct_init (void); -void mpeg2_idct_copy(int16_t * block, uint8_t * dest, - const int stride); -void mpeg2_idct_add(const int last, int16_t * block, - uint8_t * dest, const int stride); - -extern const uint8_t default_mpeg2_scan_norm[64]; -extern const uint8_t default_mpeg2_scan_alt[64]; -extern uint8_t mpeg2_scan_norm[64]; -extern uint8_t mpeg2_scan_alt[64]; - -/* motion_comp.c */ -void mpeg2_mc_init (void); - -typedef struct -{ - mpeg2_mc_fct * put [8]; - mpeg2_mc_fct * avg [8]; -} mpeg2_mc_t; - -extern const mpeg2_mc_t mpeg2_mc; - -#endif /* MPEG2_INTERNAL_H */ - diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h deleted file mode 100644 index c34ee374df..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id$ */ -#ifndef MPEG2DEC_CONFIG_H -#define MPEG2DEC_CONFIG_H - -#define ATTRIBUTE_ALIGNED_MAX 16 - -#ifdef HAVE_LCD_COLOR -#define MPEG2_COLOR 1 -#define MPEG2_COMPONENTS 3 -#else -#define MPEG2_COLOR 0 -#define MPEG2_COMPONENTS 1 -#endif - -#endif /* MPEG2DEC_CONFIG_H */ diff --git a/apps/plugins/mpegplayer/libmpeg2/slice.c b/apps/plugins/mpegplayer/libmpeg2/slice.c deleted file mode 100644 index 926333d5d0..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/slice.c +++ /dev/null @@ -1,2898 +0,0 @@ -/* - * slice.c - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 2003 Peter Gubanov - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.55 - */ - -#include "plugin.h" - -#include "mpeg2dec_config.h" - -#include "mpeg2.h" -#include "attributes.h" -#include "mpeg2_internal.h" - -#include "vlc.h" - -static inline int get_macroblock_modes (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - int macroblock_modes; - const MBtab * tab; - - switch (decoder->coding_type) - { - case I_TYPE: - tab = MB_I + UBITS (bit_buf, 1); - DUMPBITS (bit_buf, bits, tab->len); - macroblock_modes = tab->modes; - - if (!(decoder->frame_pred_frame_dct) && - decoder->picture_structure == FRAME_PICTURE) - { - macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; - DUMPBITS (bit_buf, bits, 1); - } - - return macroblock_modes; - - case P_TYPE: - tab = MB_P + UBITS (bit_buf, 5); - DUMPBITS (bit_buf, bits, tab->len); - macroblock_modes = tab->modes; - - if (decoder->picture_structure != FRAME_PICTURE) - { - if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) - { - macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; - DUMPBITS (bit_buf, bits, 2); - } - - return macroblock_modes | MACROBLOCK_MOTION_FORWARD; - } - else if (decoder->frame_pred_frame_dct) - { - if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) - macroblock_modes |= MC_FRAME << MOTION_TYPE_SHIFT; - - return macroblock_modes | MACROBLOCK_MOTION_FORWARD; - } - else - { - if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) - { - macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; - DUMPBITS (bit_buf, bits, 2); - } - - if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) - { - macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; - DUMPBITS (bit_buf, bits, 1); - } - - return macroblock_modes | MACROBLOCK_MOTION_FORWARD; - } - - case B_TYPE: - tab = MB_B + UBITS (bit_buf, 6); - DUMPBITS (bit_buf, bits, tab->len); - macroblock_modes = tab->modes; - - if (decoder->picture_structure != FRAME_PICTURE) - { - if (! (macroblock_modes & MACROBLOCK_INTRA)) - { - macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; - DUMPBITS (bit_buf, bits, 2); - } - - return macroblock_modes; - } - else if (decoder->frame_pred_frame_dct) - { - /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ - macroblock_modes |= MC_FRAME << MOTION_TYPE_SHIFT; - return macroblock_modes; - } - else - { - if (macroblock_modes & MACROBLOCK_INTRA) - goto intra; - - macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; - DUMPBITS (bit_buf, bits, 2); - - if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) - { - intra: - macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; - DUMPBITS (bit_buf, bits, 1); - } - return macroblock_modes; - } - - case D_TYPE: - DUMPBITS (bit_buf, bits, 1); - return MACROBLOCK_INTRA; - - default: - return 0; - } -#undef bit_buf -#undef bits -#undef bit_ptr -} - -static inline void get_quantizer_scale (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - int quantizer_scale_code; - - quantizer_scale_code = UBITS (bit_buf, 5); - DUMPBITS (bit_buf, bits, 5); - - decoder->quantizer_matrix[0] = - decoder->quantizer_prescale[0][quantizer_scale_code]; - - decoder->quantizer_matrix[1] = - decoder->quantizer_prescale[1][quantizer_scale_code]; - - decoder->quantizer_matrix[2] = - decoder->chroma_quantizer[0][quantizer_scale_code]; - - decoder->quantizer_matrix[3] = - decoder->chroma_quantizer[1][quantizer_scale_code]; -#undef bit_buf -#undef bits -#undef bit_ptr -} - -static inline int get_motion_delta (mpeg2_decoder_t * const decoder, - const int f_code) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - int delta; - int sign; - const MVtab * tab; - - if (bit_buf & 0x80000000) - { - DUMPBITS (bit_buf, bits, 1); - return 0; - } - else if (bit_buf >= 0x0c000000) - { - tab = MV_4 + UBITS (bit_buf, 4); - delta = (tab->delta << f_code) + 1; - bits += tab->len + f_code + 1; - bit_buf <<= tab->len; - - sign = SBITS (bit_buf, 1); - bit_buf <<= 1; - - if (f_code) - delta += UBITS (bit_buf, f_code); - bit_buf <<= f_code; - - return (delta ^ sign) - sign; - } - else - { - tab = MV_10 + UBITS (bit_buf, 10); - delta = (tab->delta << f_code) + 1; - bits += tab->len + 1; - bit_buf <<= tab->len; - - sign = SBITS (bit_buf, 1); - bit_buf <<= 1; - - if (f_code) - { - NEEDBITS (bit_buf, bits, bit_ptr); - delta += UBITS (bit_buf, f_code); - DUMPBITS (bit_buf, bits, f_code); - } - - return (delta ^ sign) - sign; - - } -#undef bit_buf -#undef bits -#undef bit_ptr -} - -static inline int bound_motion_vector (const int vector, const int f_code) -{ - return ((int32_t)vector << (27 - f_code)) >> (27 - f_code); -} - -static inline int get_dmv (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - const DMVtab * tab; - - tab = DMV_2 + UBITS (bit_buf, 2); - DUMPBITS (bit_buf, bits, tab->len); - return tab->dmv; - -#undef bit_buf -#undef bits -#undef bit_ptr -} - -static inline int get_coded_block_pattern (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - const CBPtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - if (bit_buf >= 0x20000000) - { - tab = CBP_7 + (UBITS (bit_buf, 7) - 16); - DUMPBITS (bit_buf, bits, tab->len); - return tab->cbp; - } - else - { - tab = CBP_9 + UBITS (bit_buf, 9); - DUMPBITS (bit_buf, bits, tab->len); - return tab->cbp; - } - -#undef bit_buf -#undef bits -#undef bit_ptr -} - -static inline int get_luma_dc_dct_diff (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - const DCtab * tab; - int size; - int dc_diff; - - if (bit_buf < 0xf8000000) - { - tab = DC_lum_5 + UBITS (bit_buf, 5); - size = tab->size; - - if (size) - { - bits += tab->len + size; - bit_buf <<= tab->len; - dc_diff = - UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); - bit_buf <<= size; - return dc_diff << decoder->intra_dc_precision; - } - else - { - DUMPBITS (bit_buf, bits, 3); - return 0; - } - } - else - { - tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); - size = tab->size; - DUMPBITS (bit_buf, bits, tab->len); - NEEDBITS (bit_buf, bits, bit_ptr); - dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); - DUMPBITS (bit_buf, bits, size); - return dc_diff << decoder->intra_dc_precision; - } - -#undef bit_buf -#undef bits -#undef bit_ptr -} - -#if MPEG2_COLOR -static inline int get_chroma_dc_dct_diff (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - const DCtab * tab; - int size; - int dc_diff; - - if (bit_buf < 0xf8000000) - { - tab = DC_chrom_5 + UBITS (bit_buf, 5); - size = tab->size; - - if (size) - { - bits += tab->len + size; - bit_buf <<= tab->len; - dc_diff = - UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); - bit_buf <<= size; - return dc_diff << decoder->intra_dc_precision; - } - else - { - DUMPBITS (bit_buf, bits, 2); - return 0; - } - } - else - { - tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); - size = tab->size; - DUMPBITS (bit_buf, bits, tab->len + 1); - NEEDBITS (bit_buf, bits, bit_ptr); - dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); - DUMPBITS (bit_buf, bits, size); - return dc_diff << decoder->intra_dc_precision; - } - -#undef bit_buf -#undef bits -#undef bit_ptr -} -#endif /* MPEG2_COLOR */ - -#define SATURATE(val) \ - do { \ - val <<= 4; \ - if (unlikely (val != (int16_t) val)) \ - val = (SBITS (val, 1) ^ 2047) << 4; \ - } while (0) - -static void get_intra_block_B14 (mpeg2_decoder_t * const decoder, - const uint16_t * const quant_matrix) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - const uint8_t * const scan = decoder->scan; - int16_t * const dest = decoder->DCTblock; - int mismatch = ~dest[0]; - int i = 0; - int j; - int val; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - while (1) - { - if (bit_buf >= 0x28000000) - { - tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); - - i += tab->run; - if (i >= 64) - break; /* end of block */ - - normal_code: - j = scan[i]; - bit_buf <<= tab->len; - bits += tab->len + 1; - val = (tab->level * quant_matrix[j]) >> 4; - - /* if (bitstream_get (1)) val = -val; */ - val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); - - SATURATE (val); - dest[j] = val; - mismatch ^= val; - - bit_buf <<= 1; - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - else if (bit_buf >= 0x04000000) - { - tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - if (i < 64) - goto normal_code; - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check needed to avoid buffer overflow */ - - j = scan[i]; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - val = (SBITS (bit_buf, 12) * quant_matrix[j]) / 16; - - SATURATE (val); - dest[j] = val; - mismatch ^= val; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - dest[63] ^= mismatch & 16; - DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; -} - -static void get_intra_block_B15 (mpeg2_decoder_t * const decoder, - const uint16_t * const quant_matrix) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - const uint8_t * const scan = decoder->scan; - int16_t * const dest = decoder->DCTblock; - int mismatch = ~dest[0]; - int i = 0; - int j; - int val; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - while (1) - { - if (bit_buf >= 0x04000000) - { - tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - - if (i < 64) - { - normal_code: - j = scan[i]; - bit_buf <<= tab->len; - bits += tab->len + 1; - val = (tab->level * quant_matrix[j]) >> 4; - - /* if (bitstream_get (1)) val = -val; */ - val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); - - SATURATE (val); - dest[j] = val; - mismatch ^= val; - - bit_buf <<= 1; - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - else - { - /* end of block. I commented out this code because if we */ - /* dont exit here we will still exit at the later test :) */ - - /* if (i >= 128) break; */ /* end of block */ - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check against buffer overflow */ - - j = scan[i]; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - val = (SBITS (bit_buf, 12) * quant_matrix[j]) / 16; - - SATURATE (val); - dest[j] = val; - mismatch ^= val; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - dest[63] ^= mismatch & 16; - DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; -} - -static int get_non_intra_block (mpeg2_decoder_t * const decoder, - const uint16_t * const quant_matrix) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - const uint8_t * const scan = decoder->scan; - int16_t * const dest = decoder->DCTblock; - int mismatch = -1; - int i = -1; - int j; - int val; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - if (bit_buf >= 0x28000000) - { - tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); - goto entry_1; - } - else - { - goto entry_2; - } - - while (1) - { - if (bit_buf >= 0x28000000) - { - tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); - - entry_1: - i += tab->run; - if (i >= 64) - break; /* end of block */ - - normal_code: - j = scan[i]; - bit_buf <<= tab->len; - bits += tab->len + 1; - val = ((2 * tab->level + 1) * quant_matrix[j]) >> 5; - - /* if (bitstream_get (1)) val = -val; */ - val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); - - SATURATE (val); - dest[j] = val; - mismatch ^= val; - - bit_buf <<= 1; - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - - entry_2: - if (bit_buf >= 0x04000000) - { - tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - if (i < 64) - goto normal_code; - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check needed to avoid buffer overflow */ - - j = scan[i]; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1; - val = (val * quant_matrix[j]) / 32; - - SATURATE (val); - dest[j] = val; - mismatch ^= val; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - dest[63] ^= mismatch & 16; - DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; - return i; -} - -static void get_mpeg1_intra_block (mpeg2_decoder_t * const decoder) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - const uint8_t * const scan = decoder->scan; - const uint16_t * const quant_matrix = decoder->quantizer_matrix[0]; - int16_t * const dest = decoder->DCTblock; - int i = 0; - int j; - int val; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - while (1) - { - if (bit_buf >= 0x28000000) - { - tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); - - i += tab->run; - if (i >= 64) - break; /* end of block */ - - normal_code: - j = scan[i]; - bit_buf <<= tab->len; - bits += tab->len + 1; - val = (tab->level * quant_matrix[j]) >> 4; - - /* oddification */ - val = (val - 1) | 1; - - /* if (bitstream_get (1)) val = -val; */ - val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); - - SATURATE (val); - dest[j] = val; - - bit_buf <<= 1; - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - else if (bit_buf >= 0x04000000) - { - tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - if (i < 64) - goto normal_code; - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check needed to avoid buffer overflow */ - - j = scan[i]; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - val = SBITS (bit_buf, 8); - - if (! (val & 0x7f)) - { - DUMPBITS (bit_buf, bits, 8); - val = UBITS (bit_buf, 8) + 2 * val; - } - - val = (val * quant_matrix[j]) / 16; - - /* oddification */ - val = (val + ~SBITS (val, 1)) | 1; - - SATURATE (val); - dest[j] = val; - - DUMPBITS (bit_buf, bits, 8); - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; -} - -static int get_mpeg1_non_intra_block (mpeg2_decoder_t * const decoder) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - const uint8_t * const scan = decoder->scan; - const uint16_t * const quant_matrix = decoder->quantizer_matrix[1]; - int16_t * const dest = decoder->DCTblock; - int i = -1; - int j; - int val; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - if (bit_buf >= 0x28000000) - { - tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); - goto entry_1; - } - else - { - goto entry_2; - } - - while (1) - { - if (bit_buf >= 0x28000000) - { - tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); - - entry_1: - i += tab->run; - if (i >= 64) - break; /* end of block */ - - normal_code: - j = scan[i]; - bit_buf <<= tab->len; - bits += tab->len + 1; - val = ((2 * tab->level + 1) * quant_matrix[j]) >> 5; - - /* oddification */ - val = (val - 1) | 1; - - /* if (bitstream_get (1)) val = -val; */ - val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); - - SATURATE (val); - dest[j] = val; - - bit_buf <<= 1; - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - - entry_2: - if (bit_buf >= 0x04000000) - { - tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - if (i < 64) - goto normal_code; - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check needed to avoid buffer overflow */ - - j = scan[i]; - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - val = SBITS (bit_buf, 8); - - if (! (val & 0x7f)) - { - DUMPBITS (bit_buf, bits, 8); - val = UBITS (bit_buf, 8) + 2 * val; - } - - val = 2 * (val + SBITS (val, 1)) + 1; - val = (val * quant_matrix[j]) / 32; - - /* oddification */ - val = (val + ~SBITS (val, 1)) | 1; - - SATURATE (val); - dest[j] = val; - - DUMPBITS (bit_buf, bits, 8); - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; - return i; -} - -static inline void slice_intra_DCT (mpeg2_decoder_t * const decoder, - const int cc, - uint8_t * const dest, const int stride) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - NEEDBITS (bit_buf, bits, bit_ptr); - /* Get the intra DC coefficient and inverse quantize it */ - if (cc == 0) - { - decoder->dc_dct_pred[0] += get_luma_dc_dct_diff (decoder); - decoder->DCTblock[0] = decoder->dc_dct_pred[0]; - - } -#if MPEG2_COLOR - else - { - decoder->dc_dct_pred[cc] += get_chroma_dc_dct_diff (decoder); - decoder->DCTblock[0] = decoder->dc_dct_pred[cc]; - } -#endif - - if (decoder->mpeg1) - { - if (decoder->coding_type != D_TYPE) - get_mpeg1_intra_block (decoder); - } - else if (decoder->intra_vlc_format) - { - get_intra_block_B15 (decoder, decoder->quantizer_matrix[cc ? 2 : 0]); - } - else - { - get_intra_block_B14 (decoder, decoder->quantizer_matrix[cc ? 2 : 0]); - } - - mpeg2_idct_copy (decoder->DCTblock, dest, stride); - -#undef bit_buf -#undef bits -#undef bit_ptr -} - -static inline void slice_non_intra_DCT (mpeg2_decoder_t * const decoder, - const int cc, - uint8_t * const dest, const int stride) -{ - int last; - - if (decoder->mpeg1) - { - last = get_mpeg1_non_intra_block (decoder); - } - else - { - last = get_non_intra_block (decoder, - decoder->quantizer_matrix[cc ? 3 : 1]); - } - - mpeg2_idct_add (last, decoder->DCTblock, dest, stride); -} - -#if !MPEG2_COLOR -static void skip_mpeg1_intra_block (mpeg2_decoder_t * const decoder) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - int i = 0; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - while (1) - { - if (bit_buf >= 0x28000000) - { - tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); - - i += tab->run; - if (i >= 64) - break; /* end of block */ - - normal_code: - bit_buf <<= tab->len + 1; - bits += tab->len + 1; - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - } - else if (bit_buf >= 0x04000000) - { - tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - if (i < 64) - goto normal_code; - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check needed to avoid buffer overflow */ - - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - - if (!(SBITS (bit_buf, 8) & 0x7f)) - DUMPBITS (bit_buf, bits, 8); - - DUMPBITS (bit_buf, bits, 8); - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; -} - -static void skip_intra_block_B14 (mpeg2_decoder_t * const decoder) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - int i = 0; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - while (1) - { - if (bit_buf >= 0x28000000) - { - tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); - - i += tab->run; - if (i >= 64) - break; /* end of block */ - - normal_code: - bit_buf <<= tab->len + 1; - bits += tab->len + 1; - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - } - else if (bit_buf >= 0x04000000) - { - tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - if (i < 64) - goto normal_code; - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check needed to avoid buffer overflow */ - - DUMPBITS (bit_buf, bits, 12); /* Can't dump more than 16 atm */ - NEEDBITS (bit_buf, bits, bit_ptr); - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; -} - -static void skip_intra_block_B15 (mpeg2_decoder_t * const decoder) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - int i = 0; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - while (1) - { - if (bit_buf >= 0x04000000) - { - tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - - if (i < 64) - { - normal_code: - bit_buf <<= tab->len + 1; - bits += tab->len + 1; - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - } - else - { - /* end of block. I commented out this code because if we */ - /* dont exit here we will still exit at the later test :) */ - - /* if (i >= 128) break; */ /* end of block */ - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check against buffer overflow */ - - DUMPBITS (bit_buf, bits, 12); /* Can't dump more than 16 atm */ - NEEDBITS (bit_buf, bits, bit_ptr); - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - } - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - DUMPBITS (bit_buf, bits, 4); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; -} - -static void skip_non_intra_block (mpeg2_decoder_t * const decoder) -{ - uint32_t bit_buf = decoder->bitstream_buf; - int bits = decoder->bitstream_bits; - const uint8_t * bit_ptr = decoder->bitstream_ptr; - int i = -1; - const DCTtab * tab; - - NEEDBITS (bit_buf, bits, bit_ptr); - - if (bit_buf >= 0x28000000) - { - tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); - goto entry_1; - } - else - { - goto entry_2; - } - - while (1) - { - if (bit_buf >= 0x28000000) - { - tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); - - entry_1: - i += tab->run; - if (i >= 64) - break; /* end of block */ - - normal_code: - bit_buf <<= tab->len + 1; - bits += tab->len + 1; - NEEDBITS (bit_buf, bits, bit_ptr); - - continue; - } - - entry_2: - if (bit_buf >= 0x04000000) - { - tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); - - i += tab->run; - if (i < 64) - goto normal_code; - - /* escape code */ - - i += UBITS (bit_buf << 6, 6) - 64; - if (i >= 64) - break; /* illegal, check needed to avoid buffer overflow */ - - if (decoder->mpeg1) - { - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - - if (!(SBITS (bit_buf, 8) & 0x7f)) - DUMPBITS (bit_buf, bits, 8); - - DUMPBITS (bit_buf, bits, 8); - } - else - { - DUMPBITS (bit_buf, bits, 12); - NEEDBITS (bit_buf, bits, bit_ptr); - DUMPBITS (bit_buf, bits, 12); - } - - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - } - else if (bit_buf >= 0x02000000) - { - tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00800000) - { - tab = DCT_13 + (UBITS (bit_buf, 13) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else if (bit_buf >= 0x00200000) - { - tab = DCT_15 + (UBITS (bit_buf, 15) - 16); - i += tab->run; - if (i < 64) - goto normal_code; - } - else - { - tab = DCT_16 + UBITS (bit_buf, 16); - bit_buf <<= 16; - GETWORD (bit_buf, bits + 16, bit_ptr); - i += tab->run; - if (i < 64) - goto normal_code; - } - break; /* illegal, check needed to avoid buffer overflow */ - } - - DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ - decoder->bitstream_buf = bit_buf; - decoder->bitstream_bits = bits; - decoder->bitstream_ptr = bit_ptr; -} - -static void skip_chroma_dc_dct_diff (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - const DCtab * tab; - int size; - - if (bit_buf < 0xf8000000) - { - tab = DC_chrom_5 + UBITS (bit_buf, 5); - size = tab->size; - - if (size) - { - bits += tab->len + size; - bit_buf <<= tab->len; - bit_buf <<= size; - } - else - { - DUMPBITS (bit_buf, bits, 2); - } - } - else - { - tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); - size = tab->size; - DUMPBITS (bit_buf, bits, tab->len + 1); - NEEDBITS (bit_buf, bits, bit_ptr); - DUMPBITS (bit_buf, bits, size); - } - -#undef bit_buf -#undef bits -#undef bit_ptr -} - -static void skip_chroma_non_intra (mpeg2_decoder_t * const decoder, - uint32_t coded_block_pattern) -{ - static const uint32_t cbp_mask[3] = - { - 0x00000030, - 0xc0000030, - 0xfc000030, - }; - - uint32_t cbp = coded_block_pattern & - cbp_mask[MIN((unsigned)decoder->chroma_format, 2u)]; - - while (cbp) - { - skip_non_intra_block (decoder); - cbp &= (cbp - 1); - } -} - -static void skip_chroma_intra (mpeg2_decoder_t * const decoder) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - int i = 2 << decoder->chroma_format; - - if ((unsigned)i > 8) - i = 8; - - while (i-- > 0) - { - NEEDBITS (bit_buf, bits, bit_ptr); - - skip_chroma_dc_dct_diff (decoder); - - if (decoder->mpeg1) - { - if (decoder->coding_type != D_TYPE) - skip_mpeg1_intra_block (decoder); - } - else if (decoder->intra_vlc_format) - { - skip_intra_block_B15 (decoder); - } - else - { - skip_intra_block_B14 (decoder); - } - } - - if (decoder->chroma_format == 0 && decoder->coding_type == D_TYPE) - { - NEEDBITS (bit_buf, bits, bit_ptr); - DUMPBITS (bit_buf, bits, 1); - } - -#undef bit_buf -#undef bits -#undef bit_ptr -} -#endif /* !MPEG2_COLOR */ - -#define MOTION_420(table, ref, motion_x, motion_y, size, y) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y_ ## size)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \ - motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \ - ref[0] + (pos_x >> 1) + (pos_y >> 1) * decoder->stride, \ - decoder->stride, size); \ - \ - if (MPEG2_COLOR) \ - { \ - motion_x /= 2; \ - motion_y /= 2; \ - xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \ - offset = ((decoder->offset + motion_x) >> 1) + \ - ((((decoder->v_offset + motion_y) >> 1) + y/2) * \ - decoder->uv_stride); \ - \ - table[4+xy_half] (decoder->dest[1] + y/2 * decoder->uv_stride + \ - (decoder->offset >> 1), ref[1] + offset, \ - decoder->uv_stride, size/2); \ - table[4+xy_half] (decoder->dest[2] + y/2 * decoder->uv_stride + \ - (decoder->offset >> 1), ref[2] + offset, \ - decoder->uv_stride, size/2); \ - } - -#define MOTION_FIELD_420(table, ref, motion_x, motion_y, \ - dest_field, op, src_field) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = decoder->v_offset + motion_y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ - motion_y = pos_y - decoder->v_offset; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \ - decoder->offset, \ - (ref[0] + (pos_x >> 1) + \ - ((pos_y op) + src_field) * decoder->stride), \ - 2 * decoder->stride, 8); \ - \ - if (MPEG2_COLOR) \ - { \ - motion_x /= 2; \ - motion_y /= 2; \ - xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \ - offset = ((decoder->offset + motion_x) >> 1) + \ - (((decoder->v_offset >> 1) + (motion_y op) + src_field) * \ - decoder->uv_stride); \ - \ - table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride + \ - (decoder->offset >> 1), ref[1] + offset, \ - 2 * decoder->uv_stride, 4); \ - table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride + \ - (decoder->offset >> 1), ref[2] + offset, \ - 2 * decoder->uv_stride, 4); \ - } - -#define MOTION_DMV_420(table, ref, motion_x, motion_y) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = decoder->v_offset + motion_y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ - motion_y = pos_y - decoder->v_offset; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \ - table[xy_half] (decoder->dest[0] + decoder->offset, \ - ref[0] + offset, 2 * decoder->stride, 8); \ - table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \ - ref[0] + decoder->stride + offset, \ - 2 * decoder->stride, 8); \ - \ - if (MPEG2_COLOR) \ - { \ - motion_x /= 2; \ - motion_y /= 2; \ - xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \ - offset = ((decoder->offset + motion_x) >> 1) + \ - (((decoder->v_offset >> 1) + (motion_y & ~1)) * \ - decoder->uv_stride); \ - \ - table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1), \ - ref[1] + offset, 2 * decoder->uv_stride, 4); \ - table[4+xy_half] (decoder->dest[1] + decoder->uv_stride + \ - (decoder->offset >> 1), \ - ref[1] + decoder->uv_stride + offset, \ - 2 * decoder->uv_stride, 4); \ - table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1), \ - ref[2] + offset, 2 * decoder->uv_stride, 4); \ - table[4+xy_half] (decoder->dest[2] + decoder->uv_stride + \ - (decoder->offset >> 1), \ - ref[2] + decoder->uv_stride + offset, \ - 2 * decoder->uv_stride, 4); \ - } - -#define MOTION_ZERO_420(table, ref) \ - table[0] (decoder->dest[0] + decoder->offset, \ - (ref[0] + decoder->offset + \ - decoder->v_offset * decoder->stride), decoder->stride, 16); \ - \ - if (MPEG2_COLOR) \ - { \ - offset = ((decoder->offset >> 1) + \ - (decoder->v_offset >> 1) * decoder->uv_stride); \ - \ - table[4] (decoder->dest[1] + (decoder->offset >> 1), \ - ref[1] + offset, decoder->uv_stride, 8); \ - table[4] (decoder->dest[2] + (decoder->offset >> 1), \ - ref[2] + offset, decoder->uv_stride, 8); \ - } - -#define MOTION_422(table, ref, motion_x, motion_y, size, y) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y_ ## size)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \ - motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride; \ - \ - table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \ - ref[0] + offset, decoder->stride, size); \ - \ - if (MPEG2_COLOR) \ - { \ - offset = (offset + (motion_x & (motion_x < 0))) >> 1; \ - motion_x /= 2; \ - xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \ - \ - table[4+xy_half] (decoder->dest[1] + y * decoder->uv_stride + \ - (decoder->offset >> 1), ref[1] + offset, \ - decoder->uv_stride, size); \ - table[4+xy_half] (decoder->dest[2] + y * decoder->uv_stride + \ - (decoder->offset >> 1), ref[2] + offset, \ - decoder->uv_stride, size); \ - } - -#define MOTION_FIELD_422(table, ref, motion_x, motion_y, \ - dest_field, op, src_field) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = decoder->v_offset + motion_y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ - motion_y = pos_y - decoder->v_offset; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride; \ - \ - table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \ - decoder->offset, ref[0] + offset, \ - 2 * decoder->stride, 8); \ - \ - if (MPEG2_COLOR) \ - { \ - offset = (offset + (motion_x & (motion_x < 0))) >> 1; \ - motion_x /= 2; \ - xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \ - \ - table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride + \ - (decoder->offset >> 1), ref[1] + offset, \ - 2 * decoder->uv_stride, 8); \ - table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride + \ - (decoder->offset >> 1), ref[2] + offset, \ - 2 * decoder->uv_stride, 8); \ - } - -#define MOTION_DMV_422(table, ref, motion_x, motion_y) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = decoder->v_offset + motion_y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ - motion_y = pos_y - decoder->v_offset; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \ - \ - table[xy_half] (decoder->dest[0] + decoder->offset, \ - ref[0] + offset, 2 * decoder->stride, 8); \ - table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \ - ref[0] + decoder->stride + offset, \ - 2 * decoder->stride, 8); \ - \ - if (MPEG2_COLOR) \ - { \ - offset = (offset + (motion_x & (motion_x < 0))) >> 1; \ - motion_x /= 2; \ - xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \ - \ - table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1), \ - ref[1] + offset, 2 * decoder->uv_stride, 8); \ - table[4+xy_half] (decoder->dest[1] + decoder->uv_stride + \ - (decoder->offset >> 1), \ - ref[1] + decoder->uv_stride + offset, \ - 2 * decoder->uv_stride, 8); \ - table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1), \ - ref[2] + offset, 2 * decoder->uv_stride, 8); \ - table[4+xy_half] (decoder->dest[2] + decoder->uv_stride + \ - (decoder->offset >> 1), \ - ref[2] + decoder->uv_stride + offset, \ - 2 * decoder->uv_stride, 8); \ - } - -#define MOTION_ZERO_422(table, ref) \ - offset = decoder->offset + decoder->v_offset * decoder->stride; \ - table[0] (decoder->dest[0] + decoder->offset, \ - ref[0] + offset, decoder->stride, 16); \ - \ - if (MPEG2_COLOR) \ - { \ - offset >>= 1; \ - table[4] (decoder->dest[1] + (decoder->offset >> 1), \ - ref[1] + offset, decoder->uv_stride, 16); \ - table[4] (decoder->dest[2] + (decoder->offset >> 1), \ - ref[2] + offset, decoder->uv_stride, 16); \ - } - -#define MOTION_444(table, ref, motion_x, motion_y, size, y) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y_ ## size)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \ - motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride; \ - \ - table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \ - ref[0] + offset, decoder->stride, size); \ - \ - if (MPEG2_COLOR) \ - { \ - table[xy_half] (decoder->dest[1] + y * decoder->stride + decoder->offset, \ - ref[1] + offset, decoder->stride, size); \ - table[xy_half] (decoder->dest[2] + y * decoder->stride + decoder->offset, \ - ref[2] + offset, decoder->stride, size); \ - } - -#define MOTION_FIELD_444(table, ref, motion_x, motion_y, \ - dest_field, op, src_field) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = decoder->v_offset + motion_y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ - motion_y = pos_y - decoder->v_offset; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride; \ - \ - table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \ - decoder->offset, ref[0] + offset, \ - 2 * decoder->stride, 8); \ - \ - if (MPEG2_COLOR) \ - { \ - table[xy_half] (decoder->dest[1] + dest_field * decoder->stride + \ - decoder->offset, ref[1] + offset, \ - 2 * decoder->stride, 8); \ - table[xy_half] (decoder->dest[2] + dest_field * decoder->stride + \ - decoder->offset, ref[2] + offset, \ - 2 * decoder->stride, 8); \ - } - -#define MOTION_DMV_444(table, ref, motion_x, motion_y) \ - pos_x = 2 * decoder->offset + motion_x; \ - pos_y = decoder->v_offset + motion_y; \ - \ - if (unlikely (pos_x > decoder->limit_x)) \ - { \ - pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ - motion_x = pos_x - 2 * decoder->offset; \ - } \ - \ - if (unlikely (pos_y > decoder->limit_y)) \ - { \ - pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ - motion_y = pos_y - decoder->v_offset; \ - } \ - \ - xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ - offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \ - \ - table[xy_half] (decoder->dest[0] + decoder->offset, \ - ref[0] + offset, 2 * decoder->stride, 8); \ - table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \ - ref[0] + decoder->stride + offset, \ - 2 * decoder->stride, 8); \ - \ - if (MPEG2_COLOR) \ - { \ - table[xy_half] (decoder->dest[1] + decoder->offset, \ - ref[1] + offset, 2 * decoder->stride, 8); \ - table[xy_half] (decoder->dest[1] + decoder->stride + decoder->offset, \ - ref[1] + decoder->stride + offset, \ - 2 * decoder->stride, 8); \ - table[xy_half] (decoder->dest[2] + decoder->offset, \ - ref[2] + offset, 2 * decoder->stride, 8); \ - table[xy_half] (decoder->dest[2] + decoder->stride + decoder->offset, \ - ref[2] + decoder->stride + offset, \ - 2 * decoder->stride, 8); \ - } - -#define MOTION_ZERO_444(table, ref) \ - offset = decoder->offset + decoder->v_offset * decoder->stride; \ - \ - table[0] (decoder->dest[0] + decoder->offset, \ - ref[0] + offset, decoder->stride, 16); \ - \ - if (MPEG2_COLOR) \ - { \ - table[4] (decoder->dest[1] + decoder->offset, \ - ref[1] + offset, decoder->stride, 16); \ - table[4] (decoder->dest[2] + decoder->offset, \ - ref[2] + offset, decoder->stride, 16); \ - } - -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - -static void motion_mp1 (mpeg2_decoder_t * const decoder, - motion_t * const motion, - mpeg2_mc_fct * const * const table) -{ - int motion_x, motion_y; - unsigned int pos_x, pos_y, xy_half, offset; - - NEEDBITS (bit_buf, bits, bit_ptr); - motion_x = motion->pmv[0][0] + - (get_motion_delta (decoder, - motion->f_code[0]) << motion->f_code[1]); - motion_x = bound_motion_vector (motion_x, - motion->f_code[0] + motion->f_code[1]); - motion->pmv[0][0] = motion_x; - - NEEDBITS (bit_buf, bits, bit_ptr); - motion_y = motion->pmv[0][1] + - (get_motion_delta (decoder, - motion->f_code[0]) << motion->f_code[1]); - motion_y = bound_motion_vector (motion_y, - motion->f_code[0] + motion->f_code[1]); - motion->pmv[0][1] = motion_y; - - MOTION_420 (table, motion->ref[0], motion_x, motion_y, 16, 0); -} - -#define MOTION_FUNCTIONS(FORMAT, MOTION, MOTION_FIELD, \ - MOTION_DMV, MOTION_ZERO) \ - \ -static void motion_fr_frame_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - int motion_x, motion_y; \ - unsigned int pos_x, pos_y, xy_half, offset; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ - motion->f_code[1]); \ - motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ - motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \ - \ - MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); \ -} \ - \ -static void motion_fr_field_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - int motion_x, motion_y, field; \ - unsigned int pos_x, pos_y, xy_half, offset; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - field = UBITS (bit_buf, 1); \ - DUMPBITS (bit_buf, bits, 1); \ - \ - motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[0][0] = motion_x; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_y = ((motion->pmv[0][1] >> 1) + \ - get_motion_delta (decoder, motion->f_code[1])); \ - /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \ - motion->pmv[0][1] = motion_y << 1; \ - \ - MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 0, & ~1, field); \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - field = UBITS (bit_buf, 1); \ - DUMPBITS (bit_buf, bits, 1); \ - \ - motion_x = motion->pmv[1][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[1][0] = motion_x; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_y = ((motion->pmv[1][1] >> 1) + \ - get_motion_delta (decoder, motion->f_code[1])); \ - /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \ - motion->pmv[1][1] = motion_y << 1; \ - \ - MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 1, & ~1, field); \ -} \ - \ -static void motion_fr_dmv_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - int motion_x, motion_y, dmv_x, dmv_y, m, other_x, other_y; \ - unsigned int pos_x, pos_y, xy_half, offset; \ - \ - (void)table; \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - dmv_x = get_dmv (decoder); \ - \ - motion_y = ((motion->pmv[0][1] >> 1) + \ - get_motion_delta (decoder, motion->f_code[1])); \ - /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \ - motion->pmv[1][1] = motion->pmv[0][1] = motion_y << 1; \ - dmv_y = get_dmv (decoder); \ - \ - m = decoder->top_field_first ? 1 : 3; \ - other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; \ - other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y - 1; \ - MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 0, | 1, 0); \ - \ - m = decoder->top_field_first ? 3 : 1; \ - other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; \ - other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y + 1; \ - MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 1, & ~1, 0);\ - \ - MOTION_DMV (mpeg2_mc.avg, motion->ref[0], motion_x, motion_y); \ -} \ - \ -static void motion_reuse_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - int motion_x, motion_y; \ - unsigned int pos_x, pos_y, xy_half, offset; \ - \ - motion_x = motion->pmv[0][0]; \ - motion_y = motion->pmv[0][1]; \ - \ - MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); \ -} \ - \ -static void motion_zero_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - unsigned int offset; \ - \ - motion->pmv[0][0] = motion->pmv[0][1] = 0; \ - motion->pmv[1][0] = motion->pmv[1][1] = 0; \ - \ - MOTION_ZERO (table, motion->ref[0]); \ -} \ - \ -static void motion_fi_field_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - int motion_x, motion_y; \ - uint8_t ** ref_field; \ - unsigned int pos_x, pos_y, xy_half, offset; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - ref_field = motion->ref2[UBITS (bit_buf, 1)]; \ - DUMPBITS (bit_buf, bits, 1); \ - \ - motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ - motion->f_code[1]); \ - motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ - motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \ - \ - MOTION (table, ref_field, motion_x, motion_y, 16, 0); \ -} \ - \ -static void motion_fi_16x8_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - int motion_x, motion_y; \ - uint8_t ** ref_field; \ - unsigned int pos_x, pos_y, xy_half, offset; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - ref_field = motion->ref2[UBITS (bit_buf, 1)]; \ - DUMPBITS (bit_buf, bits, 1); \ - \ - motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[0][0] = motion_x; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ - motion->f_code[1]); \ - motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ - motion->pmv[0][1] = motion_y; \ - \ - MOTION (table, ref_field, motion_x, motion_y, 8, 0); \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - ref_field = motion->ref2[UBITS (bit_buf, 1)]; \ - DUMPBITS (bit_buf, bits, 1); \ - \ - motion_x = motion->pmv[1][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[1][0] = motion_x; \ - \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_y = motion->pmv[1][1] + get_motion_delta (decoder, \ - motion->f_code[1]); \ - motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ - motion->pmv[1][1] = motion_y; \ - \ - MOTION (table, ref_field, motion_x, motion_y, 8, 8); \ -} \ - \ -static void motion_fi_dmv_##FORMAT (mpeg2_decoder_t * const decoder, \ - motion_t * const motion, \ - mpeg2_mc_fct * const * const table) \ -{ \ - int motion_x, motion_y, other_x, other_y; \ - unsigned int pos_x, pos_y, xy_half, offset; \ - \ - (void)table; \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ - motion->f_code[0]); \ - motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ - motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ - NEEDBITS (bit_buf, bits, bit_ptr); \ - other_x = ((motion_x + (motion_x > 0)) >> 1) + get_dmv (decoder); \ - \ - motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ - motion->f_code[1]); \ - motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ - motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \ - other_y = (((motion_y + (motion_y > 0)) >> 1) + get_dmv (decoder) + \ - decoder->dmv_offset); \ - \ - MOTION (mpeg2_mc.put, motion->ref[0], motion_x, motion_y, 16, 0); \ - MOTION (mpeg2_mc.avg, motion->ref[1], other_x, other_y, 16, 0); \ -} \ - -MOTION_FUNCTIONS (420, MOTION_420, MOTION_FIELD_420, MOTION_DMV_420, - MOTION_ZERO_420) -MOTION_FUNCTIONS (422, MOTION_422, MOTION_FIELD_422, MOTION_DMV_422, - MOTION_ZERO_422) -MOTION_FUNCTIONS (444, MOTION_444, MOTION_FIELD_444, MOTION_DMV_444, - MOTION_ZERO_444) - -/* like motion_frame, but parsing without actual motion compensation */ -static void motion_fr_conceal (mpeg2_decoder_t * const decoder) -{ - int tmp; - - NEEDBITS (bit_buf, bits, bit_ptr); - tmp = (decoder->f_motion.pmv[0][0] + - get_motion_delta (decoder, decoder->f_motion.f_code[0])); - tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]); - decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[0][0] = tmp; - - NEEDBITS (bit_buf, bits, bit_ptr); - tmp = (decoder->f_motion.pmv[0][1] + - get_motion_delta (decoder, decoder->f_motion.f_code[1])); - tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]); - decoder->f_motion.pmv[1][1] = decoder->f_motion.pmv[0][1] = tmp; - - DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */ -} - -static void motion_fi_conceal (mpeg2_decoder_t * const decoder) -{ - int tmp; - - NEEDBITS (bit_buf, bits, bit_ptr); - DUMPBITS (bit_buf, bits, 1); /* remove field_select */ - - tmp = decoder->f_motion.pmv[0][0] + - get_motion_delta (decoder, decoder->f_motion.f_code[0]); - tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]); - - decoder->f_motion.pmv[1][0] = - decoder->f_motion.pmv[0][0] = tmp; - - NEEDBITS (bit_buf, bits, bit_ptr); - - tmp = (decoder->f_motion.pmv[0][1] + - get_motion_delta (decoder, decoder->f_motion.f_code[1])); - tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]); - - decoder->f_motion.pmv[1][1] = - decoder->f_motion.pmv[0][1] = tmp; - - DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */ -} - -#undef bit_buf -#undef bits -#undef bit_ptr - -#define MOTION_CALL(routine, direction) \ -do { \ - if ((direction) & MACROBLOCK_MOTION_FORWARD) \ - routine (decoder, &decoder->f_motion, mpeg2_mc.put); \ - \ - if ((direction) & MACROBLOCK_MOTION_BACKWARD) \ - { \ - routine (decoder, &decoder->b_motion, \ - ((direction) & MACROBLOCK_MOTION_FORWARD ? \ - mpeg2_mc.avg : mpeg2_mc.put)); \ - } \ -} while (0) - -#define NEXT_MACROBLOCK \ -do { \ - decoder->offset += 16; \ - \ - if (decoder->offset == decoder->width) \ - { \ - do { /* just so we can use the break statement */ \ - if (decoder->convert) \ - { \ - decoder->convert (decoder->convert_id, decoder->dest, \ - decoder->v_offset); \ - if (decoder->coding_type == B_TYPE) \ - break; \ - } \ - \ - decoder->dest[0] += decoder->slice_stride; \ - if (MPEG2_COLOR) \ - { \ - decoder->dest[1] += decoder->slice_uv_stride; \ - decoder->dest[2] += decoder->slice_uv_stride; \ - } \ - } while (0); \ - \ - decoder->v_offset += 16; \ - \ - if (decoder->v_offset > decoder->limit_y) \ - return; \ - \ - decoder->offset = 0; \ - } \ -} while (0) - -void mpeg2_init_fbuf (mpeg2_decoder_t * decoder, - uint8_t * current_fbuf[MPEG2_COMPONENTS], - uint8_t * forward_fbuf[MPEG2_COMPONENTS], - uint8_t * backward_fbuf[MPEG2_COMPONENTS]) -{ - int offset, stride, height, bottom_field; - - stride = decoder->stride_frame; - bottom_field = (decoder->picture_structure == BOTTOM_FIELD); - offset = bottom_field ? stride : 0; - height = decoder->height; - - decoder->picture_dest[0] = current_fbuf[0] + offset; -#if MPEG2_COLOR - decoder->picture_dest[1] = current_fbuf[1] + (offset >> 1); - decoder->picture_dest[2] = current_fbuf[2] + (offset >> 1); -#endif - - decoder->f_motion.ref[0][0] = forward_fbuf[0] + offset; -#if MPEG2_COLOR - decoder->f_motion.ref[0][1] = forward_fbuf[1] + (offset >> 1); - decoder->f_motion.ref[0][2] = forward_fbuf[2] + (offset >> 1); -#endif - - decoder->b_motion.ref[0][0] = backward_fbuf[0] + offset; -#if MPEG2_COLOR - decoder->b_motion.ref[0][1] = backward_fbuf[1] + (offset >> 1); - decoder->b_motion.ref[0][2] = backward_fbuf[2] + (offset >> 1); -#endif - - if (decoder->picture_structure != FRAME_PICTURE) - { - decoder->dmv_offset = bottom_field ? 1 : -1; - decoder->f_motion.ref2[0] = decoder->f_motion.ref[bottom_field]; - decoder->f_motion.ref2[1] = decoder->f_motion.ref[!bottom_field]; - decoder->b_motion.ref2[0] = decoder->b_motion.ref[bottom_field]; - decoder->b_motion.ref2[1] = decoder->b_motion.ref[!bottom_field]; - offset = stride - offset; - - if (decoder->second_field && (decoder->coding_type != B_TYPE)) - forward_fbuf = current_fbuf; - - decoder->f_motion.ref[1][0] = forward_fbuf[0] + offset; -#if MPEG2_COLOR - decoder->f_motion.ref[1][1] = forward_fbuf[1] + (offset >> 1); - decoder->f_motion.ref[1][2] = forward_fbuf[2] + (offset >> 1); -#endif - decoder->b_motion.ref[1][0] = backward_fbuf[0] + offset; -#if MPEG2_COLOR - decoder->b_motion.ref[1][1] = backward_fbuf[1] + (offset >> 1); - decoder->b_motion.ref[1][2] = backward_fbuf[2] + (offset >> 1); -#endif - stride <<= 1; - height >>= 1; - } - - decoder->stride = stride; - decoder->slice_stride = 16 * stride; -#if MPEG2_COLOR - decoder->uv_stride = stride >> 1; - decoder->slice_uv_stride = - decoder->slice_stride >> (2 - decoder->chroma_format); -#endif - decoder->limit_x = 2 * decoder->width - 32; - decoder->limit_y_16 = 2 * height - 32; - decoder->limit_y_8 = 2 * height - 16; - decoder->limit_y = height - 16; - - if (decoder->mpeg1) - { - decoder->motion_parser[0] = motion_zero_420; - decoder->motion_parser[MC_FRAME] = motion_mp1; - decoder->motion_parser[4] = motion_reuse_420; - } - else if (decoder->picture_structure == FRAME_PICTURE) - { - if (decoder->chroma_format == 0) - { - decoder->motion_parser[0] = motion_zero_420; - decoder->motion_parser[MC_FIELD] = motion_fr_field_420; - decoder->motion_parser[MC_FRAME] = motion_fr_frame_420; - decoder->motion_parser[MC_DMV] = motion_fr_dmv_420; - decoder->motion_parser[4] = motion_reuse_420; - } - else if (decoder->chroma_format == 1) - { - decoder->motion_parser[0] = motion_zero_422; - decoder->motion_parser[MC_FIELD] = motion_fr_field_422; - decoder->motion_parser[MC_FRAME] = motion_fr_frame_422; - decoder->motion_parser[MC_DMV] = motion_fr_dmv_422; - decoder->motion_parser[4] = motion_reuse_422; - } - else - { - decoder->motion_parser[0] = motion_zero_444; - decoder->motion_parser[MC_FIELD] = motion_fr_field_444; - decoder->motion_parser[MC_FRAME] = motion_fr_frame_444; - decoder->motion_parser[MC_DMV] = motion_fr_dmv_444; - decoder->motion_parser[4] = motion_reuse_444; - } - } - else - { - if (decoder->chroma_format == 0) - { - decoder->motion_parser[0] = motion_zero_420; - decoder->motion_parser[MC_FIELD] = motion_fi_field_420; - decoder->motion_parser[MC_16X8] = motion_fi_16x8_420; - decoder->motion_parser[MC_DMV] = motion_fi_dmv_420; - decoder->motion_parser[4] = motion_reuse_420; - } - else if (decoder->chroma_format == 1) - { - decoder->motion_parser[0] = motion_zero_422; - decoder->motion_parser[MC_FIELD] = motion_fi_field_422; - decoder->motion_parser[MC_16X8] = motion_fi_16x8_422; - decoder->motion_parser[MC_DMV] = motion_fi_dmv_422; - decoder->motion_parser[4] = motion_reuse_422; - } - else - { - decoder->motion_parser[0] = motion_zero_444; - decoder->motion_parser[MC_FIELD] = motion_fi_field_444; - decoder->motion_parser[MC_16X8] = motion_fi_16x8_444; - decoder->motion_parser[MC_DMV] = motion_fi_dmv_444; - decoder->motion_parser[4] = motion_reuse_444; - } - } -} - -static inline int slice_init (mpeg2_decoder_t * const decoder, int code) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - int offset; - const MBAtab * mba; - -#if MPEG2_COLOR - decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = - decoder->dc_dct_pred[2] = 16384; -#else - decoder->dc_dct_pred[0] = 16384; -#endif - - decoder->f_motion.pmv[0][0] = decoder->f_motion.pmv[0][1] = 0; - decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[1][1] = 0; - decoder->b_motion.pmv[0][0] = decoder->b_motion.pmv[0][1] = 0; - decoder->b_motion.pmv[1][0] = decoder->b_motion.pmv[1][1] = 0; - - if (decoder->vertical_position_extension) - { - code += UBITS (bit_buf, 3) << 7; - DUMPBITS (bit_buf, bits, 3); - } - - decoder->v_offset = (code - 1) * 16; - offset = 0; - - if (!(decoder->convert) || decoder->coding_type != B_TYPE) - { - offset = (code - 1) * decoder->slice_stride; - } - - decoder->dest[0] = decoder->picture_dest[0] + offset; -#if MPEG2_COLOR - offset >>= (2 - decoder->chroma_format); - decoder->dest[1] = decoder->picture_dest[1] + offset; - decoder->dest[2] = decoder->picture_dest[2] + offset; -#endif - - get_quantizer_scale (decoder); - - /* ignore intra_slice and all the extra data */ - while (bit_buf & 0x80000000) - { - DUMPBITS (bit_buf, bits, 9); - NEEDBITS (bit_buf, bits, bit_ptr); - } - - /* decode initial macroblock address increment */ - offset = 0; - while (1) - { - if (bit_buf >= 0x08000000) - { - mba = MBA_5 + (UBITS (bit_buf, 6) - 2); - break; - } - else if (bit_buf >= 0x01800000) - { - mba = MBA_11 + (UBITS (bit_buf, 12) - 24); - break; - } - else - { - switch (UBITS (bit_buf, 12)) - { - case 8: /* macroblock_escape */ - offset += 33; - DUMPBITS (bit_buf, bits, 11); - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - case 15: /* macroblock_stuffing (MPEG1 only) */ - bit_buf &= 0xfffff; - DUMPBITS (bit_buf, bits, 11); - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - default: /* error */ - return 1; - } - } - } - - DUMPBITS (bit_buf, bits, mba->len + 1); - decoder->offset = (offset + mba->mba) << 4; - - while (decoder->offset - decoder->width >= 0) - { - decoder->offset -= decoder->width; - - if (!(decoder->convert) || decoder->coding_type != B_TYPE) - { - decoder->dest[0] += decoder->slice_stride; -#if MPEG2_COLOR - decoder->dest[1] += decoder->slice_uv_stride; - decoder->dest[2] += decoder->slice_uv_stride; -#endif - } - - decoder->v_offset += 16; - } - - if (decoder->v_offset > decoder->limit_y) - return 1; - - return 0; - -#undef bit_buf -#undef bits -#undef bit_ptr -} - -void mpeg2_slice (mpeg2_decoder_t * const decoder, const int code, - const uint8_t * const buffer) -{ -#define bit_buf (decoder->bitstream_buf) -#define bits (decoder->bitstream_bits) -#define bit_ptr (decoder->bitstream_ptr) - - bitstream_init (decoder, buffer); - - if (slice_init (decoder, code)) - return; - - while (1) - { - int macroblock_modes; - int mba_inc; - const MBAtab * mba; - - NEEDBITS (bit_buf, bits, bit_ptr); - - macroblock_modes = get_macroblock_modes (decoder); - - /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */ - if (macroblock_modes & MACROBLOCK_QUANT) - get_quantizer_scale (decoder); - - if (macroblock_modes & MACROBLOCK_INTRA) - { - int DCT_offset, DCT_stride; - int offset; - uint8_t * dest_y; - - if (decoder->concealment_motion_vectors) - { - if (decoder->picture_structure == FRAME_PICTURE) - motion_fr_conceal (decoder); - else - motion_fi_conceal (decoder); - } - else - { - decoder->f_motion.pmv[0][0] = decoder->f_motion.pmv[0][1] = 0; - decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[1][1] = 0; - decoder->b_motion.pmv[0][0] = decoder->b_motion.pmv[0][1] = 0; - decoder->b_motion.pmv[1][0] = decoder->b_motion.pmv[1][1] = 0; - } - - if (macroblock_modes & DCT_TYPE_INTERLACED) - { - DCT_offset = decoder->stride; - DCT_stride = decoder->stride * 2; - } - else - { - DCT_offset = decoder->stride * 8; - DCT_stride = decoder->stride; - } - - offset = decoder->offset; - dest_y = decoder->dest[0] + offset; - slice_intra_DCT (decoder, 0, dest_y, DCT_stride); - slice_intra_DCT (decoder, 0, dest_y + 8, DCT_stride); - slice_intra_DCT (decoder, 0, dest_y + DCT_offset, DCT_stride); - slice_intra_DCT (decoder, 0, dest_y + DCT_offset + 8, DCT_stride); - -#if MPEG2_COLOR - if (likely (decoder->chroma_format == 0)) - { - slice_intra_DCT (decoder, 1, decoder->dest[1] + (offset >> 1), - decoder->uv_stride); - slice_intra_DCT (decoder, 2, decoder->dest[2] + (offset >> 1), - decoder->uv_stride); - - if (decoder->coding_type == D_TYPE) - { - NEEDBITS (bit_buf, bits, bit_ptr); - DUMPBITS (bit_buf, bits, 1); - } - } - else if (likely (decoder->chroma_format == 1)) - { - uint8_t * dest_u = decoder->dest[1] + (offset >> 1); - uint8_t * dest_v = decoder->dest[2] + (offset >> 1); - - DCT_stride >>= 1; - DCT_offset >>= 1; - - slice_intra_DCT (decoder, 1, dest_u, DCT_stride); - slice_intra_DCT (decoder, 2, dest_v, DCT_stride); - slice_intra_DCT (decoder, 1, dest_u + DCT_offset, DCT_stride); - slice_intra_DCT (decoder, 2, dest_v + DCT_offset, DCT_stride); - } - else - { - uint8_t * dest_u = decoder->dest[1] + offset; - uint8_t * dest_v = decoder->dest[2] + offset; - - slice_intra_DCT (decoder, 1, dest_u, DCT_stride); - slice_intra_DCT (decoder, 2, dest_v, DCT_stride); - slice_intra_DCT (decoder, 1, dest_u + DCT_offset, DCT_stride); - slice_intra_DCT (decoder, 2, dest_v + DCT_offset, DCT_stride); - slice_intra_DCT (decoder, 1, dest_u + 8, DCT_stride); - slice_intra_DCT (decoder, 2, dest_v + 8, DCT_stride); - slice_intra_DCT (decoder, 1, dest_u + DCT_offset + 8, - DCT_stride); - slice_intra_DCT (decoder, 2, dest_v + DCT_offset + 8, - DCT_stride); - } -#else - skip_chroma_intra(decoder); -#endif /* MPEG2_COLOR */ - } - else - { - motion_parser_t * parser; - - parser = - decoder->motion_parser[macroblock_modes >> MOTION_TYPE_SHIFT]; - MOTION_CALL (parser, macroblock_modes); - - if (macroblock_modes & MACROBLOCK_PATTERN) - { - int coded_block_pattern; - int DCT_offset, DCT_stride; - - if (macroblock_modes & DCT_TYPE_INTERLACED) - { - DCT_offset = decoder->stride; - DCT_stride = decoder->stride * 2; - } - else - { - DCT_offset = decoder->stride * 8; - DCT_stride = decoder->stride; - } - - coded_block_pattern = get_coded_block_pattern (decoder); - - if (likely (decoder->chroma_format == 0)) - { - int offset = decoder->offset; - uint8_t * dest_y = decoder->dest[0] + offset; - - if (coded_block_pattern & 1) - slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride); - - if (coded_block_pattern & 2) - slice_non_intra_DCT (decoder, 0, dest_y + 8, - DCT_stride); - - if (coded_block_pattern & 4) - slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset, - DCT_stride); - - if (coded_block_pattern & 8) - slice_non_intra_DCT (decoder, 0, - dest_y + DCT_offset + 8, - DCT_stride); -#if MPEG2_COLOR - if (coded_block_pattern & 16) - slice_non_intra_DCT (decoder, 1, - decoder->dest[1] + (offset >> 1), - decoder->uv_stride); - - if (coded_block_pattern & 32) - slice_non_intra_DCT (decoder, 2, - decoder->dest[2] + (offset >> 1), - decoder->uv_stride); -#endif /* MPEG2_COLOR */ - } - else if (likely (decoder->chroma_format == 1)) - { - int offset; - uint8_t * dest_y; - - coded_block_pattern |= bit_buf & (3 << 30); - DUMPBITS (bit_buf, bits, 2); - - offset = decoder->offset; - dest_y = decoder->dest[0] + offset; - - if (coded_block_pattern & 1) - slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride); - - if (coded_block_pattern & 2) - slice_non_intra_DCT (decoder, 0, dest_y + 8, - DCT_stride); - - if (coded_block_pattern & 4) - slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset, - DCT_stride); - - if (coded_block_pattern & 8) - slice_non_intra_DCT (decoder, 0, - dest_y + DCT_offset + 8, - DCT_stride); -#if MPEG2_COLOR - DCT_stride >>= 1; - DCT_offset = (DCT_offset + offset) >> 1; - - if (coded_block_pattern & 16) - slice_non_intra_DCT (decoder, 1, - decoder->dest[1] + (offset >> 1), - DCT_stride); - - if (coded_block_pattern & 32) - slice_non_intra_DCT (decoder, 2, - decoder->dest[2] + (offset >> 1), - DCT_stride); - - if (coded_block_pattern & (2 << 30)) - slice_non_intra_DCT (decoder, 1, - decoder->dest[1] + DCT_offset, - DCT_stride); - - if (coded_block_pattern & (1 << 30)) - slice_non_intra_DCT (decoder, 2, - decoder->dest[2] + DCT_offset, - DCT_stride); -#endif /* MPEG2_COLOR */ - } - else - { - int offset = decoder->offset; - uint8_t * dest_y = decoder->dest[0] + offset; -#if MPEG2_COLOR - uint8_t * dest_u = decoder->dest[1] + offset; - uint8_t * dest_v = decoder->dest[2] + offset; -#endif - coded_block_pattern |= bit_buf & (63 << 26); - DUMPBITS (bit_buf, bits, 6); - - if (coded_block_pattern & 1) - slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride); - - if (coded_block_pattern & 2) - slice_non_intra_DCT (decoder, 0, dest_y + 8, - DCT_stride); - - if (coded_block_pattern & 4) - slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset, - DCT_stride); - - if (coded_block_pattern & 8) - slice_non_intra_DCT (decoder, 0, - dest_y + DCT_offset + 8, - DCT_stride); -#if MPEG2_COLOR - if (coded_block_pattern & 16) - slice_non_intra_DCT (decoder, 1, dest_u, DCT_stride); - - if (coded_block_pattern & 32) - slice_non_intra_DCT (decoder, 2, dest_v, DCT_stride); - - if (coded_block_pattern & (32 << 26)) - slice_non_intra_DCT (decoder, 1, dest_u + DCT_offset, - DCT_stride); - - if (coded_block_pattern & (16 << 26)) - slice_non_intra_DCT (decoder, 2, dest_v + DCT_offset, - DCT_stride); - - if (coded_block_pattern & (8 << 26)) - slice_non_intra_DCT (decoder, 1, dest_u + 8, - DCT_stride); - - if (coded_block_pattern & (4 << 26)) - slice_non_intra_DCT (decoder, 2, dest_v + 8, - DCT_stride); - - if (coded_block_pattern & (2 << 26)) - slice_non_intra_DCT (decoder, 1, - dest_u + DCT_offset + 8, - DCT_stride); - - if (coded_block_pattern & (1 << 26)) - slice_non_intra_DCT (decoder, 2, - dest_v + DCT_offset + 8, - DCT_stride); -#endif /* MPEG2_COLOR */ - } -#if !MPEG2_COLOR - skip_chroma_non_intra(decoder, coded_block_pattern); -#endif - } - -#if MPEG2_COLOR - decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = - decoder->dc_dct_pred[2] = 16384; -#else - decoder->dc_dct_pred[0] = 16384; -#endif - } - - NEXT_MACROBLOCK; - - NEEDBITS (bit_buf, bits, bit_ptr); - mba_inc = 0; - - while (1) - { - if (bit_buf >= 0x10000000) - { - mba = MBA_5 + (UBITS (bit_buf, 5) - 2); - break; - } - else if (bit_buf >= 0x03000000) - { - mba = MBA_11 + (UBITS (bit_buf, 11) - 24); - break; - } - else - { - switch (UBITS (bit_buf, 11)) - { - case 8: /* macroblock_escape */ - mba_inc += 33; - /* pass through */ - case 15: /* macroblock_stuffing (MPEG1 only) */ - DUMPBITS (bit_buf, bits, 11); - NEEDBITS (bit_buf, bits, bit_ptr); - continue; - default: /* end of slice, or error */ - return; - } - } - } - - DUMPBITS (bit_buf, bits, mba->len); - mba_inc += mba->mba; - - if (mba_inc) - { -#if MPEG2_COLOR - decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = - decoder->dc_dct_pred[2] = 16384; -#else - decoder->dc_dct_pred[0] = 16384; -#endif - if (decoder->coding_type == P_TYPE) - { - do - { - MOTION_CALL (decoder->motion_parser[0], - MACROBLOCK_MOTION_FORWARD); - NEXT_MACROBLOCK; - } - while (--mba_inc); - } - else - { - do - { - MOTION_CALL (decoder->motion_parser[4], macroblock_modes); - NEXT_MACROBLOCK; - } - while (--mba_inc); - } - } - } - -#undef bit_buf -#undef bits -#undef bit_ptr -} diff --git a/apps/plugins/mpegplayer/libmpeg2/vlc.h b/apps/plugins/mpegplayer/libmpeg2/vlc.h deleted file mode 100644 index d1b6a98cde..0000000000 --- a/apps/plugins/mpegplayer/libmpeg2/vlc.h +++ /dev/null @@ -1,433 +0,0 @@ -/* - * vlc.h - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.12 - */ - -#define GETWORD(bit_buf, shift, bit_ptr) \ -do { \ - bit_buf |= ((bit_ptr[0] << 8) | bit_ptr[1]) << (shift); \ - bit_ptr += 2; \ -} while (0) - -static inline void bitstream_init (mpeg2_decoder_t * decoder, - const uint8_t * start) -{ - decoder->bitstream_buf = - (start[0] << 24) | (start[1] << 16) | (start[2] << 8) | start[3]; - decoder->bitstream_ptr = start + 4; - decoder->bitstream_bits = -16; -} - -/* make sure that there are at least 16 valid bits in bit_buf */ -#define NEEDBITS(bit_buf, bits, bit_ptr) \ -do { \ - if (unlikely (bits > 0)) { \ - GETWORD (bit_buf, bits, bit_ptr); \ - bits -= 16; \ - } \ -} while (0) - -/* remove num valid bits from bit_buf */ -#define DUMPBITS(bit_buf, bits, num) \ -do { \ - bit_buf <<= (num); \ - bits += (num); \ -} while (0) - -/* take num bits from the high part of bit_buf and zero extend them */ -#define UBITS(bit_buf,num) (((uint32_t)(bit_buf)) >> (32 - (num))) - -/* take num bits from the high part of bit_buf and sign extend them */ -#define SBITS(bit_buf,num) (((int32_t)(bit_buf)) >> (32 - (num))) - -typedef struct { - uint8_t modes; - uint8_t len; -} MBtab; - -typedef struct { - uint8_t delta; - uint8_t len; -} MVtab; - -typedef struct { - int8_t dmv; - uint8_t len; -} DMVtab; - -typedef struct { - uint8_t cbp; - uint8_t len; -} CBPtab; - -typedef struct { - uint8_t size; - uint8_t len; -} DCtab; - -typedef struct { - uint8_t run; - uint8_t level; - uint8_t len; -} DCTtab; - -typedef struct { - uint8_t mba; - uint8_t len; -} MBAtab; - - -#define INTRA MACROBLOCK_INTRA -#define QUANT MACROBLOCK_QUANT - -static const MBtab MB_I [] ICONST_ATTR = { - {INTRA|QUANT, 2}, {INTRA, 1} -}; - -#define MC MACROBLOCK_MOTION_FORWARD -#define CODED MACROBLOCK_PATTERN - -static const MBtab MB_P [] ICONST_ATTR = { - {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5}, - {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3}, - {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, - {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, - {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, - {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, - {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, - {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1} -}; - -#define FWD MACROBLOCK_MOTION_FORWARD -#define BWD MACROBLOCK_MOTION_BACKWARD -#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD - -static const MBtab MB_B [] ICONST_ATTR = { - {0, 6}, {INTRA|QUANT, 6}, - {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6}, - {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5}, - {INTRA, 5}, {INTRA, 5}, - {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4}, - {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, - {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, - {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, - {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, - {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, - {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, - {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, - {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, - {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, - {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, - {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, - {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, - {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2} -}; - -#undef INTRA -#undef QUANT -#undef MC -#undef CODED -#undef FWD -#undef BWD -#undef INTER - - -static const MVtab MV_4 [] ICONST_ATTR = { - { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} -}; - -static const MVtab MV_10 [] ICONST_ATTR = { - { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, - { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10}, - {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9}, - { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, - { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, - { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7} -}; - - -static const DMVtab DMV_2 [] ICONST_ATTR = { - { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2} -}; - - -static const CBPtab CBP_7 [] ICONST_ATTR = { - {0x11, 7}, {0x12, 7}, {0x14, 7}, {0x18, 7}, - {0x21, 7}, {0x22, 7}, {0x24, 7}, {0x28, 7}, - {0x3f, 6}, {0x3f, 6}, {0x30, 6}, {0x30, 6}, - {0x09, 6}, {0x09, 6}, {0x06, 6}, {0x06, 6}, - {0x1f, 5}, {0x1f, 5}, {0x1f, 5}, {0x1f, 5}, - {0x10, 5}, {0x10, 5}, {0x10, 5}, {0x10, 5}, - {0x2f, 5}, {0x2f, 5}, {0x2f, 5}, {0x2f, 5}, - {0x20, 5}, {0x20, 5}, {0x20, 5}, {0x20, 5}, - {0x07, 5}, {0x07, 5}, {0x07, 5}, {0x07, 5}, - {0x0b, 5}, {0x0b, 5}, {0x0b, 5}, {0x0b, 5}, - {0x0d, 5}, {0x0d, 5}, {0x0d, 5}, {0x0d, 5}, - {0x0e, 5}, {0x0e, 5}, {0x0e, 5}, {0x0e, 5}, - {0x05, 5}, {0x05, 5}, {0x05, 5}, {0x05, 5}, - {0x0a, 5}, {0x0a, 5}, {0x0a, 5}, {0x0a, 5}, - {0x03, 5}, {0x03, 5}, {0x03, 5}, {0x03, 5}, - {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, - {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4}, - {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4}, - {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4}, - {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4}, - {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, - {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, - {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, - {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, - {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, - {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, - {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, - {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3} -}; - -static const CBPtab CBP_9 [] ICONST_ATTR = { - {0, 9}, {0x00, 9}, {0x39, 9}, {0x36, 9}, - {0x37, 9}, {0x3b, 9}, {0x3d, 9}, {0x3e, 9}, - {0x17, 8}, {0x17, 8}, {0x1b, 8}, {0x1b, 8}, - {0x1d, 8}, {0x1d, 8}, {0x1e, 8}, {0x1e, 8}, - {0x27, 8}, {0x27, 8}, {0x2b, 8}, {0x2b, 8}, - {0x2d, 8}, {0x2d, 8}, {0x2e, 8}, {0x2e, 8}, - {0x19, 8}, {0x19, 8}, {0x16, 8}, {0x16, 8}, - {0x29, 8}, {0x29, 8}, {0x26, 8}, {0x26, 8}, - {0x35, 8}, {0x35, 8}, {0x3a, 8}, {0x3a, 8}, - {0x33, 8}, {0x33, 8}, {0x3c, 8}, {0x3c, 8}, - {0x15, 8}, {0x15, 8}, {0x1a, 8}, {0x1a, 8}, - {0x13, 8}, {0x13, 8}, {0x1c, 8}, {0x1c, 8}, - {0x25, 8}, {0x25, 8}, {0x2a, 8}, {0x2a, 8}, - {0x23, 8}, {0x23, 8}, {0x2c, 8}, {0x2c, 8}, - {0x31, 8}, {0x31, 8}, {0x32, 8}, {0x32, 8}, - {0x34, 8}, {0x34, 8}, {0x38, 8}, {0x38, 8} -}; - - -static const DCtab DC_lum_5 [] ICONST_ATTR = { - {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, - {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, - {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, - {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5} -}; - -static const DCtab DC_chrom_5 [] ICONST_ATTR = { - {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, - {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, - {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, - {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5} -}; - -static const DCtab DC_long [] ICONST_ATTR = { - {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, - {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, - {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6}, - {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9} -}; - - -static const DCTtab DCT_16 [] ICONST_ATTR = { - {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, - {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, - {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, - {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, - { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0}, - { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0}, - { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0}, - { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0} -}; - -static const DCTtab DCT_15 [] ICONST_ATTR = { - { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15}, - { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15}, - { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15}, - { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15}, - { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14}, - { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14}, - { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14}, - { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14}, - { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14}, - { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14}, - { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14}, - { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14} -}; - -static const DCTtab DCT_13 [] ICONST_ATTR = { - { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13}, - { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13}, - { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13}, - { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13}, - { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12}, - { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12}, - { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12}, - { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12}, - { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12}, - { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12}, - { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12}, - { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12} -}; - -static const DCTtab DCT_B14_10 [] ICONST_ATTR = { - { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10}, - { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10} -}; - -static const DCTtab DCT_B14_8 [] ICONST_ATTR = { - { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, - { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7}, - { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7}, - { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, - { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, - { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, - { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, - { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8}, - { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8} -}; - -static const DCTtab DCT_B14AC_5 [] ICONST_ATTR = { - { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, - { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, - {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2} -}; - -static const DCTtab DCT_B14DC_5 [] ICONST_ATTR = { - { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, - { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, - { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, - { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, - { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1} -}; - -static const DCTtab DCT_B15_10 [] ICONST_ATTR = { - { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9}, - { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9} -}; - -static const DCTtab DCT_B15_8 [] ICONST_ATTR = { - { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, - { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7}, - { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7}, - { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, - { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, - { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, - { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, - { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8}, - { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8}, - { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, - { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, - { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, - { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, - { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, - { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, - {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, - {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, - {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, - {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, - { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, - { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, - { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, - { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, - { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, - { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, - { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, - { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, - { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7}, - { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7}, - { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8}, - { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8} -}; - - -static const MBAtab MBA_5 [] ICONST_ATTR = { - {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4}, - {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, - {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, - {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} -}; - -static const MBAtab MBA_11 [] ICONST_ATTR = { - {32, 11}, {31, 11}, {30, 11}, {29, 11}, - {28, 11}, {27, 11}, {26, 11}, {25, 11}, - {24, 11}, {23, 11}, {22, 11}, {21, 11}, - {20, 10}, {20, 10}, {19, 10}, {19, 10}, - {18, 10}, {18, 10}, {17, 10}, {17, 10}, - {16, 10}, {16, 10}, {15, 10}, {15, 10}, - {14, 8}, {14, 8}, {14, 8}, {14, 8}, - {14, 8}, {14, 8}, {14, 8}, {14, 8}, - {13, 8}, {13, 8}, {13, 8}, {13, 8}, - {13, 8}, {13, 8}, {13, 8}, {13, 8}, - {12, 8}, {12, 8}, {12, 8}, {12, 8}, - {12, 8}, {12, 8}, {12, 8}, {12, 8}, - {11, 8}, {11, 8}, {11, 8}, {11, 8}, - {11, 8}, {11, 8}, {11, 8}, {11, 8}, - {10, 8}, {10, 8}, {10, 8}, {10, 8}, - {10, 8}, {10, 8}, {10, 8}, {10, 8}, - { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, - { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, - { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, - { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, - { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, - { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, - { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, - { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, - { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, - { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} -}; diff --git a/apps/plugins/mpegplayer/mpeg_alloc.h b/apps/plugins/mpegplayer/mpeg_alloc.h deleted file mode 100644 index 9acfbc5dec..0000000000 --- a/apps/plugins/mpegplayer/mpeg_alloc.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef MPEG_ALLOC_H -#define MPEG_ALLOC_H - -/* returns the remaining mpeg2 buffer and it's size */ -void * mpeg2_get_buf(size_t *size); -void *mpeg_malloc(size_t size, mpeg2_alloc_t reason); -/* Grabs all the buffer available sans margin */ -void *mpeg_malloc_all(size_t *size_out, mpeg2_alloc_t reason); -/* Initializes the malloc buffer with the given base buffer */ -bool mpeg_alloc_init(unsigned char *buf, size_t mallocsize); - -#endif /* MPEG_ALLOC_H */ diff --git a/apps/plugins/mpegplayer/mpeg_misc.c b/apps/plugins/mpegplayer/mpeg_misc.c deleted file mode 100644 index 31f0644212..0000000000 --- a/apps/plugins/mpegplayer/mpeg_misc.c +++ /dev/null @@ -1,227 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Miscellaneous helper API definitions - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" - -/** Streams **/ - -/* Initializes the cursor */ -void stream_scan_init(struct stream_scan *sk) -{ - dbuf_l2_init(&sk->l2); -} - -/* Ensures direction is -1 or 1 and margin is properly initialized */ -void stream_scan_normalize(struct stream_scan *sk) -{ - if (sk->dir >= 0) - { - sk->dir = SSCAN_FORWARD; - sk->margin = sk->len; - } - else if (sk->dir < 0) - { - sk->dir = SSCAN_REVERSE; - sk->margin = 0; - } -} - -/* Moves a scan cursor. If amount is positive, the increment is in the scan - * direction, otherwise opposite the scan direction */ -void stream_scan_offset(struct stream_scan *sk, off_t by) -{ - off_t bydir = by*sk->dir; - sk->pos += bydir; - sk->margin -= bydir; - sk->len -= by; -} - -/** Time helpers **/ -void ts_to_hms(uint32_t pts, struct hms *hms) -{ - hms->frac = pts % TS_SECOND; - hms->sec = pts / TS_SECOND; - hms->min = hms->sec / 60; - hms->hrs = hms->min / 60; - hms->sec %= 60; - hms->min %= 60; -} - -void hms_format(char *buf, size_t bufsize, struct hms *hms) -{ - /* Only display hours if nonzero */ - if (hms->hrs != 0) - { - rb->snprintf(buf, bufsize, "%u:%02u:%02u", - hms->hrs, hms->min, hms->sec); - } - else - { - rb->snprintf(buf, bufsize, "%u:%02u", - hms->min, hms->sec); - } -} - -/** Maths **/ -uint32_t muldiv_uint32(uint32_t multiplicand, - uint32_t multiplier, - uint32_t divisor) -{ - if (divisor != 0) - { - uint64_t prod = (uint64_t)multiplier*multiplicand + divisor/2; - - if ((uint32_t)(prod >> 32) < divisor) - return (uint32_t)(prod / divisor); - } - else if (multiplicand == 0 || multiplier == 0) - { - return 0; /* 0/0 = 0 : yaya */ - } - /* else (> 0) / 0 = UINT32_MAX */ - - return UINT32_MAX; /* Saturate */ -} - - -/** Lists **/ - -/* Does the list have any members? */ -bool list_is_empty(void **list) -{ - return *list == NULL; -} - -/* Is the item inserted into a particular list? */ -bool list_is_member(void **list, void *item) -{ - return *rb->find_array_ptr(list, item) != NULL; -} - -/* Removes an item from a list - returns true if item was found - * and thus removed. */ -bool list_remove_item(void **list, void *item) -{ - return rb->remove_array_ptr(list, item) != -1; -} - -/* Adds a list item, insert last, if not already present. */ -void list_add_item(void **list, void *item) -{ - void **item_p = rb->find_array_ptr(list, item); - if (*item_p == NULL) - *item_p = item; -} - -/* Clears the entire list. */ -void list_clear_all(void **list) -{ - while (*list != NULL) - *list++ = NULL; -} - -/* Enumerate all items in the array, passing each item in turn to the - * callback as well as the data value. The current item may be safely - * removed. Other changes during enumeration are undefined. The callback - * may return 'false' to stop the enumeration early. */ -void list_enum_items(void **list, - list_enum_callback_t callback, - void* data) -{ - for (;;) - { - void *item = *list; - - if (item == NULL) - break; - - if (callback != NULL && !callback(item, data)) - break; - - if (*list == item) - list++; /* Item still there */ - } -} - - -/** System events **/ -static long mpeg_sysevent_id; - -void mpeg_sysevent_clear(void) -{ - mpeg_sysevent_id = 0; -} - -void mpeg_sysevent_set(void) -{ - /* Nonzero and won't invoke anything in default event handler */ - mpeg_sysevent_id = ACTION_STD_CANCEL; -} - -long mpeg_sysevent(void) -{ - return mpeg_sysevent_id; -} - -int mpeg_sysevent_callback(int btn, - const struct menu_item_ex *menu, - struct gui_synclist *this_list) -{ - (void) this_list; - switch (btn) - { - case SYS_USB_CONNECTED: - case SYS_POWEROFF: - case SYS_REBOOT: - mpeg_sysevent_id = btn; - return ACTION_STD_CANCEL; - } - - return btn; - (void)menu; -} - -void mpeg_sysevent_handle(void) -{ - long id = mpeg_sysevent(); - if (id != 0) - rb->default_event_handler(id); -} - - -/** Buttons **/ - -int mpeg_button_get(int timeout) -{ - int button; - - mpeg_sysevent_clear(); - button = timeout == TIMEOUT_BLOCK ? rb->button_get(true) : - rb->button_get_w_tmo(timeout); - - /* Produce keyclick */ - rb->keyclick_click(true, button); - - return mpeg_sysevent_callback(button, NULL, NULL); -} - diff --git a/apps/plugins/mpegplayer/mpeg_misc.h b/apps/plugins/mpegplayer/mpeg_misc.h deleted file mode 100644 index e04db0e19d..0000000000 --- a/apps/plugins/mpegplayer/mpeg_misc.h +++ /dev/null @@ -1,258 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Miscellaneous helper API declarations - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef MPEG_MISC_H -#define MPEG_MISC_H - -/* Miscellaneous helpers */ -#ifndef ALIGNED_ATTR -#define ALIGNED_ATTR(x) __attribute__((aligned(x))) -#endif - -#include "disk_buf.h" - -/* Generic states for when things are too simple to care about naming them */ -enum state_enum -{ - STATE0 = 0, - STATE1, - STATE2, - STATE3, - STATE4, - STATE5, - STATE6, - STATE7, - STATE8, - STATE9, -}; - -/* Macros for comparing memory bytes to a series of constant bytes in an - efficient manner - evaluate to true if corresponding bytes match */ -#if defined (CPU_ARM) -/* ARM must load 32-bit values at addres % 4 == 0 offsets but this data - isn't aligned nescessarily, so just byte compare */ -#define CMP_3_CONST(_a, _b) \ - ({ int _x; \ - asm volatile ( \ - "ldrb %[x], [%[a], #0] \n" \ - "eors %[x], %[x], %[b0] \n" \ - "ldreqb %[x], [%[a], #1] \n" \ - "eoreqs %[x], %[x], %[b1] \n" \ - "ldreqb %[x], [%[a], #2] \n" \ - "eoreqs %[x], %[x], %[b2] \n" \ - : [x]"=&r"(_x) \ - : [a]"r"(_a), \ - [b0]"i"(((_b) >> 24) & 0xff), \ - [b1]"i"(((_b) >> 16) & 0xff), \ - [b2]"i"(((_b) >> 8) & 0xff) \ - ); \ - _x == 0; }) - -#define CMP_4_CONST(_a, _b) \ - ({ int _x; \ - asm volatile ( \ - "ldrb %[x], [%[a], #0] \n" \ - "eors %[x], %[x], %[b0] \n" \ - "ldreqb %[x], [%[a], #1] \n" \ - "eoreqs %[x], %[x], %[b1] \n" \ - "ldreqb %[x], [%[a], #2] \n" \ - "eoreqs %[x], %[x], %[b2] \n" \ - "ldreqb %[x], [%[a], #3] \n" \ - "eoreqs %[x], %[x], %[b3] \n" \ - : [x]"=&r"(_x) \ - : [a]"r"(_a), \ - [b0]"i"(((_b) >> 24) & 0xff), \ - [b1]"i"(((_b) >> 16) & 0xff), \ - [b2]"i"(((_b) >> 8) & 0xff), \ - [b3]"i"(((_b) ) & 0xff) \ - ); \ - _x == 0; }) - -#elif defined (CPU_COLDFIRE) -/* Coldfire can just load a 32 bit value at any offset but ASM is not the - best way to integrate this with the C code */ -#define CMP_3_CONST(a, b) \ - (((*(uint32_t *)(a) >> 8) == ((uint32_t)(b) >> 8))) - -#define CMP_4_CONST(a, b) \ - ((*(uint32_t *)(a) == (b))) - -#else -/* Don't know what this is - use bytewise comparisons */ -#define CMP_3_CONST(a, b) \ - (( ((a)[0] ^ (((b) >> 24) & 0xff)) | \ - ((a)[1] ^ (((b) >> 16) & 0xff)) | \ - ((a)[2] ^ (((b) >> 8) & 0xff)) ) == 0) - -#define CMP_4_CONST(a, b) \ - (( ((a)[0] ^ (((b) >> 24) & 0xff)) | \ - ((a)[1] ^ (((b) >> 16) & 0xff)) | \ - ((a)[2] ^ (((b) >> 8) & 0xff)) | \ - ((a)[3] ^ (((b) ) & 0xff)) ) == 0) -#endif /* CPU_* */ - - -/** Streams **/ - -/* Convert PTS/DTS ticks to our clock ticks */ -#define TS_TO_TICKS(pts) ((uint64_t)CLOCK_RATE*(pts) / TS_SECOND) -/* Convert our clock ticks to PTS/DTS ticks */ -#define TICKS_TO_TS(ts) ((uint64_t)TS_SECOND*(ts) / CLOCK_RATE) -/* Convert timecode ticks to our clock ticks */ -#define TC_TO_TICKS(stamp) ((uint64_t)CLOCK_RATE*(stamp) / TC_SECOND) -/* Convert our clock ticks to timecode ticks */ -#define TICKS_TO_TC(stamp) ((uint64_t)TC_SECOND*(stamp) / CLOCK_RATE) -/* Convert timecode ticks to timestamp ticks */ -#define TC_TO_TS(stamp) ((stamp) / 600) - -/* - * S = start position, E = end position - * - * pos: - * initialize to search start position (S) - * - * len: - * initialize to = ABS(S-E) - * scanning = remaining bytes in scan direction - * - * dir: - * scan direction; >= 0 == forward, < 0 == reverse - * - * margin: - * amount of data to right of cursor - initialize by stream_scan_normalize - * - * data: - * Extra data used/returned by the function implemented - * - * Forward scan: - * S pos E - * | *<-margin->| dir-> - * | |<--len--->| - * - * Reverse scan: - * E pos S - * |<-len->*<-margin->| <-dir - * | | | - */ -struct stream_scan -{ - off_t pos; /* Initial scan position (file offset) */ - ssize_t len; /* Maximum length of scan */ - off_t dir; /* Direction - >= 0; forward, < 0 backward */ - ssize_t margin; /* Used by function to track margin between position and data end */ - intptr_t data; /* */ - struct dbuf_l2_cache l2; -}; - -#define SSCAN_REVERSE (-1) -#define SSCAN_FORWARD 1 - -/* Initializes the cursor */ -void stream_scan_init(struct stream_scan *sk); - -/* Ensures direction is -1 or 1 and margin is properly initialized */ -void stream_scan_normalize(struct stream_scan *sk); - -/* Moves a scan cursor. If amount is positive, the increment is in the scan - * direction, otherwise opposite the scan direction */ -void stream_scan_offset(struct stream_scan *sk, off_t by); - -/** Time helpers **/ -struct hms -{ - unsigned int hrs; - unsigned int min; - unsigned int sec; - unsigned int frac; -}; - -void ts_to_hms(uint32_t ts, struct hms *hms); -void hms_format(char *buf, size_t bufsize, struct hms *hms); - -/** Maths **/ - -/* Moving average */ -#define AVERAGE(var, x, count) \ - ({ typeof (count) _c = (count); \ - ((var) * (_c-1) + (x)) / (_c); }) - -/* Multiply two unsigned 32-bit integers yielding a 64-bit result and - * divide by another unsigned 32-bit integer to yield a 32-bit result. - * Rounds to nearest with saturation. */ -uint32_t muldiv_uint32(uint32_t multiplicand, - uint32_t multiplier, - uint32_t divisor); - - -/** Lists **/ - -/* Does the list have any members? */ -bool list_is_empty(void **list); - -/* Is the item inserted into a particular list? */ -bool list_is_member(void **list, void *item); - -/* Removes an item from a list - returns true if item was found - * and thus removed. */ -bool list_remove_item(void **list, void *item); - -/* Adds a list item, insert last, if not already present. */ -void list_add_item(void **list, void *item); - -/* Clears the entire list. */ -void list_clear_all(void **list); - -/* Enumerate all items in the array. */ -typedef bool (*list_enum_callback_t)(void *item, void* data); - -void list_enum_items(void **list, - list_enum_callback_t callback, - void *data); - - -/** System events **/ - -/* Clear event */ -void mpeg_sysevent_clear(void); - -/* Set to ACTION_STD_CANCEL */ -void mpeg_sysevent_set(void); - -/* Get event code */ -long mpeg_sysevent(void); - -/* Call with a system event code and used as menu callback */ -int mpeg_sysevent_callback(int btn, const struct menu_item_ex *menu, - struct gui_synclist *this_list); - -/* Handle recorded event */ -void mpeg_sysevent_handle(void); - - -/** Buttons **/ - -/* Get button codes while remembering important events for later - * processing; return of ACTION_STD_CANCEL means plugin should - * abort and handle the event */ -int mpeg_button_get(int timeout); - -#endif /* MPEG_MISC_H */ diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c deleted file mode 100644 index cc57b0c43c..0000000000 --- a/apps/plugins/mpegplayer/mpeg_parser.c +++ /dev/null @@ -1,1203 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Parser for MPEG streams - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" - -struct stream_parser str_parser SHAREDBSS_ATTR; - -static void parser_init_state(void) -{ - str_parser.last_seek_time = 0; - str_parser.format = STREAM_FMT_UNKNOWN; - str_parser.start_pts = INVALID_TIMESTAMP; - str_parser.end_pts = INVALID_TIMESTAMP; - str_parser.flags = 0; - str_parser.dims.w = 0; - str_parser.dims.h = 0; -} - -/* Place the stream in a state to begin parsing - sync will be performed - * first */ -void str_initialize(struct stream *str, off_t pos) -{ - /* Initial positions start here */ - str->hdr.win_left = str->hdr.win_right = pos; - /* No packet */ - str->curr_packet = NULL; - /* Pick up parsing from this point in the buffer */ - str->curr_packet_end = disk_buf_offset2ptr(pos); - /* No flags */ - str->pkt_flags = 0; - /* Sync first */ - str->state = SSTATE_SYNC; -} - -/* Place the stream in an end of data state */ -void str_end_of_stream(struct stream *str) -{ - /* Offsets that prevent this stream from being included in the - * min left/max right window so that no buffering is triggered on - * its behalf. Set right to the min first so a thread reading the - * overall window gets doesn't see this as valid no matter what the - * file length. */ - str->hdr.win_right = OFF_T_MIN; - str->hdr.win_left = OFF_T_MAX; - /* No packets */ - str->curr_packet = str->curr_packet_end = NULL; - /* No flags */ - str->pkt_flags = 0; - /* Fin */ - str->state = SSTATE_END; -} - -/* Return a timestamp at address p+offset if the marker bits are in tact */ -static inline uint32_t read_pts(uint8_t *p, off_t offset) -{ - return TS_CHECK_MARKERS(p, offset) ? - TS_FROM_HEADER(p, offset) : INVALID_TIMESTAMP; -} - -static inline bool validate_timestamp(uint32_t ts) -{ - return ts >= str_parser.start_pts && ts <= str_parser.end_pts; -} - -/* Find a start code before or after a given position */ -uint8_t * mpeg_parser_scan_start_code(struct stream_scan *sk, uint32_t code) -{ - stream_scan_normalize(sk); - - if (sk->dir < 0) - { - /* Reverse scan - start with at least the min needed */ - stream_scan_offset(sk, 4); - } - - code &= 0xff; /* Only the low byte matters */ - - while (sk->len >= 0 && sk->margin >= 4) - { - uint8_t *p; - off_t pos = disk_buf_lseek(sk->pos, SEEK_SET); - ssize_t len = disk_buf_getbuffer_l2(&sk->l2, 4, &p); - - if (pos < 0 || len < 4) - break; - - if (CMP_3_CONST(p, PACKET_START_CODE_PREFIX) && p[3] == code) - { - return p; - } - - stream_scan_offset(sk, 1); - } - - return NULL; -} - -/* Find a PES packet header for any stream - return stream to which it - * belongs */ -unsigned mpeg_parser_scan_pes(struct stream_scan *sk) -{ - stream_scan_normalize(sk); - - if (sk->dir < 0) - { - /* Reverse scan - start with at least the min needed */ - stream_scan_offset(sk, 4); - } - - while (sk->len >= 0 && sk->margin >= 4) - { - uint8_t *p; - off_t pos = disk_buf_lseek(sk->pos, SEEK_SET); - ssize_t len = disk_buf_getbuffer_l2(&sk->l2, 4, &p); - - if (pos < 0 || len < 4) - break; - - if (CMP_3_CONST(p, PACKET_START_CODE_PREFIX)) - { - unsigned id = p[3]; - if (id >= 0xb9) - return id; /* PES header */ - /* else some video stream element */ - } - - stream_scan_offset(sk, 1); - } - - return -1; -} - -/* Return the first SCR found from the scan direction */ -uint32_t mpeg_parser_scan_scr(struct stream_scan *sk) -{ - uint8_t *p = mpeg_parser_scan_start_code(sk, MPEG_STREAM_PACK_HEADER); - - if (p != NULL && sk->margin >= 9) /* 9 bytes total required */ - { - sk->data = 9; - - if ((p[4] & 0xc0) == 0x40) /* mpeg-2 */ - { - /* Lookhead p+8 */ - if (MPEG2_CHECK_PACK_SCR_MARKERS(p, 4)) - return MPEG2_PACK_HEADER_SCR(p, 4); - } - else if ((p[4] & 0xf0) == 0x20) /* mpeg-1 */ - { - /* Lookahead p+8 */ - if (TS_CHECK_MARKERS(p, 4)) - return TS_FROM_HEADER(p, 4); - } - /* Weird pack header */ - sk->data = 5; - } - - return INVALID_TIMESTAMP; -} - -uint32_t mpeg_parser_scan_pts(struct stream_scan *sk, unsigned id) -{ - stream_scan_normalize(sk); - - if (sk->dir < 0) - { - /* Reverse scan - start with at least the min needed */ - stream_scan_offset(sk, 4); - } - - while (sk->len >= 0 && sk->margin >= 4) - { - uint8_t *p; - off_t pos = disk_buf_lseek(sk->pos, SEEK_SET); - ssize_t len = disk_buf_getbuffer_l2(&sk->l2, 30, &p); - - if (pos < 0 || len < 4) - break; - - if (CMP_3_CONST(p, PACKET_START_CODE_PREFIX) && p[3] == id) - { - uint8_t *h = p; - - if (sk->margin < 7) - { - /* Insufficient data */ - } - else if ((h[6] & 0xc0) == 0x80) /* mpeg2 */ - { - if (sk->margin >= 14 && (h[7] & 0x80) != 0x00) - { - sk->data = 14; - return read_pts(h, 9); - } - } - else /* mpeg1 */ - { - ssize_t l = 6; - ssize_t margin = sk->margin; - - /* Skip stuffing_byte */ - while (margin > 7 && h[l] == 0xff && ++l <= 22) - --margin; - - if (margin >= 7) - { - if ((h[l] & 0xc0) == 0x40) - { - /* Skip STD_buffer_scale and STD_buffer_size */ - margin -= 2; - l += 2; - } - - if (margin >= 5) - { - /* Header points to the mpeg1 pes header */ - h += l; - - if ((h[0] & 0xe0) == 0x20) - { - /* PTS or PTS_DTS indicated */ - sk->data = (h + 5) - p; - return read_pts(h, 0); - } - } - } - } - /* No PTS present - keep searching for a matching PES header with - * one */ - } - - stream_scan_offset(sk, 1); - } - - return INVALID_TIMESTAMP; -} - -static bool init_video_info(void) -{ - DEBUGF("Getting movie size\n"); - - /* The decoder handles this in order to initialize its knowledge of the - * movie parameters making seeking easier */ - str_send_msg(&video_str, STREAM_RESET, 0); - if (str_send_msg(&video_str, VIDEO_GET_SIZE, - (intptr_t)&str_parser.dims) != 0) - { - return true; - } - - DEBUGF(" failed\n"); - return false; -} - -static bool init_times(struct stream *str) -{ - struct stream tmp_str; - const ssize_t filesize = disk_buf_filesize(); - const ssize_t max_probe = MIN(512*1024, filesize); - bool found_stream; - - /* Simply find the first earliest timestamp - this will be the one - * used when streaming anyway */ - DEBUGF("Finding start_pts: 0x%02x\n", str->id); - - found_stream = false; - str->start_pts = INVALID_TIMESTAMP; - str->end_pts = INVALID_TIMESTAMP; - - tmp_str.id = str->id; - tmp_str.hdr.pos = 0; - tmp_str.hdr.limit = max_probe; - - /* Probe for many for the start because some stamps could be anomalous. - * Video also can also have things out of order. Just see what it's got. - */ - while (1) - { - switch (parser_get_next_data(&tmp_str, STREAM_PM_RANDOM_ACCESS)) - { - case STREAM_DATA_END: - break; - case STREAM_OK: - found_stream = true; - if (tmp_str.pkt_flags & PKT_HAS_TS) - { - if (tmp_str.pts < str->start_pts) - str->start_pts = tmp_str.pts; - } - continue; - } - - break; - } - - if (!found_stream) - { - DEBUGF(" stream not found:0x%02x\n", str->id); - return false; - } - - DEBUGF(" start:%u\n", (unsigned)str->start_pts); - - /* Use the decoder thread to perform a synchronized search - no - * decoding should take place but just a simple run through timestamps - * and durations as the decoder would see them. This should give the - * precise time at the end of the last frame for the stream. */ - DEBUGF("Finding end_pts: 0x%02x\n", str->id); - - str_parser.parms.sd.time = MAX_TIMESTAMP; - str_parser.parms.sd.sk.pos = filesize - max_probe; - str_parser.parms.sd.sk.len = max_probe; - str_parser.parms.sd.sk.dir = SSCAN_FORWARD; - - str_send_msg(str, STREAM_RESET, 0); - - if (str_send_msg(str, STREAM_FIND_END_TIME, - (intptr_t)&str_parser.parms.sd) == STREAM_PERFECT_MATCH) - { - str->end_pts = str_parser.parms.sd.time; - DEBUGF(" end:%u\n", (unsigned)str->end_pts); - } - - return true; -} - -static bool check_times(const struct stream *str) -{ - return str->start_pts < str->end_pts && - str->end_pts != INVALID_TIMESTAMP; -} - -/* Return the best-fit file offset of a timestamp in the PES where - * timstamp <= time < next timestamp. Will try to return something reasonably - * valid if best-fit could not be made. */ -static off_t mpeg_parser_seek_PTS(uint32_t time, unsigned id) -{ - ssize_t pos_left = 0; - ssize_t pos_right = disk_buf.filesize; - ssize_t pos, pos_new; - uint32_t time_left = str_parser.start_pts; - uint32_t time_right = str_parser.end_pts; - uint32_t pts = 0; - uint32_t prevpts = 0; - enum state_enum state = STATE0; - struct stream_scan sk; - - stream_scan_init(&sk); - - /* Initial estimate taken from average bitrate - later interpolations are - * taken similarly based on the remaining file interval */ - pos_new = muldiv_uint32(time - time_left, pos_right - pos_left, - time_right - time_left) + pos_left; - - /* return this estimated position if nothing better comes up */ - pos = pos_new; - - DEBUGF("Seeking stream 0x%02x\n", id); - DEBUGF("$$ tl:%u t:%u ct:?? tr:%u\n pl:%ld pn:%ld pr:%ld\n", - (unsigned)time_left, (unsigned)time, (unsigned)time_right, - (long)pos_left, (long)pos_new, (long)pos_right); - - sk.dir = SSCAN_REVERSE; - - while (state < STATE9) - { - uint32_t currpts; - sk.pos = pos_new; - sk.len = (sk.dir < 0) ? pos_new - pos_left : pos_right - pos_new; - - currpts = mpeg_parser_scan_pts(&sk, id); - - if (currpts != INVALID_TIMESTAMP) - { - ssize_t pos_adj; /* Adjustment to over or under-estimate */ - - /* Found a valid timestamp - see were it lies in relation to - * target */ - if (currpts < time) - { - /* Time at current position is before seek time - move - * forward */ - if (currpts > pts) - { - /* This is less than the desired time but greater than - * the currently seeked one; move the position up */ - pts = currpts; - pos = sk.pos; - } - - /* No next timestamp can be sooner */ - pos_left = sk.pos + sk.data; - time_left = currpts; - - if (pos_right <= pos_left) - break; /* If the window disappeared - we're done */ - - pos_new = muldiv_uint32(time - time_left, - pos_right - pos_left, - time_right - time_left); - /* Point is ahead of us - fudge estimate a bit high */ - pos_adj = pos_new / 10; - - if (pos_adj > 512*1024) - pos_adj = 512*1024; - - pos_new += pos_left + pos_adj; - - if (pos_new >= pos_right) - { - /* Estimate could push too far */ - pos_new = pos_right; - } - - state = STATE2; /* Last scan was early */ - sk.dir = SSCAN_REVERSE; - - DEBUGF(">> tl:%u t:%u ct:%u tr:%u\n pl:%ld pn:%ld pr:%ld\n", - (unsigned)time_left, (unsigned)time, (unsigned)currpts, - (unsigned)time_right, (long)pos_left, (long)pos_new, - (long)pos_right); - } - else if (currpts > time) - { - /* Time at current position is past seek time - move - backward */ - pos_right = sk.pos; - time_right = currpts; - - if (pos_right <= pos_left) - break; /* If the window disappeared - we're done */ - - pos_new = muldiv_uint32(time - time_left, - pos_right - pos_left, - time_right - time_left); - /* Overshot the seek point - fudge estimate a bit low */ - pos_adj = pos_new / 10; - - if (pos_adj > 512*1024) - pos_adj = 512*1024; - - pos_new += pos_left - pos_adj; - - state = STATE3; /* Last scan was late */ - sk.dir = SSCAN_REVERSE; - - DEBUGF("<< tl:%u t:%u ct:%u tr:%u\n pl:%ld pn:%ld pr:%ld\n", - (unsigned)time_left, (unsigned)time, (unsigned)currpts, - (unsigned)time_right, (long)pos_left, (long)pos_new, - (long)pos_right); - } - else - { - /* Exact match - it happens */ - DEBUGF("|| tl:%u t:%u ct:%u tr:%u\n pl:%ld pn:%ld pr:%ld\n", - (unsigned)time_left, (unsigned)time, (unsigned)currpts, - (unsigned)time_right, (long)pos_left, (long)pos_new, - (long)pos_right); - pts = currpts; - pos = sk.pos; - state = STATE9; - } - } - else - { - /* Nothing found */ - - switch (state) - { - case STATE1: - /* We already tried the bruteforce scan and failed again - no - * more stamps could possibly exist in the interval */ - DEBUGF("!! no timestamp 2x\n"); - break; - case STATE0: - /* Hardly likely except at very beginning - just do L->R scan - * to find something */ - DEBUGF("!! no timestamp on first probe: %ld\n", sk.pos); - case STATE2: - case STATE3: - /* Could just be missing timestamps because the interval is - * narrowing down. A large block of data from another stream - * may also be in the midst of our chosen points which could - * cluster at either extreme end. If anything is there, this - * will find it. */ - pos_new = pos_left; - sk.dir = SSCAN_FORWARD; - DEBUGF("?? tl:%u t:%u ct:%u tr:%u\n pl:%ld pn:%ld pr:%ld\n", - (unsigned)time_left, (unsigned)time, (unsigned)currpts, - (unsigned)time_right, (long)pos_left, (long)pos_new, - (long)pos_right); - state = STATE1; - break; - default: - DEBUGF("?? Invalid state: %d\n", state); - } - } - - /* Same timestamp twice = quit */ - if (currpts == prevpts) - { - DEBUGF("!! currpts == prevpts (stop)\n"); - state = STATE9; - } - - prevpts = currpts; - } - -#if defined(DEBUG) || defined(SIMULATOR) - /* The next pts after the seeked-to position should be greater - - * most of the time - frames out of presentation order may muck it - * up a slight bit */ - sk.pos = pos + 1; - sk.len = disk_buf.filesize; - sk.dir = SSCAN_FORWARD; - - uint32_t nextpts = mpeg_parser_scan_pts(&sk, id); - DEBUGF("Seek pos:%ld pts:%u t:%u next pts:%u \n", - (long)pos, (unsigned)pts, (unsigned)time, (unsigned)nextpts); - - if (pts <= time && time < nextpts) - { - /* Smile - it worked */ - DEBUGF(" :) pts<=time time) - { - /* Hmm */ - DEBUGF(" :\\ pts>time\n"); - } - if (pts >= nextpts) - { - /* Weird - probably because of encoded order & tends to be right - * anyway if other criteria are met */ - DEBUGF(" :p pts>=next pts\n"); - } - if (time >= nextpts) - { - /* Ugh */ - DEBUGF(" :( time>=nextpts\n"); - } - } -#endif - - return pos; -} - -static void prepare_audio(uint32_t time) -{ - off_t pos; - - if (!str_send_msg(&audio_str, STREAM_NEEDS_SYNC, time)) - { - DEBUGF("Audio was ready\n"); - return; - } - - pos = mpeg_parser_seek_PTS(time, audio_str.id); - str_send_msg(&audio_str, STREAM_RESET, 0); - - str_parser.parms.sd.time = time; - str_parser.parms.sd.sk.pos = pos; - str_parser.parms.sd.sk.len = 1024*1024; - str_parser.parms.sd.sk.dir = SSCAN_FORWARD; - - str_send_msg(&audio_str, STREAM_SYNC, (intptr_t)&str_parser.parms.sd); -} - -/* This function demuxes the streams and gives the next stream data - * pointer. - * - * STREAM_PM_STREAMING is for operation during playback. If the nescessary - * data and worst-case lookahead margin is not available, the stream is - * registered for notification when the data becomes available. If parsing - * extends beyond the end of the file or the end of stream marker is reached, - * STREAM_DATA_END is returned and the stream state changed to SSTATE_EOS. - * - * STREAM_PM_RANDOM_ACCESS is for operation when not playing such as seeking. - * If the file cache misses for the current position + lookahead, it will be - * loaded from disk. When the specified limit is reached, STREAM_DATA_END is - * returned. - * - * The results from one mode may be used as input to the other. Random access - * requires cooperation amongst threads to avoid evicting another stream's - * data. - */ -static int parse_demux(struct stream *str, enum stream_parse_mode type) -{ - #define INC_BUF(offset) \ - ({ off_t _o = (offset); \ - str->hdr.win_right += _o; \ - if ((p += _o) >= disk_buf.end) \ - p -= disk_buf.size; }) - - static const int mpeg1_skip_table[16] = - { 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - uint8_t *p = str->curr_packet_end; - - str->pkt_flags = 0; - - while (1) - { - uint8_t *header; - unsigned id; - ssize_t length, bytes; - - switch (type) - { - case STREAM_PM_STREAMING: - /* Has the end been reached already? */ - switch (str->state) - { - case SSTATE_PARSE: /* Expected case first if no jumptable */ - /* Are we at the end of file? */ - if (str->hdr.win_left < disk_buf.filesize) - break; - str_end_of_stream(str); - return STREAM_DATA_END; - - case SSTATE_SYNC: - /* Is sync at the end of file? */ - if (str->hdr.win_right < disk_buf.filesize) - break; - str_end_of_stream(str); - /* Fall-through */ - case SSTATE_END: - return STREAM_DATA_END; - } - - if (!disk_buf_is_data_ready(&str->hdr, MIN_BUFAHEAD)) - { - /* This data range is not buffered yet - register stream to - * be notified when it becomes available. Stream is obliged - * to enter a TSTATE_DATA state if it must wait. */ - int res = str_next_data_not_ready(str); - - if (res != STREAM_OK) - return res; - } - break; - /* STREAM_PM_STREAMING: */ - - case STREAM_PM_RANDOM_ACCESS: - str->hdr.pos = disk_buf_lseek(str->hdr.pos, SEEK_SET); - - if (str->hdr.pos < 0 || str->hdr.pos >= str->hdr.limit || - disk_buf_getbuffer(MIN_BUFAHEAD, &p, NULL, NULL) <= 0) - { - str_end_of_stream(str); - return STREAM_DATA_END; - } - - str->state = SSTATE_SYNC; - str->hdr.win_left = str->hdr.pos; - str->curr_packet = NULL; - str->curr_packet_end = p; - break; - /* STREAM_PM_RANDOM_ACCESS: */ - } - - if (str->state == SSTATE_SYNC) - { - /* Scanning for start code */ - if (!CMP_3_CONST(p, PACKET_START_CODE_PREFIX)) - { - INC_BUF(1); - continue; - } - } - - /* Found a start code - enter parse state */ - str->state = SSTATE_PARSE; - - /* Pack header, skip it */ - if (CMP_4_CONST(p, PACK_START_CODE)) - { - /* Max lookahead: 14 */ - if ((p[4] & 0xc0) == 0x40) /* mpeg-2 */ - { - /* Max delta: 14 + 7 = 21 */ - /* Skip pack header and any stuffing bytes*/ - bytes = 14 + (p[13] & 7); - } - else if ((p[4] & 0xf0) == 0x20) /* mpeg-1 */ - { - bytes = 12; - } - else /* unknown - skip it */ - { - DEBUGF("weird pack header!\n"); - bytes = 5; - } - - INC_BUF(bytes); - } - - /* System header, parse and skip it - 6 bytes + size */ - if (CMP_4_CONST(p, SYSTEM_HEADER_START_CODE)) - { - /* Skip start code */ - /* Max Delta = 65535 + 6 = 65541 */ - bytes = 6 + ((p[4] << 8) | p[5]); - INC_BUF(bytes); - } - - /* Packet header, parse it */ - if (!CMP_3_CONST(p, PACKET_START_CODE_PREFIX)) - { - /* Problem? Meh...probably not but just a corrupted section. - * Try to resync the parser which will probably succeed. */ - DEBUGF("packet start code prefix not found: 0x%02x\n" - " wl:%lu wr:%lu\n" - " p:%p cp:%p cpe:%p\n" - " dbs:%p dbe:%p dbt:%p\n", - str->id, str->hdr.win_left, str->hdr.win_right, - p, str->curr_packet, str->curr_packet_end, - disk_buf.start, disk_buf.end, disk_buf.tail); - str->state = SSTATE_SYNC; - INC_BUF(1); /* Next byte - this one's no good */ - continue; - } - - /* We retrieve basic infos */ - /* Maximum packet length: 6 + 65535 = 65541 */ - id = p[3]; - length = ((p[4] << 8) | p[5]) + 6; - - if (id != str->id) - { - switch (id) - { - case MPEG_STREAM_PROGRAM_END: - /* end of stream */ - str_end_of_stream(str); - DEBUGF("MPEG program end: 0x%02x\n", str->id); - return STREAM_DATA_END; - case MPEG_STREAM_PACK_HEADER: - case MPEG_STREAM_SYSTEM_HEADER: - /* These shouldn't be here - no increment or resync - * since we'll pick it up above. */ - continue; - default: - /* It's not the packet we're looking for, skip it */ - INC_BUF(length); - continue; - } - } - - /* Ok, it's our packet */ - header = p; - - if ((header[6] & 0xc0) == 0x80) /* mpeg2 */ - { - /* Max Lookahead: 18 */ - /* Min length: 9 */ - /* Max length: 9 + 255 = 264 */ - length = 9 + header[8]; - - /* header points to the mpeg2 pes header */ - if ((header[7] & 0x80) != 0) - { - /* header has a pts */ - uint32_t pts = read_pts(header, 9); - - if (pts != INVALID_TIMESTAMP) - { - str->pts = pts; -#if 0 - /* DTS isn't used for anything since things just get - decoded ASAP but keep the code around */ - if (STREAM_IS_VIDEO(id)) - { - /* Video stream - header may have a dts as well */ - str->dts = pts; - - if (header[7] & 0x40) != 0x00) - { - pts = read_pts(header, 14); - if (pts != INVALID_TIMESTAMP) - str->dts = pts; - } - } -#endif - str->pkt_flags |= PKT_HAS_TS; - } - } - } - else /* mpeg1 */ - { - /* Max lookahead: 24 + 2 + 9 = 35 */ - /* Max len_skip: 24 + 2 = 26 */ - /* Min length: 7 */ - /* Max length: 24 + 2 + 9 = 35 */ - off_t len_skip; - uint8_t * ptsbuf; - - length = 7; - - while (header[length - 1] == 0xff) - { - if (++length > 23) - { - DEBUGF("Too much stuffing" ); - break; - } - } - - if ((header[length - 1] & 0xc0) == 0x40) - length += 2; - - len_skip = length; - length += mpeg1_skip_table[header[length - 1] >> 4]; - - /* Header points to the mpeg1 pes header */ - ptsbuf = header + len_skip; - - if ((ptsbuf[-1] & 0xe0) == 0x20 && TS_CHECK_MARKERS(ptsbuf, -1)) - { - /* header has a pts */ - uint32_t pts = read_pts(ptsbuf, -1); - - if (pts != INVALID_TIMESTAMP) - { - str->pts = pts; -#if 0 - /* DTS isn't used for anything since things just get - decoded ASAP but keep the code around */ - if (STREAM_IS_VIDEO(id)) - { - /* Video stream - header may have a dts as well */ - str->dts = pts; - - if (ptsbuf[-1] & 0xf0) == 0x30) - { - pts = read_pts(ptsbuf, 4); - - if (pts != INVALID_TIMESTAMP) - str->dts = pts; - } - } -#endif - str->pkt_flags |= PKT_HAS_TS; - } - } - } - - p += length; - /* Max bytes: 6 + 65535 - 7 = 65534 */ - bytes = 6 + (header[4] << 8) + header[5] - length; - - str->curr_packet = p; - str->curr_packet_end = p + bytes; - str->hdr.win_left = str->hdr.win_right + length; - str->hdr.win_right = str->hdr.win_left + bytes; - - if (str->hdr.win_right > disk_buf.filesize) - { - /* No packet that exceeds end of file can be valid */ - str_end_of_stream(str); - return STREAM_DATA_END; - } - - return STREAM_OK; - } /* end while */ - - #undef INC_BUF -} - -/* This simply reads data from the file one page at a time and returns a - * pointer to it in the buffer. */ -static int parse_elementary(struct stream *str, enum stream_parse_mode type) -{ - uint8_t *p; - ssize_t len = 0; - - str->pkt_flags = 0; - - switch (type) - { - case STREAM_PM_STREAMING: - /* Has the end been reached already? */ - if (str->state == SSTATE_END) - return STREAM_DATA_END; - - /* Are we at the end of file? */ - if (str->hdr.win_left >= disk_buf.filesize) - { - str_end_of_stream(str); - return STREAM_DATA_END; - } - - if (!disk_buf_is_data_ready(&str->hdr, MIN_BUFAHEAD)) - { - /* This data range is not buffered yet - register stream to - * be notified when it becomes available. Stream is obliged - * to enter a TSTATE_DATA state if it must wait. */ - int res = str_next_data_not_ready(str); - - if (res != STREAM_OK) - return res; - } - - len = DISK_BUF_PAGE_SIZE; - - if ((size_t)(str->hdr.win_right + len) > (size_t)disk_buf.filesize) - len = disk_buf.filesize - str->hdr.win_right; - - if (len <= 0) - { - str_end_of_stream(str); - return STREAM_DATA_END; - } - - p = str->curr_packet_end; - if (p >= disk_buf.end) - p -= disk_buf.size; - break; - /* STREAM_PM_STREAMING: */ - - case STREAM_PM_RANDOM_ACCESS: - str->hdr.pos = disk_buf_lseek(str->hdr.pos, SEEK_SET); - len = disk_buf_getbuffer(DISK_BUF_PAGE_SIZE, &p, NULL, NULL); - - if (len <= 0 || str->hdr.pos < 0 || str->hdr.pos >= str->hdr.limit) - { - str_end_of_stream(str); - return STREAM_DATA_END; - } - break; - /* STREAM_PM_RANDOM_ACCESS: */ - } - - str->state = SSTATE_PARSE; - str->curr_packet = p; - str->curr_packet_end = p + len; - str->hdr.win_left = str->hdr.win_right; - str->hdr.win_right = str->hdr.win_left + len; - - return STREAM_OK; -} - -bool parser_prepare_image(uint32_t time) -{ - struct stream_scan sk; - int tries; - int result; - - stream_scan_init(&sk); - - if (!str_send_msg(&video_str, STREAM_NEEDS_SYNC, time)) - { - DEBUGF("Image was ready\n"); - return true; /* Should already have the image */ - } - -#ifdef HAVE_ADJUSTABLE_CPU_FREQ - rb->cpu_boost(true); /* No interference with trigger_cpu_boost */ -#endif - - str_send_msg(&video_str, STREAM_RESET, 0); - - sk.pos = parser_can_seek() ? - mpeg_parser_seek_PTS(time, video_str.id) : 0; - sk.len = sk.pos; - sk.dir = SSCAN_REVERSE; - - tries = 1; -try_again: - - if (mpeg_parser_scan_start_code(&sk, MPEG_START_GOP)) - { - DEBUGF("GOP found at: %ld\n", sk.pos); - - unsigned id = mpeg_parser_scan_pes(&sk); - - if (id != video_str.id && sk.pos > 0) - { - /* Not part of our stream */ - DEBUGF(" wrong stream: 0x%02x\n", id); - goto try_again; - } - - /* This will hit the PES header since it's known to be there */ - uint32_t pts = mpeg_parser_scan_pts(&sk, id); - - if (pts == INVALID_TIMESTAMP || pts > time) - { - DEBUGF(" wrong timestamp: %u\n", (unsigned)pts); - goto try_again; - } - } - - str_parser.parms.sd.time = time; - str_parser.parms.sd.sk.pos = MAX(sk.pos, 0); - str_parser.parms.sd.sk.len = 1024*1024; - str_parser.parms.sd.sk.dir = SSCAN_FORWARD; - - DEBUGF("thumb pos:%ld len:%ld\n", str_parser.parms.sd.sk.pos, - (long)str_parser.parms.sd.sk.len); - - result = str_send_msg(&video_str, STREAM_SYNC, - (intptr_t)&str_parser.parms.sd); - - if (result != STREAM_PERFECT_MATCH) - { - /* Two tries should be all that is nescessary to find the exact frame - * if the first GOP actually started later than the timestamp - the - * GOP just prior must then start on or earlier. */ - if (++tries <= 2) - goto try_again; - } - -#ifdef HAVE_ADJUSTABLE_CPU_FREQ - rb->cpu_boost(false); -#endif - - return result > STREAM_OK; -} - -/* Seek parser to the specified time and return absolute time. - * No actual hard stuff is performed here. That's done when streaming is - * about to begin or something from the current position is requested */ -uint32_t parser_seek_time(uint32_t time) -{ - if (!parser_can_seek()) - time = 0; - else if (time > str_parser.duration) - time = str_parser.duration; - - str_parser.last_seek_time = time + str_parser.start_pts; - return str_parser.last_seek_time; -} - -void parser_prepare_streaming(void) -{ - struct stream_window sw; - - DEBUGF("parser_prepare_streaming\n"); - - /* Prepare initial video frame */ - parser_prepare_image(str_parser.last_seek_time); - - /* Sync audio stream */ - if (audio_str.start_pts != INVALID_TIMESTAMP) - prepare_audio(str_parser.last_seek_time); - - /* Prequeue some data and set buffer window */ - if (!stream_get_window(&sw)) - sw.left = sw.right = disk_buf.filesize; - - DEBUGF(" swl:%ld swr:%ld\n", sw.left, sw.right); - - if (sw.right > disk_buf.filesize - 4*MIN_BUFAHEAD) - sw.right = disk_buf.filesize - 4*MIN_BUFAHEAD; - - disk_buf_prepare_streaming(sw.left, - sw.right - sw.left + 4*MIN_BUFAHEAD); -} - -int parser_init_stream(void) -{ - if (disk_buf.in_file < 0) - return STREAM_ERROR; - - /* TODO: Actually find which streams are available */ - audio_str.id = MPEG_STREAM_AUDIO_FIRST; - video_str.id = MPEG_STREAM_VIDEO_FIRST; - - /* Try to pull a video PES - if not found, try video init anyway which - * should succeed if it really is a video-only stream */ - video_str.hdr.pos = 0; - video_str.hdr.limit = 256*1024; - - if (parse_demux(&video_str, STREAM_PM_RANDOM_ACCESS) == STREAM_OK) - { - /* Found a video packet - assume program stream */ - str_parser.format = STREAM_FMT_MPEG_PS; - str_parser.next_data = parse_demux; - } - else - { - /* No PES element found - assume video elementary stream */ - str_parser.format = STREAM_FMT_MPV; - str_parser.next_data = parse_elementary; - } - - if (!init_video_info()) - { - /* Cannot determine video size, etc. */ - parser_init_state(); - return STREAM_UNSUPPORTED; - } - - if (str_parser.format == STREAM_FMT_MPEG_PS) - { - /* Initalize start_pts and end_pts with the length (in 45kHz units) of - * the movie. INVALID_TIMESTAMP if the time could not be determined */ - if (!init_times(&video_str) || !check_times(&video_str)) - { - /* Must have video at least */ - parser_init_state(); - return STREAM_UNSUPPORTED; - } - - str_parser.flags |= STREAMF_CAN_SEEK; - - if (init_times(&audio_str)) - { - /* Audio will be part of playback pool */ - stream_add_stream(&audio_str); - - if (check_times(&audio_str)) - { - /* Overall duration is maximum span */ - str_parser.start_pts = MIN(audio_str.start_pts, video_str.start_pts); - str_parser.end_pts = MAX(audio_str.end_pts, video_str.end_pts); - } - else - { - /* Bad times on audio - use video times */ - str_parser.start_pts = video_str.start_pts; - str_parser.end_pts = video_str.end_pts; - - /* Questionable: could use bitrate seek and match video to that */ - audio_str.start_pts = video_str.start_pts; - audio_str.end_pts = video_str.end_pts; - } - } - else - { - /* No audio stream - use video only */ - str_parser.start_pts = video_str.start_pts; - str_parser.end_pts = video_str.end_pts; - } - - str_parser.last_seek_time = str_parser.start_pts; - } - else - { - /* There's no way to handle times on this without a full file - * scan */ - audio_str.start_pts = INVALID_TIMESTAMP; - audio_str.end_pts = INVALID_TIMESTAMP; - video_str.start_pts = 0; - video_str.end_pts = INVALID_TIMESTAMP; - str_parser.start_pts = 0; - str_parser.end_pts = INVALID_TIMESTAMP; - } - - /* Add video to playback pool */ - stream_add_stream(&video_str); - - /* Cache duration - it's used very often */ - str_parser.duration = str_parser.end_pts - str_parser.start_pts; - - DEBUGF("Movie info:\n" - " size:%dx%d\n" - " start:%u\n" - " end:%u\n" - " duration:%u\n", - str_parser.dims.w, str_parser.dims.h, - (unsigned)str_parser.start_pts, - (unsigned)str_parser.end_pts, - (unsigned)str_parser.duration); - - return STREAM_OK; -} - -void parser_close_stream(void) -{ - stream_remove_streams(); - parser_init_state(); -} - -bool parser_init(void) -{ - parser_init_state(); - return true; -} diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c deleted file mode 100644 index c904de466d..0000000000 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ /dev/null @@ -1,1454 +0,0 @@ -#include "plugin.h" -#include "lib/helper.h" -#include "lib/configfile.h" - -#include "mpegplayer.h" -#include "mpeg_settings.h" - -struct mpeg_settings settings; - -#define THUMB_DELAY (75*HZ/100) - -/* button definitions */ -#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ - (CONFIG_KEYPAD == IRIVER_H300_PAD) -#define MPEG_START_TIME_SELECT BUTTON_ON -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_OFF - -#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ - (CONFIG_KEYPAD == IPOD_3G_PAD) || \ - (CONFIG_KEYPAD == IPOD_1G2G_PAD) -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_SCROLL_FWD -#define MPEG_START_TIME_DOWN BUTTON_SCROLL_BACK -#define MPEG_START_TIME_EXIT BUTTON_MENU - -#elif CONFIG_KEYPAD == GIGABEAT_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#define MPEG_START_TIME_RC_SELECT (BUTTON_RC_PLAY | BUTTON_REL) -#define MPEG_START_TIME_RC_LEFT BUTTON_RC_REW -#define MPEG_START_TIME_RC_RIGHT BUTTON_RC_FF -#define MPEG_START_TIME_RC_UP BUTTON_RC_VOL_UP -#define MPEG_START_TIME_RC_DOWN BUTTON_RC_VOL_DOWN -#define MPEG_START_TIME_RC_EXIT (BUTTON_RC_PLAY | BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#define MPEG_START_TIME_RC_SELECT (BUTTON_RC_PLAY | BUTTON_REL) -#define MPEG_START_TIME_RC_LEFT BUTTON_RC_REW -#define MPEG_START_TIME_RC_RIGHT BUTTON_RC_FF -#define MPEG_START_TIME_RC_UP BUTTON_RC_VOL_UP -#define MPEG_START_TIME_RC_DOWN BUTTON_RC_VOL_DOWN -#define MPEG_START_TIME_RC_EXIT (BUTTON_RC_PLAY | BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == IRIVER_H10_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_SCROLL_UP -#define MPEG_START_TIME_DOWN BUTTON_SCROLL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif (CONFIG_KEYPAD == SANSA_E200_PAD) -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_SCROLL_BACK -#define MPEG_START_TIME_RIGHT2 BUTTON_SCROLL_FWD -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_SCROLL_BACK -#define MPEG_START_TIME_RIGHT2 BUTTON_SCROLL_FWD -#define MPEG_START_TIME_EXIT (BUTTON_HOME|BUTTON_REPEAT) - -#elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \ -(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \ -(CONFIG_KEYPAD == SANSA_M200_PAD) -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == MROBE500_PAD -#define MPEG_START_TIME_SELECT BUTTON_RC_HEART -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_RC_PLAY -#define MPEG_START_TIME_DOWN BUTTON_RC_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_RC_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_RC_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == MROBE100_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_PLAY -#define MPEG_START_TIME_RIGHT2 BUTTON_MENU -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == IAUDIO_M3_PAD -#define MPEG_START_TIME_SELECT BUTTON_RC_PLAY -#define MPEG_START_TIME_LEFT BUTTON_RC_REW -#define MPEG_START_TIME_RIGHT BUTTON_RC_FF -#define MPEG_START_TIME_UP BUTTON_RC_VOL_UP -#define MPEG_START_TIME_DOWN BUTTON_RC_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_RC_REC - -#elif CONFIG_KEYPAD == COWON_D2_PAD -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_PLAY -#define MPEG_START_TIME_RIGHT2 BUTTON_MENU -#define MPEG_START_TIME_EXIT BUTTON_BACK - -#elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) -#define MPEG_START_TIME_SELECT (BUTTON_PLAY|BUTTON_REL) -#define MPEG_START_TIME_LEFT BUTTON_BACK -#define MPEG_START_TIME_RIGHT BUTTON_MENU -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT (BUTTON_PLAY|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_PREV -#define MPEG_START_TIME_RIGHT BUTTON_NEXT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == ONDAVX747_PAD -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == ONDAVX777_PAD -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ - (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_REW - -#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_PREV -#define MPEG_START_TIME_RIGHT BUTTON_NEXT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_OK -#define MPEG_START_TIME_RIGHT2 BUTTON_CANCEL -#define MPEG_START_TIME_EXIT BUTTON_REC - -#elif CONFIG_KEYPAD == MPIO_HD200_PAD -#define MPEG_START_TIME_SELECT BUTTON_FUNC -#define MPEG_START_TIME_LEFT BUTTON_REW -#define MPEG_START_TIME_RIGHT BUTTON_FF -#define MPEG_START_TIME_UP BUTTON_VOL_UP -#define MPEG_START_TIME_DOWN BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_REC - -#elif CONFIG_KEYPAD == MPIO_HD300_PAD -#define MPEG_START_TIME_SELECT BUTTON_ENTER -#define MPEG_START_TIME_LEFT BUTTON_REW -#define MPEG_START_TIME_RIGHT BUTTON_FF -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_REC - -#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_BACK - -#elif (CONFIG_KEYPAD == HM60X_PAD) || (CONFIG_KEYPAD == HM801_PAD) -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == SONY_NWZ_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_BACK - -#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_BACK - -#elif CONFIG_KEYPAD == DX50_PAD -#define MPEG_START_TIME_EXIT BUTTON_POWER -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_VOL_UP -#define MPEG_START_TIME_DOWN BUTTON_VOL_DOWN - -#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == XDUOO_X3_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_PREV -#define MPEG_START_TIME_RIGHT BUTTON_NEXT -#define MPEG_START_TIME_UP BUTTON_HOME -#define MPEG_START_TIME_DOWN BUTTON_OPTION -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_PREV -#define MPEG_START_TIME_RIGHT BUTTON_NEXT -#define MPEG_START_TIME_UP BUTTON_HOME -#define MPEG_START_TIME_DOWN BUTTON_OPTION -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_PREV -#define MPEG_START_TIME_RIGHT BUTTON_NEXT -#define MPEG_START_TIME_UP BUTTON_HOME -#define MPEG_START_TIME_DOWN BUTTON_OPTION -#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP -#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_HOME -#define MPEG_START_TIME_RIGHT BUTTON_VOL_DOWN -#define MPEG_START_TIME_UP BUTTON_PREV -#define MPEG_START_TIME_DOWN BUTTON_NEXT -#define MPEG_START_TIME_LEFT2 (BUTTON_POWER + BUTTON_HOME) -#define MPEG_START_TIME_RIGHT2 (BUTTON_POWER + BUTTON_VOL_DOWN) -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == EROSQ_PAD -#define MPEG_START_TIME_SELECT BUTTON_PLAY -#define MPEG_START_TIME_LEFT BUTTON_SCROLL_BACK -#define MPEG_START_TIME_RIGHT BUTTON_SCROLL_FWD -#define MPEG_START_TIME_UP BUTTON_PREV -#define MPEG_START_TIME_DOWN BUTTON_NEXT -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == FIIO_M3K_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#elif CONFIG_KEYPAD == SHANLING_Q1_PAD -#define MPEG_START_TIME_EXIT BUTTON_POWER - -#else -#error No keymap defined! -#endif - -#ifdef HAVE_TOUCHSCREEN -#ifndef MPEG_START_TIME_SELECT -#define MPEG_START_TIME_SELECT BUTTON_CENTER -#endif -#ifndef MPEG_START_TIME_LEFT -#define MPEG_START_TIME_LEFT BUTTON_MIDLEFT -#endif -#ifndef MPEG_START_TIME_RIGHT -#define MPEG_START_TIME_RIGHT BUTTON_MIDRIGHT -#endif -#ifndef MPEG_START_TIME_UP -#define MPEG_START_TIME_UP BUTTON_TOPMIDDLE -#endif -#ifndef MPEG_START_TIME_DOWN -#define MPEG_START_TIME_DOWN BUTTON_BOTTOMMIDDLE -#endif -#ifndef MPEG_START_TIME_LEFT2 -#define MPEG_START_TIME_LEFT2 BUTTON_TOPRIGHT -#endif -#ifndef MPEG_START_TIME_RIGHT2 -#define MPEG_START_TIME_RIGHT2 BUTTON_TOPLEFT -#endif -#ifndef MPEG_START_TIME_EXIT -#define MPEG_START_TIME_EXIT BUTTON_TOPLEFT -#endif -#endif - -static struct configdata config[] = -{ - {TYPE_INT, 0, 2, { .int_p = &settings.showfps }, "Show FPS", NULL}, - {TYPE_INT, 0, 2, { .int_p = &settings.limitfps }, "Limit FPS", NULL}, - {TYPE_INT, 0, 2, { .int_p = &settings.skipframes }, "Skip frames", NULL}, - {TYPE_INT, 0, INT_MAX, { .int_p = &settings.resume_count }, "Resume count", - NULL}, - {TYPE_INT, 0, MPEG_RESUME_NUM_OPTIONS, - { .int_p = &settings.resume_options }, "Resume options", NULL}, -#if MPEG_OPTION_DITHERING_ENABLED - {TYPE_INT, 0, INT_MAX, { .int_p = &settings.displayoptions }, - "Display options", NULL}, -#endif - {TYPE_INT, 0, 2, { .int_p = &settings.tone_controls }, "Tone controls", - NULL}, - {TYPE_INT, 0, 2, { .int_p = &settings.channel_modes }, "Channel modes", - NULL}, - {TYPE_INT, 0, 2, { .int_p = &settings.crossfeed }, "Crossfeed", NULL}, - {TYPE_INT, 0, 2, { .int_p = &settings.equalizer }, "Equalizer", NULL}, - {TYPE_INT, 0, 2, { .int_p = &settings.dithering }, "Dithering", NULL}, - {TYPE_INT, 0, 2, { .int_p = &settings.play_mode }, "Play mode", NULL}, -#ifdef HAVE_BACKLIGHT_BRIGHTNESS - {TYPE_INT, -1, INT_MAX, { .int_p = &settings.backlight_brightness }, - "Backlight brightness", NULL}, -#endif -}; - -static const struct opt_items noyes[2] = { - { STR(LANG_SET_BOOL_NO) }, - { STR(LANG_SET_BOOL_YES) }, -}; - -static const struct opt_items singleall[2] = { - { STR(LANG_SINGLE) }, - { STR(LANG_ALL) }, -}; - -static const struct opt_items globaloff[2] = { - { STR(LANG_OFF) }, - { STR(LANG_USE_SOUND_SETTING) }, -}; - -static void mpeg_settings(void); -static bool mpeg_set_option(const char* string, - void* variable, - enum optiontype type, - const struct opt_items* options, - int numoptions, - void (*function)(int)) -{ - mpeg_sysevent_clear(); - - /* This eats SYS_POWEROFF - :\ */ - bool usb = rb->set_option(string, variable, type, options, numoptions, - function); - - if (usb) - mpeg_sysevent_set(); - - return usb; -} - -#ifdef HAVE_BACKLIGHT_BRIGHTNESS /* Only used for this atm */ -static bool mpeg_set_int(const char *string, const char *unit, - int voice_unit, const int *variable, - void (*function)(int), int step, - int min, - int max, - const char* (*formatter)(char*, size_t, int, const char*), - int32_t (*get_talk_id)(int, int)) -{ - mpeg_sysevent_clear(); - - bool usb = rb->set_int_ex(string, unit, voice_unit, variable, function, - step, min, max, formatter, get_talk_id); - - if (usb) - mpeg_sysevent_set(); - - return usb; -} - -static int32_t backlight_brightness_getlang(int value, int unit) -{ - if (value < 0) - return LANG_USE_COMMON_SETTING; - - return TALK_ID(value + MIN_BRIGHTNESS_SETTING, unit); -} - -void mpeg_backlight_update_brightness(int value) -{ - if (value >= 0) - { - value += MIN_BRIGHTNESS_SETTING; - backlight_brightness_set(value); - } - else - { - backlight_brightness_use_setting(); - } -} - -static void backlight_brightness_function(int value) -{ - mpeg_backlight_update_brightness(value); -} - -static const char* backlight_brightness_formatter(char *buf, size_t length, - int value, const char *input) -{ - (void)input; - - if (value < 0) - return rb->str(LANG_USE_COMMON_SETTING); - else - rb->snprintf(buf, length, "%d", value + MIN_BRIGHTNESS_SETTING); - return buf; -} -#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ - -/* Sync a particular audio setting to global or mpegplayer forced off */ -static void sync_audio_setting(int setting, bool global) -{ - switch (setting) - { - case MPEG_AUDIO_TONE_CONTROLS: - #ifdef AUDIOHW_HAVE_BASS - rb->sound_set(SOUND_BASS, (global || settings.tone_controls) - ? rb->global_settings->bass - : rb->sound_default(SOUND_BASS)); - #endif - #ifdef AUDIOHW_HAVE_TREBLE - rb->sound_set(SOUND_TREBLE, (global || settings.tone_controls) - ? rb->global_settings->treble - : rb->sound_default(SOUND_TREBLE)); - #endif - - #ifdef AUDIOHW_HAVE_EQ - for (int band = 0;; band++) - { - int setting = rb->sound_enum_hw_eq_band_setting(band, AUDIOHW_EQ_GAIN); - - if (setting == -1) - break; - - rb->sound_set(setting, (global || settings.tone_controls) - ? rb->global_settings->hw_eq_bands[band].gain - : rb->sound_default(setting)); - } - #endif /* AUDIOHW_HAVE_EQ */ - break; - - case MPEG_AUDIO_CHANNEL_MODES: - rb->sound_set(SOUND_CHANNELS, (global || settings.channel_modes) - ? rb->global_settings->channel_config - : SOUND_CHAN_STEREO); - break; - - case MPEG_AUDIO_CROSSFEED: - rb->dsp_set_crossfeed_type((global || settings.crossfeed) ? - rb->global_settings->crossfeed : - CROSSFEED_TYPE_NONE); - break; - - case MPEG_AUDIO_EQUALIZER: - rb->dsp_eq_enable((global || settings.equalizer) ? - rb->global_settings->eq_enabled : false); - break; - - case MPEG_AUDIO_DITHERING: - rb->dsp_dither_enable((global || settings.dithering) ? - rb->global_settings->dithering_enabled : false); - break; - } -} - -/* Sync all audio settings to global or mpegplayer forced off */ -static void sync_audio_settings(bool global) -{ - static const int setting_index[] = - { - MPEG_AUDIO_TONE_CONTROLS, - MPEG_AUDIO_CHANNEL_MODES, - MPEG_AUDIO_CROSSFEED, - MPEG_AUDIO_EQUALIZER, - MPEG_AUDIO_DITHERING, - }; - unsigned i; - - for (i = 0; i < ARRAYLEN(setting_index); i++) - { - sync_audio_setting(setting_index[i], global); - } -} - -#ifndef HAVE_LCD_COLOR -/* Cheapo splash implementation for the grey surface */ -static void grey_splash(int ticks, const unsigned char *fmt, ...) -{ - unsigned char buffer[256]; - int x, y, w, h; - int oldfg, oldmode; - - va_list ap; - va_start(ap, fmt); - - rb->vsnprintf(buffer, sizeof (buffer), fmt, ap); - - va_end(ap); - - grey_getstringsize(buffer, &w, &h); - - oldfg = grey_get_foreground(); - oldmode = grey_get_drawmode(); - - grey_set_drawmode(DRMODE_FG); - grey_set_foreground(GREY_LIGHTGRAY); - - x = (LCD_WIDTH - w) / 2; - y = (LCD_HEIGHT - h) / 2; - - grey_fillrect(x - 1, y - 1, w + 2, h + 2); - - grey_set_foreground(GREY_BLACK); - - grey_putsxy(x, y, buffer); - grey_drawrect(x - 2, y - 2, w + 4, h + 4); - - grey_set_foreground(oldfg); - grey_set_drawmode(oldmode); - - grey_update(); - - if (ticks > 0) - rb->sleep(ticks); -} -#endif /* !HAVE_LCD_COLOR */ - -static void show_loading(struct vo_rect *rc) -{ - int oldmode = mylcd_get_drawmode(); - mylcd_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); - mylcd_fillrect(rc->l-1, rc->t-1, rc->r - rc->l + 2, rc->b - rc->t + 2); - mylcd_set_drawmode(oldmode); - mylcd_splash(0, "Loading..."); -} - -static void draw_slider(uint32_t range, uint32_t pos, struct vo_rect *rc) -{ - #define SLIDER_WIDTH (LCD_WIDTH-SLIDER_LMARGIN-SLIDER_RMARGIN) - #define SLIDER_X SLIDER_LMARGIN - #define SLIDER_Y (LCD_HEIGHT-SLIDER_HEIGHT-SLIDER_BMARGIN) - #define SLIDER_HEIGHT 8 - #define SLIDER_TEXTMARGIN 1 - #define SLIDER_LMARGIN 1 - #define SLIDER_RMARGIN 1 - #define SLIDER_TMARGIN 1 - #define SLIDER_BMARGIN 1 - #define SCREEN_MARGIN 1 - - struct hms hms; - char str[32]; - int text_w, text_h, text_y; - - /* Put positition on left */ - ts_to_hms(pos, &hms); - hms_format(str, sizeof(str), &hms); - mylcd_getstringsize(str, NULL, &text_h); - text_y = SLIDER_Y - SLIDER_TEXTMARGIN - text_h; - - if (rc == NULL) - { - int oldmode = mylcd_get_drawmode(); - mylcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID); - mylcd_fillrect(SLIDER_X, text_y, SLIDER_WIDTH, - LCD_HEIGHT - SLIDER_BMARGIN - text_y - - SLIDER_TMARGIN); - mylcd_set_drawmode(oldmode); - - mylcd_putsxy(SLIDER_X, text_y, str); - - /* Put duration on right */ - ts_to_hms(range, &hms); - hms_format(str, sizeof(str), &hms); - mylcd_getstringsize(str, &text_w, NULL); - - mylcd_putsxy(SLIDER_X + SLIDER_WIDTH - text_w, text_y, str); - - /* Draw slider */ - mylcd_drawrect(SLIDER_X, SLIDER_Y, SLIDER_WIDTH, SLIDER_HEIGHT); - mylcd_fillrect(SLIDER_X, SLIDER_Y, - muldiv_uint32(pos, SLIDER_WIDTH, range), - SLIDER_HEIGHT); - - /* Update screen */ - mylcd_update_rect(SLIDER_X, text_y - SLIDER_TMARGIN, SLIDER_WIDTH, - LCD_HEIGHT - SLIDER_BMARGIN - text_y + SLIDER_TEXTMARGIN); - } - else - { - /* Just return slider rectangle */ - rc->l = SLIDER_X; - rc->t = text_y - SLIDER_TMARGIN; - rc->r = rc->l + SLIDER_WIDTH; - rc->b = rc->t + LCD_HEIGHT - SLIDER_BMARGIN - text_y; - } -} - -static bool display_thumb_image(const struct vo_rect *rc) -{ - bool retval = true; - unsigned ltgray = MYLCD_LIGHTGRAY; - unsigned dkgray = MYLCD_DARKGRAY; - - int oldcolor = mylcd_get_foreground(); - - if (!stream_display_thumb(rc)) - { - /* Display "No Frame" and erase any border */ - const char * const str = "No Frame"; - int x, y, w, h; - - mylcd_getstringsize(str, &w, &h); - x = (rc->r + rc->l - w) / 2; - y = (rc->b + rc->t - h) / 2; - mylcd_putsxy(x, y, str); - - mylcd_update_rect(x, y, w, h); - - ltgray = dkgray = mylcd_get_background(); - retval = false; - } - - /* Draw a raised border around the frame (or erase if no frame) */ - - mylcd_set_foreground(ltgray); - - mylcd_hline(rc->l-1, rc->r-1, rc->t-1); - mylcd_vline(rc->l-1, rc->t, rc->b-1); - - mylcd_set_foreground(dkgray); - - mylcd_hline(rc->l-1, rc->r, rc->b); - mylcd_vline(rc->r, rc->t-1, rc->b); - - mylcd_set_foreground(oldcolor); - - mylcd_update_rect(rc->l-1, rc->t-1, rc->r - rc->l + 2, 1); - mylcd_update_rect(rc->l-1, rc->t, 1, rc->b - rc->t); - mylcd_update_rect(rc->l-1, rc->b, rc->r - rc->l + 2, 1); - mylcd_update_rect(rc->r, rc->t, 1, rc->b - rc->t); - - return retval; -} - -/* Add an amount to the specified time - with saturation */ -static uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range) -{ - if (amount < 0) - { - uint32_t off = -amount; - if (range > off && val >= off) - val -= off; - else - val = 0; - } - else if (amount > 0) - { - uint32_t off = amount; - if (range > off && val <= range - off) - val += off; - else - val = range; - } - - return val; -} - -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) -static void get_start_time_lcd_enable_hook(unsigned short id, void *param) -{ - (void)id; - (void)param; - rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_0, 0); -} -#endif /* HAVE_LCD_ENABLE */ - -static int get_start_time(uint32_t duration) -{ - int button = 0; - int tmo = TIMEOUT_NOBLOCK; - uint32_t resume_time = settings.resume_time; - struct vo_rect rc_vid, rc_bound; - uint32_t aspect_vid, aspect_bound; - bool sliding = false; - - enum state_enum slider_state = STATE0; - - mylcd_clear_display(); - mylcd_update(); - -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - rb->add_event(LCD_EVENT_ACTIVATION, get_start_time_lcd_enable_hook); -#endif - - draw_slider(0, 100, &rc_bound); - rc_bound.b = rc_bound.t - SLIDER_TMARGIN; - rc_bound.t = SCREEN_MARGIN; - - DEBUGF("rc_bound: %d, %d, %d, %d\n", rc_bound.l, rc_bound.t, - rc_bound.r, rc_bound.b); - - rc_vid.l = rc_vid.t = 0; - if (!stream_vo_get_size((struct vo_ext *)&rc_vid.r)) - { - /* Can't get size - fill whole thing */ - rc_vid.r = rc_bound.r - rc_bound.l; - rc_vid.b = rc_bound.b - rc_bound.t; - } - - /* Get aspect ratio of bounding rectangle and video in u16.16 */ - aspect_bound = ((rc_bound.r - rc_bound.l) << 16) / - (rc_bound.b - rc_bound.t); - - DEBUGF("aspect_bound: %u.%02u\n", (unsigned)(aspect_bound >> 16), - (unsigned)(100*(aspect_bound & 0xffff) >> 16)); - - aspect_vid = (rc_vid.r << 16) / rc_vid.b; - - DEBUGF("aspect_vid: %u.%02u\n", (unsigned)(aspect_vid >> 16), - (unsigned)(100*(aspect_vid & 0xffff) >> 16)); - - if (aspect_vid >= aspect_bound) - { - /* Video proportionally wider than or same as bounding rectangle */ - if (rc_vid.r > rc_bound.r - rc_bound.l) - { - rc_vid.r = rc_bound.r - rc_bound.l; - rc_vid.b = (rc_vid.r << 16) / aspect_vid; - } - /* else already fits */ - } - else - { - /* Video proportionally narrower than bounding rectangle */ - if (rc_vid.b > rc_bound.b - rc_bound.t) - { - rc_vid.b = rc_bound.b - rc_bound.t; - rc_vid.r = (aspect_vid * rc_vid.b) >> 16; - } - /* else already fits */ - } - - /* Even width and height >= 2 */ - rc_vid.r = (rc_vid.r < 2) ? 2 : (rc_vid.r & ~1); - rc_vid.b = (rc_vid.b < 2) ? 2 : (rc_vid.b & ~1); - - /* Center display in bounding rectangle */ - rc_vid.l = ((rc_bound.l + rc_bound.r) - rc_vid.r) / 2; - rc_vid.r += rc_vid.l; - - rc_vid.t = ((rc_bound.t + rc_bound.b) - rc_vid.b) / 2; - rc_vid.b += rc_vid.t; - - DEBUGF("rc_vid: %d, %d, %d, %d\n", rc_vid.l, rc_vid.t, - rc_vid.r, rc_vid.b); - -#ifndef HAVE_LCD_COLOR - stream_gray_show(true); -#endif - - while (slider_state < STATE9) - { - button = mpeg_button_get(tmo); - - switch (button) - { - case BUTTON_NONE: - break; - - /* Coarse (1 minute) control */ - case MPEG_START_TIME_DOWN: - case MPEG_START_TIME_DOWN | BUTTON_REPEAT: -#ifdef MPEG_START_TIME_RC_DOWN - case MPEG_START_TIME_RC_DOWN: - case MPEG_START_TIME_RC_DOWN | BUTTON_REPEAT: -#endif - resume_time = increment_time(resume_time, -60*TS_SECOND, duration); - slider_state = STATE0; - break; - - case MPEG_START_TIME_UP: - case MPEG_START_TIME_UP | BUTTON_REPEAT: -#ifdef MPEG_START_TIME_RC_UP - case MPEG_START_TIME_RC_UP: - case MPEG_START_TIME_RC_UP | BUTTON_REPEAT: -#endif - resume_time = increment_time(resume_time, 60*TS_SECOND, duration); - slider_state = STATE0; - break; - - /* Fine (1 second) control */ - case MPEG_START_TIME_LEFT: - case MPEG_START_TIME_LEFT | BUTTON_REPEAT: -#ifdef MPEG_START_TIME_RC_LEFT - case MPEG_START_TIME_RC_LEFT: - case MPEG_START_TIME_RC_LEFT | BUTTON_REPEAT: -#endif -#ifdef MPEG_START_TIME_LEFT2 - case MPEG_START_TIME_LEFT2: - case MPEG_START_TIME_LEFT2 | BUTTON_REPEAT: -#endif - resume_time = increment_time(resume_time, -TS_SECOND, duration); - slider_state = STATE0; - break; - - case MPEG_START_TIME_RIGHT: - case MPEG_START_TIME_RIGHT | BUTTON_REPEAT: -#ifdef MPEG_START_TIME_RC_RIGHT - case MPEG_START_TIME_RC_RIGHT: - case MPEG_START_TIME_RC_RIGHT | BUTTON_REPEAT: -#endif -#ifdef MPEG_START_TIME_RIGHT2 - case MPEG_START_TIME_RIGHT2: - case MPEG_START_TIME_RIGHT2 | BUTTON_REPEAT: -#endif - resume_time = increment_time(resume_time, TS_SECOND, duration); - slider_state = STATE0; - break; - - case MPEG_START_TIME_SELECT: -#ifdef MPEG_START_TIME_RC_SELECT - case MPEG_START_TIME_RC_SELECT: -#endif - settings.resume_time = resume_time; - button = MPEG_START_SEEK; - slider_state = STATE9; - break; - - case MPEG_START_TIME_EXIT: -#ifdef MPEG_START_TIME_RC_EXIT - case MPEG_START_TIME_RC_EXIT: -#endif - button = MPEG_START_EXIT; - slider_state = STATE9; - break; - - case ACTION_STD_CANCEL: - button = MPEG_START_QUIT; - slider_state = STATE9; - break; - -#ifdef HAVE_LCD_ENABLE - case LCD_ENABLE_EVENT_0: - if (slider_state == STATE2) - display_thumb_image(&rc_vid); - continue; -#endif - - default: - rb->default_event_handler(button); - rb->yield(); - continue; - } - - switch (slider_state) - { - case STATE0: - if (!sliding) - { - if (rb->global_settings->talk_menu) - { - rb->talk_disable(true); -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_restore(); -#endif - } - trigger_cpu_boost(); - sliding = true; - } - stream_seek(resume_time, SEEK_SET); - show_loading(&rc_bound); - draw_slider(duration, resume_time, NULL); - slider_state = STATE1; - tmo = THUMB_DELAY; - break; - case STATE1: - display_thumb_image(&rc_vid); - slider_state = STATE2; - tmo = TIMEOUT_BLOCK; - if (sliding) - { - cancel_cpu_boost(); - if (rb->global_settings->talk_menu) - { -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_preserve(); -#endif - rb->talk_disable(false); - talk_val(resume_time / TS_SECOND, UNIT_TIME, false); - talk_val(resume_time * 100 / duration, UNIT_PERCENT, true); - } - sliding = false; - } - default: - break; - } - - rb->yield(); - } - -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - rb->remove_event(LCD_EVENT_ACTIVATION, get_start_time_lcd_enable_hook); -#endif -#ifndef HAVE_LCD_COLOR - stream_gray_show(false); - grey_clear_display(); - grey_update(); -#endif - - cancel_cpu_boost(); - - return button; -} - -static int show_start_menu(uint32_t duration) -{ - int selected = 0; - int result = 0; - bool menu_quit = false; - - MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, - ID2P(LANG_RESTART_PLAYBACK), - ID2P(LANG_RESUME_PLAYBACK), - ID2P(LANG_SET_RESUME_TIME), - ID2P(LANG_SETTINGS), - ID2P(LANG_MENU_QUIT)); - - if (rb->global_settings->talk_menu) - { -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_preserve(); -#endif - rb->talk_disable(false); - } - - rb->button_clear_queue(); - - while (!menu_quit) - { - mpeg_sysevent_clear(); - result = rb->do_menu(&menu, &selected, NULL, false); - - switch (result) - { - case MPEG_START_RESTART: - settings.resume_time = 0; - menu_quit = true; - break; - - case MPEG_START_RESUME: - menu_quit = true; - break; - - case MPEG_START_SEEK: - if (!stream_can_seek()) - { - rb->splash(HZ, ID2P(LANG_UNAVAILABLE)); - break; - } - - result = get_start_time(duration); - - if (result != MPEG_START_EXIT) - menu_quit = true; - break; - - case MPEG_START_SETTINGS: - mpeg_settings(); - break; - - default: - result = MPEG_START_QUIT; - menu_quit = true; - break; - } - - if (mpeg_sysevent() != 0) - { - result = MPEG_START_QUIT; - menu_quit = true; - } - } - - if (rb->global_settings->talk_menu) - { - rb->talk_disable(true); -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_restore(); -#endif - } - - return result; -} - -/* Return the desired resume action */ -int mpeg_start_menu(uint32_t duration) -{ - mpeg_sysevent_clear(); - - switch (settings.resume_options) - { - case MPEG_RESUME_MENU_IF_INCOMPLETE: - if (!stream_can_seek() || settings.resume_time == 0) - { - case MPEG_RESUME_RESTART: - settings.resume_time = 0; - return MPEG_START_RESTART; - } - default: - case MPEG_RESUME_MENU_ALWAYS: - return show_start_menu(duration); - case MPEG_RESUME_ALWAYS: - return MPEG_START_SEEK; - } -} - -int mpeg_menu(void) -{ - int result; - - MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, - ID2P(LANG_SETTINGS), - ID2P(LANG_RESUME_PLAYBACK), - ID2P(LANG_MENU_QUIT)); - - if (rb->global_settings->talk_menu) - { -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_preserve(); -#endif - rb->talk_disable(false); - } - - rb->button_clear_queue(); - - mpeg_sysevent_clear(); - - result = rb->do_menu(&menu, NULL, NULL, false); - - switch (result) - { - case MPEG_MENU_SETTINGS: - mpeg_settings(); - break; - - case MPEG_MENU_RESUME: - break; - - case MPEG_MENU_QUIT: - break; - - default: - break; - } - - if (mpeg_sysevent() != 0) - result = MPEG_MENU_QUIT; - - if (rb->global_settings->talk_menu) - { - rb->talk_disable(true); -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_restore(); -#endif - } - - return result; -} - -static void display_options(void) -{ - int selected = 0; - int result; - bool menu_quit = false; - - MENUITEM_STRINGLIST(menu, "Display Options", mpeg_sysevent_callback, -#if MPEG_OPTION_DITHERING_ENABLED - ID2P(LANG_DITHERING), -#endif - ID2P(LANG_DISPLAY_FPS), - ID2P(LANG_LIMIT_FPS), - ID2P(LANG_SKIP_FRAMES), -#ifdef HAVE_BACKLIGHT_BRIGHTNESS - ID2P(LANG_BACKLIGHT_BRIGHTNESS), -#endif - ); - - rb->button_clear_queue(); - - while (!menu_quit) - { - mpeg_sysevent_clear(); - result = rb->do_menu(&menu, &selected, NULL, false); - - switch (result) - { -#if MPEG_OPTION_DITHERING_ENABLED - case MPEG_OPTION_DITHERING: - result = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0; - mpeg_set_option(rb->str(LANG_DITHERING), &result, INT, noyes, 2, NULL); - settings.displayoptions = - (settings.displayoptions & ~LCD_YUV_DITHER) - | ((result != 0) ? LCD_YUV_DITHER : 0); - rb->lcd_yuv_set_options(settings.displayoptions); - break; -#endif /* MPEG_OPTION_DITHERING_ENABLED */ - - case MPEG_OPTION_DISPLAY_FPS: - mpeg_set_option(rb->str(LANG_DISPLAY_FPS), &settings.showfps, INT, - noyes, 2, NULL); - break; - - case MPEG_OPTION_LIMIT_FPS: - mpeg_set_option(rb->str(LANG_LIMIT_FPS), &settings.limitfps, INT, - noyes, 2, NULL); - break; - - case MPEG_OPTION_SKIP_FRAMES: - mpeg_set_option(rb->str(LANG_SKIP_FRAMES), &settings.skipframes, INT, - noyes, 2, NULL); - break; - -#ifdef HAVE_BACKLIGHT_BRIGHTNESS - case MPEG_OPTION_BACKLIGHT_BRIGHTNESS: - result = settings.backlight_brightness; - mpeg_backlight_update_brightness(result); - mpeg_set_int(rb->str(LANG_BACKLIGHT_BRIGHTNESS), NULL, UNIT_INT, &result, - backlight_brightness_function, 1, -1, - MAX_BRIGHTNESS_SETTING - MIN_BRIGHTNESS_SETTING, - backlight_brightness_formatter, - backlight_brightness_getlang); - settings.backlight_brightness = result; - mpeg_backlight_update_brightness(-1); - break; -#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ - - default: - menu_quit = true; - break; - } - - if (mpeg_sysevent() != 0) - menu_quit = true; - } -} - -static void audio_options(void) -{ - int selected = 0; - int result; - bool menu_quit = false; - - MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_sysevent_callback, - ID2P(LANG_TONE_CONTROLS), - ID2P(LANG_CHANNEL_CONFIGURATION), - ID2P(LANG_CROSSFEED), - ID2P(LANG_EQUALIZER), - ID2P(LANG_DITHERING)); - - rb->button_clear_queue(); - - while (!menu_quit) - { - mpeg_sysevent_clear(); - result = rb->do_menu(&menu, &selected, NULL, false); - - switch (result) - { - case MPEG_AUDIO_TONE_CONTROLS: - mpeg_set_option(rb->str(LANG_TONE_CONTROLS), &settings.tone_controls, INT, - globaloff, 2, NULL); - sync_audio_setting(result, false); - break; - - case MPEG_AUDIO_CHANNEL_MODES: - mpeg_set_option(rb->str(LANG_CHANNEL_CONFIGURATION), &settings.channel_modes, - INT, globaloff, 2, NULL); - sync_audio_setting(result, false); - break; - - case MPEG_AUDIO_CROSSFEED: - mpeg_set_option(rb->str(LANG_CROSSFEED), &settings.crossfeed, INT, - globaloff, 2, NULL); - sync_audio_setting(result, false); - break; - - case MPEG_AUDIO_EQUALIZER: - mpeg_set_option(rb->str(LANG_EQUALIZER), &settings.equalizer, INT, - globaloff, 2, NULL); - sync_audio_setting(result, false); - break; - - case MPEG_AUDIO_DITHERING: - mpeg_set_option(rb->str(LANG_DITHERING), &settings.dithering, INT, - globaloff, 2, NULL); - sync_audio_setting(result, false); - break; - - default: - menu_quit = true; - break; - } - - if (mpeg_sysevent() != 0) - menu_quit = true; - } -} - -static void resume_options(void) -{ - static const struct opt_items items[MPEG_RESUME_NUM_OPTIONS] = { - [MPEG_RESUME_MENU_ALWAYS] = - { STR(LANG_FORCE_START_MENU) }, - [MPEG_RESUME_MENU_IF_INCOMPLETE] = - { STR(LANG_CONDITIONAL_START_MENU) }, - [MPEG_RESUME_ALWAYS] = - { STR(LANG_AUTO_RESUME) }, - [MPEG_RESUME_RESTART] = - { STR(LANG_RESTART_PLAYBACK) }, - }; - - mpeg_set_option(rb->str(LANG_MENU_RESUME_OPTIONS), &settings.resume_options, - INT, items, MPEG_RESUME_NUM_OPTIONS, NULL); -} - -static void clear_resume_count(void) -{ - settings.resume_count = 0; - configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config), - SETTINGS_VERSION); -} - -static void mpeg_settings(void) -{ - int selected = 0; - int result; - bool menu_quit = false; - - MENUITEM_STRINGLIST(menu, "Settings", mpeg_sysevent_callback, - ID2P(LANG_MENU_DISPLAY_OPTIONS), - ID2P(LANG_MENU_AUDIO_OPTIONS), - ID2P(LANG_MENU_RESUME_OPTIONS), - ID2P(LANG_MENU_PLAY_MODE), - ID2P(LANG_CLEAR_ALL_RESUMES)); - - rb->button_clear_queue(); - - while (!menu_quit) - { - mpeg_sysevent_clear(); - - result = rb->do_menu(&menu, &selected, NULL, false); - - switch (result) - { - case MPEG_SETTING_DISPLAY_SETTINGS: - display_options(); - break; - - case MPEG_SETTING_AUDIO_SETTINGS: - audio_options(); - break; - - case MPEG_SETTING_ENABLE_START_MENU: - resume_options(); - break; - - case MPEG_SETTING_PLAY_MODE: - mpeg_set_option(rb->str(LANG_MENU_PLAY_MODE), &settings.play_mode, - INT, singleall, 2, NULL); - break; - - case MPEG_SETTING_CLEAR_RESUMES: - clear_resume_count(); - break; - - default: - menu_quit = true; - break; - } - - if (mpeg_sysevent() != 0) - menu_quit = true; - } -} - -void init_settings(const char* filename) -{ - /* Set the default settings */ - settings.showfps = 0; /* Do not show FPS */ - settings.limitfps = 1; /* Limit FPS */ - settings.skipframes = 1; /* Skip frames */ - settings.play_mode = 0; /* Play single video */ - settings.resume_options = MPEG_RESUME_MENU_ALWAYS; /* Enable start menu */ - settings.resume_count = 0; -#ifdef HAVE_BACKLIGHT_BRIGHTNESS - settings.backlight_brightness = -1; /* Use default setting */ -#endif -#if MPEG_OPTION_DITHERING_ENABLED - settings.displayoptions = 0; /* No visual effects */ -#endif - settings.tone_controls = false; - settings.channel_modes = false; - settings.crossfeed = false; - settings.equalizer = false; - settings.dithering = false; - - if (configfile_load(SETTINGS_FILENAME, config, ARRAYLEN(config), - SETTINGS_MIN_VERSION) < 0) - { - /* Generate a new config file with default values */ - configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config), - SETTINGS_VERSION); - } - - rb->strlcpy(settings.resume_filename, filename, MAX_PATH); - - /* get the resume time for the current mpeg if it exists */ - if ((settings.resume_time = configfile_get_value - (SETTINGS_FILENAME, filename)) < 0) - { - settings.resume_time = 0; - } - -#if MPEG_OPTION_DITHERING_ENABLED - rb->lcd_yuv_set_options(settings.displayoptions); -#endif - - /* Set our audio options */ - sync_audio_settings(false); -} - -void save_settings(void) -{ - unsigned i; - for (i = 0; i < ARRAYLEN(config); i++) - { - configfile_update_entry(SETTINGS_FILENAME, config[i].name, - *(config[i].int_p)); - } - - /* If this was a new resume entry then update the total resume count */ - if (configfile_update_entry(SETTINGS_FILENAME, settings.resume_filename, - settings.resume_time) == 0) - { - configfile_update_entry(SETTINGS_FILENAME, "Resume count", - ++settings.resume_count); - } - - /* Restore audio options */ - sync_audio_settings(true); -} diff --git a/apps/plugins/mpegplayer/mpeg_settings.h b/apps/plugins/mpegplayer/mpeg_settings.h deleted file mode 100644 index b1704ef707..0000000000 --- a/apps/plugins/mpegplayer/mpeg_settings.h +++ /dev/null @@ -1,110 +0,0 @@ - -#include "plugin.h" - -#define SETTINGS_VERSION 5 -#define SETTINGS_MIN_VERSION 1 -#define SETTINGS_FILENAME "mpegplayer.cfg" - -#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \ - || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) \ - || defined(SANSA_FUZE) || defined(SANSA_E200V2) || defined(SANSA_FUZEV2) \ - || defined(TOSHIBA_GIGABEAT_S) || defined(PHILIPS_SA9200) -#define MPEG_OPTION_DITHERING_ENABLED 1 -#endif - -#ifndef MPEG_OPTION_DITHERING_ENABLED -#define MPEG_OPTION_DITHERING_ENABLED 0 -#endif - -enum mpeg_option_id -{ -#if MPEG_OPTION_DITHERING_ENABLED - MPEG_OPTION_DITHERING, -#endif - MPEG_OPTION_DISPLAY_FPS, - MPEG_OPTION_LIMIT_FPS, - MPEG_OPTION_SKIP_FRAMES, -#ifdef HAVE_BACKLIGHT_BRIGHTNESS - MPEG_OPTION_BACKLIGHT_BRIGHTNESS, -#endif -}; - -enum mpeg_audio_option_id -{ - MPEG_AUDIO_TONE_CONTROLS, - MPEG_AUDIO_CHANNEL_MODES, - MPEG_AUDIO_CROSSFEED, - MPEG_AUDIO_EQUALIZER, - MPEG_AUDIO_DITHERING, -}; - -enum mpeg_resume_id -{ - MPEG_RESUME_MENU_ALWAYS = 0, - MPEG_RESUME_MENU_IF_INCOMPLETE, - MPEG_RESUME_RESTART, - MPEG_RESUME_ALWAYS, - MPEG_RESUME_NUM_OPTIONS, -}; - -enum mpeg_start_id -{ - MPEG_START_RESTART, - MPEG_START_RESUME, - MPEG_START_SEEK, - MPEG_START_SETTINGS, - MPEG_START_QUIT, - MPEG_START_EXIT, -}; - -enum mpeg_setting_id -{ - MPEG_SETTING_DISPLAY_SETTINGS, - MPEG_SETTING_AUDIO_SETTINGS, - MPEG_SETTING_ENABLE_START_MENU, - MPEG_SETTING_PLAY_MODE, - MPEG_SETTING_CLEAR_RESUMES, -}; - -enum mpeg_menu_id -{ - MPEG_MENU_SETTINGS, - MPEG_MENU_RESUME, - MPEG_MENU_QUIT, -}; - -struct mpeg_settings { - int showfps; /* flag to display fps */ - int limitfps; /* flag to limit fps */ - int skipframes; /* flag to skip frames */ - int resume_options; /* type of resume action at start */ - int resume_count; /* total # of resumes in config file */ - int resume_time; /* resume time for current mpeg (in half minutes) */ - char resume_filename[MAX_PATH]; /* filename of current mpeg */ -#if MPEG_OPTION_DITHERING_ENABLED - int displayoptions; -#endif - int play_mode; /* play single file or all files in directory */ - /* Audio options - simple on/off specification */ - int tone_controls; - int channel_modes; - int crossfeed; - int equalizer; - int dithering; - /* Backlight options */ -#ifdef HAVE_BACKLIGHT_BRIGHTNESS - int backlight_brightness; -#endif -}; - -extern struct mpeg_settings settings; - -int mpeg_start_menu(uint32_t duration); -int mpeg_menu(void); - -void init_settings(const char* filename); -void save_settings(void); - -#ifdef HAVE_BACKLIGHT_BRIGHTNESS -void mpeg_backlight_update_brightness(int value); -#endif diff --git a/apps/plugins/mpegplayer/mpeg_stream.h b/apps/plugins/mpegplayer/mpeg_stream.h deleted file mode 100644 index 26fdaf07b4..0000000000 --- a/apps/plugins/mpegplayer/mpeg_stream.h +++ /dev/null @@ -1,122 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Stream definitions for MPEG - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef MPEG_STREAM_H -#define MPEG_STREAM_H - -/* Codes for various header byte sequences - MSB represents lowest memory - address */ -#define PACKET_START_CODE_PREFIX 0x00000100ul -#define END_CODE 0x000001b9ul -#define PACK_START_CODE 0x000001baul -#define SYSTEM_HEADER_START_CODE 0x000001bbul - -/* p = base pointer, b0 - b4 = byte offsets from p */ -/* We only care about the MS 32 bits of the 33 and so the ticks are 45kHz */ -#define TS_FROM_HEADER(p, b0) \ - ((uint32_t)((((p)[(b0)+0] & 0x0e) << 28) | \ - (((p)[(b0)+1] ) << 21) | \ - (((p)[(b0)+2] & 0xfe) << 13) | \ - (((p)[(b0)+3] ) << 6) | \ - (((p)[(b0)+4] ) >> 2))) - -#define TS_CHECK_MARKERS(p, b0) \ - (((((p)[(b0)+0] & 0x01) << 2) | \ - (((p)[(b0)+2] & 0x01) << 1) | \ - (((p)[(b0)+4] & 0x01) )) == 0x07) - -/* Get the SCR in our 45kHz ticks. Ignore the 9-bit extension */ -#define MPEG2_PACK_HEADER_SCR(p, b0) \ - ((uint32_t)((((p)[(b0)+0] & 0x38) << 26) | \ - (((p)[(b0)+0] & 0x03) << 27) | \ - (((p)[(b0)+1] ) << 19) | \ - (((p)[(b0)+2] & 0xf8) << 11) | \ - (((p)[(b0)+2] & 0x03) << 12) | \ - (((p)[(b0)+3] ) << 4) | \ - (((p)[(b0)+4] ) >> 4))) - -#define MPEG2_CHECK_PACK_SCR_MARKERS(ph, b0) \ - (((((ph)[(b0)+0] & 0x04) ) | \ - (((ph)[(b0)+2] & 0x04) >> 1) | \ - (((ph)[(b0)+4] & 0x04) >> 2)) == 0x07) - -#define INVALID_TIMESTAMP (~(uint32_t)0) -#define MAX_TIMESTAMP (INVALID_TIMESTAMP-1) -#define TS_SECOND (45000) /* Timestamp ticks per second */ -#define TC_SECOND (27000000) /* MPEG timecode ticks per second */ - -/* These values immediately follow the start code prefix '00 00 01' */ - -/* Video start codes */ -#define MPEG_START_PICTURE 0x00 -#define MPEG_START_SLICE_FIRST 0x01 -#define MPEG_START_SLICE_LAST 0xaf -#define MPEG_START_RESERVED_1 0xb0 -#define MPEG_START_RESERVED_2 0xb1 -#define MPEG_START_USER_DATA 0xb2 -#define MPEG_START_SEQUENCE_HEADER 0xb3 -#define MPEG_START_SEQUENCE_ERROR 0xb4 -#define MPEG_START_EXTENSION 0xb5 -#define MPEG_START_RESERVED_3 0xb6 -#define MPEG_START_SEQUENCE_END 0xb7 -#define MPEG_START_GOP 0xb8 - -/* Stream IDs */ -#define MPEG_STREAM_PROGRAM_END 0xb9 -#define MPEG_STREAM_PACK_HEADER 0xba -#define MPEG_STREAM_SYSTEM_HEADER 0xbb -#define MPEG_STREAM_PROGRAM_STREAM_MAP 0xbc -#define MPEG_STREAM_PRIVATE_1 0xbd -#define MPEG_STREAM_PADDING 0xbe -#define MPEG_STREAM_PRIVATE_2 0xbf -#define MPEG_STREAM_AUDIO_FIRST 0xc0 -#define MPEG_STREAM_AUDIO_LAST 0xcf -#define MPEG_STREAM_VIDEO_FIRST 0xe0 -#define MPEG_STREAM_VIDEO_LAST 0xef -#define MPEG_STREAM_ECM 0xf0 -#define MPEG_STREAM_EMM 0xf1 -/* ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A or - * ISO/IEC 13818-6_DSMCC_stream */ -#define MPEG_STREAM_MISC_1 0xf2 -/* ISO/IEC_13522_stream */ -#define MPEG_STREAM_MISC_2 0xf3 -/* ITU-T Rec. H.222.1 type A - E */ -#define MPEG_STREAM_MISC_3 0xf4 -#define MPEG_STREAM_MISC_4 0xf5 -#define MPEG_STREAM_MISC_5 0xf6 -#define MPEG_STREAM_MISC_6 0xf7 -#define MPEG_STREAM_MISC_7 0xf8 -#define MPEG_STREAM_ANCILLARY 0xf9 -#define MPEG_STREAM_RESERVED_FIRST 0xfa -#define MPEG_STREAM_RESERVED_LAST 0xfe -/* Program stream directory */ -#define MPEG_STREAM_PROGRAM_DIRECTORY 0xff - -#define STREAM_IS_AUDIO(s) (((s) & 0xf0) == 0xc0) -#define STREAM_IS_VIDEO(s) (((s) & 0xf0) == 0xe0) - -#define MPEG_MAX_PACKET_SIZE (64*1024+16) - -/* Largest MPEG audio frame - MPEG1, Layer II, 384kbps, 32kHz, pad */ -#define MPA_MAX_FRAME_SIZE 1729 - -#endif /* MPEG_STREAM_H */ diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c deleted file mode 100644 index e66b4df146..0000000000 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ /dev/null @@ -1,2638 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * mpegplayer main entrypoint and UI implementation - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/**************************************************************************** - * NOTES: - * - * mpegplayer is structured as follows: - * - * +-->Video Thread-->Video Output-->LCD - * | - * UI-->Stream Manager-->+-->Audio Thread-->PCM buffer--Audio Device - * | | | | (ref. clock) - * | | +-->Buffer Thread | - * Stream Data | | (clock intf./ - * Requests | File Cache drift adj.) - * | Disk I/O - * Stream services - * (timing, etc.) - * - * Thread list: - * 1) The main thread - Handles user input, settings, basic playback control - * and USB connect. - * - * 2) Stream Manager thread - Handles playback state, events from streams - * such as when a stream is finished, stream commands, PCM state. The - * layer in which this thread run also handles arbitration of data - * requests between the streams and the disk buffer. The actual specific - * transport layer code may get moved out to support multiple container - * formats. - * - * 3) Buffer thread - Buffers data in the background, generates notifications - * to streams when their data has been buffered, and watches streams' - * progress to keep data available during playback. Handles synchronous - * random access requests when the file cache is missed. - * - * 4) Video thread (running on the COP for PortalPlayer targets) - Decodes - * the video stream and renders video frames to the LCD. Handles - * miscellaneous video tasks like frame and thumbnail printing. - * - * 5) Audio thread (running on the main CPU to maintain consistency with the - * audio FIQ hander on PP) - Decodes audio frames and places them into - * the PCM buffer for rendering by the audio device. - * - * Streams are neither aware of one another nor care about one another. All - * streams shall have their own thread (unless it is _really_ efficient to - * have a single thread handle a couple minor streams). All coordination of - * the streams is done through the stream manager. The clocking is controlled - * by and exposed by the stream manager to other streams and implemented at - * the PCM level. - * - * Notes about MPEG files: - * - * MPEG System Clock is 27MHz - i.e. 27000000 ticks/second. - * - * FPS is represented in terms of a frame period - this is always an - * integer number of 27MHz ticks. - * - * e.g. 29.97fps (30000/1001) NTSC video has an exact frame period of - * 900900 27MHz ticks. - * - * In libmpeg2, info->sequence->frame_period contains the frame_period. - * - * Working with Rockbox's 100Hz tick, the common frame rates would need - * to be as follows (1): - * - * FPS | 27Mhz | 100Hz | 44.1KHz | 48KHz - * --------|----------------------------------------------------------- - * 10* | 2700000 | 10 | 4410 | 4800 - * 12* | 2250000 | 8.3333 | 3675 | 4000 - * 15* | 1800000 | 6.6667 | 2940 | 3200 - * 23.9760 | 1126125 | 4.170833333 | 1839.3375 | 2002 - * 24 | 1125000 | 4.166667 | 1837.5 | 2000 - * 25 | 1080000 | 4 | 1764 | 1920 - * 29.9700 | 900900 | 3.336667 | 1471,47 | 1601.6 - * 30 | 900000 | 3.333333 | 1470 | 1600 - * - * *Unofficial framerates - * - * (1) But we don't really care since the audio clock is used anyway and has - * very fine resolution ;-) - *****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" -#include "lib/helper.h" -#include "mpeg_settings.h" -#include "video_out.h" -#include "stream_thread.h" -#include "stream_mgr.h" - - -/* button definitions */ -#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) -#define MPEG_MENU BUTTON_MODE -#define MPEG_STOP BUTTON_OFF -#define MPEG_PAUSE BUTTON_ON -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ - (CONFIG_KEYPAD == IPOD_1G2G_PAD) -#define MPEG_MENU BUTTON_MENU -#define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL) -#define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT) -#define MPEG_VOLDOWN BUTTON_SCROLL_BACK -#define MPEG_VOLUP BUTTON_SCROLL_FWD -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD -#define MPEG_MENU (BUTTON_REC | BUTTON_REL) -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == GIGABEAT_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_SELECT -#define MPEG_PAUSE2 BUTTON_A -#define MPEG_VOLDOWN BUTTON_LEFT -#define MPEG_VOLUP BUTTON_RIGHT -#define MPEG_VOLDOWN2 BUTTON_VOL_DOWN -#define MPEG_VOLUP2 BUTTON_VOL_UP -#define MPEG_RW BUTTON_UP -#define MPEG_FF BUTTON_DOWN - -#define MPEG_RC_MENU BUTTON_RC_DSP -#define MPEG_RC_STOP (BUTTON_RC_PLAY | BUTTON_REPEAT) -#define MPEG_RC_PAUSE (BUTTON_RC_PLAY | BUTTON_REL) -#define MPEG_RC_VOLDOWN BUTTON_RC_VOL_DOWN -#define MPEG_RC_VOLUP BUTTON_RC_VOL_UP -#define MPEG_RC_RW BUTTON_RC_REW -#define MPEG_RC_FF BUTTON_RC_FF - -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_SELECT -#define MPEG_PAUSE2 BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_LEFT -#define MPEG_VOLUP BUTTON_RIGHT -#define MPEG_VOLDOWN2 BUTTON_VOL_DOWN -#define MPEG_VOLUP2 BUTTON_VOL_UP -#define MPEG_RW BUTTON_UP -#define MPEG_RW2 BUTTON_PREV -#define MPEG_FF BUTTON_DOWN -#define MPEG_FF2 BUTTON_NEXT -#define MPEG_SHOW_OSD BUTTON_BACK - -#define MPEG_RC_MENU BUTTON_RC_DSP -#define MPEG_RC_STOP (BUTTON_RC_PLAY | BUTTON_REPEAT) -#define MPEG_RC_PAUSE (BUTTON_RC_PLAY | BUTTON_REL) -#define MPEG_RC_VOLDOWN BUTTON_RC_VOL_DOWN -#define MPEG_RC_VOLUP BUTTON_RC_VOL_UP -#define MPEG_RC_RW BUTTON_RC_REW -#define MPEG_RC_FF BUTTON_RC_FF - -#elif CONFIG_KEYPAD == IRIVER_H10_PAD -#define MPEG_MENU BUTTON_LEFT -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_SCROLL_DOWN -#define MPEG_VOLUP BUTTON_SCROLL_UP -#define MPEG_RW BUTTON_REW -#define MPEG_FF BUTTON_FF - -#elif CONFIG_KEYPAD == SANSA_E200_PAD -#define MPEG_MENU BUTTON_SELECT -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_RIGHT -#define MPEG_VOLDOWN BUTTON_SCROLL_BACK -#define MPEG_VOLUP BUTTON_SCROLL_FWD -#define MPEG_RW BUTTON_UP -#define MPEG_FF BUTTON_DOWN - -#elif CONFIG_KEYPAD == SANSA_FUZE_PAD -#define MPEG_MENU BUTTON_SELECT -#define MPEG_STOP (BUTTON_HOME|BUTTON_REPEAT) -#define MPEG_PAUSE BUTTON_UP -#define MPEG_VOLDOWN BUTTON_SCROLL_BACK -#define MPEG_VOLUP BUTTON_SCROLL_FWD -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - - -#elif CONFIG_KEYPAD == SANSA_C200_PAD || \ -CONFIG_KEYPAD == SANSA_CLIP_PAD || \ -CONFIG_KEYPAD == SANSA_M200_PAD -#define MPEG_MENU BUTTON_SELECT -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_UP -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == MROBE500_PAD -#define MPEG_STOP BUTTON_POWER - -#define MPEG_RC_MENU BUTTON_RC_HEART -#define MPEG_RC_STOP BUTTON_RC_DOWN -#define MPEG_RC_PAUSE BUTTON_RC_PLAY -#define MPEG_RC_VOLDOWN BUTTON_RC_VOL_DOWN -#define MPEG_RC_VOLUP BUTTON_RC_VOL_UP -#define MPEG_RC_RW BUTTON_RC_REW -#define MPEG_RC_FF BUTTON_RC_FF - -#elif CONFIG_KEYPAD == MROBE100_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == IAUDIO_M3_PAD -#define MPEG_MENU BUTTON_RC_MENU -#define MPEG_STOP BUTTON_RC_REC -#define MPEG_PAUSE BUTTON_RC_PLAY -#define MPEG_VOLDOWN BUTTON_RC_VOL_DOWN -#define MPEG_VOLUP BUTTON_RC_VOL_UP -#define MPEG_RW BUTTON_RC_REW -#define MPEG_FF BUTTON_RC_FF - -#elif CONFIG_KEYPAD == COWON_D2_PAD -#define MPEG_MENU (BUTTON_MENU|BUTTON_REL) -//#define MPEG_STOP BUTTON_POWER -#define MPEG_VOLDOWN BUTTON_MINUS -#define MPEG_VOLUP BUTTON_PLUS - -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_BACK -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_UP -#define MPEG_VOLUP BUTTON_DOWN -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP (BUTTON_PLAY|BUTTON_REPEAT) -#define MPEG_PAUSE (BUTTON_PLAY|BUTTON_REL) -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_DOWN -#define MPEG_FF BUTTON_UP - -#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_SELECT -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_UP -#define MPEG_FF BUTTON_DOWN - -#elif CONFIG_KEYPAD == ONDAVX747_PAD -#define MPEG_MENU (BUTTON_MENU|BUTTON_REL) -//#define MPEG_STOP BUTTON_POWER -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP - -#elif CONFIG_KEYPAD == ONDAVX777_PAD -#define MPEG_MENU BUTTON_POWER - -#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ - (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) -#define MPEG_MENU BUTTON_REW -#define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT) -#define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL) -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT -#define MPEG_SHOW_OSD BUTTON_FFWD - -#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_REC -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == MPIO_HD200_PAD -#define MPEG_MENU BUTTON_FUNC -#define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL) -#define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT) -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_REW -#define MPEG_FF BUTTON_FF - -#elif CONFIG_KEYPAD == MPIO_HD300_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL) -#define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT) -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_REW -#define MPEG_FF BUTTON_FF - -#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD -#define MPEG_MENU BUTTON_POWER -#define MPEG_PAUSE (BUTTON_PLAYPAUSE | BUTTON_REL) -#define MPEG_STOP (BUTTON_PLAYPAUSE | BUTTON_REPEAT) -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD -#define MPEG_MENU BUTTON_POWER -#define MPEG_PAUSE (BUTTON_SELECT | BUTTON_REL) -#define MPEG_STOP (BUTTON_SELECT | BUTTON_REPEAT) -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_PAUSE BUTTON_SELECT -#define MPEG_STOP BUTTON_POWER -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == HM60X_PAD -#define MPEG_MENU BUTTON_POWER -#define MPEG_PAUSE BUTTON_SELECT -#define MPEG_STOP (BUTTON_SELECT | BUTTON_POWER) -#define MPEG_VOLDOWN (BUTTON_POWER | BUTTON_DOWN) -#define MPEG_VOLUP (BUTTON_POWER | BUTTON_UP) -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == HM801_PAD -#define MPEG_MENU BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_STOP (BUTTON_POWER | BUTTON_PLAY) -#define MPEG_VOLDOWN (BUTTON_POWER | BUTTON_DOWN) -#define MPEG_VOLUP (BUTTON_POWER | BUTTON_UP) -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == SONY_NWZ_PAD -#define MPEG_MENU BUTTON_BACK -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_STOP BUTTON_POWER -#define MPEG_VOLDOWN BUTTON_UP -#define MPEG_VOLUP BUTTON_DOWN -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_PAUSE BUTTON_PLAYPAUSE -#define MPEG_STOP BUTTON_BACK -#define MPEG_VOLDOWN BUTTON_DOWN -#define MPEG_VOLUP BUTTON_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == DX50_PAD -#define MPEG_MENU BUTTON_POWER -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_STOP (BUTTON_PLAY|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD -#define MPEG_MENU BUTTON_POWER -#define MPEG_PAUSE BUTTON_MENU -#define MPEG_STOP (BUTTON_MENU|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD -#define MPEG_MENU BUTTON_POWER -#define MPEG_PAUSE BUTTON_SELECT -#define MPEG_STOP BUTTON_DOWN -#define MPEG_VOLDOWN BUTTON_VOLDOWN -#define MPEG_VOLUP BUTTON_VOLUP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == XDUOO_X3_PAD -#define MPEG_MENU BUTTON_PLAY -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_HOME -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD -#define MPEG_MENU BUTTON_PLAY -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_HOME -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD -#define MPEG_MENU BUTTON_PLAY -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_HOME -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD -#define MPEG_MENU BUTTON_PLAY -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_HOME -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == EROSQ_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_PREV -#define MPEG_FF BUTTON_NEXT - -#elif CONFIG_KEYPAD == FIIO_M3K_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_POWER -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_VOL_DOWN -#define MPEG_VOLUP BUTTON_VOL_UP -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - -#elif CONFIG_KEYPAD == SHANLING_Q1_PAD -/* use touchscreen */ - -#else -#error No keymap defined! -#endif - -#ifdef HAVE_TOUCHSCREEN -#ifndef MPEG_MENU -#define MPEG_MENU (BUTTON_TOPRIGHT|BUTTON_REL) -#endif -#ifndef MPEG_STOP -#define MPEG_STOP BUTTON_TOPLEFT -#endif -#ifndef MPEG_PAUSE -#define MPEG_PAUSE BUTTON_CENTER -#endif -#ifndef MPEG_VOLDOWN -#define MPEG_VOLDOWN BUTTON_BOTTOMMIDDLE -#endif -#ifndef MPEG_VOLUP -#define MPEG_VOLUP BUTTON_TOPMIDDLE -#endif -#ifndef MPEG_RW -#define MPEG_RW BUTTON_MIDLEFT -#endif -#ifndef MPEG_FF -#define MPEG_FF BUTTON_MIDRIGHT -#endif -#endif - -/* One thing we can do here for targets with remotes is having a display - * always on the remote instead of always forcing a popup on the main display */ - -#define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */ - /* 3% of 30min file == 54s step size */ -#define MIN_FF_REWIND_STEP (TS_SECOND/2) -#define OSD_MIN_UPDATE_INTERVAL (HZ/2) -#define FPS_UPDATE_INTERVAL (HZ) /* Get new FPS reading each second */ - -enum video_action -{ - VIDEO_STOP = 0, - VIDEO_PREV, - VIDEO_NEXT, - VIDEO_ACTION_MANUAL = 0x8000, /* Flag that says user did it */ -}; - -/* OSD status - same order as icon array */ -enum osd_status_enum -{ - OSD_STATUS_STOPPED = 0, - OSD_STATUS_PAUSED, - OSD_STATUS_PLAYING, - OSD_STATUS_FF, - OSD_STATUS_RW, - OSD_STATUS_COUNT, - OSD_STATUS_MASK = 0x7 -}; - -enum osd_bits -{ - OSD_REFRESH_DEFAULT = 0x0000, /* Only refresh elements when due */ - /* Refresh the... */ - OSD_REFRESH_VOLUME = 0x0001, /* ...volume display */ - OSD_REFRESH_TIME = 0x0002, /* ...time display+progress */ - OSD_REFRESH_STATUS = 0x0004, /* ...playback status icon */ - OSD_REFRESH_BACKGROUND = 0x0008, /* ...background (implies ALL) */ - OSD_REFRESH_VIDEO = 0x0010, /* ...video image upon timeout */ - OSD_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */ - OSD_NODRAW = 0x8000, /* OR bitflag - don't draw anything */ - OSD_SHOW = 0x4000, /* OR bitflag - show the OSD */ -#ifdef HAVE_HEADPHONE_DETECTION - OSD_HP_PAUSE = 0x2000, /* OR bitflag - headphones caused pause */ -#endif - OSD_HIDE = 0x0000, /* hide the OSD (aid readability) */ - OSD_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */ -}; - -/* Status icons selected according to font height */ -extern const unsigned char mpegplayer_status_icons_8x8x1[]; -extern const unsigned char mpegplayer_status_icons_12x12x1[]; -extern const unsigned char mpegplayer_status_icons_16x16x1[]; - -/* Main border areas that contain OSD elements */ -#define OSD_BDR_L 2 -#define OSD_BDR_T 2 -#define OSD_BDR_R 2 -#define OSD_BDR_B 2 - -struct osd -{ - long hide_tick; - long show_for; - long print_tick; - long print_delay; - long resume_tick; - long resume_delay; - long next_auto_refresh; - int x; - int y; - int width; - int height; - unsigned fgcolor; - unsigned bgcolor; - unsigned prog_fillcolor; - struct vo_rect update_rect; - struct vo_rect prog_rect; - struct vo_rect time_rect; - struct vo_rect dur_rect; - struct vo_rect vol_rect; - const unsigned char *icons; - struct vo_rect stat_rect; - int status; - uint32_t curr_time; - unsigned auto_refresh; - unsigned flags; - int font; -}; - -struct fps -{ - /* FPS Display */ - struct vo_rect rect; /* OSD coordinates */ - int pf_x; /* Screen coordinates */ - int pf_y; - int pf_width; - int pf_height; - long update_tick; /* When to next update FPS reading */ - #define FPS_FORMAT "%d.%02d" - #define FPS_DIMSTR "999.99" /* For establishing rect size */ - #define FPS_BUFSIZE sizeof("999.99") -}; - -static struct osd osd; -static struct fps fps NOCACHEBSS_ATTR; /* Accessed on other processor */ - -#ifdef LCD_PORTRAIT -static fb_data* get_framebuffer(void) -{ - struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); - return vp_main->buffer->fb_ptr; -} -#endif - -static void osd_show(unsigned show); - -#ifdef LCD_LANDSCAPE - #define __X (x + osd.x) - #define __Y (y + osd.y) - #define __W width - #define __H height -#else - #define __X (LCD_WIDTH - (y + osd.y) - height) - #define __Y (x + osd.x) - #define __W height - #define __H width -#endif - -#ifdef HAVE_LCD_COLOR -/* Blend two colors in 0-100% (0-255) mix of c2 into c1 */ -static unsigned draw_blendcolor(unsigned c1, unsigned c2, unsigned char amount) -{ - int r1 = RGB_UNPACK_RED(c1); - int g1 = RGB_UNPACK_GREEN(c1); - int b1 = RGB_UNPACK_BLUE(c1); - - int r2 = RGB_UNPACK_RED(c2); - int g2 = RGB_UNPACK_GREEN(c2); - int b2 = RGB_UNPACK_BLUE(c2); - - return LCD_RGBPACK(amount*(r2 - r1) / 255 + r1, - amount*(g2 - g1) / 255 + g1, - amount*(b2 - b1) / 255 + b1); -} -#endif - -#ifdef PLUGIN_USE_IRAM -/* IRAM preserving mechanism to enable talking menus */ -static char *iram_saved_copy; -extern char iramstart[], iramend[]; - -static void iram_saving_init(void) -{ -#ifndef SIMULATOR - size_t size; - iram_saved_copy = (char *)rb->plugin_get_buffer(&size); - - if (size >= (size_t)(iramend-iramstart)) - iram_saved_copy += size - (size_t)(iramend - iramstart); - else -#endif - iram_saved_copy = NULL; - - return; -} - -void mpegplayer_iram_preserve(void) -{ - if (iram_saved_copy) - { - rb->memcpy(iram_saved_copy, iramstart, iramend-iramstart); -#ifdef HAVE_CPUCACHE_INVALIDATE - /* make the icache (if it exists) up to date with the new code */ - rb->cpucache_invalidate(); -#endif /* HAVE_CPUCACHE_INVALIDATE */ - } - return; -} - -void mpegplayer_iram_restore(void) -{ - if (iram_saved_copy) - { - rb->audio_hard_stop(); - rb->memcpy(iramstart, iram_saved_copy, iramend-iramstart); -#ifdef HAVE_CPUCACHE_INVALIDATE - /* make the icache (if it exists) up to date with the new code */ - rb->cpucache_invalidate(); -#endif /* HAVE_CPUCACHE_INVALIDATE */ - } - return; -} -#endif - -/* Drawing functions that operate rotated on LCD_PORTRAIT displays - - * most are just wrappers of lcd_* functions with transforms applied. - * The origin is the upper-left corner of the OSD area */ -static void draw_update_rect(int x, int y, int width, int height) -{ - mylcd_update_rect(__X, __Y, __W, __H); -} - -static void draw_clear_area(int x, int y, int width, int height) -{ -#ifdef HAVE_LCD_COLOR - rb->screen_clear_area(rb->screens[SCREEN_MAIN], __X, __Y, __W, __H); -#else - int oldmode = grey_get_drawmode(); - grey_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); - grey_fillrect(__X, __Y, __W, __H); - grey_set_drawmode(oldmode); -#endif -} - -static void draw_clear_area_rect(const struct vo_rect *rc) -{ - draw_clear_area(rc->l, rc->t, rc->r - rc->l, rc->b - rc->t); -} - -static void draw_fillrect(int x, int y, int width, int height) -{ - mylcd_fillrect(__X, __Y, __W, __H); -} - -static void draw_hline(int x1, int x2, int y) -{ -#ifdef LCD_LANDSCAPE - mylcd_hline(x1 + osd.x, x2 + osd.x, y + osd.y); -#else - y = LCD_WIDTH - (y + osd.y) - 1; - mylcd_vline(y, x1 + osd.x, x2 + osd.x); -#endif -} - -static void draw_vline(int x, int y1, int y2) -{ -#ifdef LCD_LANDSCAPE - mylcd_vline(x + osd.x, y1 + osd.y, y2 + osd.y); -#else - y1 = LCD_WIDTH - (y1 + osd.y) - 1; - y2 = LCD_WIDTH - (y2 + osd.y) - 1; - mylcd_hline(y1, y2, x + osd.x); -#endif -} - -static void draw_scrollbar_draw(int x, int y, int width, int height, - uint32_t min, uint32_t max, uint32_t val) -{ - unsigned oldfg = mylcd_get_foreground(); - - draw_hline(x + 1, x + width - 2, y); - draw_hline(x + 1, x + width - 2, y + height - 1); - draw_vline(x, y + 1, y + height - 2); - draw_vline(x + width - 1, y + 1, y + height - 2); - - val = muldiv_uint32(width - 2, val, max - min); - val = MIN(val, (uint32_t)(width - 2)); - - draw_fillrect(x + 1, y + 1, val, height - 2); - - mylcd_set_foreground(osd.prog_fillcolor); - - draw_fillrect(x + 1 + val, y + 1, width - 2 - val, height - 2); - - mylcd_set_foreground(oldfg); -} - -static void draw_scrollbar_draw_rect(const struct vo_rect *rc, int min, - int max, int val) -{ - draw_scrollbar_draw(rc->l, rc->t, rc->r - rc->l, rc->b - rc->t, - min, max, val); -} - -static void draw_setfont(int font) -{ - osd.font = font; - mylcd_setfont(font); -} - -#ifdef LCD_PORTRAIT -/* Portrait displays need rotated text rendering */ - -/* Limited function that only renders in DRMODE_FG and uses absolute screen - * coordinates */ -static void draw_oriented_mono_bitmap_part(const unsigned char *src, - int src_x, int src_y, - int stride, int x, int y, - int width, int height) -{ - const unsigned char *src_end; - fb_data *dst, *dst_end; - unsigned fg_pattern; - - if (x + width > SCREEN_WIDTH) - width = SCREEN_WIDTH - x; /* Clip right */ - if (x < 0) - width += x, x = 0; /* Clip left */ - if (width <= 0) - return; /* nothing left to do */ - - if (y + height > SCREEN_HEIGHT) - height = SCREEN_HEIGHT - y; /* Clip bottom */ - if (y < 0) - height += y, y = 0; /* Clip top */ - if (height <= 0) - return; /* nothing left to do */ - - fg_pattern = rb->lcd_get_foreground(); - /*bg_pattern =*/ rb->lcd_get_background(); - - src += stride * (src_y >> 3) + src_x; /* move starting point */ - src_y &= 7; - src_end = src + width; - - dst = get_framebuffer() + (LCD_WIDTH - y) + x*LCD_WIDTH; - do - { - const unsigned char *src_col = src++; - unsigned data = *src_col >> src_y; - int numbits = 8 - src_y; - - fb_data *dst_col = dst; - dst_end = dst_col - height; - dst += LCD_WIDTH; - - do - { - dst_col--; - - if (data & 1) - *dst_col = FB_SCALARPACK(fg_pattern); -#if 0 - else - *dst_col = bg_pattern; -#endif - data >>= 1; - if (--numbits == 0) { - src_col += stride; - data = *src_col; - numbits = 8; - } - } - while (dst_col > dst_end); - } - while (src < src_end); -} - - -#define ALPHA_COLOR_FONT_DEPTH 2 -#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) -#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) -#define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) -#define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH) -#ifdef CPU_ARM -#define BLEND_INIT do {} while (0) -#define BLEND_FINISH do {} while(0) -#define BLEND_START(acc, color, alpha) \ - asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) -#define BLEND_CONT(acc, color, alpha) \ - asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) -#define BLEND_OUT(acc) do {} while (0) -#elif defined(CPU_COLDFIRE) -#define ALPHA_BITMAP_READ_WORDS -#define BLEND_INIT \ - unsigned long _macsr = coldfire_get_macsr(); \ - coldfire_set_macsr(EMAC_UNSIGNED) -#define BLEND_FINISH \ - coldfire_set_macsr(_macsr) -#define BLEND_START(acc, color, alpha) \ - asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) -#define BLEND_CONT BLEND_START -#define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) -#else -#define BLEND_INIT do {} while (0) -#define BLEND_FINISH do {} while(0) -#define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) -#define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) -#define BLEND_OUT(acc) do {} while (0) -#endif - -/* Blend the given two colors */ -static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) -{ -#if LCD_DEPTH == 16 - a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); -#if (LCD_PIXELFORMAT == RGB565SWAPPED) - c1 = swap16(c1); - c2 = swap16(c2); -#endif - unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; - unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; - unsigned p; - BLEND_START(p, c1l, a); - BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); - BLEND_OUT(p); - p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; - p |= (p >> 16); -#if (LCD_PIXELFORMAT == RGB565SWAPPED) - return swap16(p); -#else - return p; -#endif - -#else /* LCD_DEPTH == 24 */ - unsigned s = c1; - unsigned d = c2; - unsigned s1 = s & 0xff00ff; - unsigned d1 = d & 0xff00ff; - a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); - d1 = (d1 + ((s1 - d1) * a >> ALPHA_COLOR_LOOKUP_SHIFT)) & 0xff00ff; - s &= 0xff00; - d &= 0xff00; - d = (d + ((s - d) * a >> ALPHA_COLOR_LOOKUP_SHIFT)) & 0xff00; - - return d1 | d; -#endif -} - -static void draw_oriented_alpha_bitmap_part(const unsigned char *src, - int src_x, int src_y, - int stride, int x, int y, - int width, int height) -{ - fb_data *dst, *dst_start; - unsigned fg_pattern; - - if (x + width > SCREEN_WIDTH) - width = SCREEN_WIDTH - x; /* Clip right */ - if (x < 0) - width += x, x = 0; /* Clip left */ - if (width <= 0) - return; /* nothing left to do */ - - if (y + height > SCREEN_HEIGHT) - height = SCREEN_HEIGHT - y; /* Clip bottom */ - if (y < 0) - height += y, y = 0; /* Clip top */ - if (height <= 0) - return; /* nothing left to do */ - - /* initialize blending */ - BLEND_INIT; - - fg_pattern = rb->lcd_get_foreground(); - /*bg_pattern=*/ rb->lcd_get_background(); - - dst_start = get_framebuffer() + (LCD_WIDTH - y - 1) + x*LCD_WIDTH; - int col, row = height; - unsigned data, pixels; - unsigned skip_end = (stride - width); - unsigned skip_start = src_y * stride + src_x; - -#ifdef ALPHA_BITMAP_READ_WORDS - uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); - skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3); - src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD; - data = letoh32(*src_w++); -#else - src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; - data = *src; -#endif - pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD; - data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; -#ifdef ALPHA_BITMAP_READ_WORDS - pixels = 8 - pixels; -#endif - - do - { - col = width; - dst = dst_start--; -#ifdef ALPHA_BITMAP_READ_WORDS -#define UPDATE_SRC_ALPHA do { \ - if (--pixels) \ - data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ - else \ - { \ - data = letoh32(*src_w++); \ - pixels = ALPHA_COLOR_PIXEL_PER_WORD; \ - } \ - } while (0) -#elif ALPHA_COLOR_PIXEL_PER_BYTE == 2 -#define UPDATE_SRC_ALPHA do { \ - if (pixels ^= 1) \ - data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ - else \ - data = *(++src); \ - } while (0) -#else -#define UPDATE_SRC_ALPHA do { \ - if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \ - data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ - else \ - data = *(++src); \ - } while (0) -#endif - do - { - unsigned color = blend_two_colors(FB_UNPACK_SCALAR_LCD(*dst), fg_pattern, - data & ALPHA_COLOR_LOOKUP_SIZE ); - *dst= FB_SCALARPACK(color); - dst += LCD_WIDTH; - UPDATE_SRC_ALPHA; - } - while (--col); -#ifdef ALPHA_BITMAP_READ_WORDS - if (skip_end < pixels) - { - pixels -= skip_end; - data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; - } else { - pixels = skip_end - pixels; - src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD; - pixels %= ALPHA_COLOR_PIXEL_PER_WORD; - data = letoh32(*src_w++); - data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; - pixels = 8 - pixels; - } -#else - if (skip_end) - { - pixels += skip_end; - if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE) - { - src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE; - pixels %= ALPHA_COLOR_PIXEL_PER_BYTE; - data = *src; - data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; - } else - data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; - } -#endif - } while (--row); -} - -static void draw_putsxy_oriented(int x, int y, const char *str) -{ - unsigned short ch; - unsigned short *ucs; - int ofs = MIN(x, 0); - struct font* pf = rb->font_get(osd.font); - - ucs = rb->bidi_l2v(str, 1); - - x += osd.x; - y += osd.y; - - while ((ch = *ucs++) != 0 && x < SCREEN_WIDTH) - { - int width; - const unsigned char *bits; - - /* get proportional width and glyph bits */ - width = rb->font_get_width(pf, ch); - - if (ofs > width) { - ofs -= width; - continue; - } - - bits = rb->font_get_bits(pf, ch); - - if (pf->depth) - draw_oriented_alpha_bitmap_part(bits, ofs, 0, width, x, y, - width - ofs, pf->height); - else - draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, - width - ofs, pf->height); - - x += width - ofs; - ofs = 0; - } -} -#else -static void draw_oriented_mono_bitmap_part(const unsigned char *src, - int src_x, int src_y, - int stride, int x, int y, - int width, int height) -{ - int mode = mylcd_get_drawmode(); - mylcd_set_drawmode(DRMODE_FG); - mylcd_mono_bitmap_part(src, src_x, src_y, stride, x, y, width, height); - mylcd_set_drawmode(mode); -} - -static void draw_putsxy_oriented(int x, int y, const char *str) -{ - int mode = mylcd_get_drawmode(); - mylcd_set_drawmode(DRMODE_FG); - mylcd_putsxy(x + osd.x, y + osd.y, str); - mylcd_set_drawmode(mode); -} -#endif /* LCD_PORTRAIT */ - -/** FPS Display **/ - -/* Post-frame callback (on video thread) - update the FPS rectangle from the - * framebuffer */ -static void fps_post_frame_callback(void) -{ - vo_lock(); - mylcd_update_rect(fps.pf_x, fps.pf_y, - fps.pf_width, fps.pf_height); - vo_unlock(); -} - -/* Set up to have the callback only update the intersection of the video - * rectangle and the FPS text rectangle - if they don't intersect, then - * the callback is set to NULL */ -static void fps_update_post_frame_callback(void) -{ - void (*cb)(void) = NULL; - - if (settings.showfps) { - struct vo_rect cliprect; - - if (stream_vo_get_clip(&cliprect)) { - /* Oriented screen coordinates -> OSD coordinates */ - vo_rect_offset(&cliprect, -osd.x, -osd.y); - - if (vo_rect_intersect(&cliprect, &cliprect, &fps.rect)) { - int x = cliprect.l; - int y = cliprect.t; - int width = cliprect.r - cliprect.l; - int height = cliprect.b - cliprect.t; - - /* OSD coordinates -> framebuffer coordinates */ - fps.pf_x = __X; - fps.pf_y = __Y; - fps.pf_width = __W; - fps.pf_height = __H; - - cb = fps_post_frame_callback; - } - } - } - - stream_set_callback(VIDEO_SET_POST_FRAME_CALLBACK, cb); -} - -/* Refresh the FPS display */ -static void fps_refresh(void) -{ - char str[FPS_BUFSIZE]; - struct video_output_stats stats; - int w, h, sw; - long tick; - - tick = *rb->current_tick; - - if (TIME_BEFORE(tick, fps.update_tick)) - return; - - fps.update_tick = tick + FPS_UPDATE_INTERVAL; - - stream_video_stats(&stats); - - rb->snprintf(str, FPS_BUFSIZE, FPS_FORMAT, - stats.fps / 100, stats.fps % 100); - - w = fps.rect.r - fps.rect.l; - h = fps.rect.b - fps.rect.t; - - draw_clear_area(fps.rect.l, fps.rect.t, w, h); - mylcd_getstringsize(str, &sw, NULL); - draw_putsxy_oriented(fps.rect.r - sw, fps.rect.t, str); - - vo_lock(); - draw_update_rect(fps.rect.l, fps.rect.t, w, h); - vo_unlock(); -} - -/* Initialize the FPS display */ -static void fps_init(void) -{ - fps.update_tick = *rb->current_tick; - fps.rect.l = fps.rect.t = 0; - mylcd_getstringsize(FPS_DIMSTR, &fps.rect.r, &fps.rect.b); - vo_rect_offset(&fps.rect, -osd.x, -osd.y); - fps_update_post_frame_callback(); -} - -/** OSD **/ - -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) -/* So we can refresh the overlay */ -static void osd_lcd_enable_hook(unsigned short id, void* param) -{ - (void)id; - (void)param; - rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_1, 0); -} -#endif - -static void osdbacklight_hw_on_video_mode(bool video_on) -{ - if (video_on) { -#ifdef HAVE_BACKLIGHT - /* Turn off backlight timeout */ - backlight_ignore_timeout(); -#endif -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - rb->remove_event(LCD_EVENT_ACTIVATION, osd_lcd_enable_hook); -#endif - } else { -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - rb->add_event(LCD_EVENT_ACTIVATION, osd_lcd_enable_hook); -#endif -#ifdef HAVE_BACKLIGHT - /* Revert to user's backlight settings */ - backlight_use_settings(); -#endif - } -} - -#ifdef HAVE_BACKLIGHT_BRIGHTNESS -static void osd_backlight_brightness_video_mode(bool video_on) -{ - if (settings.backlight_brightness < 0) - return; - - mpeg_backlight_update_brightness( - video_on ? settings.backlight_brightness : -1); -} -#else -#define osd_backlight_brightness_video_mode(video_on) -#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ - -static void osd_text_init(void) -{ - struct hms hms; - char buf[32]; - int phys; - int spc_width; - - draw_setfont(FONT_UI); - - osd.x = 0; - osd.width = SCREEN_WIDTH; - - vo_rect_clear(&osd.time_rect); - vo_rect_clear(&osd.stat_rect); - vo_rect_clear(&osd.prog_rect); - vo_rect_clear(&osd.vol_rect); - - ts_to_hms(stream_get_duration(), &hms); - hms_format(buf, sizeof (buf), &hms); - mylcd_getstringsize(buf, &osd.time_rect.r, &osd.time_rect.b); - - /* Choose well-sized bitmap images relative to font height */ - if (osd.time_rect.b < 12) { - osd.icons = mpegplayer_status_icons_8x8x1; - osd.stat_rect.r = osd.stat_rect.b = 8; - } else if (osd.time_rect.b < 16) { - osd.icons = mpegplayer_status_icons_12x12x1; - osd.stat_rect.r = osd.stat_rect.b = 12; - } else { - osd.icons = mpegplayer_status_icons_16x16x1; - osd.stat_rect.r = osd.stat_rect.b = 16; - } - - if (osd.stat_rect.b < osd.time_rect.b) { - vo_rect_offset(&osd.stat_rect, 0, - (osd.time_rect.b - osd.stat_rect.b) / 2 + OSD_BDR_T); - vo_rect_offset(&osd.time_rect, OSD_BDR_L, OSD_BDR_T); - } else { - vo_rect_offset(&osd.time_rect, OSD_BDR_L, - osd.stat_rect.b - osd.time_rect.b + OSD_BDR_T); - vo_rect_offset(&osd.stat_rect, 0, OSD_BDR_T); - } - - osd.dur_rect = osd.time_rect; - - phys = rb->sound_val2phys(SOUND_VOLUME, rb->sound_min(SOUND_VOLUME)); - rb->snprintf(buf, sizeof(buf), "%d%s", phys, - rb->sound_unit(SOUND_VOLUME)); - - mylcd_getstringsize(" ", &spc_width, NULL); - mylcd_getstringsize(buf, &osd.vol_rect.r, &osd.vol_rect.b); - - osd.prog_rect.r = SCREEN_WIDTH - OSD_BDR_L - spc_width - - osd.vol_rect.r - OSD_BDR_R; - osd.prog_rect.b = 3*osd.stat_rect.b / 4; - vo_rect_offset(&osd.prog_rect, osd.time_rect.l, - osd.time_rect.b); - - vo_rect_offset(&osd.stat_rect, - (osd.prog_rect.r + osd.prog_rect.l - osd.stat_rect.r) / 2, - 0); - - vo_rect_offset(&osd.dur_rect, - osd.prog_rect.r - osd.dur_rect.r, 0); - - vo_rect_offset(&osd.vol_rect, osd.prog_rect.r + spc_width, - (osd.prog_rect.b + osd.prog_rect.t - osd.vol_rect.b) / 2); - - osd.height = OSD_BDR_T + MAX(osd.prog_rect.b, osd.vol_rect.b) - - MIN(osd.time_rect.t, osd.stat_rect.t) + OSD_BDR_B; - -#ifdef HAVE_LCD_COLOR - osd.height = ALIGN_UP(osd.height, 2); -#endif - osd.y = SCREEN_HEIGHT - osd.height; - - draw_setfont(FONT_SYSFIXED); -} - -static void osd_init(void) -{ - osd.flags = 0; - osd.show_for = HZ*4; - osd.print_delay = 75*HZ/100; - osd.resume_delay = HZ/2; -#ifdef HAVE_LCD_COLOR - osd.bgcolor = LCD_RGBPACK(0x73, 0x75, 0xbd); - osd.fgcolor = LCD_WHITE; - osd.prog_fillcolor = LCD_BLACK; -#else - osd.bgcolor = GREY_LIGHTGRAY; - osd.fgcolor = GREY_BLACK; - osd.prog_fillcolor = GREY_WHITE; -#endif - osd.curr_time = 0; - osd.status = OSD_STATUS_STOPPED; - osd.auto_refresh = OSD_REFRESH_TIME; - osd.next_auto_refresh = *rb->current_tick; - osd_text_init(); - fps_init(); -} - -#ifdef HAVE_HEADPHONE_DETECTION -static void osd_set_hp_pause_flag(bool set) -{ - if (set) - osd.flags |= OSD_HP_PAUSE; - else - osd.flags &= ~OSD_HP_PAUSE; -} -#else -#define osd_set_hp_pause_flag(set) -#endif /* HAVE_HEADPHONE_DETECTION */ - -static void osd_schedule_refresh(unsigned refresh) -{ - long tick = *rb->current_tick; - - if (refresh & OSD_REFRESH_VIDEO) - osd.print_tick = tick + osd.print_delay; - - if (refresh & OSD_REFRESH_RESUME) - osd.resume_tick = tick + osd.resume_delay; - - osd.auto_refresh |= refresh; -} - -static void osd_cancel_refresh(unsigned refresh) -{ - osd.auto_refresh &= ~refresh; -} - -/* Refresh the background area */ -static void osd_refresh_background(void) -{ - char buf[32]; - struct hms hms; - - unsigned bg = mylcd_get_background(); - mylcd_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); - -#ifdef HAVE_LCD_COLOR - /* Draw a "raised" area for our graphics */ - mylcd_set_background(draw_blendcolor(bg, MYLCD_WHITE, 192)); - draw_hline(0, osd.width, 0); - - mylcd_set_background(draw_blendcolor(bg, MYLCD_WHITE, 80)); - draw_hline(0, osd.width, 1); - - mylcd_set_background(draw_blendcolor(bg, MYLCD_BLACK, 48)); - draw_hline(0, osd.width, osd.height-2); - - mylcd_set_background(draw_blendcolor(bg, MYLCD_BLACK, 128)); - draw_hline(0, osd.width, osd.height-1); - - mylcd_set_background(bg); - draw_clear_area(0, 2, osd.width, osd.height - 4); -#else - /* Give contrast with the main background */ - mylcd_set_background(MYLCD_WHITE); - draw_hline(0, osd.width, 0); - - mylcd_set_background(MYLCD_DARKGRAY); - draw_hline(0, osd.width, osd.height-1); - - mylcd_set_background(bg); - draw_clear_area(0, 1, osd.width, osd.height - 2); -#endif - - vo_rect_set_ext(&osd.update_rect, 0, 0, osd.width, osd.height); - mylcd_set_drawmode(DRMODE_SOLID); - - if (stream_get_duration() != INVALID_TIMESTAMP) { - /* Draw the movie duration */ - ts_to_hms(stream_get_duration(), &hms); - hms_format(buf, sizeof (buf), &hms); - draw_putsxy_oriented(osd.dur_rect.l, osd.dur_rect.t, buf); - } - /* else don't know the duration */ -} - -/* Refresh the current time display + the progress bar */ -static void osd_refresh_time(void) -{ - char buf[32]; - struct hms hms; - - uint32_t duration = stream_get_duration(); - - draw_scrollbar_draw_rect(&osd.prog_rect, 0, duration, - osd.curr_time); - - ts_to_hms(osd.curr_time, &hms); - hms_format(buf, sizeof (buf), &hms); - - draw_clear_area_rect(&osd.time_rect); - draw_putsxy_oriented(osd.time_rect.l, osd.time_rect.t, buf); - - vo_rect_union(&osd.update_rect, &osd.update_rect, - &osd.prog_rect); - vo_rect_union(&osd.update_rect, &osd.update_rect, - &osd.time_rect); -} - -/* Refresh the volume display area */ -static void osd_refresh_volume(void) -{ - char buf[32]; - int width; - - int volume = rb->global_settings->volume; - rb->snprintf(buf, sizeof (buf), "%d%s", - rb->sound_val2phys(SOUND_VOLUME, volume), - rb->sound_unit(SOUND_VOLUME)); - mylcd_getstringsize(buf, &width, NULL); - - /* Right-justified */ - draw_clear_area_rect(&osd.vol_rect); - draw_putsxy_oriented(osd.vol_rect.r - width, osd.vol_rect.t, buf); - - vo_rect_union(&osd.update_rect, &osd.update_rect, &osd.vol_rect); -} - -/* Refresh the status icon */ -static void osd_refresh_status(void) -{ - int icon_size = osd.stat_rect.r - osd.stat_rect.l; - - draw_clear_area_rect(&osd.stat_rect); - -#ifdef HAVE_LCD_COLOR - /* Draw status icon with a drop shadow */ - unsigned oldfg = mylcd_get_foreground(); - int i = 1; - - mylcd_set_foreground(draw_blendcolor(mylcd_get_background(), - MYLCD_BLACK, 96)); - - while (1) - { - draw_oriented_mono_bitmap_part(osd.icons, - icon_size*osd.status, - 0, - icon_size*OSD_STATUS_COUNT, - osd.stat_rect.l + osd.x + i, - osd.stat_rect.t + osd.y + i, - icon_size, icon_size); - - if (--i < 0) - break; - - mylcd_set_foreground(oldfg); - } - - vo_rect_union(&osd.update_rect, &osd.update_rect, &osd.stat_rect); -#else - draw_oriented_mono_bitmap_part(osd.icons, - icon_size*osd.status, - 0, - icon_size*OSD_STATUS_COUNT, - osd.stat_rect.l + osd.x, - osd.stat_rect.t + osd.y, - icon_size, icon_size); - vo_rect_union(&osd.update_rect, &osd.update_rect, &osd.stat_rect); -#endif -} - -/* Update the current status which determines which icon is displayed */ -static bool osd_update_status(void) -{ - int status; - - switch (stream_status()) - { - default: - status = OSD_STATUS_STOPPED; - break; - case STREAM_PAUSED: - /* If paused with a pending resume, coerce it to OSD_STATUS_PLAYING */ - status = (osd.auto_refresh & OSD_REFRESH_RESUME) ? - OSD_STATUS_PLAYING : OSD_STATUS_PAUSED; - break; - case STREAM_PLAYING: - status = OSD_STATUS_PLAYING; - break; - } - - if (status != osd.status) { - /* A refresh is needed */ - osd.status = status; - return true; - } - - return false; -} - -/* Update the current time that will be displayed */ -static void osd_update_time(void) -{ - uint32_t start; - osd.curr_time = stream_get_seek_time(&start); - osd.curr_time -= start; -} - -/* Refresh various parts of the OSD - showing it if it is hidden */ -static void osd_refresh(int hint) -{ - long tick; - unsigned oldbg, oldfg; - - tick = *rb->current_tick; - - if (settings.showfps) - fps_refresh(); - - if (hint == OSD_REFRESH_DEFAULT) { - /* The default which forces no updates */ - - /* Make sure Rockbox doesn't turn off the player because of - too little activity */ - if (osd.status == OSD_STATUS_PLAYING) - rb->reset_poweroff_timer(); - - /* Redraw the current or possibly extract a new video frame */ - if ((osd.auto_refresh & OSD_REFRESH_VIDEO) && - TIME_AFTER(tick, osd.print_tick)) { - osd.auto_refresh &= ~OSD_REFRESH_VIDEO; - stream_draw_frame(false); - } - - /* Restart playback if the timout was reached */ - if ((osd.auto_refresh & OSD_REFRESH_RESUME) && - TIME_AFTER(tick, osd.resume_tick)) { - osd.auto_refresh &= ~(OSD_REFRESH_RESUME | OSD_REFRESH_VIDEO); - stream_resume(); - } - - /* If not visible, return */ - if (!(osd.flags & OSD_SHOW)) - return; - - /* Hide if the visibility duration was reached */ - if (TIME_AFTER(tick, osd.hide_tick)) { - osd_show(OSD_HIDE); - return; - } - } else { - /* A forced update of some region */ - - /* Show if currently invisible */ - if (!(osd.flags & OSD_SHOW)) { - /* Avoid call back into this function - it will be drawn */ - osd_show(OSD_SHOW | OSD_NODRAW); - hint = OSD_REFRESH_ALL; - } - - /* Move back timeouts for frame print and hide */ - osd.print_tick = tick + osd.print_delay; - osd.hide_tick = tick + osd.show_for; - } - - if (TIME_AFTER(tick, osd.next_auto_refresh)) { - /* Refresh whatever graphical elements are due automatically */ - osd.next_auto_refresh = tick + OSD_MIN_UPDATE_INTERVAL; - - if (osd.auto_refresh & OSD_REFRESH_STATUS) { - if (osd_update_status()) - hint |= OSD_REFRESH_STATUS; - } - - if (osd.auto_refresh & OSD_REFRESH_TIME) { - osd_update_time(); - hint |= OSD_REFRESH_TIME; - } - } - - if (hint == 0) - return; /* No drawing needed */ - - /* Set basic drawing params that are used. Elements that perform variations - * will restore them. */ - oldfg = mylcd_get_foreground(); - oldbg = mylcd_get_background(); - - draw_setfont(FONT_UI); - mylcd_set_foreground(osd.fgcolor); - mylcd_set_background(osd.bgcolor); - - vo_rect_clear(&osd.update_rect); - - if (hint & OSD_REFRESH_BACKGROUND) { - osd_refresh_background(); - hint |= OSD_REFRESH_ALL; /* Requires a redraw of everything */ - } - - if (hint & OSD_REFRESH_TIME) { - osd_refresh_time(); - } - - if (hint & OSD_REFRESH_VOLUME) { - osd_refresh_volume(); - } - - if (hint & OSD_REFRESH_STATUS) { - osd_refresh_status(); - } - - /* Go back to defaults */ - draw_setfont(FONT_SYSFIXED); - mylcd_set_foreground(oldfg); - mylcd_set_background(oldbg); - - /* Update the dirty rectangle */ - vo_lock(); - - draw_update_rect(osd.update_rect.l, - osd.update_rect.t, - osd.update_rect.r - osd.update_rect.l, - osd.update_rect.b - osd.update_rect.t); - - vo_unlock(); -} - -/* Show/Hide the OSD */ -static void osd_show(unsigned show) -{ - if (((show ^ osd.flags) & OSD_SHOW) == 0) - { - if (show & OSD_SHOW) { - osd.hide_tick = *rb->current_tick + osd.show_for; - } - return; - } - - if (show & OSD_SHOW) { - /* Clip away the part of video that is covered */ - struct vo_rect rc = { 0, 0, SCREEN_WIDTH, osd.y }; - - osd.flags |= OSD_SHOW; - - if (osd.status != OSD_STATUS_PLAYING) { - /* Not playing - set brightness to mpegplayer setting */ - osd_backlight_brightness_video_mode(true); - } - - stream_vo_set_clip(&rc); - - if (!(show & OSD_NODRAW)) - osd_refresh(OSD_REFRESH_ALL); - } else { - /* Uncover clipped video area and redraw it */ - osd.flags &= ~OSD_SHOW; - - draw_clear_area(0, 0, osd.width, osd.height); - - if (!(show & OSD_NODRAW)) { - vo_lock(); - draw_update_rect(0, 0, osd.width, osd.height); - vo_unlock(); - - stream_vo_set_clip(NULL); - stream_draw_frame(false); - } else { - stream_vo_set_clip(NULL); - } - - if (osd.status != OSD_STATUS_PLAYING) { - /* Not playing - restore backlight brightness */ - osd_backlight_brightness_video_mode(false); - } - } -} - -/* Set the current status - update screen if specified */ -static void osd_set_status(int status) -{ - bool draw = (status & OSD_NODRAW) == 0; - - status &= OSD_STATUS_MASK; - - if (osd.status != status) { - - osd.status = status; - - if (draw) - osd_refresh(OSD_REFRESH_STATUS); - } -} - -/* Get the current status value */ -static int osd_get_status(void) -{ - return osd.status & OSD_STATUS_MASK; -} - -/* Handle Fast-forward/Rewind keys using WPS settings (and some nicked code ;) - * Returns last button code - */ -static int osd_ff_rw(int btn, unsigned refresh, uint32_t *new_time) -{ - unsigned int step = TS_SECOND*rb->global_settings->ff_rewind_min_step; - const long ff_rw_accel = (rb->global_settings->ff_rewind_accel + 3); - uint32_t start; - uint32_t time = stream_get_seek_time(&start); - const uint32_t duration = stream_get_duration(); - unsigned int max_step = 0; - uint32_t ff_rw_count = 0; - unsigned status = osd.status; - int new_btn; - - osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME | - OSD_REFRESH_TIME); - - time -= start; /* Absolute clock => stream-relative */ - - switch (btn) - { - case MPEG_FF: -#ifdef MPEG_FF2 - case MPEG_FF2: -#endif -#ifdef MPEG_RC_FF - case MPEG_RC_FF: -#endif - osd_set_status(OSD_STATUS_FF); - new_btn = btn | BUTTON_REPEAT; /* simplify code below */ - break; - case MPEG_RW: -#ifdef MPEG_RW2 - case MPEG_RW2: -#endif -#ifdef MPEG_RC_RW - case MPEG_RC_RW: -#endif - osd_set_status(OSD_STATUS_RW); - new_btn = btn | BUTTON_REPEAT; /* simplify code below */ - break; - default: - new_btn = BUTTON_NONE; /* Fail tests below but still do proper exit */ - } - - while (1) - { - stream_keep_disk_active(); - - if (new_btn == (btn | BUTTON_REPEAT)) { - if (osd.status == OSD_STATUS_FF) { - /* fast forwarding, calc max step relative to end */ - max_step = muldiv_uint32(duration - (time + ff_rw_count), - FF_REWIND_MAX_PERCENT, 100); - } else { - /* rewinding, calc max step relative to start */ - max_step = muldiv_uint32(time - ff_rw_count, - FF_REWIND_MAX_PERCENT, 100); - } - - max_step = MAX(max_step, MIN_FF_REWIND_STEP); - - if (step > max_step) - step = max_step; - - ff_rw_count += step; - - /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */ - step += step >> ff_rw_accel; - - if (osd.status == OSD_STATUS_FF) { - if (duration - time <= ff_rw_count) - ff_rw_count = duration - time; - - osd.curr_time = time + ff_rw_count; - } else { - if (time <= ff_rw_count) - ff_rw_count = time; - - osd.curr_time = time - ff_rw_count; - } - - osd_refresh(OSD_REFRESH_TIME); - - new_btn = mpeg_button_get(TIMEOUT_BLOCK); - } - else { - if (new_btn == (btn | BUTTON_REL)) { - if (osd.status == OSD_STATUS_FF) - time += ff_rw_count; - else if (osd.status == OSD_STATUS_RW) - time -= ff_rw_count; - } - - *new_time = time; - - osd_schedule_refresh(refresh); - osd_set_status(status); - osd_schedule_refresh(OSD_REFRESH_TIME); - - return new_btn; - } - } -} - -/* Return adjusted STREAM_* status */ -static int osd_stream_status(void) -{ - int status = stream_status(); - - /* Coerce to STREAM_PLAYING if paused with a pending resume */ - if (status == STREAM_PAUSED) { - if (osd.auto_refresh & OSD_REFRESH_RESUME) - status = STREAM_PLAYING; - } - - return status; -} - -/* Change the current audio volume by a specified amount */ -static void osd_set_volume(int delta) -{ - int vol = rb->global_settings->volume; - int limit; - - vol += delta; - - if (delta < 0) { - /* Volume down - clip to lower limit */ - limit = rb->sound_min(SOUND_VOLUME); - if (vol < limit) - vol = limit; - } else { - /* Volume up - clip to upper limit */ - limit = rb->sound_max(SOUND_VOLUME); - if (vol > limit) - vol = limit; - } - - /* Sync the global settings */ - if (vol != rb->global_settings->volume) { - rb->sound_set(SOUND_VOLUME, vol); - rb->global_settings->volume = vol; - } - - /* Update the volume display */ - osd_refresh(OSD_REFRESH_VOLUME); -} - -/* Begin playback at the specified time */ -static int osd_play(uint32_t time) -{ - int retval; - - osd_set_hp_pause_flag(false); - osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); - - retval = stream_seek(time, SEEK_SET); - - if (retval >= STREAM_OK) { - osdbacklight_hw_on_video_mode(true); - osd_backlight_brightness_video_mode(true); - stream_show_vo(true); - - retval = stream_play(); - - if (retval >= STREAM_OK) - osd_set_status(OSD_STATUS_PLAYING | OSD_NODRAW); - } - - return retval; -} - -/* Halt playback - pause engine and return logical state */ -static int osd_halt(void) -{ - int status = stream_pause(); - - /* Coerce to STREAM_PLAYING if paused with a pending resume */ - if (status == STREAM_PAUSED) { - if (osd_get_status() == OSD_STATUS_PLAYING) - status = STREAM_PLAYING; - } - - /* Cancel some auto refreshes - caller will restart them if desired */ - osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); - - /* No backlight fiddling here - callers does the right thing */ - - return status; -} - -/* Pause playback if playing */ -static int osd_pause(void) -{ - unsigned refresh = osd.auto_refresh; - int status = osd_halt(); - - osd_set_hp_pause_flag(false); - - if (status == STREAM_PLAYING && (refresh & OSD_REFRESH_RESUME)) { - /* Resume pending - change to a still video frame update */ - osd_schedule_refresh(OSD_REFRESH_VIDEO); - } - - osd_set_status(OSD_STATUS_PAUSED); - - osdbacklight_hw_on_video_mode(false); - /* Leave brightness alone and restore it when OSD is hidden */ - - if (stream_can_seek() && rb->global_settings->pause_rewind) { - stream_seek(-rb->global_settings->pause_rewind*TS_SECOND, - SEEK_CUR); - osd_schedule_refresh(OSD_REFRESH_VIDEO); - /* Update time display now */ - osd_update_time(); - osd_refresh(OSD_REFRESH_TIME); - } - - return status; -} - -/* Resume playback if halted or paused */ -static void osd_resume(void) -{ - /* Cancel video and resume auto refresh - the resyc when starting - * playback will perform those tasks */ - osd_set_hp_pause_flag(false); - osdbacklight_hw_on_video_mode(true); - osd_backlight_brightness_video_mode(true); - osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); - osd_set_status(OSD_STATUS_PLAYING); - stream_resume(); -} - -/* Stop playback - remember the resume point if not closed */ -static void osd_stop(void) -{ - uint32_t resume_time; - - osd_set_hp_pause_flag(false); - osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); - osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW); - osd_show(OSD_HIDE); - - stream_stop(); - - resume_time = stream_get_resume_time(); - - if (resume_time != INVALID_TIMESTAMP) - settings.resume_time = resume_time; - - osdbacklight_hw_on_video_mode(false); - osd_backlight_brightness_video_mode(false); -} - -/* Perform a seek by button if seeking is possible for this stream. - * - * A delay will be inserted before restarting in case the user decides to - * seek again soon after. - * - * Returns last button code - */ -static int osd_seek_btn(int btn) -{ - int status; - unsigned refresh = 0; - uint32_t time; - - if (!stream_can_seek()) - return true; - - /* Halt playback - not strictly necessary but nice when doing - * buttons */ - status = osd_halt(); - - if (status == STREAM_STOPPED) - return true; - - osd_show(OSD_SHOW); - - /* Obtain a new playback point according to the buttons */ - if (status == STREAM_PLAYING) - refresh = OSD_REFRESH_RESUME; /* delay resume if playing */ - else - refresh = OSD_REFRESH_VIDEO; /* refresh if paused */ - - btn = osd_ff_rw(btn, refresh, &time); - - /* Tell engine to resume at that time */ - stream_seek(time, SEEK_SET); - - return btn; -} - -/* Perform a seek by time if seeking is possible for this stream - * - * If playing, the seeking is immediate, otherise a delay is added to showing - * a still if paused in case the user does another seek soon after. - * - * If seeking isn't possible, a time of zero performs a skip to the - * beginning. - */ -static void osd_seek_time(uint32_t time) -{ - int status; - unsigned refresh = 0; - - if (!stream_can_seek() && time != 0) - return; - - stream_wait_status(); - status = osd_stream_status(); - - if (status == STREAM_STOPPED) - return; - - if (status == STREAM_PLAYING) /* merely preserve resume */ - refresh = osd.auto_refresh & OSD_REFRESH_RESUME; - else - refresh = OSD_REFRESH_VIDEO; /* refresh if paused */ - - /* Cancel print or resume if pending */ - osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); - - /* Tell engine to seek to the given time - no state change */ - stream_seek(time, SEEK_SET); - - osd_update_time(); - osd_refresh(OSD_REFRESH_TIME); - osd_schedule_refresh(refresh); -} - -/* Has this file one of the supported extensions? */ -static bool is_videofile(const char* file) -{ - static const char * const extensions[] = - { - /* Should match apps/plugins/viewers.config */ - "mpg", "mpeg", "mpv", "m2v" - }; - - const char* ext = rb->strrchr(file, '.'); - int i; - - if (!ext) - return false; - - for (i = ARRAYLEN(extensions) - 1; i >= 0; i--) - { - if (!rb->strcasecmp(ext + 1, extensions[i])) - break; - } - - return i >= 0; -} - -/* deliver the next/previous video file in the current directory. - returns false if there is none. */ -static bool get_videofile(int direction, char* videofile, size_t bufsize) -{ - struct tree_context *tree = rb->tree_get_context(); - struct entry *dircache = rb->tree_get_entries(tree); - int i, step, end, found = 0; - char *videoname = rb->strrchr(videofile, '/') + 1; - size_t rest = bufsize - (videoname - videofile) - 1; - - if (direction == VIDEO_NEXT) { - i = 0; - step = 1; - end = tree->filesindir; - } else { - i = tree->filesindir-1; - step = -1; - end = -1; - } - for (; i != end; i += step) - { - const char* name = dircache[i].name; - if (!rb->strcmp(name, videoname)) { - found = 1; - continue; - } - if (found && rb->strlen(name) <= rest && - !(dircache[i].attr & ATTR_DIRECTORY) && is_videofile(name)) - { - rb->strcpy(videoname, name); - return true; - } - } - - return false; -} - -#ifdef HAVE_HEADPHONE_DETECTION -/* Handle SYS_PHONE_PLUGGED/UNPLUGGED */ -static void osd_handle_phone_plug(bool inserted) -{ - if (rb->global_settings->unplug_mode == 0) - return; - - /* Wait for any incomplete state transition to complete first */ - stream_wait_status(); - - int status = osd_stream_status(); - - if (inserted) { - if (rb->global_settings->unplug_mode > 1) { - if (status == STREAM_PAUSED && - (osd.flags & OSD_HP_PAUSE)) { - osd_resume(); - } - } - } else { - if (status == STREAM_PLAYING) { - osd_pause(); - - osd_set_hp_pause_flag(true); - } - } -} -#endif - -static int button_loop(void) -{ - int next_action = (settings.play_mode == 0) ? VIDEO_STOP : VIDEO_NEXT; - - rb->lcd_setfont(FONT_SYSFIXED); -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(LCD_WHITE); - rb->lcd_set_background(LCD_BLACK); -#endif - rb->lcd_clear_display(); - rb->lcd_update(); - -#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV) - rb->lcd_set_mode(LCD_MODE_YUV); -#endif - - osd_init(); - - /* Start playback at the specified starting time */ - if (osd_play(settings.resume_time) < STREAM_OK) { - rb->splash(HZ*2, "Playback failed"); - return VIDEO_STOP; - } - - /* Gently poll the video player for EOS and handle UI */ - while (stream_status() != STREAM_STOPPED) - { - int button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL/2); - - switch (button) - { - case BUTTON_NONE: - { - osd_refresh(OSD_REFRESH_DEFAULT); - continue; - } /* BUTTON_NONE: */ - -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - case LCD_ENABLE_EVENT_1: - { - /* Draw the current frame if prepared already */ - stream_draw_frame(true); - break; - } /* LCD_ENABLE_EVENT_1: */ -#endif - - case MPEG_VOLUP: - case MPEG_VOLUP|BUTTON_REPEAT: -#ifdef MPEG_VOLUP2 - case MPEG_VOLUP2: - case MPEG_VOLUP2|BUTTON_REPEAT: -#endif -#ifdef MPEG_RC_VOLUP - case MPEG_RC_VOLUP: - case MPEG_RC_VOLUP|BUTTON_REPEAT: -#endif - { - osd_set_volume(+1); - break; - } /* MPEG_VOLUP*: */ - - case MPEG_VOLDOWN: - case MPEG_VOLDOWN|BUTTON_REPEAT: -#ifdef MPEG_VOLDOWN2 - case MPEG_VOLDOWN2: - case MPEG_VOLDOWN2|BUTTON_REPEAT: -#endif -#ifdef MPEG_RC_VOLDOWN - case MPEG_RC_VOLDOWN: - case MPEG_RC_VOLDOWN|BUTTON_REPEAT: -#endif - { - osd_set_volume(-1); - break; - } /* MPEG_VOLDOWN*: */ - - case MPEG_MENU: -#ifdef MPEG_RC_MENU - case MPEG_RC_MENU: -#endif - { - int state = osd_halt(); /* save previous state */ - int result; - - /* Hide video output */ - osd_show(OSD_HIDE | OSD_NODRAW); - stream_show_vo(false); - osd_backlight_brightness_video_mode(false); - -#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV) - rb->lcd_set_mode(LCD_MODE_RGB565); -#endif - - result = mpeg_menu(); - - next_action = (settings.play_mode == 0) ? VIDEO_STOP : VIDEO_NEXT; - - fps_update_post_frame_callback(); - - /* The menu can change the font, so restore */ - rb->lcd_setfont(FONT_SYSFIXED); -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(LCD_WHITE); - rb->lcd_set_background(LCD_BLACK); -#endif - rb->lcd_clear_display(); - rb->lcd_update(); - - switch (result) - { - case MPEG_MENU_QUIT: - next_action = VIDEO_STOP; - osd_stop(); - break; - - default: -#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV) - rb->lcd_set_mode(LCD_MODE_YUV); -#endif - /* If not stopped, show video again */ - if (state != STREAM_STOPPED) { - osd_show(OSD_SHOW); - stream_show_vo(true); - } - - /* If stream was playing, restart it */ - if (state == STREAM_PLAYING) { - osd_resume(); - } - break; - } - break; - } /* MPEG_MENU: */ - -#ifdef MPEG_SHOW_OSD - case MPEG_SHOW_OSD: - case MPEG_SHOW_OSD | BUTTON_REPEAT: - /* Show if not visible */ - osd_show(OSD_SHOW); - /* Make sure it refreshes */ - osd_refresh(OSD_REFRESH_DEFAULT); - break; -#endif - - case MPEG_STOP: -#ifdef MPEG_RC_STOP - case MPEG_RC_STOP: -#endif - case ACTION_STD_CANCEL: - { - cancel_playback: - next_action = VIDEO_STOP; - osd_stop(); - break; - } /* MPEG_STOP: */ - - case MPEG_PAUSE: -#ifdef MPEG_PAUSE2 - case MPEG_PAUSE2: -#endif -#ifdef MPEG_RC_PAUSE - case MPEG_RC_PAUSE: -#endif - { - int status = osd_stream_status(); - - if (status == STREAM_PLAYING) { - /* Playing => Paused */ - osd_pause(); - } - else if (status == STREAM_PAUSED) { - /* Paused => Playing */ - osd_resume(); - } - - break; - } /* MPEG_PAUSE*: */ - - case MPEG_RW: -#ifdef MPEG_RW2 - case MPEG_RW2: -#endif -#ifdef MPEG_RC_RW - case MPEG_RC_RW: -#endif - { - int old_button = button; - - /* If button has been released: skip to next/previous file */ - button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL); - - if ((old_button | BUTTON_REL) == button) { - /* Check current playback position */ - osd_update_time(); - - if (settings.play_mode == 0 || osd.curr_time >= 3*TS_SECOND) { - /* Start the current video from the beginning */ - osd_seek_time(0*TS_SECOND); - } - else { - /* Release within 3 seconds of start: skip to previous - * file */ - osd_stop(); - next_action = VIDEO_PREV | VIDEO_ACTION_MANUAL; - } - } - else if ((button & ~BUTTON_REPEAT) == old_button) { - button = osd_seek_btn(old_button); - } - - if (button == ACTION_STD_CANCEL) - goto cancel_playback; /* jump to stop handling above */ - - rb->default_event_handler(button); - break; - } /* MPEG_RW: */ - - case MPEG_FF: -#ifdef MPEG_FF2 - case MPEG_FF2: -#endif -#ifdef MPEG_RC_FF - case MPEG_RC_FF: -#endif - { - int old_button = button; - - if (settings.play_mode != 0) - button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL); - - if ((old_button | BUTTON_REL) == button) { - /* If button has been released: skip to next file */ - osd_stop(); - next_action = VIDEO_NEXT | VIDEO_ACTION_MANUAL; - } - else if ((button & ~BUTTON_REPEAT) == old_button) { - button = osd_seek_btn(old_button); - } - - if (button == ACTION_STD_CANCEL) - goto cancel_playback; /* jump to stop handling above */ - - rb->default_event_handler(button); - break; - } /* MPEG_FF: */ - -#ifdef HAVE_HEADPHONE_DETECTION - case SYS_PHONE_PLUGGED: - case SYS_PHONE_UNPLUGGED: - { - osd_handle_phone_plug(button == SYS_PHONE_PLUGGED); - break; - } /* SYS_PHONE_*: */ -#endif - - default: - { - osd_refresh(OSD_REFRESH_DEFAULT); - rb->default_event_handler(button); - break; - } /* default: */ - } - - rb->yield(); - } /* end while */ - - osd_stop(); - -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - /* Be sure hook is removed before exiting since the stop will put it - * back because of the backlight restore. */ - rb->remove_event(LCD_EVENT_ACTIVATION, osd_lcd_enable_hook); -#endif - - rb->lcd_setfont(FONT_UI); - - return next_action; -} - -enum plugin_status plugin_start(const void* parameter) -{ - static char videofile[MAX_PATH]; - int status = PLUGIN_OK; /* assume success */ - bool quit = false; - -#if defined(PLUGIN_USE_IRAM) && !defined(SIMULATOR) - bool preserved_talk_state; -#endif - - if (parameter == NULL) { - /* No file = GTFO */ - rb->splash(HZ*2, "No File"); - return PLUGIN_ERROR; - } - - /* Disable all talking before initializing IRAM */ - rb->talk_disable(true); - -#ifdef PLUGIN_USE_IRAM - iram_saving_init(); - -#ifndef SIMULATOR - preserved_talk_state = rb->global_settings->talk_menu; - if (!iram_saved_copy) - rb->global_settings->talk_menu = false; -#endif -#endif - -#ifdef HAVE_LCD_COLOR - rb->lcd_set_backdrop(NULL); - rb->lcd_set_foreground(LCD_WHITE); - rb->lcd_set_background(LCD_BLACK); -#endif - - rb->lcd_clear_display(); - rb->lcd_update(); - - rb->strcpy(videofile, (const char*) parameter); - - if (stream_init() < STREAM_OK) { - /* Fatal because this should not fail */ - DEBUGF("Could not initialize streams\n"); - status = PLUGIN_ERROR; - } else { - int next_action = VIDEO_STOP; - bool get_videofile_says = true; - - while (!quit) - { - init_settings(videofile); - - int result = stream_open(videofile); - bool manual_skip = false; - - if (result >= STREAM_OK) { - /* start menu */ - rb->lcd_clear_display(); - rb->lcd_update(); - result = mpeg_start_menu(stream_get_duration()); - - next_action = VIDEO_STOP; - if (result != MPEG_START_QUIT) { - /* Enter button loop and process UI */ - next_action = button_loop(); - manual_skip = next_action & VIDEO_ACTION_MANUAL; - next_action &= ~VIDEO_ACTION_MANUAL; - } - - stream_close(); - - rb->lcd_clear_display(); - rb->lcd_update(); - - save_settings(); - } else { - /* Problem with file; display message about it - not - * considered a plugin error */ - long tick; - const char *errstring; - - DEBUGF("Could not open %s\n", videofile); - switch (result) - { - case STREAM_UNSUPPORTED: - errstring = "Unsupported format"; - break; - default: - errstring = "Error opening file: %d"; - } - - tick = *rb->current_tick + HZ*2; - - rb->splashf(0, errstring, result); - - /* Be sure it doesn't get stuck in an unbreakable loop of bad - * files, just in case! Otherwise, keep searching in the - * chosen direction until a good one is found. */ - while (!quit && TIME_BEFORE(*rb->current_tick, tick)) - { - int button = mpeg_button_get(HZ*2); - - switch (button) - { - case MPEG_STOP: - case ACTION_STD_CANCEL: - /* Abort the search and exit */ - next_action = VIDEO_STOP; - quit = true; - break; - - case BUTTON_NONE: - if (settings.play_mode != 0) { - if (next_action == VIDEO_STOP) { - /* Default to next file */ - next_action = VIDEO_NEXT; - } - else if (next_action == VIDEO_PREV && - !get_videofile_says) { - /* Was first file already; avoid endlessly - * retrying it */ - next_action = VIDEO_STOP; - } - } - break; - - default: - rb->default_event_handler(button); - } /* switch */ - } /* while */ - } - - /* return value of button_loop says, what's next */ - switch (next_action) - { - case VIDEO_NEXT: - { - get_videofile_says = get_videofile(VIDEO_NEXT, videofile, - sizeof(videofile)); - /* quit after finished the last videofile */ - quit = !get_videofile_says; - - if (manual_skip) - { - rb->system_sound_play(get_videofile_says ? - SOUND_TRACK_SKIP : SOUND_TRACK_NO_MORE); - } - - break; - } - case VIDEO_PREV: - { - get_videofile_says = get_videofile(VIDEO_PREV, videofile, - sizeof(videofile)); - /* if there is no previous file, play the same videofile */ - - if (manual_skip) - { - rb->system_sound_play(get_videofile_says ? - SOUND_TRACK_SKIP : SOUND_TRACK_NO_MORE); - } - - break; - } - case VIDEO_STOP: - { - quit = true; - break; - } - } - } /* while */ - } - -#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV) - rb->lcd_set_mode(LCD_MODE_RGB565); -#endif - - stream_exit(); - -#if defined(PLUGIN_USE_IRAM) && !defined(SIMULATOR) - if (!iram_saved_copy) - rb->global_settings->talk_menu = preserved_talk_state; -#endif - - rb->talk_disable(false); - - /* Actually handle delayed processing of system events of interest - * that were captured in other button loops */ - mpeg_sysevent_handle(); - - return status; -} diff --git a/apps/plugins/mpegplayer/mpegplayer.h b/apps/plugins/mpegplayer/mpegplayer.h deleted file mode 100644 index 51fb9a8f8a..0000000000 --- a/apps/plugins/mpegplayer/mpegplayer.h +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Main mpegplayer config header. - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef MPEGPLAYER_H -#define MPEGPLAYER_H - -#ifdef HAVE_SCHEDULER_BOOSTCTRL -#define trigger_cpu_boost rb->trigger_cpu_boost -#define cancel_cpu_boost rb->cancel_cpu_boost -#endif -/* #else function-like empty macros are defined in the headers */ - -/* Should be enough for now */ -#define MPEGPLAYER_MAX_STREAMS 4 - -/* Memory allotments for various subsystems */ -#define MIN_MEMMARGIN (4*1024) - -/** Video thread **/ -#define LIBMPEG2_ALLOC_SIZE (2*1024*1024) - -/** MPEG audio buffer **/ -#define AUDIOBUF_GUARD_SIZE (MPA_MAX_FRAME_SIZE + 2*MAD_BUFFER_GUARD) -#define AUDIOBUF_SIZE (64*1024) -#define AUDIOBUF_ALLOC_SIZE (AUDIOBUF_SIZE+AUDIOBUF_GUARD_SIZE) - -/** PCM buffer **/ -#define CLOCK_RATE 44100 /* Our clock rate in ticks/second (samplerate) */ - -/* Define this as "1" to have a test tone instead of silence clip */ -#define SILENCE_TEST_TONE 0 - -/* NOTE: Sizes make no frame header allowance when considering duration */ -#define PCMOUT_BUFSIZE (CLOCK_RATE/2*4) /* 1/2s */ -#define PCMOUT_GUARD_SIZE (PCMOUT_BUFSIZE) /* guarantee contiguous sizes */ -#define PCMOUT_ALLOC_SIZE (PCMOUT_BUFSIZE + PCMOUT_GUARD_SIZE) - /* Start pcm playback @ 25% full */ -#define PCMOUT_PLAY_WM (PCMOUT_BUFSIZE/4) -#define PCMOUT_LOW_WM (0) - -/** disk buffer **/ -#define DISK_BUF_LOW_WATERMARK (1024*1024) -/* 65535+6 is required since each PES has a 6 byte header with a 16 bit - * packet length field */ -#define DISK_GUARDBUF_SIZE ALIGN_UP(65535+6, 4) - -#ifdef HAVE_LCD_COLOR -#define mylcd_splash rb->splash -#else -#include "lib/grey.h" -#define mylcd_splash grey_splash -#endif - -#include "lib/mylcd.h" - -#include "libmpeg2/mpeg2.h" -#include "video_out.h" -#include "mpeg_stream.h" -#include "mpeg_misc.h" -#include "mpeg_alloc.h" -#include "stream_thread.h" -#include "parser.h" -#include "pcm_output.h" -#include "disk_buf.h" -#include "stream_mgr.h" - -#define LCD_ENABLE_EVENT_0 MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0) -#define LCD_ENABLE_EVENT_1 MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 1) - -#ifdef PLUGIN_USE_IRAM -/* IRAM preserving mechanism to enable talking menus */ -extern void mpegplayer_iram_preserve(void); -extern void mpegplayer_iram_restore(void); -#endif - -#endif /* MPEGPLAYER_H */ diff --git a/apps/plugins/mpegplayer/mpegplayer.make b/apps/plugins/mpegplayer/mpegplayer.make deleted file mode 100644 index af2156787e..0000000000 --- a/apps/plugins/mpegplayer/mpegplayer.make +++ /dev/null @@ -1,32 +0,0 @@ -# __________ __ ___. -# Open \______ \ ____ ____ | | _\_ |__ _______ ___ -# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -# \/ \/ \/ \/ \/ -# $Id$ -# - -MPEGSRCDIR := $(APPSDIR)/plugins/mpegplayer -MPEGBUILDDIR := $(BUILDDIR)/apps/plugins/mpegplayer - -ROCKS += $(MPEGBUILDDIR)/mpegplayer.rock - -MPEG_SRC := $(call preprocess, $(MPEGSRCDIR)/SOURCES) -MPEG_OBJ := $(call c2obj, $(MPEG_SRC)) - -# add source files to OTHER_SRC to get automatic dependencies -OTHER_SRC += $(MPEG_SRC) - -# Set '-fgnu89-inline' if supported (GCCVER >= 4.1.3, GCCNUM > 401) -ifeq ($(shell expr $(GCCNUM) \> 401),1) - MPEGCFLAGS = $(PLUGINFLAGS) -fgnu89-inline -else - MPEGCFLAGS = $(PLUGINFLAGS) -endif - -$(MPEGBUILDDIR)/mpegplayer.rock: $(MPEG_OBJ) $(CODECDIR)/libmad-mpeg.a - -$(MPEGBUILDDIR)/%.o: $(MPEGSRCDIR)/%.c $(MPEGSRCDIR)/mpegplayer.make - $(SILENT)mkdir -p $(dir $@) - $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(MPEGCFLAGS) -c $< -o $@ diff --git a/apps/plugins/mpegplayer/parser.h b/apps/plugins/mpegplayer/parser.h deleted file mode 100644 index ba2181e98b..0000000000 --- a/apps/plugins/mpegplayer/parser.h +++ /dev/null @@ -1,103 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * AV parser inteface declarations - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef PARSER_H -#define PARSER_H - -enum stream_formats -{ - STREAM_FMT_UNKNOWN = -1, - STREAM_FMT_MPEG_TS, /* MPEG transport stream */ - STREAM_FMT_MPEG_PS, /* MPEG program stream */ - STREAM_FMT_MPV, /* MPEG Video only (1 or 2) */ - STREAM_FMT_MPA, /* MPEG Audio only */ -}; - -/* Structure used by a thread that handles a single demuxed data stream and - * receives commands from the stream manager */ -enum stream_parse_states -{ - /* Stream is... */ - SSTATE_SYNC, /* synchronizing by trying to find a start code */ - SSTATE_PARSE, /* parsing the stream looking for packets */ - SSTATE_END, /* at the end of data */ -}; - -enum stream_parse_mode -{ - STREAM_PM_STREAMING = 0, /* Next packet when streaming */ - STREAM_PM_RANDOM_ACCESS, /* Random-access parsing */ -}; - -enum stream_parser_flags -{ - STREAMF_CAN_SEEK = 0x1, /* Seeking possible for this stream */ -}; - -struct stream_parser -{ - /* Common generic parser data */ - enum stream_formats format; /* Stream format */ - uint32_t start_pts; /* The movie start time as represented by - the first audio PTS tag in the - stream converted to half minutes */ - uint32_t end_pts; /* The movie end time as represented by - the maximum audio PTS tag in the - stream converted to half minutes */ - uint32_t duration; /* Duration in PTS units */ - unsigned flags; /* Various attributes set at init */ - struct vo_ext dims; /* Movie dimensions in pixels */ - uint32_t last_seek_time; - int (*next_data)(struct stream *str, enum stream_parse_mode type); - union /* A place for reusable no-cache parameters */ - { - struct str_sync_data sd; - } parms; -}; - -extern struct stream_parser str_parser; - -/* MPEG parsing */ -uint8_t * mpeg_parser_scan_start_code(struct stream_scan *sk, uint32_t code); -unsigned mpeg_parser_scan_pes(struct stream_scan *sk); -uint32_t mpeg_parser_scan_scr(struct stream_scan *sk); -uint32_t mpeg_parser_scan_pts(struct stream_scan *sk, unsigned id); -off_t mpeg_stream_stream_seek_PTS(uint32_t time, int id); - -/* General parsing */ -bool parser_init(void); -void str_initialize(struct stream *str, off_t pos); -bool parser_prepare_image(uint32_t time); -bool parser_get_video_size(struct vo_ext *sz); -int parser_init_stream(void); -void parser_close_stream(void); -static inline bool parser_can_seek(void) - { return str_parser.flags & STREAMF_CAN_SEEK; } -uint32_t parser_seek_time(uint32_t time); -void parser_prepare_streaming(void); -void str_end_of_stream(struct stream *str); - -static inline int parser_get_next_data(struct stream *str, - enum stream_parse_mode type) - { return str_parser.next_data(str, type); } - -#endif /* PARSER_H */ diff --git a/apps/plugins/mpegplayer/pcm_output.c b/apps/plugins/mpegplayer/pcm_output.c deleted file mode 100644 index 5e95d16316..0000000000 --- a/apps/plugins/mpegplayer/pcm_output.c +++ /dev/null @@ -1,396 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * PCM output buffer definitions - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" - -/* PCM channel we're using */ -#define MPEG_PCM_CHANNEL PCM_MIXER_CHAN_PLAYBACK - -/* Pointers */ - -/* Start of buffer */ -static struct pcm_frame_header * ALIGNED_ATTR(4) pcm_buffer; -/* End of buffer (not guard) */ -static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_end; -/* Read pointer */ -static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_head IBSS_ATTR; -/* Write pointer */ -static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_tail IBSS_ATTR; - -/* Bytes */ -static ssize_t pcmbuf_curr_size IBSS_ATTR; /* Size of currently playing frame */ -static ssize_t pcmbuf_read IBSS_ATTR; /* Number of bytes read by DMA */ -static ssize_t pcmbuf_written IBSS_ATTR; /* Number of bytes written by source */ -static ssize_t pcmbuf_threshold IBSS_ATTR; /* Non-silence threshold */ - -/* Clock */ -static uint32_t clock_start IBSS_ATTR; /* Clock at playback start */ -static uint32_t volatile clock_tick IBSS_ATTR; /* Our base clock */ -static uint32_t volatile clock_time IBSS_ATTR; /* Timestamp adjusted */ - -static int pcm_skipped = 0; -static int pcm_underruns = 0; - -static unsigned int old_sampr = 0; - -/* Small silence clip. ~5.80ms @ 44.1kHz */ -static int16_t silence[256*2] ALIGNED_ATTR(4) = { 0 }; - -/* Delete all buffer contents */ -static void pcm_reset_buffer(void) -{ - pcmbuf_threshold = PCMOUT_PLAY_WM; - pcmbuf_curr_size = pcmbuf_read = pcmbuf_written = 0; - pcmbuf_head = pcmbuf_tail = pcm_buffer; - pcm_skipped = pcm_underruns = 0; -} - -/* Advance a PCM buffer pointer by size bytes circularly */ -static inline void pcm_advance_buffer(struct pcm_frame_header **p, - size_t size) -{ - *p = SKIPBYTES(*p, size); - if (*p >= pcmbuf_end) - *p = SKIPBYTES(*p, -PCMOUT_BUFSIZE); -} - -/* Return physical space used */ -static inline ssize_t pcm_output_bytes_used(void) -{ - return pcmbuf_written - pcmbuf_read; /* wrap-safe */ -} - -/* Return physical space free */ -static inline ssize_t pcm_output_bytes_free(void) -{ - return PCMOUT_BUFSIZE - pcm_output_bytes_used(); -} - -/* Audio DMA handler */ -static void get_more(const void **start, size_t *size) -{ - ssize_t sz; - - /* Free-up the last frame played frame if any */ - pcmbuf_read += pcmbuf_curr_size; - pcmbuf_curr_size = 0; - - sz = pcm_output_bytes_used(); - - if (sz > pcmbuf_threshold) - { - pcmbuf_threshold = PCMOUT_LOW_WM; - - while (1) - { - uint32_t time = pcmbuf_head->time; - int32_t offset = time - clock_time; - - sz = pcmbuf_head->size; - - if (sz < (ssize_t)(PCM_HDR_SIZE + 4) || - (sz & 3) != 0) - { - /* Just show a warning about this - will never happen - * without a corrupted buffer */ - DEBUGF("get_more: invalid size (%ld)\n", (long)sz); - } - - if (offset < -100*CLOCK_RATE/1000) - { - /* Frame more than 100ms late - drop it */ - pcm_advance_buffer(&pcmbuf_head, sz); - pcmbuf_read += sz; - pcm_skipped++; - if (pcm_output_bytes_used() > 0) - continue; - - /* Ran out so revert to default watermark */ - pcmbuf_threshold = PCMOUT_PLAY_WM; - pcm_underruns++; - } - else if (offset < 100*CLOCK_RATE/1000) - { - /* Frame less than 100ms early - play it */ - struct pcm_frame_header *head = pcmbuf_head; - - pcm_advance_buffer(&pcmbuf_head, sz); - pcmbuf_curr_size = sz; - - sz -= PCM_HDR_SIZE; - - /* Audio is time master - keep clock synchronized */ - clock_time = time + (sz >> 2); - - /* Update base clock */ - clock_tick += sz >> 2; - - *start = head->data; - *size = sz; - return; - } - /* Frame will be dropped - play silence clip */ - break; - } - } - else - { - /* Ran out so revert to default watermark */ - if (pcmbuf_threshold == PCMOUT_LOW_WM) - pcm_underruns++; - - pcmbuf_threshold = PCMOUT_PLAY_WM; - } - - /* Keep clock going at all times */ - clock_time += sizeof (silence) / 4; - clock_tick += sizeof (silence) / 4; - - *start = silence; - *size = sizeof (silence); - - if (sz < 0) - pcmbuf_read = pcmbuf_written; -} - -/** Public interface **/ - -/* Return a buffer pointer if at least size bytes are available and if so, - * give the actual free space */ -void * pcm_output_get_buffer(ssize_t *size) -{ - ssize_t sz = *size; - ssize_t free = pcm_output_bytes_free() - PCM_HDR_SIZE; - - if (sz >= 0 && free >= sz) - { - *size = free; /* return actual free space (- header) */ - return pcmbuf_tail->data; - } - - /* Leave *size alone so caller doesn't have to reinit */ - return NULL; -} - -/* Commit the buffer returned by pcm_ouput_get_buffer; timestamp is PCM - * clock time units, not video format time units */ -bool pcm_output_commit_data(ssize_t size, uint32_t timestamp) -{ - if (size <= 0 || (size & 3)) - return false; /* invalid */ - - size += PCM_HDR_SIZE; - - if (size > pcm_output_bytes_free()) - return false; /* too big */ - - pcmbuf_tail->size = size; - pcmbuf_tail->time = timestamp; - - pcm_advance_buffer(&pcmbuf_tail, size); - pcmbuf_written += size; - - return true; -} - -/* Returns 'true' if the buffer is completely empty */ -bool pcm_output_empty(void) -{ - return pcm_output_bytes_used() <= 0; -} - -/* Flushes the buffer - clock keeps counting */ -void pcm_output_flush(void) -{ - rb->pcm_play_lock(); - - enum channel_status status = rb->mixer_channel_status(MPEG_PCM_CHANNEL); - - /* Stop PCM to clear current buffer */ - if (status != CHANNEL_STOPPED) - rb->mixer_channel_stop(MPEG_PCM_CHANNEL); - - rb->pcm_play_unlock(); - - pcm_reset_buffer(); - - /* Restart if playing state was current */ - if (status == CHANNEL_PLAYING) - rb->mixer_channel_play_data(MPEG_PCM_CHANNEL, - get_more, NULL, 0); -} - -/* Seek the reference clock to the specified time - next audio data ready to - go to DMA should be on the buffer with the same time index or else the PCM - buffer should be empty */ -void pcm_output_set_clock(uint32_t time) -{ - rb->pcm_play_lock(); - - clock_start = time; - clock_tick = time; - clock_time = time; - - rb->pcm_play_unlock(); -} - -/* Return the clock as synchronized by audio frame timestamps */ -uint32_t pcm_output_get_clock(void) -{ - uint32_t time, rem; - - /* Reread if data race detected - rem will be 0 if driver hasn't yet - * updated to the new buffer size. Also be sure pcm state doesn't - * cause indefinite loop. - * - * FYI: NOT scrutinized for rd/wr reordering on different cores. */ - do - { - time = clock_time; - rem = rb->mixer_channel_get_bytes_waiting(MPEG_PCM_CHANNEL) >> 2; - } - while (UNLIKELY(time != clock_time || - (rem == 0 && - rb->mixer_channel_status(MPEG_PCM_CHANNEL) == CHANNEL_PLAYING)) - ); - - return time - rem; - -} - -/* Return the raw clock as counted from the last pcm_output_set_clock - * call */ -uint32_t pcm_output_get_ticks(uint32_t *start) -{ - uint32_t tick, rem; - - /* Same procedure as pcm_output_get_clock */ - do - { - tick = clock_tick; - rem = rb->mixer_channel_get_bytes_waiting(MPEG_PCM_CHANNEL) >> 2; - } - while (UNLIKELY(tick != clock_tick || - (rem == 0 && - rb->mixer_channel_status(MPEG_PCM_CHANNEL) == CHANNEL_PLAYING)) - ); - - if (start) - *start = clock_start; - - return tick - rem; -} - -/* Pauses/Starts pcm playback - and the clock */ -void pcm_output_play_pause(bool play) -{ - rb->pcm_play_lock(); - - if (rb->mixer_channel_status(MPEG_PCM_CHANNEL) != CHANNEL_STOPPED) - { - rb->mixer_channel_play_pause(MPEG_PCM_CHANNEL, play); - rb->pcm_play_unlock(); - } - else - { - rb->pcm_play_unlock(); - - if (play) - { - rb->mixer_channel_set_amplitude(MPEG_PCM_CHANNEL, MIX_AMP_UNITY); - rb->mixer_channel_play_data(MPEG_PCM_CHANNEL, - get_more, NULL, 0); - } - } -} - -/* Stops all playback and resets the clock */ -void pcm_output_stop(void) -{ - rb->pcm_play_lock(); - - if (rb->mixer_channel_status(MPEG_PCM_CHANNEL) != CHANNEL_STOPPED) - rb->mixer_channel_stop(MPEG_PCM_CHANNEL); - - rb->pcm_play_unlock(); - - pcm_output_flush(); - pcm_output_set_clock(0); -} - -/* Drains any data if the start threshold hasn't been reached */ -void pcm_output_drain(void) -{ - rb->pcm_play_lock(); - pcmbuf_threshold = PCMOUT_LOW_WM; - rb->pcm_play_unlock(); -} - -bool pcm_output_init(void) -{ - pcm_buffer = mpeg_malloc(PCMOUT_ALLOC_SIZE, MPEG_ALLOC_PCMOUT); - if (pcm_buffer == NULL) - return false; - - pcmbuf_end = SKIPBYTES(pcm_buffer, PCMOUT_BUFSIZE); - - pcm_reset_buffer(); - -#if INPUT_SRC_CAPS != 0 - /* Select playback */ - rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); - rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); -#endif - -#if SILENCE_TEST_TONE - /* Make the silence clip a square wave */ - const int16_t silence_amp = INT16_MAX / 16; - unsigned i; - - for (i = 0; i < ARRAYLEN(silence); i += 2) - { - if (i < ARRAYLEN(silence)/2) - { - silence[i] = silence_amp; - silence[i+1] = silence_amp; - } - else - { - silence[i] = -silence_amp; - silence[i+1] = -silence_amp; - } - } -#endif - - old_sampr = rb->mixer_get_frequency(); - rb->mixer_set_frequency(CLOCK_RATE); - rb->pcmbuf_fade(false, true); - return true; -} - -void pcm_output_exit(void) -{ - rb->pcmbuf_fade(false, false); - if (old_sampr != 0) - rb->mixer_set_frequency(old_sampr); -} diff --git a/apps/plugins/mpegplayer/pcm_output.h b/apps/plugins/mpegplayer/pcm_output.h deleted file mode 100644 index bae00cd045..0000000000 --- a/apps/plugins/mpegplayer/pcm_output.h +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * PCM output buffer declarations - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef PCM_OUTPUT_H -#define PCM_OUTPUT_H - -#define PCM_HDR_SIZE (sizeof (struct pcm_frame_header)) -struct pcm_frame_header /* Header added to pcm data every time a decoded - audio frame is sent out */ -{ - uint32_t size; /* size of this frame - including header */ - uint32_t time; /* timestamp for this frame in audio ticks */ - unsigned char data[]; /* open array of audio data */ -} ALIGNED_ATTR(4); - -bool pcm_output_init(void); -void pcm_output_exit(void); -void pcm_output_flush(void); -void pcm_output_set_clock(uint32_t time); -uint32_t pcm_output_get_clock(void); -uint32_t pcm_output_get_ticks(uint32_t *start); -void pcm_output_play_pause(bool play); -void pcm_output_stop(void); -void pcm_output_drain(void); -void * pcm_output_get_buffer(ssize_t *size); -bool pcm_output_commit_data(ssize_t size, uint32_t timestamp); -bool pcm_output_empty(void); - -#endif /* PCM_OUTPUT_H */ diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c deleted file mode 100644 index 3cac8c0f57..0000000000 --- a/apps/plugins/mpegplayer/stream_mgr.c +++ /dev/null @@ -1,1163 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * AV stream manager implementation - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" -#include "lib/grey.h" -#include "mpeg_settings.h" - -#ifndef HAVE_LCD_COLOR -GREY_INFO_STRUCT_IRAM -#endif - -static struct event_queue stream_mgr_queue SHAREDBSS_ATTR; -static struct queue_sender_list stream_mgr_queue_send SHAREDBSS_ATTR; -static uint32_t stream_mgr_thread_stack[DEFAULT_STACK_SIZE*2/sizeof(uint32_t)]; - -struct stream_mgr stream_mgr SHAREDBSS_ATTR; - -/* Forward decs */ -static int stream_on_close(void); - -struct str_broadcast_data -{ - long cmd; /* Command to send to stream */ - intptr_t data; /* Data to send with command */ -}; - -static inline void stream_mgr_lock(void) -{ - rb->mutex_lock(&stream_mgr.str_mtx); -} - -static inline void stream_mgr_unlock(void) -{ - rb->mutex_unlock(&stream_mgr.str_mtx); -} - -static inline void actl_lock(void) -{ - rb->mutex_lock(&stream_mgr.actl_mtx); -} - -static inline void actl_unlock(void) -{ - rb->mutex_unlock(&stream_mgr.actl_mtx); -} - -static inline void stream_mgr_post_msg(long id, intptr_t data) -{ - rb->queue_post(stream_mgr.q, id, data); -} - -static inline intptr_t stream_mgr_send_msg(long id, intptr_t data) -{ - return rb->queue_send(stream_mgr.q, id, data); -} - -static inline void stream_mgr_reply_msg(intptr_t retval) -{ - rb->queue_reply(stream_mgr.q, retval); -} - -int str_next_data_not_ready(struct stream *str) -{ - /* Save the current window since it actually might be ready by the time - * the registration is received by buffering. */ - off_t win_right = str->hdr.win_right; - - if (str->hdr.win_right < disk_buf.filesize - MIN_BUFAHEAD && - disk_buf.filesize > MIN_BUFAHEAD) - { - /* Set right edge to where probing left off + the minimum margin */ - str->hdr.win_right += MIN_BUFAHEAD; - } - else - { - /* Request would be passed the end of the file */ - str->hdr.win_right = disk_buf.filesize; - } - - switch (disk_buf_send_msg(DISK_BUF_DATA_NOTIFY, (intptr_t)str)) - { - case DISK_BUF_NOTIFY_OK: - /* Was ready - restore window and process */ - str->hdr.win_right = win_right; - return STREAM_OK; - - case DISK_BUF_NOTIFY_ERROR: - /* Error - quit parsing */ - str_end_of_stream(str); - return STREAM_DATA_END; - - default: - /* Not ready - go wait for notification from buffering. */ - str->pkt_flags = 0; - return STREAM_DATA_NOT_READY; - } -} - -void str_data_notify_received(struct stream *str) -{ - /* Normalize win_right back to the packet length */ - if (str->state == SSTATE_END) - return; - - if (str->curr_packet == NULL) - { - /* Nothing was yet parsed since init */ - str->hdr.win_right = str->hdr.win_left; - } - else - { - /* Restore window based upon current packet */ - str->hdr.win_right = str->hdr.win_left + - (str->curr_packet_end - str->curr_packet); - } -} - -/* Set stream manager to a "no-file" state */ -static void stream_mgr_init_state(void) -{ - stream_mgr.filename = NULL; - stream_mgr.resume_time = INVALID_TIMESTAMP; - stream_mgr.seeked = false; -} - -/* Add a stream to the playback pool */ -void stream_add_stream(struct stream *str) -{ - actl_lock(); - - list_remove_item(stream_mgr.strl, str); - list_add_item(stream_mgr.strl, str); - - actl_unlock(); -} - -/* Callback for various list-moving operations */ -static bool strl_enum_callback(struct stream *str, void *data) -{ - actl_lock(); - - list_remove_item(stream_mgr.strl, str); - - if (*(int*)data == 1) - list_add_item(stream_mgr.actl, str); - - actl_unlock(); - - return true; -} - -/* Clear all streams from active and playback pools */ -void stream_remove_streams(void) -{ - int add_item = 0; - list_enum_items(stream_mgr.strl, - (list_enum_callback_t)strl_enum_callback, (void *)&add_item); -} - -/* Move the playback pool to the active list */ -void move_strl_to_actl(void) -{ - int add_item = 1; - list_enum_items(stream_mgr.strl, - (list_enum_callback_t)strl_enum_callback, (void *)&add_item); -} - -/* Remove a stream from the active list and return it to the pool */ -static bool actl_stream_remove(struct stream *str) -{ - bool retval; - - actl_lock(); - - retval = list_remove_item(stream_mgr.actl, str); - - if (retval) - list_add_item(stream_mgr.strl, str); - - actl_unlock(); - - return retval; -} - -/* Broadcast a message to all active streams */ -static bool actl_stream_broadcast_callback(struct stream *str, - struct str_broadcast_data *sbd) -{ - switch (sbd->cmd) - { - case STREAM_PLAY: - case STREAM_PAUSE: - break; - - case STREAM_STOP: - if (sbd->data != 0) - { - actl_lock(); - - list_remove_item(stream_mgr.actl, str); - list_add_item(stream_mgr.strl, str); - - actl_unlock(); - sbd->data = 0; - } - break; - - default: - return false; - } - - str_send_msg(str, sbd->cmd, sbd->data); - return true; -} - -static void actl_stream_broadcast(int cmd, intptr_t data) -{ - struct str_broadcast_data sbd; - sbd.cmd = cmd; - sbd.data = data; - list_enum_items(stream_mgr.actl, - (list_enum_callback_t)actl_stream_broadcast_callback, - (void*)&sbd); -} - -/* Set the current base clock */ -static void set_stream_clock(uint32_t time) -{ - /* Fudge: Start clock 100ms early to allow for some filling time */ - if (time > 100*TS_SECOND/1000) - time -= 100*TS_SECOND/1000; - else - time = 0; - - pcm_output_set_clock(TS_TO_TICKS(time)); -} - -static void stream_start_playback(uint32_t time, bool fill_buffer) -{ - if (stream_mgr.seeked) - { - /* Clear any seeked status */ - stream_mgr.seeked = false; - - /* Flush old PCM data */ - pcm_output_flush(); - - /* Set the master clock */ - set_stream_clock(time); - - /* Make sure streams are back in active pool */ - move_strl_to_actl(); - - /* Prepare the parser and associated streams */ - parser_prepare_streaming(); - } - - /* Start buffer which optional force fill */ - disk_buf_send_msg(STREAM_PLAY, fill_buffer); - - /* Tell each stream to start - may generate end of stream signals - * now - we'll handle this when finished */ - actl_stream_broadcast(STREAM_PLAY, 0); - - /* Actually start the clock */ - pcm_output_play_pause(true); -} - -/* Return the play time relative to the specified play time */ -static uint32_t time_from_whence(uint32_t time, int whence) -{ - int64_t currtime; - uint32_t start; - - switch (whence) - { - case SEEK_SET: - /* Set the current time (time = unsigned offset from 0) */ - if (time > str_parser.duration) - time = str_parser.duration; - break; - case SEEK_CUR: - /* Seek forward or backward from the current time - * (time = signed offset from current) */ - currtime = stream_get_seek_time(&start); - currtime -= start; - currtime += (int32_t)time; - - if (currtime < 0) - currtime = 0; - else if ((uint64_t)currtime > str_parser.duration) - currtime = str_parser.duration; - - time = (uint32_t)currtime; - break; - case SEEK_END: - /* Seek from the end (time = unsigned offset from end) */ - if (time > str_parser.duration) - time = str_parser.duration; - time = str_parser.duration - time; - break; - } - - return time; -} - -/* Handle seeking details if playing or paused */ -static uint32_t stream_seek_intl(uint32_t time, int whence, - int status, bool *was_buffering) -{ - if (status != STREAM_STOPPED) - { - bool wb; - - /* Place streams in a non-running state - keep them on actl if - * still there */ - actl_stream_broadcast(STREAM_PAUSE, 0); - - /* Stop all buffering or else risk clobbering random-access data */ - wb = disk_buf_send_msg(STREAM_STOP, 0); - - if (was_buffering != NULL) - *was_buffering = wb; - } - - time = time_from_whence(time, whence); - - stream_mgr.seeked = true; - - return parser_seek_time(time); -} - -/* Store the resume time at the last seek/current clock point */ -static void stream_remember_resume_time(void) -{ - /* Assume invalidity */ - stream_mgr.resume_time = 0; - - if (stream_can_seek()) - { - /* Read the current stream time or the last seeked position */ - uint32_t start; - uint32_t time = stream_get_seek_time(&start); - - if (time >= str_parser.start_pts && time <= str_parser.end_pts) - { - /* Save the current stream time */ - stream_mgr.resume_time = time - start; - } - } -} - -/* Handle STREAM_OPEN */ -void stream_on_open(const char *filename) -{ - int err = STREAM_ERROR; - - stream_mgr_lock(); - - trigger_cpu_boost(); - - /* Open the video file */ - if (disk_buf_open(filename) >= 0) - { - /* Initialize the parser */ - err = parser_init_stream(); - - if (err >= STREAM_OK) - { - /* File ok - save the opened filename */ - stream_mgr.filename = filename; - } - } - - /* If error - cleanup */ - if (err < STREAM_OK) - stream_on_close(); - - cancel_cpu_boost(); - - stream_mgr_unlock(); - - stream_mgr_reply_msg(err); -} - -/* Handler STREAM_PLAY */ -static void stream_on_play(void) -{ - int status = stream_mgr.status; - - stream_mgr_lock(); - - if (status == STREAM_STOPPED) - { - uint32_t start; - - /* We just say we're playing now */ - stream_mgr.status = STREAM_PLAYING; - - /* Reply with previous state */ - stream_mgr_reply_msg(status); - - trigger_cpu_boost(); - - /* Seek to initial position and set clock to that time */ - - /* Save the resume time */ - stream_remember_resume_time(); - - /* Prepare seek to start point */ - start = stream_seek_intl(stream_mgr.resume_time, SEEK_SET, - STREAM_STOPPED, NULL); - - /* Sync and start - force buffer fill */ - stream_start_playback(start, true); - } - else - { - /* Reply with previous state */ - stream_mgr_reply_msg(status); - } - - stream_mgr_unlock(); -} - -/* Handle STREAM_PAUSE */ -static void stream_on_pause(void) -{ - int status = stream_mgr.status; - - stream_mgr_lock(); - - /* Reply with previous state */ - stream_mgr_reply_msg(status); - - if (status == STREAM_PLAYING) - { - /* Pause the clock */ - pcm_output_play_pause(false); - - /* Pause each active stream */ - actl_stream_broadcast(STREAM_PAUSE, 0); - - /* Pause the disk buffer - buffer may continue filling */ - disk_buf_send_msg(STREAM_PAUSE, false); - - /* Unboost the CPU */ - cancel_cpu_boost(); - - /* Offically paused */ - stream_mgr.status = STREAM_PAUSED; - } - - stream_mgr_unlock(); -} - -/* Handle STREAM_RESUME */ -static void stream_on_resume(void) -{ - int status = stream_mgr.status; - - stream_mgr_lock(); - - /* Reply with previous state */ - stream_mgr_reply_msg(status); - - if (status == STREAM_PAUSED) - { - /* Boost the CPU */ - trigger_cpu_boost(); - - /* Sync and start - no force buffering */ - stream_start_playback(str_parser.last_seek_time, false); - - /* Officially playing */ - stream_mgr.status = STREAM_PLAYING; - } - - stream_mgr_unlock(); -} - -/* Handle STREAM_STOP */ -static void stream_on_stop(bool reply) -{ - int status = stream_mgr.status; - - stream_mgr_lock(); - - if (reply) - stream_mgr_reply_msg(status); - - if (status != STREAM_STOPPED) - { - /* Pause the clock */ - pcm_output_play_pause(false); - - /* Update the resume time info */ - stream_remember_resume_time(); - - /* Not stopped = paused or playing */ - stream_mgr.seeked = false; - - /* Stop buffering */ - disk_buf_send_msg(STREAM_STOP, 0); - - /* Clear any still-active streams and remove from actl */ - actl_stream_broadcast(STREAM_STOP, 1); - - /* Stop PCM output (and clock) */ - pcm_output_stop(); - - /* Cancel our processor boost */ - cancel_cpu_boost(); - - stream_mgr.status = STREAM_STOPPED; - } - - stream_mgr_unlock(); -} - -/* Handle STREAM_SEEK */ -static void stream_on_seek(struct stream_seek_data *skd) -{ - uint32_t time = skd->time; - int whence = skd->whence; - - switch (whence) - { - case SEEK_SET: - case SEEK_CUR: - case SEEK_END: - if (stream_mgr.filename == NULL) - break; - - /* Keep things spinning if already doing so */ - stream_keep_disk_active(); - - /* Have data - reply in order to acquire lock */ - stream_mgr_reply_msg(STREAM_OK); - - stream_mgr_lock(); - - /* Either seeking must be possible or a full rewind must be done */ - if (stream_can_seek() || time_from_whence(time, whence) == 0) - { - bool buffer = false; - - if (stream_mgr.status == STREAM_PLAYING) - { - /* Keep clock from advancing while seeking */ - pcm_output_play_pause(false); - } - - time = stream_seek_intl(time, whence, stream_mgr.status, &buffer); - stream_remember_resume_time(); - - if (stream_mgr.status == STREAM_PLAYING) - { - /* Sync and restart - no force buffering */ - stream_start_playback(time, buffer); - } - } - - stream_mgr_unlock(); - return; - } - - /* Invalid parameter or no file */ - stream_mgr_reply_msg(STREAM_ERROR); -} - -/* Handle STREAM_CLOSE */ -static int stream_on_close(void) -{ - int status = STREAM_STOPPED; - - stream_mgr_lock(); - - /* Any open file that was accepted for playback? */ - if (stream_mgr.filename != NULL) - { - /* Yes - hide video */ - stream_show_vo(false); - /* Stop any playback */ - status = stream_mgr.status; - stream_on_stop(false); - /* Tell parser file is finished */ - parser_close_stream(); - /* Reinitialize manager */ - stream_mgr_init_state(); - } - - /* Let disk buffer reset itself - file might be open even if no good */ - disk_buf_close(); - - stream_mgr_unlock(); - - return status; -} - -/* Handle STREAM_EV_COMPLETE */ -static void stream_on_ev_complete(struct stream *str) -{ - stream_mgr_lock(); - - /* Stream is active? */ - if (actl_stream_remove(str)) - { - /* No - remove this stream from the active list */ - DEBUGF(" finished: 0x%02x\n", str->id); - if (list_is_empty(stream_mgr.actl)) - { - /* All streams have acked - stop playback */ - stream_on_stop(false); - stream_mgr.resume_time = 0; /* Played to end - no resume */ - } - else - { - /* Stream is done - stop it and place back in pool */ - str_send_msg(str, STREAM_STOP, 1); - } - } - - stream_mgr_unlock(); -} - -/* Callback for stream to notify about events internal to them */ -void stream_generate_event(struct stream *str, long id, intptr_t data) -{ - if (str == NULL) - return; - - switch (id) - { - case STREAM_EV_COMPLETE: - /* The last stream has ended */ - stream_mgr_post_msg(STREAM_EV_COMPLETE, (intptr_t)str); - break; - } - - (void)data; -} - -/* Clear any particular notification for which a stream registered */ -void stream_clear_notify(struct stream *str, int for_msg) -{ - switch (for_msg) - { - case DISK_BUF_DATA_NOTIFY: - disk_buf_send_msg(DISK_BUF_CLEAR_DATA_NOTIFY, (intptr_t)str); - break; - } -} - -/* Special handling for certain messages since they involve multiple - * operations behind the scenes */ -static intptr_t send_video_msg(long id, intptr_t data) -{ - intptr_t retval = 0; - - if (video_str.thread != 0 && disk_buf.in_file >= 0) - { - - switch (id) - { - case VIDEO_DISPLAY_SHOW: - if (data != 0 && disk_buf_status() == STREAM_STOPPED) - { /* Only prepare image if showing and not playing */ - parser_prepare_image(str_parser.last_seek_time); - } - break; - - case VIDEO_PRINT_FRAME: - if (data) - break; - case VIDEO_PRINT_THUMBNAIL: - if (disk_buf_status() != STREAM_STOPPED) - break; /* Prepare image if not playing */ - - /* Ignore return and try video thread anyway */ - parser_prepare_image(str_parser.last_seek_time); - - /* Image ready - pass message to video thread */ - break; - } - - retval = str_send_msg(&video_str, id, data); - } - - return retval; -} - -/* Show/hide the video output */ -bool stream_show_vo(bool show) -{ - bool vis; - stream_mgr_lock(); - - vis = send_video_msg(VIDEO_DISPLAY_SHOW, show); -#ifndef HAVE_LCD_COLOR - grey_show(show); -#endif - stream_mgr_unlock(); - - return vis; -} - -/* Query the visibility of video output */ -bool stream_vo_is_visible(void) -{ - bool vis; - stream_mgr_lock(); - vis = send_video_msg(VIDEO_DISPLAY_IS_VISIBLE, 0); - stream_mgr_unlock(); - return vis; -} - -/* Return the video dimensions */ -bool stream_vo_get_size(struct vo_ext *sz) -{ - bool retval = false; - - stream_mgr_lock(); - - if (str_parser.dims.w > 0 && str_parser.dims.h > 0) - { - *sz = str_parser.dims; - retval = true; - } - - stream_mgr_unlock(); - - return retval; -} - -void stream_vo_set_clip(const struct vo_rect *rc) -{ - stream_mgr_lock(); - - if (rc) - { - stream_mgr.parms.rc = *rc; - rc = &stream_mgr.parms.rc; - } - - send_video_msg(VIDEO_SET_CLIP_RECT, (intptr_t)rc); - - stream_mgr_unlock(); -} - -bool stream_vo_get_clip(struct vo_rect *rc) -{ - bool retval; - - if (!rc) - return false; - - stream_mgr_lock(); - - retval = send_video_msg(VIDEO_GET_CLIP_RECT, - (intptr_t)&stream_mgr.parms.rc); - - *rc = stream_mgr.parms.rc; - - stream_mgr_unlock(); - - return retval; -} - -#ifndef HAVE_LCD_COLOR -/* Show/hide the gray video overlay (independently of vo visibility). */ -void stream_gray_show(bool show) -{ - stream_mgr_lock(); - - grey_show(show); - - stream_mgr_unlock(); -} - -#endif /* !HAVE_LCD_COLOR */ - -/* Display a thumbnail at the last seek point */ -bool stream_display_thumb(const struct vo_rect *rc) -{ - bool retval; - - if (rc == NULL) - return false; - - stream_mgr_lock(); - - stream_mgr.parms.rc = *rc; - retval = send_video_msg(VIDEO_PRINT_THUMBNAIL, - (intptr_t)&stream_mgr.parms.rc); - - stream_mgr_unlock(); - - return retval; -} - -bool stream_draw_frame(bool no_prepare) -{ - bool retval; - stream_mgr_lock(); - - retval = send_video_msg(VIDEO_PRINT_FRAME, no_prepare); - - stream_mgr_unlock(); - - return retval; -} - -bool stream_set_callback(long id, void *fn) -{ - bool retval = false; - - stream_mgr_lock(); - - switch (id) - { - case VIDEO_SET_POST_FRAME_CALLBACK: - retval = send_video_msg(id, (intptr_t)fn); - } - - stream_mgr_unlock(); - - return retval; -} - -/* Return the time playback should resume if interrupted */ -uint32_t stream_get_resume_time(void) -{ - uint32_t resume_time; - - /* A stop request is async and replies before setting this - must lock */ - stream_mgr_lock(); - - resume_time = stream_mgr.resume_time; - - stream_mgr_unlock(); - - return resume_time; -} - -uint32_t stream_get_seek_time(uint32_t *start) -{ - uint32_t time; - - stream_mgr_lock(); - - if (stream_mgr.seeked) - { - time = str_parser.last_seek_time; - } - else - { - time = TICKS_TO_TS(pcm_output_get_clock()); - - /* Clock can be start early so keep in range */ - if (time < str_parser.start_pts) - time = str_parser.start_pts; - } - - if (start != NULL) - *start = str_parser.start_pts; - - stream_mgr_unlock(); - - return time; -} - -/* Wait for a state transistion to complete */ -void stream_wait_status(void) -{ - stream_mgr_lock(); - stream_mgr_unlock(); -} - -/* Returns the smallest file window that includes all active streams' - * windows */ -static bool stream_get_window_callback(struct stream *str, - struct stream_window *sw) -{ - off_t swl = str->hdr.win_left; - off_t swr = str->hdr.win_right; - - if (swl < sw->left) - sw->left = swl; - - if (swr > sw->right) - sw->right = swr; - - return true; -} - -bool stream_get_window(struct stream_window *sw) -{ - if (sw == NULL) - return false; - - sw->left = LONG_MAX; - sw->right = LONG_MIN; - - actl_lock(); - list_enum_items(stream_mgr.actl, - (list_enum_callback_t)stream_get_window_callback, - (void*)sw); - actl_unlock(); - - return sw->left <= sw->right; -} - -/* Playback control thread */ -static void stream_mgr_thread(void) -{ - struct queue_event ev; - - while (1) - { - rb->queue_wait(stream_mgr.q, &ev); - - switch (ev.id) - { - case STREAM_OPEN: - stream_on_open((const char *)ev.data); - break; - - case STREAM_CLOSE: - stream_on_close(); - break; - - case STREAM_PLAY: - stream_on_play(); - break; - - case STREAM_PAUSE: - if (ev.data) - stream_on_resume(); - else - stream_on_pause(); - break; - - case STREAM_STOP: - stream_on_stop(true); - break; - - case STREAM_SEEK: - stream_on_seek((struct stream_seek_data *)ev.data); - break; - - case STREAM_EV_COMPLETE: - stream_on_ev_complete((struct stream *)ev.data); - break; - - case STREAM_QUIT: - if (stream_mgr.status != STREAM_STOPPED) - stream_on_stop(false); - return; - } - } -} - -/* Stream command interface APIs */ - -/* Opens a new file */ -int stream_open(const char *filename) -{ - if (stream_mgr.thread != 0) - return stream_mgr_send_msg(STREAM_OPEN, (intptr_t)filename); - return STREAM_ERROR; -} - -/* Plays the current file starting at time 'start' */ -int stream_play(void) -{ - if (stream_mgr.thread != 0) - return stream_mgr_send_msg(STREAM_PLAY, 0); - return STREAM_ERROR; -} - -/* Pauses playback if playing */ -int stream_pause(void) -{ - if (stream_mgr.thread != 0) - return stream_mgr_send_msg(STREAM_PAUSE, false); - return STREAM_ERROR; -} - -/* Resumes playback if paused */ -int stream_resume(void) -{ - if (stream_mgr.thread != 0) - return stream_mgr_send_msg(STREAM_PAUSE, true); - return STREAM_ERROR; -} - -/* Stops playback if not stopped */ -int stream_stop(void) -{ - if (stream_mgr.thread != 0) - return stream_mgr_send_msg(STREAM_STOP, 0); - return STREAM_ERROR; -} - -/* Seeks playback time to/by the specified time */ -int stream_seek(uint32_t time, int whence) -{ - int ret; - - if (stream_mgr.thread == 0) - return STREAM_ERROR; - - stream_mgr_lock(); - - stream_mgr.parms.skd.time = time; - stream_mgr.parms.skd.whence = whence; - - ret = stream_mgr_send_msg(STREAM_SEEK, (intptr_t)&stream_mgr.parms.skd); - - stream_mgr_unlock(); - - return ret; -} - -/* Closes the current file */ -int stream_close(void) -{ - if (stream_mgr.thread != 0) - return stream_mgr_send_msg(STREAM_CLOSE, 0); - return STREAM_ERROR; -} - -/* Initializes the playback engine */ -int stream_init(void) -{ - void *mem; - size_t memsize; - - stream_mgr.status = STREAM_STOPPED; - stream_mgr_init_state(); - - /* Initialize our window to the outside world first */ - rb->mutex_init(&stream_mgr.str_mtx); - rb->mutex_init(&stream_mgr.actl_mtx); - - stream_mgr.q = &stream_mgr_queue; - rb->queue_init(stream_mgr.q, false); - - /* sets audiosize and returns buffer pointer */ - mem = rb->plugin_get_audio_buffer(&memsize); - - /* Initialize non-allocator blocks first */ -#ifndef HAVE_LCD_COLOR - long greysize; - - /* Greylib init handles all necessary cache alignment */ - if (!grey_init(mem, memsize, GREY_BUFFERED|GREY_ON_COP, - LCD_WIDTH, LCD_HEIGHT, &greysize)) - { - rb->splash(HZ, "greylib init failed!"); - return STREAM_ERROR; - } - - mem += greysize; - memsize -= greysize; - - grey_clear_display(); -#endif /* !HAVE_LCD_COLOR */ - - stream_mgr.thread = rb->create_thread(stream_mgr_thread, - stream_mgr_thread_stack, sizeof(stream_mgr_thread_stack), - 0, "mpgstream_mgr" IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU)); - - rb->queue_enable_queue_send(stream_mgr.q, &stream_mgr_queue_send, - stream_mgr.thread); - - if (stream_mgr.thread == 0) - { - rb->splash(HZ, "Could not create stream manager thread!"); - return STREAM_ERROR; - } - - /* Wait for thread to initialize */ - stream_mgr_send_msg(STREAM_NULL, 0); - - /* Initialise our malloc buffer */ - if (!mpeg_alloc_init(mem, memsize)) - { - rb->splash(HZ, "Out of memory in stream_init"); - } - /* These inits use the allocator */ - else if (!pcm_output_init()) - { - rb->splash(HZ, "Could not initialize PCM!"); - } - else if (!audio_thread_init()) - { - rb->splash(HZ, "Cannot create audio thread!"); - } - else if (!video_thread_init()) - { - rb->splash(HZ, "Cannot create video thread!"); - } - /* Disk buffer takes max allotment of what's left so it must be last */ - else if (!disk_buf_init()) - { - rb->splash(HZ, "Cannot create buffering thread!"); - } - else if (!parser_init()) - { - rb->splash(HZ, "Parser init failed!"); - } - else - { - return STREAM_OK; - } - - return STREAM_ERROR; -} - -/* Cleans everything up */ -void stream_exit(void) -{ - stream_close(); - - /* Stop the threads and wait for them to terminate */ - video_thread_exit(); - audio_thread_exit(); - disk_buf_exit(); - pcm_output_exit(); - - if (stream_mgr.thread != 0) - { - stream_mgr_post_msg(STREAM_QUIT, 0); - rb->thread_wait(stream_mgr.thread); - stream_mgr.thread = 0; - } - -#ifndef HAVE_LCD_COLOR - grey_release(); -#endif -} diff --git a/apps/plugins/mpegplayer/stream_mgr.h b/apps/plugins/mpegplayer/stream_mgr.h deleted file mode 100644 index 7dba9acc09..0000000000 --- a/apps/plugins/mpegplayer/stream_mgr.h +++ /dev/null @@ -1,168 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * AV stream manager decalarations - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef STREAM_MGR_H -#define STREAM_MGR_H - -/* Basic media control interface - this handles state changes and stream - * coordination with assistance from the parser */ -struct stream_mgr -{ - unsigned int thread; /* Playback control thread */ - struct event_queue *q; /* event queue for control thread */ - const char *filename; /* Current filename */ - uint32_t resume_time; /* The stream tick where playback was - stopped (or started) */ - bool seeked; /* A seek happened and things must be - resynced */ - int status; /* Current playback status */ - void *strl[MPEGPLAYER_MAX_STREAMS+1]; /* List of available streams */ - void *actl[MPEGPLAYER_MAX_STREAMS+1]; /* List of active streams */ - struct mutex str_mtx; /* Main stream manager mutex */ - struct mutex actl_mtx; /* Lock for current-streams list */ - union /* A place for reusable non-cacheable parameters */ - { - struct vo_rect rc; - struct stream_seek_data skd; - } parms; -}; - -extern struct stream_mgr stream_mgr SHAREDBSS_ATTR; - -struct stream_window -{ - off_t left, right; -}; - -/** Interface for use by streams and other internal objects **/ -bool stream_get_window(struct stream_window *sw); -void stream_clear_notify(struct stream *str, int for_msg); -int str_next_data_not_ready(struct stream *str); -/* Called by a stream to say it got its buffering notification */ -void str_data_notify_received(struct stream *str); -void stream_add_stream(struct stream *str); -void stream_remove_streams(void); - -enum stream_events -{ - __STREAM_EV_FIRST = STREAM_MESSAGE_LAST-1, - STREAM_EV_COMPLETE, -}; - -void stream_generate_event(struct stream *str, long id, intptr_t data); - -/** Main control functions **/ - -/* Initialize the playback engine */ -int stream_init(void); - -/* Close the playback engine */ -void stream_exit(void); - -/* Open a new file */ -int stream_open(const char *filename); - -/* Close the current file */ -int stream_close(void); - -/* Plays from the current seekpoint if stopped */ -int stream_play(void); - -/* Pauses playback if playing */ -int stream_pause(void); - -/* Resumes playback if paused */ -int stream_resume(void); - -/* Stops all streaming activity if playing or paused */ -int stream_stop(void); - -/* Point stream at a particular time. - * whence = one of SEEK_SET, SEEK_CUR, SEEK_END */ -int stream_seek(uint32_t time, int whence); - -/* Show/Hide the video image at the current seekpoint */ -bool stream_show_vo(bool show); - -/* Set the visible section of video */ -void stream_vo_set_clip(const struct vo_rect *rc); - -/* Return current visible section of video */ -bool stream_vo_get_clip(struct vo_rect *rc); - -#ifndef HAVE_LCD_COLOR -void stream_gray_show(bool show); -#endif - -/* Display thumbnail of the current seekpoint */ -bool stream_display_thumb(const struct vo_rect *rc); - -/* Draw the frame at the current position */ -bool stream_draw_frame(bool no_prepare); - -/* Return video dimensions */ -bool stream_vo_get_size(struct vo_ext *sz); - -/* Returns the resume time in timestamp ticks */ -uint32_t stream_get_resume_time(void); - -/* Returns stream_get_time if no seek is pending or else the - last time give to seek */ -uint32_t stream_get_seek_time(uint32_t *start); - -/* Return the absolute stream time in clock ticks - adjusted by - * master clock stream via audio timestamps */ -static inline uint32_t stream_get_time(void) - { return pcm_output_get_clock(); } - -/* Return the absolute clock time in clock ticks - unadjusted */ -static inline uint32_t stream_get_ticks(uint32_t *start) - { return pcm_output_get_ticks(start); } - -/* Returns the current playback status */ -static inline int stream_status(void) - { return stream_mgr.status; } - -/* Wait for a state transistion to complete */ -void stream_wait_status(void); - -/* Returns the playback length of the stream */ -static inline uint32_t stream_get_duration(void) - { return str_parser.duration; } - -static inline bool stream_can_seek(void) - { return parser_can_seek(); } - -static inline void stream_video_stats(struct video_output_stats *s) - { video_thread_get_stats(s); } - -bool stream_set_callback(long id, void * fn); - -/* Keep the disk spinning (for seeking and browsing) */ -static inline void stream_keep_disk_active(void) -{ -#ifdef HAVE_DISK_STORAGE - rb->storage_spin(); -#endif - } - -#endif /* STREAM_MGR_H */ diff --git a/apps/plugins/mpegplayer/stream_thread.h b/apps/plugins/mpegplayer/stream_thread.h deleted file mode 100644 index dfa6e8c9a1..0000000000 --- a/apps/plugins/mpegplayer/stream_thread.h +++ /dev/null @@ -1,201 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Declarations for stream-specific threading - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef STREAM_THREAD_H -#define STREAM_THREAD_H - -#define PKT_HAS_TS 0x1 - -/* Stream header which is the minimum to receive asynchronous buffering - * notifications. - * Layed-out to allow streaming access after random-access parsing */ -struct stream_hdr -{ - struct event_queue *q; /* Communication queue - separate to allow it - to be placed in another section */ - off_t win_left; /* Left position within data stream */ - union - { - off_t win_right; /* Right position within data stream */ - off_t pos; /* Start/current position for random-access read */ - }; - off_t limit; /* Limit for random-access read */ -}; - -struct stream -{ - struct stream_hdr hdr; /* Base stream data */ - unsigned int thread; /* Stream's thread */ - uint8_t* curr_packet; /* Current stream packet beginning */ - uint8_t* curr_packet_end; /* Current stream packet end */ - int state; /* State machine parsing mode */ - uint32_t start_pts; /* First timestamp for stream */ - uint32_t end_pts; /* Last timestamp for stream */ - uint32_t pts; /* Last presentation timestamp */ - uint32_t pkt_flags; /* PKT_* flags */ - unsigned id; /* Stream identifier */ -}; - -#define STR_FROM_HDR(sh) ((struct stream *)(sh)) - -/* Make sure there there is always enough data buffered ahead for - * the worst possible case - regardless of whether a valid stream - * would actually produce that */ -#define MIN_BUFAHEAD (21+65535+6+65535+6) /* 131103 */ - -/* States that a stream's thread assumes internally */ -enum thread_states -{ - /* Stream thread... */ - TSTATE_INIT = 0, /* is initialized and primed */ - TSTATE_DATA, /* is awaiting data to be available */ - TSTATE_BUFFERING, /* is buffering data */ - TSTATE_EOS, /* has hit the end of data */ - TSTATE_DECODE, /* is in a decoding state */ - TSTATE_RENDER, /* is in a rendering state */ - TSTATE_RENDER_WAIT, /* is waiting to render */ -}; - -/* Commands that streams respond to */ -enum stream_message -{ - STREAM_NULL = 0, /* A NULL message for whatever reason - - usually ignored */ - STREAM_PLAY, /* Start playback at current position */ - STREAM_PAUSE, /* Stop playing and await further commands */ - STREAM_RESET, /* Reset the stream for a discontinuity */ - STREAM_STOP, /* Stop stream - requires a reset later */ - STREAM_SEEK, /* Seek the current stream to a new location */ - STREAM_OPEN, /* Open a new file */ - STREAM_CLOSE, /* Close the current file */ - STREAM_QUIT, /* Exit the stream and thread */ - STREAM_NEEDS_SYNC, /* Need to sync before stream decoding? */ - STREAM_SYNC, /* Sync to the specified time from some key point */ - STREAM_FIND_END_TIME, /* Get the exact end time of an elementary - * stream - ie. time just after last frame is finished */ - /* Disk buffer */ - STREAM_DISK_BUF_FIRST, - DISK_BUF_DATA_NOTIFY = STREAM_DISK_BUF_FIRST, - DISK_BUF_CLEAR_DATA_NOTIFY, /* Cancel pending data notification */ - DISK_BUF_CACHE_RANGE, /* Cache a range of the file in the buffer */ - /* Audio stream */ - STREAM_AUDIO_FIRST, - /* Video stream */ - STREAM_VIDEO_FIRST, - VIDEO_DISPLAY_SHOW = STREAM_VIDEO_FIRST, /* Show/hide video output */ - VIDEO_DISPLAY_IS_VISIBLE, /* Is the video output visible? */ - VIDEO_GET_SIZE, /* Get the video dimensions */ - VIDEO_PRINT_FRAME, /* Print the frame at the current position */ - VIDEO_PRINT_THUMBNAIL, /* Print a thumbnail of the current position */ - VIDEO_SET_CLIP_RECT, /* Set the visible video area */ - VIDEO_GET_CLIP_RECT, /* Return the visible video area */ - VIDEO_SET_POST_FRAME_CALLBACK, /* Set a callback after frame is drawn */ - STREAM_MESSAGE_LAST, -}; - -/* Data parameter for STREAM_SEEK */ -struct stream_seek_data -{ - uint32_t time; /* Time to seek to/by */ - int whence; /* Specification of relationship to current position/file */ -}; - -/* Data parameter for STREAM_SYNC */ -struct str_sync_data -{ - uint32_t time; /* Time to sync to */ - struct stream_scan sk; /* Specification of start/limits/direction */ -}; - -/* Stream status codes - not eqivalent to thread states */ -enum stream_status -{ - /* Stream status is... */ - STREAM_DATA_END = -4, /* Stream has ended */ - STREAM_DATA_NOT_READY = -3, /* Data was not available yet */ - STREAM_UNSUPPORTED = -2, /* Format is unsupported */ - STREAM_ERROR = -1, /* some kind of error - quit it or reset it */ - STREAM_OK = 0, /* General inequality for success >= is OK, < error */ - STREAM_STOPPED = 0, /* stopped and awaiting commands - send STREAM_INIT */ - STREAM_PLAYING, /* playing and rendering its data */ - STREAM_PAUSED, /* paused and awaiting commands */ - /* Other status codes (> STREAM_OK) */ - STREAM_MATCH, /* A good match was found */ - STREAM_PERFECT_MATCH, /* Exactly what was wanted was found or - no better match is possible */ - STREAM_NOT_FOUND, /* Match not found */ -}; - -/* Clip time to range for a particular stream */ -static inline uint32_t clip_time(struct stream *str, uint32_t time) -{ - if (time < str->start_pts) - time = str->start_pts; - else if (time >= str->end_pts) - time = str->end_pts; - - return time; -} - -extern struct stream video_str IBSS_ATTR; -extern struct stream audio_str IBSS_ATTR; - -bool video_thread_init(void); -void video_thread_exit(void); - -struct video_output_stats -{ - int num_drawn; /* Number of frames drawn since reset */ - int num_skipped; /* Number of frames skipped since reset */ - int fps; /* fps rate in 100ths of a frame per second */ -}; - -void video_thread_get_stats(struct video_output_stats *s); - -bool audio_thread_init(void); -void audio_thread_exit(void); - - -/* Some queue function wrappers to keep things clean-ish */ - -/* For stream use only */ -static inline bool str_have_msg(struct stream *str) - { return !rb->queue_empty(str->hdr.q); } - -static inline void str_get_msg(struct stream *str, struct queue_event *ev) - { rb->queue_wait(str->hdr.q, ev); } - -static inline void str_get_msg_w_tmo(struct stream *str, struct queue_event *ev, - int timeout) - { rb->queue_wait_w_tmo(str->hdr.q, ev, timeout); } - -static inline void str_reply_msg(struct stream *str, intptr_t reply) - { rb->queue_reply(str->hdr.q, reply); } - -/* Public use */ -static inline intptr_t str_send_msg(struct stream *str, long id, intptr_t data) - { return rb->queue_send(str->hdr.q, id, data); } - -static inline void str_post_msg(struct stream *str, long id, intptr_t data) - { rb->queue_post(str->hdr.q, id, data); } - -#endif /* STREAM_THREAD_H */ diff --git a/apps/plugins/mpegplayer/video_out.h b/apps/plugins/mpegplayer/video_out.h deleted file mode 100644 index 2a3364c382..0000000000 --- a/apps/plugins/mpegplayer/video_out.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * video_out.h - * Copyright (C) 2000-2003 Michel Lespinasse - * Copyright (C) 1999-2000 Aaron Holtzman - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * See http://libmpeg2.sourceforge.net/ for updates. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - * libmpeg2 sync history: - * 2008-07-01 - CVS revision 1.22 - */ - -#ifndef VIDEO_OUT_H -#define VIDEO_OUT_H - -#if LCD_WIDTH >= LCD_HEIGHT -#define SCREEN_WIDTH LCD_WIDTH -#define SCREEN_HEIGHT LCD_HEIGHT -#define LCD_LANDSCAPE -#else /* Assume the screen is rotated on portrait LCDs */ -#define SCREEN_WIDTH LCD_HEIGHT -#define SCREEN_HEIGHT LCD_WIDTH -#define LCD_PORTRAIT -#endif - -/* Structure to hold width and height values */ -struct vo_ext -{ - int w, h; -}; - -/* Structure that defines a rectangle by its edges */ -struct vo_rect -{ - int l, t, r, b; -}; - -void vo_draw_frame (uint8_t * const * buf); -bool vo_draw_frame_thumb (uint8_t * const * buf, - const struct vo_rect *rc); -bool vo_init (void); -bool vo_show (bool show); -bool vo_is_visible(void); -void vo_setup (const mpeg2_sequence_t * sequence); -void vo_set_clip_rect(const struct vo_rect *rc); -bool vo_get_clip_rect(struct vo_rect *rc); -void vo_dimensions(struct vo_ext *sz); -void vo_cleanup (void); -void vo_set_post_draw_callback(void (*cb)(void)); - -#if NUM_CORES > 1 -void vo_lock(void); -void vo_unlock(void); -#else -static inline void vo_lock(void) {} -static inline void vo_unlock(void) {} -#endif - -/* Sets all coordinates of a vo_rect to 0 */ -void vo_rect_clear(struct vo_rect *rc); -/* Returns true if left >= right or top >= bottom */ -bool vo_rect_empty(const struct vo_rect *rc); -/* Initializes a vo_rect using upper-left corner and extents */ -void vo_rect_set_ext(struct vo_rect *rc, int x, int y, - int width, int height); -/* Query if two rectangles intersect - * If either are empty returns false */ -bool vo_rects_intersect(const struct vo_rect *rc1, - const struct vo_rect *rc2); - -/* Intersect two rectangles - * Resulting rectangle is placed in rc_dst. - * rc_dst is set to empty if they don't intersect. - * Empty source rectangles do not intersect any rectangle. - * rc_dst may be the same structure as rc1 or rc2. - * Returns true if the resulting rectangle is not empty. */ -bool vo_rect_intersect(struct vo_rect *rc_dst, - const struct vo_rect *rc1, - const struct vo_rect *rc2); - -bool vo_rect_union(struct vo_rect *rc_dst, - const struct vo_rect *rc1, - const struct vo_rect *rc2); - -void vo_rect_offset(struct vo_rect *rc, int dx, int dy); - -#endif /* VIDEO_OUT_H */ diff --git a/apps/plugins/mpegplayer/video_out_rockbox.c b/apps/plugins/mpegplayer/video_out_rockbox.c deleted file mode 100644 index 331383843b..0000000000 --- a/apps/plugins/mpegplayer/video_out_rockbox.c +++ /dev/null @@ -1,576 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * mpegplayer video output routines - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "libmpeg2/mpeg2dec_config.h" - -#include "plugin.h" -#include "mpegplayer.h" - -#define VO_NON_NULL_RECT 0x1 -#define VO_VISIBLE 0x2 - -struct vo_data -{ - int image_width; - int image_height; - int image_chroma_x; - int image_chroma_y; - int display_width; - int display_height; - int output_x; - int output_y; - int output_width; - int output_height; - unsigned flags; - struct vo_rect rc_vid; - struct vo_rect rc_clip; - void (*post_draw_callback)(void); -}; - -#if NUM_CORES > 1 -/* Cache aligned and padded to avoid clobbering other processors' cacheable - * data */ -static union { - uint8_t __vo_data[CACHEALIGN_UP(sizeof(struct vo_data))]; - struct vo_data vo; -} vo_raw CACHEALIGN_ATTR; -#define vo vo_raw.vo -#else -static struct vo_data vo; -#endif - -#if NUM_CORES > 1 -static struct mutex vo_mtx SHAREDBSS_ATTR; -#endif - -static inline void video_lock_init(void) -{ -#if NUM_CORES > 1 - rb->mutex_init(&vo_mtx); -#endif -} - -static inline void video_lock(void) -{ -#if NUM_CORES > 1 - rb->mutex_lock(&vo_mtx); -#endif -} - -static inline void video_unlock(void) -{ -#if NUM_CORES > 1 - rb->mutex_unlock(&vo_mtx); -#endif -} - - -/* Draw a black rectangle if no video frame is available */ -static void vo_draw_black(struct vo_rect *rc) -{ - int foreground; - int x, y, w, h; - - video_lock(); - - foreground = mylcd_get_foreground(); - - mylcd_set_foreground(MYLCD_BLACK); - - if (rc) - { - x = rc->l; - y = rc->t; - w = rc->r - rc->l; - h = rc->b - rc->t; - } - else - { -#if LCD_WIDTH >= LCD_HEIGHT - x = vo.output_x; - y = vo.output_y; - w = vo.output_width; - h = vo.output_height; -#else - x = LCD_WIDTH - vo.output_height - vo.output_y; - y = vo.output_x; - w = vo.output_height; - h = vo.output_width; -#endif - } - - mylcd_fillrect(x, y, w, h); - mylcd_update_rect(x, y, w, h); - - mylcd_set_foreground(foreground); - - video_unlock(); -} - -static inline void yuv_blit(uint8_t * const * buf, int src_x, int src_y, - int stride, int x, int y, int width, int height) -{ - video_lock(); - -#ifdef HAVE_LCD_COLOR - rb->lcd_blit_yuv(buf, src_x, src_y, stride, x, y , width, height); -#else - grey_ub_gray_bitmap_part(buf[0], src_x, src_y, stride, x, y, width, height); -#endif - - video_unlock(); -} - -void vo_draw_frame(uint8_t * const * buf) -{ - if ((vo.flags & (VO_NON_NULL_RECT | VO_VISIBLE)) != - (VO_NON_NULL_RECT | VO_VISIBLE)) - { - /* Frame is hidden - either by being set invisible or is clipped - * away - copout */ - DEBUGF("vo hidden\n"); - } - else if (buf == NULL) - { - /* No frame exists - draw black */ - vo_draw_black(NULL); - DEBUGF("vo no frame\n"); - } - else - { - yuv_blit(buf, 0, 0, vo.image_width, - vo.output_x, vo.output_y, vo.output_width, - vo.output_height); - } - - if (vo.post_draw_callback) - vo.post_draw_callback(); -} - -static inline void vo_rect_clear_inl(struct vo_rect *rc) -{ - rc->l = rc->t = rc->r = rc->b = 0; -} - -static inline bool vo_rect_empty_inl(const struct vo_rect *rc) -{ - return rc == NULL || rc->l >= rc->r || rc->t >= rc->b; -} - -static inline bool vo_rects_intersect_inl(const struct vo_rect *rc1, - const struct vo_rect *rc2) -{ - return !vo_rect_empty_inl(rc1) && - !vo_rect_empty_inl(rc2) && - rc1->l < rc2->r && rc1->r > rc2->l && - rc1->t < rc2->b && rc1->b > rc2->t; -} - -/* Sets all coordinates of a vo_rect to 0 */ -void vo_rect_clear(struct vo_rect *rc) -{ - vo_rect_clear_inl(rc); -} - -/* Returns true if left >= right or top >= bottom */ -bool vo_rect_empty(const struct vo_rect *rc) -{ - return vo_rect_empty_inl(rc); -} - -/* Initializes a vo_rect using upper-left corner and extents */ -void vo_rect_set_ext(struct vo_rect *rc, int x, int y, - int width, int height) -{ - rc->l = x; - rc->t = y; - rc->r = x + width; - rc->b = y + height; -} - -/* Query if two rectangles intersect */ -bool vo_rects_intersect(const struct vo_rect *rc1, - const struct vo_rect *rc2) -{ - return vo_rects_intersect_inl(rc1, rc2); -} - -/* Intersect two rectangles, placing the result in rc_dst */ -bool vo_rect_intersect(struct vo_rect *rc_dst, - const struct vo_rect *rc1, - const struct vo_rect *rc2) -{ - if (rc_dst != NULL) - { - if (vo_rects_intersect_inl(rc1, rc2)) - { - rc_dst->l = MAX(rc1->l, rc2->l); - rc_dst->r = MIN(rc1->r, rc2->r); - rc_dst->t = MAX(rc1->t, rc2->t); - rc_dst->b = MIN(rc1->b, rc2->b); - return true; - } - - vo_rect_clear_inl(rc_dst); - } - - return false; -} - -bool vo_rect_union(struct vo_rect *rc_dst, - const struct vo_rect *rc1, - const struct vo_rect *rc2) -{ - if (rc_dst != NULL) - { - if (!vo_rect_empty_inl(rc1)) - { - if (!vo_rect_empty_inl(rc2)) - { - rc_dst->l = MIN(rc1->l, rc2->l); - rc_dst->t = MIN(rc1->t, rc2->t); - rc_dst->r = MAX(rc1->r, rc2->r); - rc_dst->b = MAX(rc1->b, rc2->b); - } - else - { - *rc_dst = *rc1; - } - - return true; - } - else if (!vo_rect_empty_inl(rc2)) - { - *rc_dst = *rc2; - return true; - } - - vo_rect_clear_inl(rc_dst); - } - - return false; -} - -void vo_rect_offset(struct vo_rect *rc, int dx, int dy) -{ - rc->l += dx; - rc->t += dy; - rc->r += dx; - rc->b += dy; -} - -/* Shink or stretch each axis - rotate counter-clockwise to retain upright - * orientation on rotated displays (they rotate clockwise) */ -void stretch_image_plane(const uint8_t * src, uint8_t *dst, int stride, - int src_w, int src_h, int dst_w, int dst_h) -{ - uint8_t *dst_end = dst + dst_w*dst_h; - -#if LCD_WIDTH >= LCD_HEIGHT - int src_w2 = src_w*2; /* 2x dimensions (for rounding before division) */ - int dst_w2 = dst_w*2; - int src_h2 = src_h*2; - int dst_h2 = dst_h*2; - int qw = src_w2 / dst_w2; /* src-dst width ratio quotient */ - int rw = src_w2 - qw*dst_w2; /* src-dst width ratio remainder */ - int qh = src_h2 / dst_h2; /* src-dst height ratio quotient */ - int rh = src_h2 - qh*dst_h2; /* src-dst height ratio remainder */ - int dw = dst_w; /* Width error accumulator */ - int dh = dst_h; /* Height error accumulator */ -#else - int src_w2 = src_w*2; - int dst_w2 = dst_h*2; - int src_h2 = src_h*2; - int dst_h2 = dst_w*2; - int qw = src_h2 / dst_w2; - int rw = src_h2 - qw*dst_w2; - int qh = src_w2 / dst_h2; - int rh = src_w2 - qh*dst_h2; - int dw = dst_h; - int dh = dst_w; - - src += src_w - 1; -#endif - - while (1) - { - const uint8_t *s = src; -#if LCD_WIDTH >= LCD_HEIGHT - uint8_t * const dst_line_end = dst + dst_w; -#else - uint8_t * const dst_line_end = dst + dst_h; -#endif - while (1) - { - *dst++ = *s; - - if (dst >= dst_line_end) - { - dw = dst_w; - break; - } - -#if LCD_WIDTH >= LCD_HEIGHT - s += qw; -#else - s += qw*stride; -#endif - dw += rw; - - if (dw >= dst_w2) - { - dw -= dst_w2; -#if LCD_WIDTH >= LCD_HEIGHT - s++; -#else - s += stride; -#endif - } - } - - if (dst >= dst_end) - break; -#if LCD_WIDTH >= LCD_HEIGHT - src += qh*stride; -#else - src -= qh; -#endif - dh += rh; - - if (dh >= dst_h2) - { - dh -= dst_h2; -#if LCD_WIDTH >= LCD_HEIGHT - src += stride; -#else - src--; -#endif - } - } -} - -bool vo_draw_frame_thumb(uint8_t * const * buf, const struct vo_rect *rc) -{ - void *mem; - size_t bufsize = 0; - uint8_t *yuv[3]; - struct vo_rect thumb_rc; - int thumb_width, thumb_height; -#ifdef HAVE_LCD_COLOR - int thumb_uv_width, thumb_uv_height; -#endif - - /* Obtain rectangle as clipped to the screen */ - vo_rect_set_ext(&thumb_rc, 0, 0, LCD_WIDTH, LCD_HEIGHT); - if (!vo_rect_intersect(&thumb_rc, rc, &thumb_rc)) - return true; - - if (buf == NULL) - goto no_thumb_exit; - - DEBUGF("thumb_rc: %d, %d, %d, %d\n", thumb_rc.l, thumb_rc.t, - thumb_rc.r, thumb_rc.b); - - thumb_width = rc->r - rc->l; - thumb_height = rc->b - rc->t; -#ifdef HAVE_LCD_COLOR - thumb_uv_width = thumb_width / 2; - thumb_uv_height = thumb_height / 2; - - DEBUGF("thumb: w: %d h: %d uvw: %d uvh: %d\n", thumb_width, - thumb_height, thumb_uv_width, thumb_uv_height); -#else - DEBUGF("thumb: w: %d h: %d\n", thumb_width, thumb_height); -#endif - - /* Use remaining mpeg2 buffer as temp space */ - mem = mpeg2_get_buf(&bufsize); - - if (bufsize < (size_t)(thumb_width*thumb_height) -#ifdef HAVE_LCD_COLOR - + 2u*(thumb_uv_width * thumb_uv_height) -#endif - ) - { - DEBUGF("thumb: insufficient buffer\n"); - goto no_thumb_exit; - } - - yuv[0] = mem; - stretch_image_plane(buf[0], yuv[0], vo.image_width, - vo.display_width, vo.display_height, - thumb_width, thumb_height); - -#ifdef HAVE_LCD_COLOR - yuv[1] = yuv[0] + thumb_width*thumb_height; - yuv[2] = yuv[1] + thumb_uv_width*thumb_uv_height; - - stretch_image_plane(buf[1], yuv[1], vo.image_width / 2, - vo.display_width / 2, vo.display_height / 2, - thumb_uv_width, thumb_uv_height); - - stretch_image_plane(buf[2], yuv[2], vo.image_width / 2, - vo.display_width / 2, vo.display_height / 2, - thumb_uv_width, thumb_uv_height); -#endif - -#if LCD_WIDTH >= LCD_HEIGHT - yuv_blit(yuv, 0, 0, thumb_width, - thumb_rc.l, thumb_rc.t, - thumb_rc.r - thumb_rc.l, - thumb_rc.b - thumb_rc.t); -#else - yuv_blit(yuv, 0, 0, thumb_height, - thumb_rc.t, thumb_rc.l, - thumb_rc.b - thumb_rc.t, - thumb_rc.r - thumb_rc.l); -#endif /* LCD_WIDTH >= LCD_HEIGHT */ - - return true; - -no_thumb_exit: - vo_draw_black(&thumb_rc); - return false; -} - -void vo_setup(const mpeg2_sequence_t * sequence) -{ - vo.image_width = sequence->width; - vo.image_height = sequence->height; - vo.display_width = sequence->display_width; - vo.display_height = sequence->display_height; - - DEBUGF("vo_setup - w:%d h:%d\n", vo.display_width, vo.display_height); - - vo.image_chroma_x = vo.image_width / sequence->chroma_width; - vo.image_chroma_y = vo.image_height / sequence->chroma_height; - - if (sequence->display_width >= SCREEN_WIDTH) - { - vo.rc_vid.l = 0; - vo.rc_vid.r = SCREEN_WIDTH; - } - else - { - vo.rc_vid.l = (SCREEN_WIDTH - sequence->display_width) / 2; -#ifdef HAVE_LCD_COLOR - vo.rc_vid.l &= ~1; -#endif - vo.rc_vid.r = vo.rc_vid.l + sequence->display_width; - } - - if (sequence->display_height >= SCREEN_HEIGHT) - { - vo.rc_vid.t = 0; - vo.rc_vid.b = SCREEN_HEIGHT; - } - else - { - vo.rc_vid.t = (SCREEN_HEIGHT - sequence->display_height) / 2; -#ifdef HAVE_LCD_COLOR - vo.rc_vid.t &= ~1; -#endif - vo.rc_vid.b = vo.rc_vid.t + sequence->display_height; - } - - vo_set_clip_rect(&vo.rc_clip); -} - -void vo_dimensions(struct vo_ext *sz) -{ - sz->w = vo.display_width; - sz->h = vo.display_height; -} - -bool vo_init(void) -{ - vo.flags = 0; - vo_rect_set_ext(&vo.rc_clip, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - video_lock_init(); - return true; -} - -bool vo_show(bool show) -{ - bool vis = vo.flags & VO_VISIBLE; - - if (show) - vo.flags |= VO_VISIBLE; - else - vo.flags &= ~VO_VISIBLE; - - return vis; -} - -bool vo_is_visible(void) -{ - return vo.flags & VO_VISIBLE; -} - -void vo_cleanup(void) -{ - vo.flags = 0; -} - -void vo_set_clip_rect(const struct vo_rect *rc) -{ - struct vo_rect rc_out; - - if (rc == NULL) - vo_rect_set_ext(&vo.rc_clip, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - else - vo.rc_clip = *rc; - - if (!vo_rect_intersect(&rc_out, &vo.rc_vid, &vo.rc_clip)) - vo.flags &= ~VO_NON_NULL_RECT; - else - vo.flags |= VO_NON_NULL_RECT; - - vo.output_x = rc_out.l; - vo.output_y = rc_out.t; - vo.output_width = rc_out.r - rc_out.l; - vo.output_height = rc_out.b - rc_out.t; -} - -bool vo_get_clip_rect(struct vo_rect *rc) -{ - rc->l = vo.output_x; - rc->t = vo.output_y; - rc->r = rc->l + vo.output_width; - rc->b = rc->t + vo.output_height; - return (vo.flags & VO_NON_NULL_RECT) != 0; -} - -void vo_set_post_draw_callback(void (*cb)(void)) -{ - vo.post_draw_callback = cb; -} - -#if NUM_CORES > 1 -void vo_lock(void) -{ - video_lock(); -} - -void vo_unlock(void) -{ - video_unlock(); -} -#endif diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c deleted file mode 100644 index 392cc6179f..0000000000 --- a/apps/plugins/mpegplayer/video_thread.c +++ /dev/null @@ -1,1059 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * mpegplayer video thread implementation - * - * Copyright (c) 2007 Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" -#include "libmpeg2/mpeg2dec_config.h" -#include "lib/grey.h" -#include "video_out.h" -#include "mpeg_settings.h" - -/** Video stream and thread **/ - -/* Video thread data passed around to its various functions */ -struct video_thread_data -{ - /* Stream data */ - mpeg2dec_t *mpeg2dec; /* Our video decoder */ - const mpeg2_info_t *info; /* Info about video stream */ - int state; /* Thread state */ - int status; /* Media status */ - struct queue_event ev;/* Our event queue to receive commands */ - /* Operational info */ - uint32_t stream_time; /* Current time from beginning of stream */ - uint32_t goal_time; /* Scheduled time of current frame */ - int32_t remain_time; /* T-minus value to frame_time (-:early, +:late) */ - int skip_ref_pics; /* Severe skipping - wait for I-frame */ - int skip_level; /* Number of frames still to skip */ - int num_picture; /* Number of picture headers read */ - int num_intra; /* Number of I-picture headers read */ - int group_est; /* Estmated number remaining as of last I */ - long last_render; /* Last time a frame was drawn */ - /* Sync info */ - uint32_t frame_time; /* Current due time of frame (unadjusted) */ - uint32_t frame_period; /* Frame period in clock ticks */ - int num_ref_pics; /* Number of I and P frames since sync/skip */ - int syncf_perfect; /* Last sync fit result */ -}; - -/* Number drawn since reset */ -static int video_num_drawn SHAREDBSS_ATTR; -/* Number skipped since reset */ -static int video_num_skipped SHAREDBSS_ATTR; - -/* TODO: Check if 4KB is appropriate - it works for my test streams, - so maybe we can reduce it. */ -#define VIDEO_STACKSIZE (4*1024) -static uint32_t video_stack[VIDEO_STACKSIZE / sizeof(uint32_t)] IBSS_ATTR; -static struct event_queue video_str_queue SHAREDBSS_ATTR; -static struct queue_sender_list video_str_queue_send SHAREDBSS_ATTR; -struct stream video_str IBSS_ATTR; - -#define DEFAULT_GOP_SIZE INT_MAX /* no I/P skips until it learns */ -#define DROP_THRESHOLD (100*TS_SECOND/1000) -#define MAX_EARLINESS (120*TS_SECOND/1000) - -#if defined(DEBUG) || defined(SIMULATOR) -static unsigned char pic_coding_type_char(unsigned type) -{ - switch (type) - { - case PIC_FLAG_CODING_TYPE_I: - return 'I'; /* Intra-coded */ - case PIC_FLAG_CODING_TYPE_P: - return 'P'; /* Forward-predicted */ - case PIC_FLAG_CODING_TYPE_B: - return 'B'; /* Bidirectionally-predicted */ - case PIC_FLAG_CODING_TYPE_D: - return 'D'; /* DC-coded */ - default: - return '?'; /* Say what? */ - } -} -#endif /* defined(DEBUG) || defined(SIMULATOR) */ - -/* Multi-use: - * 1) Find the sequence header and initialize video out - * 2) Find the end of the final frame - */ -static int video_str_scan(struct video_thread_data *td, - struct str_sync_data *sd) -{ - int retval = STREAM_ERROR; - uint32_t time = INVALID_TIMESTAMP; - uint32_t period = 0; - struct stream tmp_str; - - tmp_str.id = video_str.id; - tmp_str.hdr.pos = sd->sk.pos; - tmp_str.hdr.limit = sd->sk.pos + sd->sk.len; - - /* Fully reset if obtaining size for a new stream */ - mpeg2_reset(td->mpeg2dec, td->ev.id == VIDEO_GET_SIZE); - mpeg2_skip(td->mpeg2dec, 1); - - while (1) - { - mpeg2_state_t mp2state = mpeg2_parse(td->mpeg2dec); - rb->yield(); - - switch (mp2state) - { - case STATE_BUFFER: - switch (parser_get_next_data(&tmp_str, STREAM_PM_RANDOM_ACCESS)) - { - case STREAM_DATA_END: - DEBUGF("video_stream_scan:STREAM_DATA_END\n"); - goto scan_finished; - - case STREAM_OK: - if (tmp_str.pkt_flags & PKT_HAS_TS) - mpeg2_tag_picture(td->mpeg2dec, tmp_str.pts, 0); - - mpeg2_buffer(td->mpeg2dec, tmp_str.curr_packet, - tmp_str.curr_packet_end); - td->info = mpeg2_info(td->mpeg2dec); - break; - } - break; - - case STATE_SEQUENCE: - DEBUGF("video_stream_scan:STATE_SEQUENCE\n"); - vo_setup(td->info->sequence); - - if (td->ev.id == VIDEO_GET_SIZE) - { - retval = STREAM_OK; - goto scan_finished; - } - break; - - case STATE_SLICE: - case STATE_END: - case STATE_INVALID_END: - { - if (td->info->display_picture == NULL) - break; - - switch (td->ev.id) - { - case STREAM_SYNC: - retval = STREAM_OK; - goto scan_finished; - - case STREAM_FIND_END_TIME: - if (td->info->display_picture->flags & PIC_FLAG_TAGS) - time = td->info->display_picture->tag; - else if (time != INVALID_TIMESTAMP) - time += period; - - period = TC_TO_TS(td->info->sequence->frame_period); - break; - } - - break; - } - - default: - break; - } - } - -scan_finished: - - if (td->ev.id == STREAM_FIND_END_TIME) - { - if (time != INVALID_TIMESTAMP) - { - sd->time = time + period; - retval = STREAM_PERFECT_MATCH; - } - else - { - retval = STREAM_NOT_FOUND; - } - } - - mpeg2_skip(td->mpeg2dec, 0); - return retval; -} - -static bool init_sequence(struct video_thread_data *td) -{ - struct str_sync_data sd; - - sd.time = 0; /* Ignored */ - sd.sk.pos = 0; - sd.sk.len = 1024*1024; - sd.sk.dir = SSCAN_FORWARD; - - return video_str_scan(td, &sd) == STREAM_OK; -} - -static bool check_needs_sync(struct video_thread_data *td, uint32_t time) -{ - uint32_t end_time; - - DEBUGF("check_needs_sync:\n"); - if (td->info == NULL || td->info->display_fbuf == NULL) - { - DEBUGF(" no fbuf\n"); - return true; - } - - if (td->syncf_perfect == 0) - { - DEBUGF(" no frame\n"); - return true; - } - - time = clip_time(&video_str, time); - end_time = td->frame_time + td->frame_period; - - DEBUGF(" sft:%u t:%u sfte:%u\n", (unsigned)td->frame_time, - (unsigned)time, (unsigned)end_time); - - if (time < td->frame_time) - return true; - - if (time >= end_time) - return time < video_str.end_pts || end_time < video_str.end_pts; - - return false; -} - -/* Do any needed decoding/slide up to the specified time */ -static int sync_decoder(struct video_thread_data *td, - struct str_sync_data *sd) -{ - int retval = STREAM_ERROR; - uint32_t time = clip_time(&video_str, sd->time); - - td->syncf_perfect = 0; - td->frame_time = 0; - td->frame_period = 0; - td->num_ref_pics = 0; - - /* Sometimes theres no sequence headers nearby and libmpeg2 may have reset - * fully at some point */ - if ((td->info == NULL || td->info->sequence == NULL) && !init_sequence(td)) - { - DEBUGF("sync_decoder=>init_sequence failed\n"); - goto sync_finished; - } - - video_str.hdr.pos = sd->sk.pos; - video_str.hdr.limit = sd->sk.pos + sd->sk.len; - mpeg2_reset(td->mpeg2dec, false); - mpeg2_skip(td->mpeg2dec, 1); - - while (1) - { - mpeg2_state_t mp2state = mpeg2_parse(td->mpeg2dec); - - switch (mp2state) - { - case STATE_BUFFER: - switch (parser_get_next_data(&video_str, STREAM_PM_RANDOM_ACCESS)) - { - case STREAM_DATA_END: - DEBUGF("sync_decoder:STR_DATA_END\n"); - if (td->info && td->info->display_picture && - !(td->info->display_picture->flags & PIC_FLAG_SKIP)) - { - /* No frame matching the time was found up to the end of - * the stream - consider a perfect match since no better - * can be made */ - retval = STREAM_PERFECT_MATCH; - td->syncf_perfect = 1; - } - goto sync_finished; - - case STREAM_OK: - if (video_str.pkt_flags & PKT_HAS_TS) - mpeg2_tag_picture(td->mpeg2dec, video_str.pts, 0); - mpeg2_buffer(td->mpeg2dec, video_str.curr_packet, - video_str.curr_packet_end); - td->info = mpeg2_info(td->mpeg2dec); - break; - } - break; - - case STATE_SEQUENCE: - DEBUGF(" STATE_SEQUENCE\n"); - vo_setup(td->info->sequence); - break; - - case STATE_GOP: - DEBUGF(" STATE_GOP: (%s)\n", - (td->info->gop->flags & GOP_FLAG_CLOSED_GOP) ? - "closed" : "open"); - break; - - case STATE_PICTURE: - { - int type = td->info->current_picture->flags - & PIC_MASK_CODING_TYPE; - - switch (type) - { - case PIC_FLAG_CODING_TYPE_I: - /* I-frame; start decoding */ - mpeg2_skip(td->mpeg2dec, 0); - td->num_ref_pics++; - break; - - case PIC_FLAG_CODING_TYPE_P: - /* P-frames don't count without I-frames */ - if (td->num_ref_pics > 0) - td->num_ref_pics++; - break; - } - - if (td->info->current_picture->flags & PIC_FLAG_TAGS) - { - DEBUGF(" STATE_PICTURE (%c): %u\n", pic_coding_type_char(type), - (unsigned)td->info->current_picture->tag); - } - else - { - DEBUGF(" STATE_PICTURE (%c): -\n", pic_coding_type_char(type)); - } - - break; - } - - case STATE_SLICE: - case STATE_END: - case STATE_INVALID_END: - { - uint32_t end_time; - - if (td->info->display_picture == NULL) - { - DEBUGF(" td->info->display_picture == NULL\n"); - break; /* No picture */ - } - - int type = td->info->display_picture->flags - & PIC_MASK_CODING_TYPE; - - if (td->info->display_picture->flags & PIC_FLAG_TAGS) - { - td->frame_time = td->info->display_picture->tag; - DEBUGF(" frame tagged:%u (%c%s)\n", (unsigned)td->frame_time, - pic_coding_type_char(type), - (td->info->display_picture->flags & PIC_FLAG_SKIP) ? - " skipped" : ""); - } - else - { - td->frame_time += td->frame_period; - DEBUGF(" add frame_period:%u (%c%s)\n", (unsigned)td->frame_time, - pic_coding_type_char(type), - (td->info->display_picture->flags & PIC_FLAG_SKIP) ? - " skipped" : ""); - } - - td->frame_period = TC_TO_TS(td->info->sequence->frame_period); - end_time = td->frame_time + td->frame_period; - - DEBUGF(" ft:%u t:%u fe:%u (%c%s)", - (unsigned)td->frame_time, - (unsigned)time, - (unsigned)end_time, - pic_coding_type_char(type), - (td->info->display_picture->flags & PIC_FLAG_SKIP) ? - " skipped" : ""); - - if (end_time <= time && end_time < video_str.end_pts) - { - /* Still too early and have not hit at EOS */ - DEBUGF(" too early\n"); - break; - } - else if (!(td->info->display_picture->flags & PIC_FLAG_SKIP)) - { - /* One perfect point if dependent frames were decoded */ - switch (type) - { - case PIC_FLAG_CODING_TYPE_B: - if (td->num_ref_pics > 1) - { - case PIC_FLAG_CODING_TYPE_P: - if (td->num_ref_pics > 0) - { - case PIC_FLAG_CODING_TYPE_I: - td->syncf_perfect = 1; - break; - } - } - } - - if ((td->frame_time <= time && time < end_time) || - end_time >= video_str.end_pts) - { - /* One perfect point for matching time goal */ - DEBUGF(" ft<=tsyncf_perfect++; - } - else - { - DEBUGF(" ft>t\n"); - } - - /* Two or more perfect points = perfect match - yay! */ - retval = (td->syncf_perfect >= 2) ? - STREAM_PERFECT_MATCH : STREAM_MATCH; - } - else - { - /* Too late, no I-Frame yet */ - DEBUGF("\n"); - } - - goto sync_finished; - } - - default: - break; - } - - rb->yield(); - } /* end while */ - -sync_finished: - mpeg2_skip(td->mpeg2dec, 0); - return retval; -} - -static bool frame_print_handler(struct video_thread_data *td) -{ - bool retval; - uint8_t * const * buf = NULL; - - if (td->info != NULL && td->info->display_fbuf != NULL && - td->syncf_perfect > 0) - buf = td->info->display_fbuf->buf; - - if (td->ev.id == VIDEO_PRINT_THUMBNAIL) - { - /* Print a thumbnail of whatever was last decoded - scale and - * position to fill the specified rectangle */ - retval = vo_draw_frame_thumb(buf, (struct vo_rect *)td->ev.data); - } - else - { - /* Print the last frame decoded */ - vo_draw_frame(buf); - retval = buf != NULL; - } - - return retval; -} - -/* This only returns to play or quit */ -static void video_thread_msg(struct video_thread_data *td) -{ - while (1) - { - intptr_t reply = 0; - - switch (td->ev.id) - { - case STREAM_PLAY: - td->status = STREAM_PLAYING; - - switch (td->state) - { - case TSTATE_INIT: - /* Begin decoding state */ - td->state = TSTATE_DECODE; - /* */ - case TSTATE_DECODE: - if (td->syncf_perfect <= 0) - break; - /* There should be a frame already, just draw it */ - td->goal_time = td->frame_time; - td->state = TSTATE_RENDER_WAIT; - /* */ - case TSTATE_RENDER_WAIT: - /* Settings may have changed to nonlimited - just draw - * what was previously being waited for */ - td->stream_time = TICKS_TO_TS(stream_get_time()); - if (!settings.limitfps) - td->state = TSTATE_RENDER; - /* */ - case TSTATE_RENDER: - break; - - case TSTATE_EOS: - /* At end of stream - no playback possible so fire the - * completion event */ - stream_generate_event(&video_str, STREAM_EV_COMPLETE, 0); - break; - } - - reply = td->state != TSTATE_EOS; - break; - - case STREAM_PAUSE: - td->status = STREAM_PAUSED; - reply = td->state != TSTATE_EOS; - break; - - case STREAM_STOP: - if (td->state == TSTATE_DATA) - stream_clear_notify(&video_str, DISK_BUF_DATA_NOTIFY); - - td->status = STREAM_STOPPED; - td->state = TSTATE_EOS; - reply = true; - break; - - case VIDEO_DISPLAY_IS_VISIBLE: - reply = vo_is_visible(); - break; - - case VIDEO_DISPLAY_SHOW: - /* Show video and draw the last frame we had if any or reveal the - * underlying framebuffer if hiding */ - reply = vo_show(!!td->ev.data); - -#ifdef HAVE_LCD_COLOR - /* Match graylib behavior as much as possible */ - if (!td->ev.data == !reply) - break; - - if (td->ev.data) - { - frame_print_handler(td); - } - else - { - IF_COP(rb->commit_discard_dcache()); - vo_lock(); - rb->lcd_update(); - vo_unlock(); - } -#endif - break; - - case STREAM_RESET: - if (td->state == TSTATE_DATA) - stream_clear_notify(&video_str, DISK_BUF_DATA_NOTIFY); - - td->state = TSTATE_INIT; - td->status = STREAM_STOPPED; - - /* Reset operational info but not sync info */ - td->stream_time = UINT32_MAX; - td->goal_time = 0; - td->remain_time = 0; - td->skip_ref_pics = 0; - td->skip_level = 0; - td->num_picture = 0; - td->num_intra = 0; - td->group_est = DEFAULT_GOP_SIZE; - td->last_render = *rb->current_tick - HZ; - video_num_drawn = 0; - video_num_skipped = 0; - - reply = true; - break; - - case STREAM_NEEDS_SYNC: - reply = check_needs_sync(td, td->ev.data); - break; - - case STREAM_SYNC: - if (td->state == TSTATE_INIT) - reply = sync_decoder(td, (struct str_sync_data *)td->ev.data); - break; - - case DISK_BUF_DATA_NOTIFY: - /* Our bun is done */ - if (td->state != TSTATE_DATA) - break; - - td->state = TSTATE_DECODE; - str_data_notify_received(&video_str); - break; - - case VIDEO_PRINT_FRAME: - case VIDEO_PRINT_THUMBNAIL: - reply = frame_print_handler(td); - break; - - case VIDEO_SET_CLIP_RECT: - vo_set_clip_rect((const struct vo_rect *)td->ev.data); - break; - - case VIDEO_GET_CLIP_RECT: - reply = vo_get_clip_rect((struct vo_rect *)td->ev.data); - break; - - case VIDEO_GET_SIZE: - { - if (td->state != TSTATE_INIT) - break; /* Can only use after a reset was issued */ - - /* This will reset the decoder in full for this particular event */ - if (init_sequence(td)) - { - reply = true; - vo_dimensions((struct vo_ext *)td->ev.data); - } - break; - } - - case STREAM_FIND_END_TIME: - if (td->state != TSTATE_INIT) - { - reply = STREAM_ERROR; - break; - } - - reply = video_str_scan(td, (struct str_sync_data *)td->ev.data); - break; - - case VIDEO_SET_POST_FRAME_CALLBACK: - vo_set_post_draw_callback((void (*)(void))td->ev.data); - reply = true; - break; - - case STREAM_QUIT: - /* Time to go - make thread exit */ - td->state = TSTATE_EOS; - return; - } - - str_reply_msg(&video_str, reply); - - if (td->status == STREAM_PLAYING) - { - switch (td->state) - { - case TSTATE_DECODE: - case TSTATE_RENDER: - case TSTATE_RENDER_WAIT: - /* These return when in playing state */ - return; - } - } - - str_get_msg(&video_str, &td->ev); - } -} - -static void video_thread(void) -{ - struct video_thread_data td; - - memset(&td, 0, sizeof (td)); - td.mpeg2dec = mpeg2_init(); - td.status = STREAM_STOPPED; - td.state = TSTATE_EOS; - - if (td.mpeg2dec == NULL) - { - td.status = STREAM_ERROR; - /* Loop and wait for quit message */ - while (1) - { - str_get_msg(&video_str, &td.ev); - if (td.ev.id == STREAM_QUIT) - return; - str_reply_msg(&video_str, STREAM_ERROR); - } - } - - vo_init(); - - goto message_wait; - - while (1) - { - mpeg2_state_t mp2state; - td.state = TSTATE_DECODE; - - /* Check for any pending messages and process them */ - if (str_have_msg(&video_str)) - { - message_wait: - /* Wait for a message to be queued */ - str_get_msg(&video_str, &td.ev); - - message_process: - /* Process a message already dequeued */ - video_thread_msg(&td); - - switch (td.state) - { - /* These states are the only ones that should return */ - case TSTATE_DECODE: goto picture_decode; - case TSTATE_RENDER: goto picture_draw; - case TSTATE_RENDER_WAIT: goto picture_wait; - /* Anything else is interpreted as an exit */ - default: goto video_exit; - } - } - - picture_decode: - mp2state = mpeg2_parse (td.mpeg2dec); - - switch (mp2state) - { - case STATE_BUFFER: - /* Request next packet data */ - switch (parser_get_next_data(&video_str, STREAM_PM_STREAMING)) - { - case STREAM_DATA_NOT_READY: - /* Wait for data to be buffered */ - td.state = TSTATE_DATA; - goto message_wait; - - case STREAM_DATA_END: - /* No more data. */ - td.state = TSTATE_EOS; - if (td.status == STREAM_PLAYING) - stream_generate_event(&video_str, STREAM_EV_COMPLETE, 0); - goto message_wait; - - case STREAM_OK: - if (video_str.pkt_flags & PKT_HAS_TS) - mpeg2_tag_picture(td.mpeg2dec, video_str.pts, 0); - - mpeg2_buffer(td.mpeg2dec, video_str.curr_packet, - video_str.curr_packet_end); - td.info = mpeg2_info(td.mpeg2dec); - break; - } - break; - - case STATE_SEQUENCE: - /* New video sequence, inform output of any changes */ - vo_setup(td.info->sequence); - break; - - case STATE_PICTURE: - { - /* This is not in presentation order - do our best anyway */ - int skip = td.skip_ref_pics; - - /* Frame type: I/P/B/D */ - switch (td.info->current_picture->flags & PIC_MASK_CODING_TYPE) - { - case PIC_FLAG_CODING_TYPE_I: - if (++td.num_intra >= 2) - td.group_est = td.num_picture / (td.num_intra - 1); - - /* Things are extremely late and all frames will be - dropped until the next key frame */ - if (td.skip_level > 0 && td.skip_level >= td.group_est) - { - td.skip_level--; /* skip frame */ - skip = td.skip_ref_pics = 1; /* wait for I-frame */ - td.num_ref_pics = 0; - } - else if (skip != 0) - { - skip = td.skip_ref_pics = 0; /* now, decode */ - td.num_ref_pics = 1; - } - break; - - case PIC_FLAG_CODING_TYPE_P: - if (skip == 0) - { - td.num_ref_pics++; - - /* If skip_level at least the estimated number of frames - left in I-I span, skip until next I-frame */ - if (td.group_est > 0 && td.skip_level >= td.group_est) - { - skip = td.skip_ref_pics = 1; /* wait for I-frame */ - td.num_ref_pics = 0; - } - } - - if (skip != 0) - td.skip_level--; - break; - - case PIC_FLAG_CODING_TYPE_B: - /* We want to drop something, so this B-frame won't even be - decoded. Drawing can happen on the next frame if so desired - so long as the B-frames were not dependent upon those from - a previous open GOP where the needed reference frames were - skipped */ - if (td.skip_level > 0 || td.num_ref_pics < 2) - { - skip = 1; - td.skip_level--; - } - break; - - default: - skip = 1; - break; - } - - if (td.num_intra > 0) - td.num_picture++; - - td.group_est--; - - mpeg2_skip(td.mpeg2dec, skip); - break; - } - - case STATE_SLICE: - case STATE_END: - case STATE_INVALID_END: - { - int32_t offset; /* Tick adjustment to keep sync */ - - if (td.info->display_fbuf == NULL) - break; /* No picture */ - - /* Get presentation times in audio samples - quite accurate - enough - add previous frame duration if not stamped */ - if (td.info->display_picture->flags & PIC_FLAG_TAGS) - td.frame_time = td.info->display_picture->tag; - else - td.frame_time += td.frame_period; - - td.frame_period = TC_TO_TS(td.info->sequence->frame_period); - - if (!settings.limitfps) - { - /* No limiting => no dropping or waiting - draw this frame */ - td.remain_time = 0; - td.skip_level = 0; - td.syncf_perfect = 1; /* have frame */ - goto picture_draw; - } - - td.goal_time = td.frame_time; - td.stream_time = TICKS_TO_TS(stream_get_time()); - - /* How early/late are we? > 0 = late, < 0 early */ - offset = td.stream_time - td.goal_time; - - if (offset >= 0) - { - /* Late or on-time */ - if (td.remain_time < 0) - td.remain_time = 0; /* now, late */ - - offset = AVERAGE(td.remain_time, offset, 4); - td.remain_time = offset; - } - else - { - /* Early */ - if (td.remain_time >= 0) - td.remain_time = 0; /* now, early */ - else if (offset > td.remain_time) - td.remain_time = MAX(offset, -MAX_EARLINESS); /* less early */ - else if (td.remain_time != 0) - td.remain_time = AVERAGE(td.remain_time, 0, 8); /* earlier/same */ - /* else there's been no frame drop */ - - offset = -td.remain_time; - } - - /* Skip anything not decoded */ - if (td.info->display_picture->flags & PIC_FLAG_SKIP) - goto picture_skip; - - td.syncf_perfect = 1; /* have frame (assume so from now on) */ - - /* Keep goal_time >= 0 */ - if ((uint32_t)offset > td.goal_time) - offset = td.goal_time; - - td.goal_time -= offset; - - if (!settings.skipframes) - { - /* No skipping - just wait if we're early and correct for - lateness as much as possible. */ - td.skip_level = 0; - goto picture_wait; - } - - /** Possibly skip this frame **/ - - /* Frameskipping has the following order of preference: - * - * Frame Type Who Notes/Rationale - * B decoder arbitrarily drop - no decode or draw - * Any renderer arbitrarily drop - I/P unless B decoded - * P decoder must wait for I-frame - * I decoder must wait for I-frame - * - * If a frame can be drawn and it has been at least 1/2 second, - * the image will be updated no matter how late it is just to - * avoid looking stuck. - */ - if (td.skip_level > 0 && - TIME_BEFORE(*rb->current_tick, td.last_render + HZ/2)) - { - /* Frame skip was set previously but either there wasn't anything - dropped yet or not dropped enough. So we quit at least rendering - the actual frame to avoid further increase of a/v-drift. */ - td.skip_level--; - goto picture_skip; - } - - /* At this point a frame _will_ be drawn - a skip may happen on - the next however */ - - /* Calculate number of frames to drop/skip - allow brief periods - of lateness before producing skips */ - td.skip_level = 0; - if (td.remain_time > 0 && (uint32_t)offset > DROP_THRESHOLD) - { - td.skip_level = (offset - DROP_THRESHOLD + td.frame_period) - / td.frame_period; - } - - picture_wait: - td.state = TSTATE_RENDER_WAIT; - - /* Wait until time catches up */ - while (1) - { - int32_t twait = td.goal_time - td.stream_time; - /* Watch for messages while waiting for the frame time */ - - if (twait <= 0) - break; - - if (twait > TS_SECOND/HZ) - { - /* Several ticks to wait - do some sleeping */ - int timeout = (twait - HZ) / (TS_SECOND/HZ); - str_get_msg_w_tmo(&video_str, &td.ev, MAX(timeout, 1)); - if (td.ev.id != SYS_TIMEOUT) - goto message_process; - } - else - { - /* Just a little left - spin and be accurate */ - rb->yield(); - if (str_have_msg(&video_str)) - goto message_wait; - } - - td.stream_time = TICKS_TO_TS(stream_get_time()); - } - - picture_draw: - /* Record last frame time */ - td.last_render = *rb->current_tick; - - vo_draw_frame(td.info->display_fbuf->buf); - video_num_drawn++; - break; - - picture_skip: - if (td.remain_time <= DROP_THRESHOLD) - { - td.skip_level = 0; - if (td.remain_time <= 0) - td.remain_time = INT32_MIN; - } - - video_num_skipped++; - break; - } - - default: - break; - } - - rb->yield(); - } /* end while */ - -video_exit: - vo_cleanup(); - mpeg2_close(td.mpeg2dec); -} - -/* Initializes the video thread */ -bool video_thread_init(void) -{ - intptr_t rep; - - IF_COP(rb->commit_dcache()); - - video_str.hdr.q = &video_str_queue; - rb->queue_init(video_str.hdr.q, false); - - /* We put the video thread on another processor for multi-core targets. */ - video_str.thread = rb->create_thread( - video_thread, video_stack, VIDEO_STACKSIZE, 0, - "mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK) IF_COP(, COP)); - - rb->queue_enable_queue_send(video_str.hdr.q, &video_str_queue_send, - video_str.thread); - - if (video_str.thread == 0) - return false; - - /* Wait for thread to initialize */ - rep = str_send_msg(&video_str, STREAM_NULL, 0); - IF_COP(rb->commit_discard_dcache()); - - return rep == 0; /* Normally STREAM_NULL should be ignored */ -} - -/* Terminates the video thread */ -void video_thread_exit(void) -{ - if (video_str.thread != 0) - { - str_post_msg(&video_str, STREAM_QUIT, 0); - rb->thread_wait(video_str.thread); - IF_COP(rb->commit_discard_dcache()); - video_str.thread = 0; - } -} - - -/** Misc **/ -void video_thread_get_stats(struct video_output_stats *s) -{ - uint32_t start; - uint32_t now = stream_get_ticks(&start); - s->num_drawn = video_num_drawn; - s->num_skipped = video_num_skipped; - - s->fps = 0; - - if (now > start) - s->fps = muldiv_uint32(CLOCK_RATE*100, s->num_drawn, now - start); -} - diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config index 8d266966d0..26c1543fdd 100644 --- a/apps/plugins/viewers.config +++ b/apps/plugins/viewers.config @@ -71,10 +71,6 @@ wav,viewers/wavview,10 wav,viewers/wav2wv,- wav,viewers/mp3_encoder,- wav,viewers/test_codec,- -mpg,viewers/mpegplayer,4 -mpeg,viewers/mpegplayer,4 -mpv,viewers/mpegplayer,4 -m2v,viewers/mpegplayer,4 iriver,viewers/iriver_flash,3 tap,viewers/zxbox,12 opx,viewers/open_plugins,- diff --git a/docs/MAINTAINERS b/docs/MAINTAINERS index 143e6fa2b4..2771adb7ad 100644 --- a/docs/MAINTAINERS +++ b/docs/MAINTAINERS @@ -189,7 +189,6 @@ Plugins :minesweeper: Antoine Cellerier :mosaique: :mp3_encoder: -:mpegplayer: Michael Sevakis :nim: :oscilloscope: Jens Arnold :pacbox: Dave Chapman diff --git a/lib/rbcodec/codecs/libmad/libmad.make b/lib/rbcodec/codecs/libmad/libmad.make index 6c50e1d201..479dd54773 100644 --- a/lib/rbcodec/codecs/libmad/libmad.make +++ b/lib/rbcodec/codecs/libmad/libmad.make @@ -7,16 +7,9 @@ # $Id$ # -# we need to build two different mad libraries -# (one for codec, one for mpegplayer) -# so a little trickery is necessary - MADFLAGS = $(CODECFLAGS) -I$(RBCODECLIB_DIR)/codecs/libmad MADFLAGS += -UDEBUG -DNDEBUG -DHAVE_LIMITS_H -DHAVE_ASSERT_H -# MPEGplayer -MPEGMADFLAGS = $(MADFLAGS) -DMPEGPLAYER - # libmad MADLIB := $(CODECDIR)/libmad.a MADLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libmad/SOURCES) @@ -27,26 +20,8 @@ $(MADLIB): $(MADLIB_OBJ) $(SILENT)$(shell rm -f $@) $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null -# libmad-mpeg -MPEGMADLIB := $(CODECDIR)/libmad-mpeg.a -MPEGMADLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libmad/SOURCES) -MPEGMADLIB_OBJ := $(addsuffix .o,$(basename $(subst $(RBCODECLIB_DIR)/codecs/libmad,$(RBCODEC_BLD)/codecs/libmad-mpeg,$(MPEGMADLIB_SRC)))) - -$(MPEGMADLIB): $(MPEGMADLIB_OBJ) - $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null - # pattern rules -$(CODECDIR)/libmad-mpeg/%.o : $(RBCODECLIB_DIR)/codecs/libmad/%.c - $(SILENT)mkdir -p $(dir $@) - $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<)) \ - $(CC) $(MPEGMADFLAGS) -c $< -o $@ - -$(CODECDIR)/libmad-mpeg/%.o : $(RBCODECLIB_DIR)/codecs/libmad/%.S - $(SILENT)mkdir -p $(dir $@) - $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<)) \ - $(CC) $(MPEGMADFLAGS) -c $< -o $@ - $(CODECDIR)/libmad/%.o: $(RBCODECLIB_DIR)/codecs/libmad/%.c $(SILENT)mkdir -p $(dir $@) $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<)) \ diff --git a/lib/rbcodec/codecs/libmad/mad_iram.h b/lib/rbcodec/codecs/libmad/mad_iram.h index ac0b64cca9..5a315c0381 100644 --- a/lib/rbcodec/codecs/libmad/mad_iram.h +++ b/lib/rbcodec/codecs/libmad/mad_iram.h @@ -35,10 +35,9 @@ #define ICODE_ATTR_MPA_SYNTH #define ICONST_ATTR_MPA_HUFFMAN #else -/* Code performs slower in IRAM on PP502x and there is no space in - mpegplayer on the PP5002. S3C2440 doesn't have any IRAM available for - codecs */ -#if defined(CPU_PP502x) || (CONFIG_CPU == PP5002 && defined(MPEGPLAYER)) +/* Code performs slower in IRAM on PP502x + S3C2440 doesn't have any IRAM available for codecs */ +#if defined(CPU_PP502x) #define ICODE_SECTION_MPA_ARM .text #define ICODE_ATTR_MPA_SYNTH #else diff --git a/lib/rbcodec/codecs/mpa.c b/lib/rbcodec/codecs/mpa.c index d6bcc04910..db33f17c3b 100644 --- a/lib/rbcodec/codecs/mpa.c +++ b/lib/rbcodec/codecs/mpa.c @@ -26,7 +26,7 @@ CODEC_HEADER -#if NUM_CORES > 1 && !defined(MPEGPLAYER) +#if NUM_CORES > 1 #define MPA_SYNTH_ON_COP #endif diff --git a/manual/plugins/main.tex b/manual/plugins/main.tex index 3348b1fce5..73cc1a2ada 100644 --- a/manual/plugins/main.tex +++ b/manual/plugins/main.tex @@ -201,8 +201,6 @@ option from the \setting{Context Menu} (see \reference{ref:Contextmenu}).} \nopt{lowmem}{\input{plugins/midiplay.tex}} \nopt{lowmem}{\input{plugins/mikmod.tex}} -\nopt{lowmem}{\input{plugins/mpegplayer.tex}} - \input{plugins/mp3_encoder.tex} \opt{iriverh300,iriverh100,SANSA_FUZE_PAD,SANSA_E200_PAD,IPOD_4G_PAD,IPOD_3G_PAD% diff --git a/manual/plugins/mpegplayer.tex b/manual/plugins/mpegplayer.tex deleted file mode 100644 index 9fa438dabe..0000000000 --- a/manual/plugins/mpegplayer.tex +++ /dev/null @@ -1,119 +0,0 @@ -% $Id$ % -\subsection{MPEG Player} -The Mpeg Player is a video player plugin capable of playing back MPEG-1 and -MPEG-2 video streams with MPEG audio multiplexed into \fname{.mpg} files. - -To play a video file, you just select it in the Rockbox \setting{File Browser}. -If your file does not have the \fname{.mpg} extension but is encoded in the -supported format, you will need to use the \setting{Open With...} context menu -option and choose \setting{mpegplayer}. - -\begin{btnmap} - \opt{GIGABEAT_S_PAD}{\ButtonSelect{} or \ButtonPlay} - \opt{GIGABEAT_PAD}{\ButtonSelect{} or \ButtonA} - \nopt{GIGABEAT_S_PAD,GIGABEAT_PAD}{\ActionWpsPlay} - \opt{HAVEREMOTEKEYMAP}{& } - & Pause / Resume\\ - \ActionWpsStop - \opt{HAVEREMOTEKEYMAP}{& } - & Stop\\ - \nopt{GIGABEAT_S_PAD,GIGABEAT_PAD}{\ActionWpsVolUp{} / \ActionWpsVolDown} - \opt{GIGABEAT_S_PAD,GIGABEAT_PAD}{\ButtonLeft{} or \ButtonVolDown{} / - \ButtonRight{} or \ButtonVolUp} - \opt{HAVEREMOTEKEYMAP}{& } - & Adjust volume up / down\\ - \nopt{GIGABEAT_S_PAD,GIGABEAT_PAD,SAMSUNG_YH92X_PAD,SAMSUNG_YH820_PAD}{% - \ActionWpsSkipPrev{} / \ActionWpsSkipNext} - \opt{GIGABEAT_S_PAD,GIGABEAT_PAD}{\ButtonUp{} / \ButtonDown} - \opt{SAMSUNG_YH92X_PAD,SAMSUNG_YH820_PAD}{\ButtonLeft{} / \ButtonRight} - \opt{HAVEREMOTEKEYMAP}{& } - & Rewind / Fast Forward\\ - \opt{IRIVER_H100_PAD,IRIVER_H300_PAD}{\ButtonMode} - \opt{IPOD_4G_PAD,IPOD_3G_PAD,GIGABEAT_PAD,GIGABEAT_S_PAD,MROBE100_PAD,PBELL_VIBE500_PAD} - {\ButtonMenu} - \opt{IAUDIO_X5_PAD}{\ButtonRec} - \opt{IRIVER_H10_PAD}{\ButtonRew} - \opt{SAMSUNG_YH92X_PAD,SAMSUNG_YH820_PAD}{\ButtonRew} - \opt{SANSA_E200_PAD,SANSA_FUZE_PAD,SANSA_C200_PAD,SANSA_CLIP_PAD}{\ButtonSelect} - \opt{HAVEREMOTEKEYMAP}{& } - & Open the MPEG Player menu\\ -\end{btnmap} - -When a video file is selected, the Start Menu will be displayed, unless it is -disabled via the \setting{Resume Options} (see below). In the latter case the video -will start playing immediately. - -Start Menu - -\begin{description} -\item[Play from beginning] Resume information is discarded and the video plays - from the start. -\item[Resume at: mm:ss] Resume video playback at stored resume time mm:ss - (start of the video if no resume time is found). -\item[Set start time] A preview screen is presented consisting of a - thumbnail preview and a progress bar where the user can select a start time - by `seeking' through the video. The video playback is started by pressing - the select button. -\item[Settings] Open \setting{Settings} submenu -- see below. -\item[Quit mpegplayer] Exit the plugin. -\end{description} - -Main Menu - -\begin{description} -\item[Settings] Open \setting{Settings} submenu -- see below. -\item[Resume playback] Return to playback screen. -\item[Quit mpegplayer] Exit the plugin. -\end{description} - -Settings Menu - -\begin{description} -\item[Display Options] Open \setting{Display Options} submenu -- see below. -\item[Audio Options] Open \setting{Audio Options} submenu -- see below. -\item[Resume Options] (default: Start menu) Enable/disable the start menu. -\item[Play Mode] (default: Single) Set to \setting{All} to play multiple - \fname{.mpg} files in the directory continuously. -\item[Clear all resumes: x] Discard all x resume points. -\end{description} - -Display Options Menu - -\begin{description} -\item[Dithering] (default: off) Prevent banding effects in gradients by blending - of colours. (only available on Sansa e200, Sansa c200 and Gigabeat F/X) -\item[Display FPS] (default: off) This option displays (once a second -- if your - video is full-screen this means it will get overwritten by the video and - appear to flash once per second) the average number of frames decoded per - second, the total number of frames skipped (see the Skip Frames option), - the current time (in 100~Hz ticks) and the time the current frame is due to - be displayed. -\item[Limit FPS] (default: on) With this option disabled, mpegplayer will - display the video as fast as it can. Useful for benchmarking. -\item[Skip frames] (default: on) This option causes mpegplayer to attempt to - maintain realtime playback by skipping the display of frames -- but these - frames are still decoded. Disabling this option can cause loss of A/V sync. -\opt{backlight_brightness}{ - \item[Backlight Brightness] (default: Use setting) Choose brightness to use - during video playback. Set to \setting{Use setting} to use the Brightness - setting. -} -\end{description} - -Audio Options Menu - -\begin{description} -\item[Tone Controls] (default: force off) Use the bass and treble control - settings or force them off. -\item[Channel Modes] (default: force off) Use the channel configuration setting - or force Stereo mode. -\item[Crossfeed] (default: force off) Use the Crossfeed setting or force - crossfeed off. -\item[Equalizer] (default: force off) Use the Equalizer setting or force the - equalizer off. -\item[Dithering] (default: force off) Use the Dithering setting or force - audio dithering off. -\end{description} - -See this page in the Rockbox wiki for information on how to encode your videos -to the supported format. \wikilink{PluginMpegplayer}