Initial commit of work-in-progress MPEG video player plugin based on libmpeg2. Works on all targets with colour LCDs, but most optimised for the ipod Color/Photo and Nano. It currently only plays raw MPEG-1 or MPEG-2 video streams (no audio). Also adds a new lcd_yuv_blit() function to the plugin API - currently only implemented for the ipod Color/Photo and Nano.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10479 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
754e173c25
commit
c9d66562af
|
@ -462,6 +462,11 @@ static const struct plugin_api rockbox_api = {
|
|||
lcd_remote_bitmap_part,
|
||||
lcd_remote_bitmap,
|
||||
#endif
|
||||
|
||||
#if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO) && \
|
||||
!defined(SIMULATOR)
|
||||
lcd_yuv_blit,
|
||||
#endif
|
||||
};
|
||||
|
||||
int plugin_load(const char* plugin, void* parameter)
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
||||
|
||||
/* increase this every time the api struct changes */
|
||||
#define PLUGIN_API_VERSION 25
|
||||
#define PLUGIN_API_VERSION 26
|
||||
|
||||
/* update this to latest version if a change to the api struct breaks
|
||||
backwards compatibility (and please take the opportunity to sort in any
|
||||
|
@ -539,6 +539,13 @@ struct plugin_api {
|
|||
void (*lcd_remote_bitmap)(const fb_remote_data *src, int x, int y, int width,
|
||||
int height);
|
||||
#endif
|
||||
#if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO) && \
|
||||
!defined(SIMULATOR)
|
||||
void (*lcd_yuv_blit)(unsigned char * const src[3],
|
||||
int src_x, int src_y, int stride,
|
||||
int x, int y, int width, int height);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/* plugin header */
|
||||
|
|
|
@ -32,5 +32,10 @@ pacbox
|
|||
doom
|
||||
#endif
|
||||
|
||||
/* For all the colour targets */
|
||||
#if defined(HAVE_LCD_COLOR)
|
||||
mpegplayer
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* IRIVER_IFP7XX_SERIES */
|
||||
|
|
33
apps/plugins/mpegplayer/AUTHORS
Normal file
33
apps/plugins/mpegplayer/AUTHORS
Normal file
|
@ -0,0 +1,33 @@
|
|||
Aaron Holtzman <aholtzma@ess.engr.uvic.ca> started the project and
|
||||
made the initial working implementation.
|
||||
|
||||
Michel Lespinasse <walken@zoy.org> 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 <barreyra@ufl.edu> - build fixes
|
||||
Gildas Bazin <gbazin@netcourrier.com> - mingw32 port
|
||||
Alexander W. Chin <alexc@newt.phys.unsw.edu.au> - progressive_seq fix
|
||||
Stephen Crowley <stephenc@dns2.digitalpassage.com> - build fixes
|
||||
Didier Gautheron <dgautheron@magic.fr> - bug fixes
|
||||
Ryan C. Gordon <icculus@lokigames.com> - SDL support
|
||||
Peter Gubanov <peter@elecard.net.ru> - MMX IDCT scheduling
|
||||
Håkan Hjort <d95hjort@dtek.chalmers.se> - Solaris fixes, mlib code
|
||||
Nicolas Joly <njoly@pasteur.fr> - assorted bug fixes
|
||||
Gerd Knorr <kraxel@goldbach.in-berlin.de> - Xv support
|
||||
David I. Lehn <dlehn@vt.edu> - motion_comp mmx code
|
||||
Olie Lho <ollie@sis.com.tw> - MMX yuv2rgb routine
|
||||
David S. Miller <davem@redhat.com> - sparc VIS optimizations
|
||||
Rick Niles <niles@scyld.com> - build fixes
|
||||
Real Ouellet <realo@sympatico.ca> - g200 fixes
|
||||
Bajusz Peter <hyp-x@inf.bme.hu> - motion comp fixes
|
||||
Franck Sicard <Franck.Sicard@miniruth.solsoft.fr> - x11 fixes
|
||||
Brion Vibber <brion@gizmo.usc.edu> - x11 fixes
|
||||
Martin Vogt <mvogt@rhrk.uni-kl.de> - reentrancy fixes
|
||||
Fredrik Vraalsen <vraalsen@cs.uiuc.edu> - 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.
|
116
apps/plugins/mpegplayer/Makefile
Normal file
116
apps/plugins/mpegplayer/Makefile
Normal file
|
@ -0,0 +1,116 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
INCLUDES = -I$(APPSDIR) -I.. -I. $(TARGET_INC) -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
|
||||
-I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) -I$(BUILDDIR)
|
||||
CFLAGS = $(INCLUDES) $(GCCOPTS) -O2 $(TARGET) $(EXTRA_DEFINES) \
|
||||
-DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN
|
||||
|
||||
|
||||
ifdef APPEXTRA
|
||||
INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA)))
|
||||
endif
|
||||
|
||||
LINKFILE := $(OBJDIR)/link.lds
|
||||
DEPFILE = $(OBJDIR)/dep-mpegplayer
|
||||
|
||||
# This sets up 'SRC' based on the files mentioned in SOURCES
|
||||
include $(TOOLSDIR)/makesrc.inc
|
||||
|
||||
SOURCES = $(SRC)
|
||||
OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2))
|
||||
DIRS = .
|
||||
|
||||
LDS := ../plugin.lds
|
||||
OUTPUT = $(OUTDIR)/mpegplayer.rock
|
||||
|
||||
all: $(OUTPUT)
|
||||
|
||||
ifndef SIMVER
|
||||
$(OBJDIR)/mpegplayer.elf: $(OBJS) $(LINKFILE)
|
||||
@echo "LD "`basename $@`
|
||||
@$(CC) $(GCCOPTS) -O -nostdlib -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc \
|
||||
-T$(LINKFILE) -Wl,-Map,$(OBJDIR)/mpegplayer.map
|
||||
|
||||
$(OUTPUT): $(OBJDIR)/mpegplayer.elf
|
||||
@echo "OBJCOPY "`basename $@`
|
||||
@$(OC) -O binary $< $@
|
||||
else
|
||||
|
||||
ifeq ($(SIMVER), x11)
|
||||
###################################################
|
||||
# This is the X11 simulator version
|
||||
|
||||
$(OUTPUT): $(OBJS)
|
||||
@echo "LD $<"
|
||||
@$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@
|
||||
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
|
||||
# 'x' must be kept or you'll have "Win32 error 5"
|
||||
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
|
||||
# #define ERROR_ACCESS_DENIED 5L
|
||||
else
|
||||
@chmod -x $@
|
||||
endif
|
||||
|
||||
else # end of x11-simulator
|
||||
ifeq ($(SIMVER), sdl)
|
||||
###################################################
|
||||
# This is the SDL simulator version
|
||||
|
||||
$(OUTPUT): $(OBJS)
|
||||
@echo "LD $<"
|
||||
@$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@
|
||||
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
|
||||
# 'x' must be kept or you'll have "Win32 error 5"
|
||||
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
|
||||
# #define ERROR_ACCESS_DENIED 5L
|
||||
else
|
||||
@chmod -x $@
|
||||
endif
|
||||
|
||||
else # end of sdl-simulator
|
||||
###################################################
|
||||
# This is the win32 simulator version
|
||||
DLLTOOLFLAGS = --export-all
|
||||
DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin
|
||||
|
||||
$(OUTPUT): $(OBJS)
|
||||
@echo "DLL "`basename $@`
|
||||
@$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $(OBJS)
|
||||
@$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $(OBJS) \
|
||||
$(BUILDDIR)/libplugin.a -o $@
|
||||
ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
|
||||
# 'x' must be kept or you'll have "Win32 error 5"
|
||||
# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
|
||||
# #define ERROR_ACCESS_DENIED 5L
|
||||
else
|
||||
@chmod -x $@
|
||||
endif
|
||||
endif # end of win32-simulator
|
||||
endif
|
||||
endif # end of simulator section
|
||||
|
||||
|
||||
include $(TOOLSDIR)/make.inc
|
||||
|
||||
# MEMORYSIZE should be passed on to this makefile with the chosen memory size
|
||||
# given in number of MB
|
||||
$(LINKFILE): $(LDS)
|
||||
@echo "build "`basename $@`
|
||||
@cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) \
|
||||
$(DEFINES) -E -P - >$@
|
||||
|
||||
clean:
|
||||
@echo "cleaning mpegplayer"
|
||||
@rm -rf $(OBJDIR)/mpegplayer
|
||||
@rm -f $(OBJDIR)/mpegplayer.* $(DEPFILE)
|
||||
|
||||
-include $(DEPFILE)
|
||||
|
204
apps/plugins/mpegplayer/README
Normal file
204
apps/plugins/mpegplayer/README
Normal file
|
@ -0,0 +1,204 @@
|
|||
|
||||
|
||||
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.
|
44
apps/plugins/mpegplayer/README.rockbox
Normal file
44
apps/plugins/mpegplayer/README.rockbox
Normal file
|
@ -0,0 +1,44 @@
|
|||
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
|
10
apps/plugins/mpegplayer/SOURCES
Normal file
10
apps/plugins/mpegplayer/SOURCES
Normal file
|
@ -0,0 +1,10 @@
|
|||
alloc.c
|
||||
cpu_accel.c
|
||||
cpu_state.c
|
||||
decode.c
|
||||
header.c
|
||||
idct.c
|
||||
motion_comp.c
|
||||
slice.c
|
||||
video_out_rockbox.c
|
||||
mpegplayer.c
|
76
apps/plugins/mpegplayer/alloc.c
Normal file
76
apps/plugins/mpegplayer/alloc.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* alloc.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "plugin.h"
|
||||
|
||||
#include "mpeg2.h"
|
||||
|
||||
extern struct plugin_api* rb;
|
||||
|
||||
long mem_ptr;
|
||||
long bufsize;
|
||||
unsigned char* mallocbuf;
|
||||
|
||||
void mpeg2_alloc_init(unsigned char* buf, int mallocsize)
|
||||
{
|
||||
mem_ptr = 0;
|
||||
bufsize = mallocsize;
|
||||
mallocbuf = buf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void * mpeg2_malloc (unsigned size, mpeg2_alloc_t reason)
|
||||
{
|
||||
void* x;
|
||||
|
||||
(void)reason;
|
||||
|
||||
if (mem_ptr + (long)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 mpeg2_free(void* ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
|
||||
/* gcc may want to use memcpy before rb is initialised, so here's a trivial
|
||||
implementation */
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n) {
|
||||
size_t i;
|
||||
char* d=(char*)dest;
|
||||
char* s=(char*)src;
|
||||
|
||||
for (i=0;i<n;i++)
|
||||
d[i]=s[i];
|
||||
|
||||
return dest;
|
||||
}
|
37
apps/plugins/mpegplayer/attributes.h
Normal file
37
apps/plugins/mpegplayer/attributes.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* attributes.h
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* 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
|
||||
|
||||
#ifdef HAVE_BUILTIN_EXPECT
|
||||
#define likely(x) __builtin_expect ((x) != 0, 1)
|
||||
#define unlikely(x) __builtin_expect ((x) != 0, 0)
|
||||
#else
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
#endif
|
220
apps/plugins/mpegplayer/cpu_accel.c
Normal file
220
apps/plugins/mpegplayer/cpu_accel.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* cpu_accel.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "plugin.h"
|
||||
|
||||
#include "mpeg2dec_config.h"
|
||||
|
||||
#include "mpeg2.h"
|
||||
#include "attributes.h"
|
||||
#include "mpeg2_internal.h"
|
||||
|
||||
#ifdef ACCEL_DETECT
|
||||
#ifdef ARCH_X86
|
||||
static inline uint32_t arch_accel (void)
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
int AMD;
|
||||
uint32_t caps;
|
||||
|
||||
#if !defined(PIC) && !defined(__PIC__)
|
||||
#define cpuid(op,eax,ebx,ecx,edx) \
|
||||
__asm__ ("cpuid" \
|
||||
: "=a" (eax), \
|
||||
"=b" (ebx), \
|
||||
"=c" (ecx), \
|
||||
"=d" (edx) \
|
||||
: "a" (op) \
|
||||
: "cc")
|
||||
#else /* PIC version : save ebx */
|
||||
#define cpuid(op,eax,ebx,ecx,edx) \
|
||||
__asm__ ("push %%ebx\n\t" \
|
||||
"cpuid\n\t" \
|
||||
"movl %%ebx,%1\n\t" \
|
||||
"pop %%ebx" \
|
||||
: "=a" (eax), \
|
||||
"=r" (ebx), \
|
||||
"=c" (ecx), \
|
||||
"=d" (edx) \
|
||||
: "a" (op) \
|
||||
: "cc")
|
||||
#endif
|
||||
|
||||
__asm__ ("pushf\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %0\n\t"
|
||||
"movl %0,%1\n\t"
|
||||
"xorl $0x200000,%0\n\t"
|
||||
"push %0\n\t"
|
||||
"popf\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %0\n\t"
|
||||
"popf"
|
||||
: "=r" (eax),
|
||||
"=r" (ebx)
|
||||
:
|
||||
: "cc");
|
||||
|
||||
if (eax == ebx) /* no cpuid */
|
||||
return 0;
|
||||
|
||||
cpuid (0x00000000, eax, ebx, ecx, edx);
|
||||
if (!eax) /* vendor string only */
|
||||
return 0;
|
||||
|
||||
AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
|
||||
|
||||
cpuid (0x00000001, eax, ebx, ecx, edx);
|
||||
if (! (edx & 0x00800000)) /* no MMX */
|
||||
return 0;
|
||||
|
||||
caps = MPEG2_ACCEL_X86_MMX;
|
||||
if (edx & 0x02000000) /* SSE - identical to AMD MMX extensions */
|
||||
caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT;
|
||||
|
||||
cpuid (0x80000000, eax, ebx, ecx, edx);
|
||||
if (eax < 0x80000001) /* no extended capabilities */
|
||||
return caps;
|
||||
|
||||
cpuid (0x80000001, eax, ebx, ecx, edx);
|
||||
|
||||
if (edx & 0x80000000)
|
||||
caps |= MPEG2_ACCEL_X86_3DNOW;
|
||||
|
||||
if (AMD && (edx & 0x00400000)) /* AMD MMX extensions */
|
||||
caps |= MPEG2_ACCEL_X86_MMXEXT;
|
||||
|
||||
return caps;
|
||||
}
|
||||
#endif /* ARCH_X86 */
|
||||
|
||||
#if defined(ARCH_PPC) || defined(ARCH_SPARC)
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
static sigjmp_buf jmpbuf;
|
||||
static volatile sig_atomic_t canjump = 0;
|
||||
|
||||
static RETSIGTYPE sigill_handler (int sig)
|
||||
{
|
||||
if (!canjump) {
|
||||
signal (sig, SIG_DFL);
|
||||
raise (sig);
|
||||
}
|
||||
|
||||
canjump = 0;
|
||||
siglongjmp (jmpbuf, 1);
|
||||
}
|
||||
|
||||
#ifdef ARCH_PPC
|
||||
static inline uint32_t arch_accel (void)
|
||||
{
|
||||
static RETSIGTYPE (* oldsig) (int);
|
||||
|
||||
oldsig = signal (SIGILL, sigill_handler);
|
||||
if (sigsetjmp (jmpbuf, 1)) {
|
||||
signal (SIGILL, oldsig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
canjump = 1;
|
||||
|
||||
#ifdef HAVE_ALTIVEC_H /* gnu */
|
||||
#define VAND(a,b,c) "vand " #a "," #b "," #c "\n\t"
|
||||
#else /* apple */
|
||||
#define VAND(a,b,c) "vand v" #a ",v" #b ",v" #c "\n\t"
|
||||
#endif
|
||||
asm volatile ("mtspr 256, %0\n\t"
|
||||
VAND (0, 0, 0)
|
||||
:
|
||||
: "r" (-1));
|
||||
|
||||
canjump = 0;
|
||||
|
||||
signal (SIGILL, oldsig);
|
||||
return MPEG2_ACCEL_PPC_ALTIVEC;
|
||||
}
|
||||
#endif /* ARCH_PPC */
|
||||
|
||||
#ifdef ARCH_SPARC
|
||||
static inline uint32_t arch_accel (void)
|
||||
{
|
||||
static RETSIGTYPE (* oldsig) (int);
|
||||
|
||||
oldsig = signal (SIGILL, sigill_handler);
|
||||
if (sigsetjmp (jmpbuf, 1)) {
|
||||
signal (SIGILL, oldsig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
canjump = 1;
|
||||
|
||||
/* pdist %f0, %f0, %f0 */
|
||||
__asm__ __volatile__(".word\t0x81b007c0");
|
||||
|
||||
canjump = 0;
|
||||
|
||||
if (sigsetjmp (jmpbuf, 1)) {
|
||||
signal (SIGILL, oldsig);
|
||||
return MPEG2_ACCEL_SPARC_VIS;
|
||||
}
|
||||
|
||||
canjump = 1;
|
||||
|
||||
/* edge8n %g0, %g0, %g0 */
|
||||
__asm__ __volatile__(".word\t0x81b00020");
|
||||
|
||||
canjump = 0;
|
||||
|
||||
signal (SIGILL, oldsig);
|
||||
return MPEG2_ACCEL_SPARC_VIS | MPEG2_ACCEL_SPARC_VIS2;
|
||||
}
|
||||
#endif /* ARCH_SPARC */
|
||||
#endif /* ARCH_PPC || ARCH_SPARC */
|
||||
|
||||
#ifdef ARCH_ALPHA
|
||||
static inline uint32_t arch_accel (void)
|
||||
{
|
||||
uint64_t no_mvi;
|
||||
|
||||
asm volatile ("amask %1, %0"
|
||||
: "=r" (no_mvi)
|
||||
: "rI" (256)); /* AMASK_MVI */
|
||||
return no_mvi ? MPEG2_ACCEL_ALPHA : (MPEG2_ACCEL_ALPHA |
|
||||
MPEG2_ACCEL_ALPHA_MVI);
|
||||
}
|
||||
#endif /* ARCH_ALPHA */
|
||||
#endif /* ACCEL_DETECT */
|
||||
|
||||
uint32_t mpeg2_detect_accel (void)
|
||||
{
|
||||
uint32_t accel;
|
||||
|
||||
accel = 0;
|
||||
#ifdef ACCEL_DETECT
|
||||
#if defined (ARCH_X86) || defined (ARCH_PPC) || defined (ARCH_ALPHA) || defined (ARCH_SPARC)
|
||||
accel = arch_accel ();
|
||||
#endif
|
||||
#endif
|
||||
return accel;
|
||||
}
|
129
apps/plugins/mpegplayer/cpu_state.c
Normal file
129
apps/plugins/mpegplayer/cpu_state.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* cpu_state.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "plugin.h"
|
||||
|
||||
#include "mpeg2dec_config.h"
|
||||
|
||||
#include "mpeg2.h"
|
||||
#include "attributes.h"
|
||||
#include "mpeg2_internal.h"
|
||||
#ifdef ARCH_X86
|
||||
#include "mmx.h"
|
||||
#endif
|
||||
|
||||
void (* mpeg2_cpu_state_save) (cpu_state_t * state) = NULL;
|
||||
void (* mpeg2_cpu_state_restore) (cpu_state_t * state) = NULL;
|
||||
|
||||
#ifdef ARCH_X86
|
||||
static void state_restore_mmx (cpu_state_t * state)
|
||||
{
|
||||
emms ();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_PPC
|
||||
#ifdef HAVE_ALTIVEC_H /* gnu */
|
||||
#define LI(a,b) "li " #a "," #b "\n\t"
|
||||
#define STVX0(a,b,c) "stvx " #a ",0," #c "\n\t"
|
||||
#define STVX(a,b,c) "stvx " #a "," #b "," #c "\n\t"
|
||||
#define LVX0(a,b,c) "lvx " #a ",0," #c "\n\t"
|
||||
#define LVX(a,b,c) "lvx " #a "," #b "," #c "\n\t"
|
||||
#else /* apple */
|
||||
#define LI(a,b) "li r" #a "," #b "\n\t"
|
||||
#define STVX0(a,b,c) "stvx v" #a ",0,r" #c "\n\t"
|
||||
#define STVX(a,b,c) "stvx v" #a ",r" #b ",r" #c "\n\t"
|
||||
#define LVX0(a,b,c) "lvx v" #a ",0,r" #c "\n\t"
|
||||
#define LVX(a,b,c) "lvx v" #a ",r" #b ",r" #c "\n\t"
|
||||
#endif
|
||||
|
||||
static void state_save_altivec (cpu_state_t * state)
|
||||
{
|
||||
asm (LI (9, 16)
|
||||
STVX0 (20, 0, 3)
|
||||
LI (11, 32)
|
||||
STVX (21, 9, 3)
|
||||
LI (9, 48)
|
||||
STVX (22, 11, 3)
|
||||
LI (11, 64)
|
||||
STVX (23, 9, 3)
|
||||
LI (9, 80)
|
||||
STVX (24, 11, 3)
|
||||
LI (11, 96)
|
||||
STVX (25, 9, 3)
|
||||
LI (9, 112)
|
||||
STVX (26, 11, 3)
|
||||
LI (11, 128)
|
||||
STVX (27, 9, 3)
|
||||
LI (9, 144)
|
||||
STVX (28, 11, 3)
|
||||
LI (11, 160)
|
||||
STVX (29, 9, 3)
|
||||
LI (9, 176)
|
||||
STVX (30, 11, 3)
|
||||
STVX (31, 9, 3));
|
||||
}
|
||||
|
||||
static void state_restore_altivec (cpu_state_t * state)
|
||||
{
|
||||
asm (LI (9, 16)
|
||||
LVX0 (20, 0, 3)
|
||||
LI (11, 32)
|
||||
LVX (21, 9, 3)
|
||||
LI (9, 48)
|
||||
LVX (22, 11, 3)
|
||||
LI (11, 64)
|
||||
LVX (23, 9, 3)
|
||||
LI (9, 80)
|
||||
LVX (24, 11, 3)
|
||||
LI (11, 96)
|
||||
LVX (25, 9, 3)
|
||||
LI (9, 112)
|
||||
LVX (26, 11, 3)
|
||||
LI (11, 128)
|
||||
LVX (27, 9, 3)
|
||||
LI (9, 144)
|
||||
LVX (28, 11, 3)
|
||||
LI (11, 160)
|
||||
LVX (29, 9, 3)
|
||||
LI (9, 176)
|
||||
LVX (30, 11, 3)
|
||||
LVX (31, 9, 3));
|
||||
}
|
||||
#endif
|
||||
|
||||
void mpeg2_cpu_state_init (uint32_t accel)
|
||||
{
|
||||
(void)accel;
|
||||
#ifdef ARCH_X86
|
||||
if (accel & MPEG2_ACCEL_X86_MMX) {
|
||||
mpeg2_cpu_state_restore = state_restore_mmx;
|
||||
}
|
||||
#endif
|
||||
#ifdef ARCH_PPC
|
||||
if (accel & MPEG2_ACCEL_PPC_ALTIVEC) {
|
||||
mpeg2_cpu_state_save = state_save_altivec;
|
||||
mpeg2_cpu_state_restore = state_restore_altivec;
|
||||
}
|
||||
#endif
|
||||
}
|
447
apps/plugins/mpegplayer/decode.c
Normal file
447
apps/plugins/mpegplayer/decode.c
Normal file
|
@ -0,0 +1,447 @@
|
|||
/*
|
||||
* decode.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "plugin.h"
|
||||
|
||||
#include "mpeg2dec_config.h"
|
||||
|
||||
extern struct plugin_api* rb;
|
||||
|
||||
#include "mpeg2.h"
|
||||
#include "attributes.h"
|
||||
#include "mpeg2_internal.h"
|
||||
|
||||
static int mpeg2_accels = 0;
|
||||
|
||||
#define BUFFER_SIZE (1194 * 1024)
|
||||
|
||||
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 (mpeg2_state_t)-1;
|
||||
}
|
||||
|
||||
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 ? mpeg2_parse_header (mpeg2dec) :
|
||||
mpeg2_header_picture_start (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 ((int)state >= 0)
|
||||
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;
|
||||
}
|
||||
|
||||
switch (mpeg2dec->code) {
|
||||
case 0x00:
|
||||
mpeg2dec->action = mpeg2_header_picture_start;
|
||||
return mpeg2dec->state;
|
||||
case 0xb7:
|
||||
mpeg2dec->action = mpeg2_header_end;
|
||||
break;
|
||||
case 0xb3:
|
||||
case 0xb8:
|
||||
mpeg2dec->action = mpeg2_parse_header;
|
||||
break;
|
||||
default:
|
||||
mpeg2dec->action = seek_chunk;
|
||||
return STATE_INVALID;
|
||||
}
|
||||
return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID;
|
||||
}
|
||||
|
||||
mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
|
||||
{
|
||||
static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = {
|
||||
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):
|
||||
mpeg2dec->action = mpeg2_header_picture_start;
|
||||
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);
|
||||
mpeg2dec->action = mpeg2_header_picture_start;
|
||||
break;
|
||||
case RECEIVED (0x01, STATE_PICTURE):
|
||||
case RECEIVED (0x01, STATE_PICTURE_2ND):
|
||||
mpeg2_header_picture_finalize (mpeg2dec, mpeg2_accels);
|
||||
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,
|
||||
mpeg2_accels, 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,
|
||||
mpeg2_accels, 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[3], 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];
|
||||
fbuf->buf[1] = buf[1];
|
||||
fbuf->buf[2] = buf[2];
|
||||
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;
|
||||
}
|
||||
|
||||
uint32_t mpeg2_accel (uint32_t accel)
|
||||
{
|
||||
if (!mpeg2_accels) {
|
||||
if (accel & MPEG2_ACCEL_DETECT)
|
||||
accel |= mpeg2_detect_accel ();
|
||||
mpeg2_accels = accel |= MPEG2_ACCEL_DETECT;
|
||||
mpeg2_cpu_state_init (accel);
|
||||
mpeg2_idct_init (accel);
|
||||
mpeg2_mc_init (accel);
|
||||
}
|
||||
return mpeg2_accels & ~MPEG2_ACCEL_DETECT;
|
||||
}
|
||||
|
||||
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_accel (MPEG2_ACCEL_DETECT);
|
||||
|
||||
mpeg2dec = (mpeg2dec_t *) mpeg2_malloc (sizeof (mpeg2dec_t),
|
||||
MPEG2_ALLOC_MPEG2DEC);
|
||||
if (mpeg2dec == NULL)
|
||||
return NULL;
|
||||
|
||||
rb->memset (mpeg2dec->decoder.DCTblock, 0, 64 * sizeof (int16_t));
|
||||
rb->memset (mpeg2dec->quantizer_matrix, 0, 4 * 64 * sizeof (uint8_t));
|
||||
|
||||
mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc (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);
|
||||
mpeg2_free (mpeg2dec->chunk_buffer);
|
||||
mpeg2_free (mpeg2dec);
|
||||
}
|
892
apps/plugins/mpegplayer/header.c
Normal file
892
apps/plugins/mpegplayer/header.c
Normal file
|
@ -0,0 +1,892 @@
|
|||
/*
|
||||
* header.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 2003 Regis Duchesne <hpreg@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "plugin.h"
|
||||
|
||||
#include "mpeg2dec_config.h"
|
||||
|
||||
extern struct plugin_api* rb;
|
||||
|
||||
#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] IBSS_ATTR = {
|
||||
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
|
||||
};
|
||||
|
||||
uint8_t mpeg2_scan_norm[64] ICONST_ATTR = {
|
||||
/* 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
|
||||
};
|
||||
|
||||
uint8_t mpeg2_scan_alt[64] ICONST_ATTR = {
|
||||
/* 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
|
||||
};
|
||||
|
||||
void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec)
|
||||
{
|
||||
if (mpeg2dec->sequence.width != (unsigned)-1) {
|
||||
int i;
|
||||
|
||||
mpeg2dec->sequence.width = (unsigned)-1;
|
||||
if (!mpeg2dec->custom_fbuf)
|
||||
for (i = mpeg2dec->alloc_index_user;
|
||||
i < mpeg2dec->alloc_index; i++) {
|
||||
mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[0]);
|
||||
mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[1]);
|
||||
mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[2]);
|
||||
}
|
||||
if (mpeg2dec->convert_start)
|
||||
for (i = 0; i < 3; i++) {
|
||||
mpeg2_free (mpeg2dec->yuv_buf[i][0]);
|
||||
mpeg2_free (mpeg2dec->yuv_buf[i][1]);
|
||||
mpeg2_free (mpeg2dec->yuv_buf[i][2]);
|
||||
}
|
||||
if (mpeg2dec->decoder.convert_id)
|
||||
mpeg2_free (mpeg2dec->decoder.convert_id);
|
||||
}
|
||||
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)
|
||||
{
|
||||
uint8_t * buffer = mpeg2dec->chunk_start;
|
||||
mpeg2_sequence_t * sequence = &(mpeg2dec->new_sequence);
|
||||
static 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
|
||||
};
|
||||
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->display_width = sequence->picture_width +=
|
||||
((buffer[1] << 13) | (buffer[2] << 5)) & 0x3000;
|
||||
sequence->display_height = sequence->picture_height +=
|
||||
(buffer[2] << 7) & 0x3000;
|
||||
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;
|
||||
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);
|
||||
uint32_t flags;
|
||||
|
||||
flags = ((sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) |
|
||||
((buffer[0]<<4) & SEQ_MASK_VIDEO_FORMAT));
|
||||
if (buffer[0] & 1) {
|
||||
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;
|
||||
|
||||
sequence->display_width = (buffer[1] << 6) | (buffer[2] >> 2);
|
||||
sequence->display_height =
|
||||
((buffer[2]& 1 ) << 13) | (buffer[3] << 5) | (buffer[4] >> 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 12: /* 720*480 4:3 */
|
||||
sequence->pixel_width = 8; sequence->pixel_height = 9; return;
|
||||
default:
|
||||
height = 88 * sequence->pixel_width + 1171;
|
||||
width = 2000;
|
||||
}
|
||||
}
|
||||
|
||||
sequence->pixel_width = width;
|
||||
sequence->pixel_height = height;
|
||||
while (width) { /* find greatest common divisor */
|
||||
int tmp = width;
|
||||
width = height % tmp;
|
||||
height = tmp;
|
||||
}
|
||||
sequence->pixel_width /= height;
|
||||
sequence->pixel_height /= height;
|
||||
}
|
||||
|
||||
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) {
|
||||
unsigned int new_byte_rate;
|
||||
|
||||
/*
|
||||
* According to 6.1.1.6, repeat sequence headers should be
|
||||
* identical to the original. However some DVDs dont respect
|
||||
* that and have different bitrates in the repeat sequence
|
||||
* headers. So we'll ignore that in the comparison and still
|
||||
* consider these as repeat sequence headers.
|
||||
*
|
||||
* However, be careful not to alter the current sequence when
|
||||
* returning STATE_INVALID_END.
|
||||
*/
|
||||
new_byte_rate = sequence->byte_rate;
|
||||
sequence->byte_rate = mpeg2dec->sequence.byte_rate;
|
||||
if (rb->memcmp (&(mpeg2dec->sequence), sequence,
|
||||
sizeof (mpeg2_sequence_t))) {
|
||||
decoder->stride_frame = sequence->width;
|
||||
sequence->byte_rate = new_byte_rate;
|
||||
mpeg2_header_end (mpeg2dec);
|
||||
mpeg2dec->action = invalid_end_action;
|
||||
mpeg2dec->state = STATE_INVALID_END;
|
||||
return;
|
||||
}
|
||||
sequence->byte_rate = new_byte_rate;
|
||||
mpeg2dec->state = 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;
|
||||
}
|
||||
}
|
||||
|
||||
mpeg2_state_t mpeg2_header_picture_start (mpeg2dec_t * mpeg2dec)
|
||||
{
|
||||
mpeg2_picture_t * picture = &(mpeg2dec->new_picture);
|
||||
|
||||
mpeg2dec->state = ((mpeg2dec->state != STATE_SLICE_1ST) ?
|
||||
STATE_PICTURE : STATE_PICTURE_2ND);
|
||||
picture->flags = 0;
|
||||
picture->tag = picture->tag2 = 0;
|
||||
if (mpeg2dec->num_tags) {
|
||||
if (mpeg2dec->bytes_since_tag >= 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->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;
|
||||
return mpeg2_parse_header (mpeg2dec);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
type = (buffer [1] >> 3) & 7;
|
||||
mpeg2dec->ext_state = PIC_CODING_EXT;
|
||||
|
||||
picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6);
|
||||
|
||||
picture->flags |= type;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* XXXXXX decode extra_information_picture as well */
|
||||
|
||||
picture->nb_fields = 2;
|
||||
|
||||
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;
|
||||
flags |= (buffer[4] & 0x80) ? PIC_FLAG_PROGRESSIVE_FRAME : 0;
|
||||
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, uint32_t accels)
|
||||
{
|
||||
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) {
|
||||
int y_size, uv_size;
|
||||
|
||||
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, accels,
|
||||
mpeg2dec->convert_arg, &convert_init);
|
||||
mpeg2dec->convert_start = convert_init.start;
|
||||
mpeg2dec->decoder.convert = convert_init.copy;
|
||||
|
||||
y_size = decoder->stride_frame * mpeg2dec->sequence.height;
|
||||
uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format);
|
||||
mpeg2dec->yuv_buf[0][0] =
|
||||
(uint8_t *) mpeg2_malloc (y_size, MPEG2_ALLOC_YUV);
|
||||
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);
|
||||
mpeg2dec->yuv_buf[1][0] =
|
||||
(uint8_t *) mpeg2_malloc (y_size, MPEG2_ALLOC_YUV);
|
||||
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);
|
||||
y_size = decoder->stride_frame * 32;
|
||||
uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format);
|
||||
mpeg2dec->yuv_buf[2][0] =
|
||||
(uint8_t *) mpeg2_malloc (y_size, MPEG2_ALLOC_YUV);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE));
|
||||
}
|
||||
} else if (!mpeg2dec->custom_fbuf) {
|
||||
while (mpeg2dec->alloc_index < 3) {
|
||||
mpeg2_fbuf_t * fbuf;
|
||||
int y_size, uv_size;
|
||||
|
||||
fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf);
|
||||
fbuf->id = NULL;
|
||||
y_size = decoder->stride_frame * mpeg2dec->sequence.height;
|
||||
uv_size = y_size >> (2 - decoder->chroma_format);
|
||||
fbuf->buf[0] = (uint8_t *) mpeg2_malloc (y_size,
|
||||
MPEG2_ALLOC_YUV);
|
||||
fbuf->buf[1] = (uint8_t *) mpeg2_malloc (uv_size,
|
||||
MPEG2_ALLOC_YUV);
|
||||
fbuf->buf[2] = (uint8_t *) mpeg2_malloc (uv_size,
|
||||
MPEG2_ALLOC_YUV);
|
||||
}
|
||||
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 (* parser[]) (mpeg2dec_t *) = {
|
||||
0, sequence_ext, sequence_display_ext, quant_matrix_ext,
|
||||
copyright_ext, 0, 0, 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 int non_linear_scale [] = {
|
||||
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 (mpeg2_state_t)-1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
287
apps/plugins/mpegplayer/idct.c
Normal file
287
apps/plugins/mpegplayer/idct.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* idct.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "plugin.h"
|
||||
|
||||
#include "mpeg2dec_config.h"
|
||||
|
||||
#include "mpeg2.h"
|
||||
#include "attributes.h"
|
||||
#include "mpeg2_internal.h"
|
||||
|
||||
#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) */
|
||||
|
||||
/* idct main entry point */
|
||||
void (* mpeg2_idct_copy) (int16_t * block, uint8_t * dest, int stride);
|
||||
void (* mpeg2_idct_add) (int last, int16_t * block,
|
||||
uint8_t * dest, int stride);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
uint8_t mpeg2_clip[3840 * 2 + 256] IBSS_ATTR;
|
||||
#define CLIP(i) ((mpeg2_clip + 3840)[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;
|
||||
}
|
||||
|
||||
static void mpeg2_idct_copy_c (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);
|
||||
}
|
||||
|
||||
static void mpeg2_idct_add_c (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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void mpeg2_idct_init (uint32_t accel)
|
||||
{
|
||||
(void)accel;
|
||||
#ifdef ARCH_X86
|
||||
if (accel & MPEG2_ACCEL_X86_MMXEXT) {
|
||||
mpeg2_idct_copy = mpeg2_idct_copy_mmxext;
|
||||
mpeg2_idct_add = mpeg2_idct_add_mmxext;
|
||||
mpeg2_idct_mmx_init ();
|
||||
} else if (accel & MPEG2_ACCEL_X86_MMX) {
|
||||
mpeg2_idct_copy = mpeg2_idct_copy_mmx;
|
||||
mpeg2_idct_add = mpeg2_idct_add_mmx;
|
||||
mpeg2_idct_mmx_init ();
|
||||
} else
|
||||
#endif
|
||||
#ifdef ARCH_PPC
|
||||
if (accel & MPEG2_ACCEL_PPC_ALTIVEC) {
|
||||
mpeg2_idct_copy = mpeg2_idct_copy_altivec;
|
||||
mpeg2_idct_add = mpeg2_idct_add_altivec;
|
||||
mpeg2_idct_altivec_init ();
|
||||
} else
|
||||
#endif
|
||||
#ifdef ARCH_ALPHA
|
||||
if (accel & MPEG2_ACCEL_ALPHA_MVI) {
|
||||
mpeg2_idct_copy = mpeg2_idct_copy_mvi;
|
||||
mpeg2_idct_add = mpeg2_idct_add_mvi;
|
||||
mpeg2_idct_alpha_init ();
|
||||
} else if (accel & MPEG2_ACCEL_ALPHA) {
|
||||
int i;
|
||||
|
||||
mpeg2_idct_copy = mpeg2_idct_copy_alpha;
|
||||
mpeg2_idct_add = mpeg2_idct_add_alpha;
|
||||
mpeg2_idct_alpha_init ();
|
||||
for (i = -3840; i < 3840 + 256; i++)
|
||||
CLIP(i) = (i < 0) ? 0 : ((i > 255) ? 255 : i);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
extern uint8_t mpeg2_scan_norm[64];
|
||||
extern uint8_t mpeg2_scan_alt[64];
|
||||
int i, j;
|
||||
|
||||
mpeg2_idct_copy = mpeg2_idct_copy_c;
|
||||
mpeg2_idct_add = mpeg2_idct_add_c;
|
||||
for (i = -3840; i < 3840 + 256; i++)
|
||||
CLIP(i) = (i < 0) ? 0 : ((i > 255) ? 255 : i);
|
||||
for (i = 0; i < 64; i++) {
|
||||
j = mpeg2_scan_norm[i];
|
||||
mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
|
||||
j = mpeg2_scan_alt[i];
|
||||
mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
|
||||
}
|
||||
}
|
||||
}
|
131
apps/plugins/mpegplayer/motion_comp.c
Normal file
131
apps/plugins/mpegplayer/motion_comp.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* motion_comp.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "plugin.h"
|
||||
|
||||
#include "mpeg2dec_config.h"
|
||||
|
||||
#include "mpeg2.h"
|
||||
#include "attributes.h"
|
||||
#include "mpeg2_internal.h"
|
||||
|
||||
mpeg2_mc_t mpeg2_mc;
|
||||
|
||||
void mpeg2_mc_init (uint32_t accel)
|
||||
{
|
||||
(void)accel;
|
||||
#ifdef ARCH_X86
|
||||
if (accel & MPEG2_ACCEL_X86_MMXEXT)
|
||||
mpeg2_mc = mpeg2_mc_mmxext;
|
||||
else if (accel & MPEG2_ACCEL_X86_3DNOW)
|
||||
mpeg2_mc = mpeg2_mc_3dnow;
|
||||
else if (accel & MPEG2_ACCEL_X86_MMX)
|
||||
mpeg2_mc = mpeg2_mc_mmx;
|
||||
else
|
||||
#endif
|
||||
#ifdef ARCH_PPC
|
||||
if (accel & MPEG2_ACCEL_PPC_ALTIVEC)
|
||||
mpeg2_mc = mpeg2_mc_altivec;
|
||||
else
|
||||
#endif
|
||||
#ifdef ARCH_ALPHA
|
||||
if (accel & MPEG2_ACCEL_ALPHA)
|
||||
mpeg2_mc = mpeg2_mc_alpha;
|
||||
else
|
||||
#endif
|
||||
#ifdef ARCH_SPARC
|
||||
if (accel & MPEG2_ACCEL_SPARC_VIS)
|
||||
mpeg2_mc = mpeg2_mc_vis;
|
||||
else
|
||||
#endif
|
||||
mpeg2_mc = mpeg2_mc_c;
|
||||
}
|
||||
|
||||
#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) \
|
||||
static void MC_##op##_##xy##_16_c (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); \
|
||||
} \
|
||||
static void MC_##op##_##xy##_8_c (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); \
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
MPEG2_MC_EXTERN (c)
|
195
apps/plugins/mpegplayer/mpeg2.h
Normal file
195
apps/plugins/mpegplayer/mpeg2.h
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* mpeg2.h
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef MPEG2_H
|
||||
#define MPEG2_H
|
||||
|
||||
#define MPEG2_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
|
||||
#define MPEG2_RELEASE MPEG2_VERSION (0, 4, 0) /* 0.4.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 0
|
||||
#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[3];
|
||||
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_BUFFER = 0,
|
||||
STATE_SEQUENCE = 1,
|
||||
STATE_SEQUENCE_REPEATED = 2,
|
||||
STATE_GOP = 3,
|
||||
STATE_PICTURE = 4,
|
||||
STATE_SLICE_1ST = 5,
|
||||
STATE_PICTURE_2ND = 6,
|
||||
STATE_SLICE = 7,
|
||||
STATE_END = 8,
|
||||
STATE_INVALID = 9,
|
||||
STATE_INVALID_END = 10
|
||||
} mpeg2_state_t;
|
||||
|
||||
typedef struct mpeg2_convert_init_s {
|
||||
unsigned int id_size;
|
||||
unsigned int buf_size[3];
|
||||
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,
|
||||
uint32_t accel, 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[3], void * id);
|
||||
void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf);
|
||||
|
||||
#define MPEG2_ACCEL_X86_MMX 1
|
||||
#define MPEG2_ACCEL_X86_3DNOW 2
|
||||
#define MPEG2_ACCEL_X86_MMXEXT 4
|
||||
#define MPEG2_ACCEL_PPC_ALTIVEC 1
|
||||
#define MPEG2_ACCEL_ALPHA 1
|
||||
#define MPEG2_ACCEL_ALPHA_MVI 2
|
||||
#define MPEG2_ACCEL_SPARC_VIS 1
|
||||
#define MPEG2_ACCEL_SPARC_VIS2 2
|
||||
#define MPEG2_ACCEL_DETECT 0x80000000
|
||||
|
||||
uint32_t mpeg2_accel (uint32_t accel);
|
||||
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[3],
|
||||
uint8_t * forward_fbuf[3], uint8_t * backward_fbuf[3]);
|
||||
void mpeg2_slice (mpeg2_decoder_t * decoder, int code, const uint8_t * buffer);
|
||||
|
||||
typedef enum {
|
||||
MPEG2_ALLOC_MPEG2DEC = 0,
|
||||
MPEG2_ALLOC_CHUNK = 1,
|
||||
MPEG2_ALLOC_YUV = 2,
|
||||
MPEG2_ALLOC_CONVERT_ID = 3,
|
||||
MPEG2_ALLOC_CONVERTED = 4
|
||||
} mpeg2_alloc_t;
|
||||
|
||||
void * mpeg2_malloc (unsigned size, mpeg2_alloc_t reason);
|
||||
void mpeg2_free (void * buf);
|
||||
void mpeg2_alloc_init(unsigned char* buf, int mallocsize);
|
||||
|
||||
#endif /* MPEG2_H */
|
300
apps/plugins/mpegplayer/mpeg2_internal.h
Normal file
300
apps/plugins/mpegplayer/mpeg2_internal.h
Normal file
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* mpeg2_internal.h
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* 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][3];
|
||||
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[3];
|
||||
|
||||
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[3];
|
||||
|
||||
/* DCT coefficients */
|
||||
int16_t DCTblock[64] ATTR_ALIGN(64);
|
||||
|
||||
uint8_t * picture_dest[3];
|
||||
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 * 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][3];
|
||||
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];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
#ifdef ARCH_PPC
|
||||
uint8_t regv[12*16];
|
||||
#endif
|
||||
int dummy;
|
||||
} cpu_state_t;
|
||||
|
||||
/* cpu_accel.c */
|
||||
uint32_t mpeg2_detect_accel (void);
|
||||
|
||||
/* cpu_state.c */
|
||||
void mpeg2_cpu_state_init (uint32_t accel);
|
||||
|
||||
/* 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);
|
||||
mpeg2_state_t mpeg2_header_picture_start (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, uint32_t accels);
|
||||
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 (uint32_t accel);
|
||||
|
||||
/* idct_mmx.c */
|
||||
void mpeg2_idct_copy_mmxext (int16_t * block, uint8_t * dest, int stride);
|
||||
void mpeg2_idct_add_mmxext (int last, int16_t * block,
|
||||
uint8_t * dest, int stride);
|
||||
void mpeg2_idct_copy_mmx (int16_t * block, uint8_t * dest, int stride);
|
||||
void mpeg2_idct_add_mmx (int last, int16_t * block,
|
||||
uint8_t * dest, int stride);
|
||||
void mpeg2_idct_mmx_init (void);
|
||||
|
||||
/* idct_altivec.c */
|
||||
void mpeg2_idct_copy_altivec (int16_t * block, uint8_t * dest, int stride);
|
||||
void mpeg2_idct_add_altivec (int last, int16_t * block,
|
||||
uint8_t * dest, int stride);
|
||||
void mpeg2_idct_altivec_init (void);
|
||||
|
||||
/* idct_alpha.c */
|
||||
void mpeg2_idct_copy_mvi (int16_t * block, uint8_t * dest, int stride);
|
||||
void mpeg2_idct_add_mvi (int last, int16_t * block,
|
||||
uint8_t * dest, int stride);
|
||||
void mpeg2_idct_copy_alpha (int16_t * block, uint8_t * dest, int stride);
|
||||
void mpeg2_idct_add_alpha (int last, int16_t * block,
|
||||
uint8_t * dest, int stride);
|
||||
void mpeg2_idct_alpha_init (void);
|
||||
|
||||
/* motion_comp.c */
|
||||
void mpeg2_mc_init (uint32_t accel);
|
||||
|
||||
typedef struct {
|
||||
mpeg2_mc_fct * put [8];
|
||||
mpeg2_mc_fct * avg [8];
|
||||
} mpeg2_mc_t;
|
||||
|
||||
#define MPEG2_MC_EXTERN(x) mpeg2_mc_t mpeg2_mc_##x = { \
|
||||
{MC_put_o_16_##x, MC_put_x_16_##x, MC_put_y_16_##x, MC_put_xy_16_##x, \
|
||||
MC_put_o_8_##x, MC_put_x_8_##x, MC_put_y_8_##x, MC_put_xy_8_##x}, \
|
||||
{MC_avg_o_16_##x, MC_avg_x_16_##x, MC_avg_y_16_##x, MC_avg_xy_16_##x, \
|
||||
MC_avg_o_8_##x, MC_avg_x_8_##x, MC_avg_y_8_##x, MC_avg_xy_8_##x} \
|
||||
};
|
||||
|
||||
extern mpeg2_mc_t mpeg2_mc_c;
|
||||
extern mpeg2_mc_t mpeg2_mc_mmx;
|
||||
extern mpeg2_mc_t mpeg2_mc_mmxext;
|
||||
extern mpeg2_mc_t mpeg2_mc_3dnow;
|
||||
extern mpeg2_mc_t mpeg2_mc_altivec;
|
||||
extern mpeg2_mc_t mpeg2_mc_alpha;
|
||||
extern mpeg2_mc_t mpeg2_mc_vis;
|
2
apps/plugins/mpegplayer/mpeg2dec_config.h
Normal file
2
apps/plugins/mpegplayer/mpeg2dec_config.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define ATTRIBUTE_ALIGNED_MAX 16
|
||||
|
246
apps/plugins/mpegplayer/mpegplayer.c
Normal file
246
apps/plugins/mpegplayer/mpegplayer.c
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* mpegplayer.c - based on mpeg2dec.c
|
||||
*
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "mpeg2dec_config.h"
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "mpeg2.h"
|
||||
#include "video_out.h"
|
||||
|
||||
PLUGIN_HEADER
|
||||
|
||||
#ifdef USE_IRAM
|
||||
extern char iramcopy[];
|
||||
extern char iramstart[];
|
||||
extern char iramend[];
|
||||
extern char iedata[];
|
||||
extern char iend[];
|
||||
#endif
|
||||
|
||||
struct plugin_api* rb;
|
||||
|
||||
#define BUFFER_SIZE 25*1024*1024
|
||||
|
||||
static mpeg2dec_t * mpeg2dec;
|
||||
static vo_open_t * output_open = NULL;
|
||||
static vo_instance_t * output;
|
||||
static int total_offset = 0;
|
||||
|
||||
extern vo_open_t vo_rockbox_open;
|
||||
|
||||
static void decode_mpeg2 (uint8_t * current, uint8_t * end)
|
||||
{
|
||||
const mpeg2_info_t * info;
|
||||
mpeg2_state_t state;
|
||||
vo_setup_result_t setup_result;
|
||||
|
||||
mpeg2_buffer (mpeg2dec, current, end);
|
||||
total_offset += end - current;
|
||||
|
||||
info = mpeg2_info (mpeg2dec);
|
||||
while (1) {
|
||||
state = mpeg2_parse (mpeg2dec);
|
||||
|
||||
switch (state) {
|
||||
case STATE_BUFFER:
|
||||
return;
|
||||
case STATE_SEQUENCE:
|
||||
/* might set nb fbuf, convert format, stride */
|
||||
/* might set fbufs */
|
||||
if (output->setup (output, info->sequence->width,
|
||||
info->sequence->height,
|
||||
info->sequence->chroma_width,
|
||||
info->sequence->chroma_height, &setup_result)) {
|
||||
//fprintf (stderr, "display setup failed\n");
|
||||
return;
|
||||
}
|
||||
if (setup_result.convert &&
|
||||
mpeg2_convert (mpeg2dec, setup_result.convert, NULL)) {
|
||||
//fprintf (stderr, "color conversion setup failed\n");
|
||||
return;
|
||||
}
|
||||
if (output->set_fbuf) {
|
||||
uint8_t * buf[3];
|
||||
void * id;
|
||||
|
||||
mpeg2_custom_fbuf (mpeg2dec, 1);
|
||||
output->set_fbuf (output, buf, &id);
|
||||
mpeg2_set_buf (mpeg2dec, buf, id);
|
||||
output->set_fbuf (output, buf, &id);
|
||||
mpeg2_set_buf (mpeg2dec, buf, id);
|
||||
} else if (output->setup_fbuf) {
|
||||
uint8_t * buf[3];
|
||||
void * id;
|
||||
|
||||
output->setup_fbuf (output, buf, &id);
|
||||
mpeg2_set_buf (mpeg2dec, buf, id);
|
||||
output->setup_fbuf (output, buf, &id);
|
||||
mpeg2_set_buf (mpeg2dec, buf, id);
|
||||
output->setup_fbuf (output, buf, &id);
|
||||
mpeg2_set_buf (mpeg2dec, buf, id);
|
||||
}
|
||||
mpeg2_skip (mpeg2dec, (output->draw == NULL));
|
||||
break;
|
||||
case STATE_PICTURE:
|
||||
/* might skip */
|
||||
/* might set fbuf */
|
||||
if (output->set_fbuf) {
|
||||
uint8_t * buf[3];
|
||||
void * id;
|
||||
|
||||
output->set_fbuf (output, buf, &id);
|
||||
mpeg2_set_buf (mpeg2dec, buf, id);
|
||||
}
|
||||
if (output->start_fbuf)
|
||||
output->start_fbuf (output, info->current_fbuf->buf,
|
||||
info->current_fbuf->id);
|
||||
break;
|
||||
case STATE_SLICE:
|
||||
case STATE_END:
|
||||
case STATE_INVALID_END:
|
||||
/* draw current picture */
|
||||
/* might free frame buffer */
|
||||
if (info->display_fbuf) {
|
||||
if (output->draw)
|
||||
output->draw (output, info->display_fbuf->buf,
|
||||
info->display_fbuf->id);
|
||||
//print_fps (0);
|
||||
}
|
||||
if (output->discard && info->discard_fbuf)
|
||||
output->discard (output, info->discard_fbuf->buf,
|
||||
info->discard_fbuf->id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rb->yield();
|
||||
}
|
||||
}
|
||||
|
||||
static void es_loop (int in_file)
|
||||
{
|
||||
static uint8_t* buffer;
|
||||
uint8_t * end;
|
||||
|
||||
buffer=mpeg2_malloc(BUFFER_SIZE,0);
|
||||
|
||||
if (buffer==NULL)
|
||||
return;
|
||||
|
||||
do {
|
||||
rb->splash(0,true,"Buffering...");
|
||||
end = buffer + rb->read (in_file, buffer, BUFFER_SIZE);
|
||||
decode_mpeg2 (buffer, end);
|
||||
} while (end == buffer + BUFFER_SIZE);
|
||||
}
|
||||
|
||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||
{
|
||||
(void)parameter;
|
||||
void* audiobuf;
|
||||
int audiosize;
|
||||
int in_file;
|
||||
|
||||
rb = api;
|
||||
|
||||
/* This also stops audio playback - so we do it before using IRAM */
|
||||
audiobuf = rb->plugin_get_audio_buffer(&audiosize);
|
||||
|
||||
/* Initialise our malloc buffer */
|
||||
mpeg2_alloc_init(audiobuf,audiosize);
|
||||
|
||||
#ifdef USE_IRAM
|
||||
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
|
||||
rb->memset(iedata, 0, iend - iedata);
|
||||
#endif
|
||||
|
||||
#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 (parameter == NULL) {
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
|
||||
in_file = rb->open((char*)parameter,O_RDONLY);
|
||||
|
||||
if (in_file < 0) {
|
||||
//fprintf(stderr,"Could not open %s\n",argv[1]);
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
|
||||
output_open = vo_rockbox_open;
|
||||
|
||||
if (output_open == NULL) {
|
||||
//fprintf (stderr, "output_open is NULL\n");
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
|
||||
output = output_open ();
|
||||
|
||||
if (output == NULL) {
|
||||
//fprintf (stderr, "Can not open output\n");
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
|
||||
mpeg2dec = mpeg2_init ();
|
||||
|
||||
if (mpeg2dec == NULL)
|
||||
return PLUGIN_ERROR;
|
||||
|
||||
/* make sure the backlight is always on when viewing video
|
||||
(actually it should also set the timeout when plugged in,
|
||||
but the function backlight_set_timeout_plugged is not
|
||||
available in plugins) */
|
||||
#ifdef CONFIG_BACKLIGHT
|
||||
if (rb->global_settings->backlight_timeout > 0)
|
||||
rb->backlight_set_timeout(1);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
rb->cpu_boost(true);
|
||||
#endif
|
||||
|
||||
es_loop (in_file);
|
||||
|
||||
mpeg2_close (mpeg2dec);
|
||||
|
||||
rb->close (in_file);
|
||||
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
rb->cpu_boost(false);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT
|
||||
/* reset backlight settings */
|
||||
rb->backlight_set_timeout(rb->global_settings->backlight_timeout);
|
||||
#endif
|
||||
|
||||
return PLUGIN_OK;
|
||||
}
|
2060
apps/plugins/mpegplayer/slice.c
Normal file
2060
apps/plugins/mpegplayer/slice.c
Normal file
File diff suppressed because it is too large
Load Diff
58
apps/plugins/mpegplayer/video_out.h
Normal file
58
apps/plugins/mpegplayer/video_out.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* video_out.h
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
struct mpeg2_sequence_s;
|
||||
struct mpeg2_convert_init_s;
|
||||
typedef struct {
|
||||
int (* convert) (int stage, void * id,
|
||||
const struct mpeg2_sequence_s * sequence,
|
||||
int stride, uint32_t accel, void * arg,
|
||||
struct mpeg2_convert_init_s * result);
|
||||
} vo_setup_result_t;
|
||||
|
||||
typedef struct vo_instance_s vo_instance_t;
|
||||
struct vo_instance_s {
|
||||
int (* setup) (vo_instance_t * instance, unsigned int width,
|
||||
unsigned int height, unsigned int chroma_width,
|
||||
unsigned int chroma_height, vo_setup_result_t * result);
|
||||
void (* setup_fbuf) (vo_instance_t * instance, uint8_t ** buf, void ** id);
|
||||
void (* set_fbuf) (vo_instance_t * instance, uint8_t ** buf, void ** id);
|
||||
void (* start_fbuf) (vo_instance_t * instance,
|
||||
uint8_t * const * buf, void * id);
|
||||
void (* draw) (vo_instance_t * instance, uint8_t * const * buf, void * id);
|
||||
void (* discard) (vo_instance_t * instance,
|
||||
uint8_t * const * buf, void * id);
|
||||
void (* close) (vo_instance_t * instance);
|
||||
};
|
||||
|
||||
typedef vo_instance_t * vo_open_t (void);
|
||||
|
||||
typedef struct {
|
||||
char * name;
|
||||
vo_open_t * open;
|
||||
} vo_driver_t;
|
||||
|
||||
void vo_accel (uint32_t accel);
|
||||
|
||||
/* return NULL terminated array of all drivers */
|
||||
vo_driver_t const * vo_drivers (void);
|
285
apps/plugins/mpegplayer/video_out_rockbox.c
Normal file
285
apps/plugins/mpegplayer/video_out_rockbox.c
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* video_out_null.c
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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 "mpeg2dec_config.h"
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
extern struct plugin_api* rb;
|
||||
|
||||
#include "mpeg2.h"
|
||||
#include "video_out.h"
|
||||
|
||||
static int starttick;
|
||||
|
||||
#define CSUB_X 2
|
||||
#define CSUB_Y 2
|
||||
|
||||
static int image_x;
|
||||
static int image_y;
|
||||
static int image_width;
|
||||
static int image_height;
|
||||
static int image_chroma_x;
|
||||
static int image_chroma_y;
|
||||
|
||||
#if (LCD_DEPTH == 16) && \
|
||||
((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED))
|
||||
|
||||
#define RYFAC (31*257)
|
||||
#define GYFAC (63*257)
|
||||
#define BYFAC (31*257)
|
||||
#define RVFAC 11170 /* 31 * 257 * 1.402 */
|
||||
#define GVFAC (-11563) /* 63 * 257 * -0.714136 */
|
||||
#define GUFAC (-5572) /* 63 * 257 * -0.344136 */
|
||||
#define BUFAC 14118 /* 31 * 257 * 1.772 */
|
||||
|
||||
#define ROUNDOFFS (127*257)
|
||||
|
||||
/* Draw a partial YUV colour bitmap - taken from the Rockbox JPEG viewer */
|
||||
void yuv_bitmap_part(unsigned char * const src[3],
|
||||
int src_x, int src_y, int stride,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
fb_data *dst, *dst_end;
|
||||
|
||||
/* nothing to draw? */
|
||||
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
|
||||
|| (x + width <= 0) || (y + height <= 0))
|
||||
return;
|
||||
|
||||
/* clipping */
|
||||
if (x < 0)
|
||||
{
|
||||
width += x;
|
||||
src_x -= x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
height += y;
|
||||
src_y -= y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + width > LCD_WIDTH)
|
||||
width = LCD_WIDTH - x;
|
||||
if (y + height > LCD_HEIGHT)
|
||||
height = LCD_HEIGHT - y;
|
||||
|
||||
dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
|
||||
dst_end = dst + LCD_WIDTH * height;
|
||||
|
||||
do
|
||||
{
|
||||
fb_data *dst_row = dst;
|
||||
fb_data *row_end = dst_row + width;
|
||||
const unsigned char *ysrc = src[0] + stride * src_y + src_x;
|
||||
int y, u, v;
|
||||
int red, green, blue;
|
||||
unsigned rbits, gbits, bbits;
|
||||
|
||||
if (CSUB_Y) /* colour */
|
||||
{
|
||||
/* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
|
||||
const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y)
|
||||
+ (src_x/CSUB_X);
|
||||
const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y)
|
||||
+ (src_x/CSUB_X);
|
||||
int xphase = src_x % CSUB_X;
|
||||
int rc, gc, bc;
|
||||
|
||||
u = *usrc++ - 128;
|
||||
v = *vsrc++ - 128;
|
||||
rc = RVFAC * v + ROUNDOFFS;
|
||||
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
|
||||
bc = BUFAC * u + ROUNDOFFS;
|
||||
|
||||
do
|
||||
{
|
||||
y = *ysrc++;
|
||||
red = RYFAC * y + rc;
|
||||
green = GYFAC * y + gc;
|
||||
blue = BYFAC * y + bc;
|
||||
|
||||
if ((unsigned)red > (RYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (red < 0)
|
||||
red = 0;
|
||||
else
|
||||
red = (RYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)green > (GYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (green < 0)
|
||||
green = 0;
|
||||
else
|
||||
green = (GYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)blue > (BYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (blue < 0)
|
||||
blue = 0;
|
||||
else
|
||||
blue = (BYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
rbits = ((unsigned)red) >> 16 ;
|
||||
gbits = ((unsigned)green) >> 16 ;
|
||||
bbits = ((unsigned)blue) >> 16 ;
|
||||
#if LCD_PIXELFORMAT == RGB565
|
||||
*dst_row++ = (rbits << 11) | (gbits << 5) | bbits;
|
||||
#elif LCD_PIXELFORMAT == RGB565SWAPPED
|
||||
*dst_row++ = swap16((rbits << 11) | (gbits << 5) | bbits);
|
||||
#endif
|
||||
|
||||
if (++xphase >= CSUB_X)
|
||||
{
|
||||
u = *usrc++ - 128;
|
||||
v = *vsrc++ - 128;
|
||||
rc = RVFAC * v + ROUNDOFFS;
|
||||
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
|
||||
bc = BUFAC * u + ROUNDOFFS;
|
||||
xphase = 0;
|
||||
}
|
||||
}
|
||||
while (dst_row < row_end);
|
||||
}
|
||||
else /* monochrome */
|
||||
{
|
||||
do
|
||||
{
|
||||
y = *ysrc++;
|
||||
red = RYFAC * y + ROUNDOFFS; /* blue == red */
|
||||
green = GYFAC * y + ROUNDOFFS;
|
||||
rbits = ((unsigned)red) >> 16;
|
||||
gbits = ((unsigned)green) >> 16;
|
||||
#if LCD_PIXELFORMAT == RGB565
|
||||
*dst_row++ = (rbits << 11) | (gbits << 5) | rbits;
|
||||
#elif LCD_PIXELFORMAT == RGB565SWAPPED
|
||||
*dst_row++ = swap16((rbits << 11) | (gbits << 5) | rbits);
|
||||
#endif
|
||||
}
|
||||
while (dst_row < row_end);
|
||||
}
|
||||
|
||||
src_y++;
|
||||
dst += LCD_WIDTH;
|
||||
}
|
||||
while (dst < dst_end);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rockbox_draw_frame (vo_instance_t * instance,
|
||||
uint8_t * const * buf, void * id)
|
||||
{
|
||||
char str[80];
|
||||
static int frame=0;
|
||||
int ticks,fps;
|
||||
|
||||
(void)id;
|
||||
(void)instance;
|
||||
|
||||
#if (CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO) && \
|
||||
!defined(SIMULATOR)
|
||||
rb->lcd_yuv_blit(buf,
|
||||
0,0,image_width,
|
||||
image_x,image_y,image_width,image_height);
|
||||
#elif (LCD_DEPTH == 16) && \
|
||||
((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED))
|
||||
yuv_bitmap_part(buf,0,0,image_width,
|
||||
image_x,image_y,image_width,image_height);
|
||||
rb->lcd_update_rect(image_x,image_y,image_width,image_height);
|
||||
#endif
|
||||
|
||||
if (starttick==0) starttick=*rb->current_tick-1; /* Avoid divby0 */
|
||||
|
||||
/* Calculate fps */
|
||||
frame++;
|
||||
if ((frame % 125) == 0) {
|
||||
ticks=(*rb->current_tick)-starttick;
|
||||
|
||||
fps=(frame*1000)/ticks;
|
||||
rb->snprintf(str,sizeof(str),"%d.%d",(fps/10),fps%10);
|
||||
rb->lcd_putsxy(0,0,str);
|
||||
|
||||
rb->lcd_update_rect(0,0,80,8);
|
||||
}
|
||||
}
|
||||
|
||||
vo_instance_t static_instance;
|
||||
|
||||
static vo_instance_t * internal_open (int setup (vo_instance_t *, unsigned int,
|
||||
unsigned int, unsigned int,
|
||||
unsigned int,
|
||||
vo_setup_result_t *),
|
||||
void draw (vo_instance_t *,
|
||||
uint8_t * const *, void *))
|
||||
{
|
||||
vo_instance_t * instance;
|
||||
|
||||
instance = (vo_instance_t *) &static_instance;
|
||||
if (instance == NULL)
|
||||
return NULL;
|
||||
|
||||
instance->setup = setup;
|
||||
instance->setup_fbuf = NULL;
|
||||
instance->set_fbuf = NULL;
|
||||
instance->start_fbuf = NULL;
|
||||
instance->draw = draw;
|
||||
instance->discard = NULL;
|
||||
//instance->close = (void (*) (vo_instance_t *)) free;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
static int rockbox_setup (vo_instance_t * instance, unsigned int width,
|
||||
unsigned int height, unsigned int chroma_width,
|
||||
unsigned int chroma_height,
|
||||
vo_setup_result_t * result)
|
||||
{
|
||||
(void)instance;
|
||||
|
||||
result->convert = NULL;
|
||||
|
||||
image_width=width;
|
||||
image_height=height;
|
||||
image_chroma_x=image_width/chroma_width;
|
||||
image_chroma_y=image_height/chroma_height;
|
||||
|
||||
if (image_width >= LCD_WIDTH) {
|
||||
image_x = 0;
|
||||
} else {
|
||||
image_x = (LCD_WIDTH-image_width)/2;
|
||||
}
|
||||
|
||||
if (image_height >= LCD_HEIGHT) {
|
||||
image_y = 0;
|
||||
} else {
|
||||
image_y = (LCD_HEIGHT-image_height)/2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
vo_instance_t * vo_rockbox_open (void)
|
||||
{
|
||||
return internal_open (rockbox_setup, rockbox_draw_frame);
|
||||
}
|
429
apps/plugins/mpegplayer/vlc.h
Normal file
429
apps/plugins/mpegplayer/vlc.h
Normal file
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
* vlc.h
|
||||
* Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
|
||||
* Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#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 [] = {
|
||||
{INTRA|QUANT, 2}, {INTRA, 1}
|
||||
};
|
||||
|
||||
#define MC MACROBLOCK_MOTION_FORWARD
|
||||
#define CODED MACROBLOCK_PATTERN
|
||||
|
||||
static const MBtab MB_P [] = {
|
||||
{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 [] = {
|
||||
{0, 0}, {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 [] = {
|
||||
{ 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
|
||||
};
|
||||
|
||||
static const MVtab MV_10 [] = {
|
||||
{ 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 [] = {
|
||||
{ 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
|
||||
};
|
||||
|
||||
|
||||
static const CBPtab CBP_7 [] = {
|
||||
{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 [] = {
|
||||
{0, 0}, {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 [] = {
|
||||
{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 [] = {
|
||||
{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 [] = {
|
||||
{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 [] = {
|
||||
{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 [] = {
|
||||
{ 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 [] = {
|
||||
{ 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 [] = {
|
||||
{ 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 [] = {
|
||||
{ 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
|
||||
{ 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 [] = {
|
||||
{ 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 [] = {
|
||||
{ 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 [] = {
|
||||
{ 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 [] = {
|
||||
{ 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
|
||||
{ 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 [] = {
|
||||
{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 [] = {
|
||||
{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}
|
||||
};
|
|
@ -21,4 +21,4 @@ wav,viewers/wav2wv, 00 00 00 00 00 00
|
|||
wav,viewers/mp3_encoder, 00 00 00 00 00 00
|
||||
wav,viewers/wavplay,60 7F 05 35 3F 00
|
||||
bmp,rocks/rockpaint, 01 10 01 10 01 10
|
||||
|
||||
m2v,viewers/mpegplayer,60 7F 05 35 3F 00
|
||||
|
|
|
@ -400,6 +400,237 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
|
|||
(void)stride;
|
||||
}
|
||||
|
||||
#define CSUB_X 2
|
||||
#define CSUB_Y 2
|
||||
|
||||
#define RYFAC (31*257)
|
||||
#define GYFAC (63*257)
|
||||
#define BYFAC (31*257)
|
||||
#define RVFAC 11170 /* 31 * 257 * 1.402 */
|
||||
#define GVFAC (-11563) /* 63 * 257 * -0.714136 */
|
||||
#define GUFAC (-5572) /* 63 * 257 * -0.344136 */
|
||||
#define BUFAC 14118 /* 31 * 257 * 1.772 */
|
||||
|
||||
#define ROUNDOFFS (127*257)
|
||||
|
||||
/* Performance function to blit a YUV bitmap directly to the LCD */
|
||||
void lcd_yuv_blit(unsigned char * const src[3],
|
||||
int src_x, int src_y, int stride,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
int y0, x0, y1, x1;
|
||||
int h;
|
||||
|
||||
/* nothing to draw? */
|
||||
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
|
||||
|| (x + width <= 0) || (y + height <= 0))
|
||||
return;
|
||||
|
||||
/* clipping */
|
||||
if (x < 0)
|
||||
{
|
||||
width += x;
|
||||
src_x -= x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
height += y;
|
||||
src_y -= y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + width > LCD_WIDTH)
|
||||
width = LCD_WIDTH - x;
|
||||
if (y + height > LCD_HEIGHT)
|
||||
height = LCD_HEIGHT - y;
|
||||
|
||||
/* calculate the drawing region */
|
||||
#if CONFIG_LCD == LCD_IPODNANO
|
||||
y0 = x; /* start horiz */
|
||||
x0 = y; /* start vert */
|
||||
y1 = (x + width) - 1; /* max horiz */
|
||||
x1 = (y + height) - 1; /* max vert */
|
||||
#elif CONFIG_LCD == LCD_IPODCOLOR
|
||||
y0 = y; /* start vert */
|
||||
x0 = (LCD_WIDTH - 1) - x; /* start horiz */
|
||||
y1 = (y + height) - 1; /* end vert */
|
||||
x1 = (x0 - width) + 1; /* end horiz */
|
||||
#endif
|
||||
|
||||
/* setup the drawing region */
|
||||
if (lcd_type == 0) {
|
||||
lcd_cmd_data(0x12, y0); /* start vert */
|
||||
lcd_cmd_data(0x13, x0); /* start horiz */
|
||||
lcd_cmd_data(0x15, y1); /* end vert */
|
||||
lcd_cmd_data(0x16, x1); /* end horiz */
|
||||
} else {
|
||||
/* swap max horiz < start horiz */
|
||||
if (y1 < y0) {
|
||||
int t;
|
||||
t = y0;
|
||||
y0 = y1;
|
||||
y1 = t;
|
||||
}
|
||||
|
||||
/* swap max vert < start vert */
|
||||
if (x1 < x0) {
|
||||
int t;
|
||||
t = x0;
|
||||
x0 = x1;
|
||||
x1 = t;
|
||||
}
|
||||
|
||||
/* max horiz << 8 | start horiz */
|
||||
lcd_cmd_data(LCD_CNTL_HORIZ_RAM_ADDR_POS, (y1 << 8) | y0);
|
||||
/* max vert << 8 | start vert */
|
||||
lcd_cmd_data(LCD_CNTL_VERT_RAM_ADDR_POS, (x1 << 8) | x0);
|
||||
|
||||
/* start vert = max vert */
|
||||
#if CONFIG_LCD == LCD_IPODCOLOR
|
||||
x0 = x1;
|
||||
#endif
|
||||
|
||||
/* position cursor (set AD0-AD15) */
|
||||
/* start vert << 8 | start horiz */
|
||||
lcd_cmd_data(LCD_CNTL_RAM_ADDR_SET, ((x0 << 8) | y0));
|
||||
|
||||
/* start drawing */
|
||||
lcd_send_lo(0x0);
|
||||
lcd_send_lo(LCD_CNTL_WRITE_TO_GRAM);
|
||||
}
|
||||
|
||||
h=0;
|
||||
while (1) {
|
||||
int pixels_to_write;
|
||||
const unsigned char *ysrc = src[0] + stride * src_y + src_x;
|
||||
const unsigned char *row_end = ysrc + width;
|
||||
int y, u, v;
|
||||
int red, green, blue;
|
||||
unsigned rbits, gbits, bbits;
|
||||
fb_data pixel1,pixel2;
|
||||
|
||||
if (h==0) {
|
||||
while ((inl(0x70008a20) & 0x4000000) == 0);
|
||||
outl(0x0, 0x70008a24);
|
||||
|
||||
if (height == 0) break;
|
||||
|
||||
pixels_to_write = (width * height) * 2;
|
||||
h = height;
|
||||
|
||||
/* calculate how much we can do in one go */
|
||||
if (pixels_to_write > 64000) {
|
||||
h = (64000/2) / width;
|
||||
pixels_to_write = (width * h) * 2;
|
||||
}
|
||||
|
||||
height -= h;
|
||||
outl(0x10000080, 0x70008a20);
|
||||
outl((pixels_to_write - 1) | 0xc0010000, 0x70008a24);
|
||||
outl(0x34000000, 0x70008a20);
|
||||
}
|
||||
|
||||
/* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
|
||||
const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y)
|
||||
+ (src_x/CSUB_X);
|
||||
const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y)
|
||||
+ (src_x/CSUB_X);
|
||||
int rc, gc, bc;
|
||||
|
||||
u = *usrc++ - 128;
|
||||
v = *vsrc++ - 128;
|
||||
rc = RVFAC * v + ROUNDOFFS;
|
||||
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
|
||||
bc = BUFAC * u + ROUNDOFFS;
|
||||
|
||||
do
|
||||
{
|
||||
y = *ysrc++;
|
||||
red = RYFAC * y + rc;
|
||||
green = GYFAC * y + gc;
|
||||
blue = BYFAC * y + bc;
|
||||
|
||||
if ((unsigned)red > (RYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (red < 0)
|
||||
red = 0;
|
||||
else
|
||||
red = (RYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)green > (GYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (green < 0)
|
||||
green = 0;
|
||||
else
|
||||
green = (GYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)blue > (BYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (blue < 0)
|
||||
blue = 0;
|
||||
else
|
||||
blue = (BYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
rbits = ((unsigned)red) >> 16 ;
|
||||
gbits = ((unsigned)green) >> 16 ;
|
||||
bbits = ((unsigned)blue) >> 16 ;
|
||||
|
||||
pixel1 = swap16((rbits << 11) | (gbits << 5) | bbits);
|
||||
|
||||
y = *ysrc++;
|
||||
red = RYFAC * y + rc;
|
||||
green = GYFAC * y + gc;
|
||||
blue = BYFAC * y + bc;
|
||||
|
||||
if ((unsigned)red > (RYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (red < 0)
|
||||
red = 0;
|
||||
else
|
||||
red = (RYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)green > (GYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (green < 0)
|
||||
green = 0;
|
||||
else
|
||||
green = (GYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)blue > (BYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (blue < 0)
|
||||
blue = 0;
|
||||
else
|
||||
blue = (BYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
rbits = ((unsigned)red) >> 16 ;
|
||||
gbits = ((unsigned)green) >> 16 ;
|
||||
bbits = ((unsigned)blue) >> 16 ;
|
||||
|
||||
pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits);
|
||||
|
||||
u = *usrc++ - 128;
|
||||
v = *vsrc++ - 128;
|
||||
rc = RVFAC * v + ROUNDOFFS;
|
||||
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
|
||||
bc = BUFAC * u + ROUNDOFFS;
|
||||
|
||||
while ((inl(0x70008a20) & 0x1000000) == 0);
|
||||
|
||||
/* output 2 pixels */
|
||||
outl((pixel2<<16)|pixel1, 0x70008b00);
|
||||
}
|
||||
while (ysrc < row_end);
|
||||
|
||||
src_y++;
|
||||
h--;
|
||||
}
|
||||
|
||||
while ((inl(0x70008a20) & 0x4000000) == 0);
|
||||
outl(0x0, 0x70008a24);
|
||||
}
|
||||
|
||||
|
||||
/* Update a fraction of the display. */
|
||||
void lcd_update_rect(int x, int y, int width, int height)
|
||||
{
|
||||
|
|
|
@ -71,6 +71,12 @@ extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string,
|
|||
int style);
|
||||
extern void lcd_icon(int icon, bool enable);
|
||||
|
||||
#if CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO
|
||||
void lcd_yuv_blit(unsigned char * const src[3],
|
||||
int src_x, int src_y, int stride,
|
||||
int x, int y, int width, int height);
|
||||
#endif
|
||||
|
||||
#if defined(SIMULATOR) || defined(HAVE_LCD_BITMAP)
|
||||
/* performance function */
|
||||
extern void lcd_blit(const fb_data* data, int x, int by, int width,
|
||||
|
|
Loading…
Reference in New Issue
Block a user