summaryrefslogtreecommitdiffstats
path: root/apps/plugins/mpegplayer/libmpeg2
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpegplayer/libmpeg2')
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/AUTHORS33
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/README204
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/README.rockbox44
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/attributes.h42
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/decode.c527
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/header.c1286
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/idct.c274
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/idct_arm.S443
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/idct_armv6.S297
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S575
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/motion_comp.c66
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/motion_comp.h86
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c39
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S342
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c40
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c38
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S436
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/mpeg2.h223
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h274
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h15
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/slice.c2898
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/vlc.h433
22 files changed, 8615 insertions, 0 deletions
diff --git a/apps/plugins/mpegplayer/libmpeg2/AUTHORS b/apps/plugins/mpegplayer/libmpeg2/AUTHORS
new file mode 100644
index 0000000000..4722897c97
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/AUTHORS
@@ -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.
diff --git a/apps/plugins/mpegplayer/libmpeg2/README b/apps/plugins/mpegplayer/libmpeg2/README
new file mode 100644
index 0000000000..2a58846772
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/README
@@ -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.
diff --git a/apps/plugins/mpegplayer/libmpeg2/README.rockbox b/apps/plugins/mpegplayer/libmpeg2/README.rockbox
new file mode 100644
index 0000000000..95f5a3d4b5
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/README.rockbox
@@ -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
diff --git a/apps/plugins/mpegplayer/libmpeg2/attributes.h b/apps/plugins/mpegplayer/libmpeg2/attributes.h
new file mode 100644
index 0000000000..24b069223b
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/attributes.h
@@ -0,0 +1,42 @@
+/*
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.5
+ */
+
+/* use gcc attribs to align critical data structures */
+#ifdef ATTRIBUTE_ALIGNED_MAX
+#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
+#else
+#define ATTR_ALIGN(align)
+#endif
+
+#if defined(LIKELY) && defined (UNLIKELY)
+#define likely(x) LIKELY(x)
+#define unlikely(x) UNLIKELY(x)
+#else
+#define likely(x) (x)
+#define unlikely(x) (x)
+#endif
+
diff --git a/apps/plugins/mpegplayer/libmpeg2/decode.c b/apps/plugins/mpegplayer/libmpeg2/decode.c
new file mode 100644
index 0000000000..9c8081efbe
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/decode.c
@@ -0,0 +1,527 @@
+/*
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.114
+ */
+
+#include "plugin.h"
+
+#include "mpeg2dec_config.h"
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+#define BUFFER_SIZE (1194 * 1024)
+
+#if defined(CPU_COLDFIRE) || (defined(CPU_ARM) && ARM_ARCH >= 6)
+/* twice as large as on other targets because coldfire uses
+ * a secondary, transposed buffer for optimisation */
+static int16_t static_dct_block[128] IBSS_ATTR ATTR_ALIGN(16);
+#define DCT_BLOCKSIZE (128 * sizeof (int16_t))
+#else
+static int16_t static_dct_block[64] IBSS_ATTR ATTR_ALIGN(16);
+#define DCT_BLOCKSIZE (64 * sizeof (int16_t))
+#endif
+
+const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec)
+{
+ return &mpeg2dec->info;
+}
+
+static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes)
+{
+ uint8_t * current;
+ uint32_t shift;
+ uint8_t * limit;
+ uint8_t byte;
+
+ if (!bytes)
+ return 0;
+
+ current = mpeg2dec->buf_start;
+ shift = mpeg2dec->shift;
+ limit = current + bytes;
+
+ do
+ {
+ byte = *current++;
+
+ if (shift == 0x00000100)
+ {
+ int skipped;
+
+ mpeg2dec->shift = 0xffffff00;
+ skipped = current - mpeg2dec->buf_start;
+ mpeg2dec->buf_start = current;
+
+ return skipped;
+ }
+
+ shift = (shift | byte) << 8;
+ }
+ while (current < limit);
+
+ mpeg2dec->shift = shift;
+ mpeg2dec->buf_start = current;
+
+ return 0;
+}
+
+static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes)
+{
+ uint8_t * current;
+ uint32_t shift;
+ uint8_t * chunk_ptr;
+ uint8_t * limit;
+ uint8_t byte;
+
+ if (!bytes)
+ return 0;
+
+ current = mpeg2dec->buf_start;
+ shift = mpeg2dec->shift;
+ chunk_ptr = mpeg2dec->chunk_ptr;
+ limit = current + bytes;
+
+ do
+ {
+ byte = *current++;
+
+ if (shift == 0x00000100)
+ {
+ int copied;
+
+ mpeg2dec->shift = 0xffffff00;
+ mpeg2dec->chunk_ptr = chunk_ptr + 1;
+ copied = current - mpeg2dec->buf_start;
+ mpeg2dec->buf_start = current;
+ return copied;
+ }
+
+ shift = (shift | byte) << 8;
+ *chunk_ptr++ = byte;
+ }
+ while (current < limit);
+
+ mpeg2dec->shift = shift;
+ mpeg2dec->buf_start = current;
+ return 0;
+}
+
+void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end)
+{
+ mpeg2dec->buf_start = start;
+ mpeg2dec->buf_end = end;
+}
+
+int mpeg2_getpos (mpeg2dec_t * mpeg2dec)
+{
+ return mpeg2dec->buf_end - mpeg2dec->buf_start;
+}
+
+static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec)
+{
+ int size, skipped;
+
+ size = mpeg2dec->buf_end - mpeg2dec->buf_start;
+ skipped = skip_chunk (mpeg2dec, size);
+
+ if (!skipped)
+ {
+ mpeg2dec->bytes_since_tag += size;
+ return STATE_BUFFER;
+ }
+
+ mpeg2dec->bytes_since_tag += skipped;
+ mpeg2dec->code = mpeg2dec->buf_start[-1];
+
+ return STATE_INTERNAL_NORETURN;
+}
+
+mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec)
+{
+ while (!(mpeg2dec->code == 0xb3 ||
+ ((mpeg2dec->code == 0xb7 || mpeg2dec->code == 0xb8 ||
+ !mpeg2dec->code) && mpeg2dec->sequence.width != (unsigned)-1)))
+ {
+ if (seek_chunk (mpeg2dec) == STATE_BUFFER)
+ return STATE_BUFFER;
+ }
+
+ mpeg2dec->chunk_start =
+ mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+
+ mpeg2dec->user_data_len = 0;
+
+ return ((mpeg2dec->code == 0xb7) ?
+ mpeg2_header_end(mpeg2dec) : mpeg2_parse_header(mpeg2dec));
+}
+
+#define RECEIVED(code,state) (((state) << 8) + (code))
+
+mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec)
+{
+ int size_buffer, size_chunk, copied;
+
+ if (mpeg2dec->action)
+ {
+ mpeg2_state_t state;
+
+ state = mpeg2dec->action (mpeg2dec);
+
+ if (state > STATE_INTERNAL_NORETURN)
+ return state;
+ }
+
+ while (1)
+ {
+ while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) <
+ mpeg2dec->nb_decode_slices)
+ {
+ size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
+ size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE -
+ mpeg2dec->chunk_ptr;
+
+ if (size_buffer <= size_chunk)
+ {
+ copied = copy_chunk (mpeg2dec, size_buffer);
+
+ if (!copied)
+ {
+ mpeg2dec->bytes_since_tag += size_buffer;
+ mpeg2dec->chunk_ptr += size_buffer;
+ return STATE_BUFFER;
+ }
+ }
+ else
+ {
+ copied = copy_chunk (mpeg2dec, size_chunk);
+
+ if (!copied)
+ {
+ /* filled the chunk buffer without finding a start code */
+ mpeg2dec->bytes_since_tag += size_chunk;
+ mpeg2dec->action = seek_chunk;
+ return STATE_INVALID;
+ }
+ }
+
+ mpeg2dec->bytes_since_tag += copied;
+
+ mpeg2_slice (&mpeg2dec->decoder, mpeg2dec->code,
+ mpeg2dec->chunk_start);
+ mpeg2dec->code = mpeg2dec->buf_start[-1];
+ mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
+ }
+
+ if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1)
+ break;
+
+ if (seek_chunk (mpeg2dec) == STATE_BUFFER)
+ return STATE_BUFFER;
+ }
+
+ mpeg2dec->action = mpeg2_seek_header;
+
+ switch (mpeg2dec->code)
+ {
+ case 0x00:
+ return mpeg2dec->state;
+ case 0xb3:
+ case 0xb7:
+ case 0xb8:
+ return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID;
+ default:
+ mpeg2dec->action = seek_chunk;
+ return STATE_INVALID;
+ }
+}
+
+mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
+{
+ static int (* const process_header[9]) (mpeg2dec_t *) =
+ {
+ mpeg2_header_picture,
+ mpeg2_header_extension,
+ mpeg2_header_user_data,
+ mpeg2_header_sequence,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ mpeg2_header_gop
+ };
+
+ int size_buffer, size_chunk, copied;
+
+ mpeg2dec->action = mpeg2_parse_header;
+ mpeg2dec->info.user_data = NULL;
+ mpeg2dec->info.user_data_len = 0;
+
+ while (1)
+ {
+ size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
+ size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE -
+ mpeg2dec->chunk_ptr;
+
+ if (size_buffer <= size_chunk)
+ {
+ copied = copy_chunk (mpeg2dec, size_buffer);
+
+ if (!copied)
+ {
+ mpeg2dec->bytes_since_tag += size_buffer;
+ mpeg2dec->chunk_ptr += size_buffer;
+ return STATE_BUFFER;
+ }
+ }
+ else
+ {
+ copied = copy_chunk (mpeg2dec, size_chunk);
+
+ if (!copied)
+ {
+ /* filled the chunk buffer without finding a start code */
+ mpeg2dec->bytes_since_tag += size_chunk;
+ mpeg2dec->code = 0xb4;
+ mpeg2dec->action = mpeg2_seek_header;
+ return STATE_INVALID;
+ }
+ }
+
+ mpeg2dec->bytes_since_tag += copied;
+
+ if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec))
+ {
+ mpeg2dec->code = mpeg2dec->buf_start[-1];
+ mpeg2dec->action = mpeg2_seek_header;
+ return STATE_INVALID;
+ }
+
+ mpeg2dec->code = mpeg2dec->buf_start[-1];
+
+ switch (RECEIVED (mpeg2dec->code, mpeg2dec->state))
+ {
+ /* state transition after a sequence header */
+ case RECEIVED (0x00, STATE_SEQUENCE):
+ case RECEIVED (0xb8, STATE_SEQUENCE):
+ mpeg2_header_sequence_finalize (mpeg2dec);
+ break;
+
+ /* other legal state transitions */
+ case RECEIVED (0x00, STATE_GOP):
+ mpeg2_header_gop_finalize (mpeg2dec);
+ break;
+ case RECEIVED (0x01, STATE_PICTURE):
+ case RECEIVED (0x01, STATE_PICTURE_2ND):
+ mpeg2_header_picture_finalize (mpeg2dec);
+ mpeg2dec->action = mpeg2_header_slice_start;
+ break;
+
+ /* legal headers within a given state */
+ case RECEIVED (0xb2, STATE_SEQUENCE):
+ case RECEIVED (0xb2, STATE_GOP):
+ case RECEIVED (0xb2, STATE_PICTURE):
+ case RECEIVED (0xb2, STATE_PICTURE_2ND):
+ case RECEIVED (0xb5, STATE_SEQUENCE):
+ case RECEIVED (0xb5, STATE_PICTURE):
+ case RECEIVED (0xb5, STATE_PICTURE_2ND):
+ mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
+ continue;
+
+ default:
+ mpeg2dec->action = mpeg2_seek_header;
+ return STATE_INVALID;
+ }
+
+ mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
+ mpeg2dec->user_data_len = 0;
+
+ return mpeg2dec->state;
+ }
+}
+
+int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg)
+{
+ mpeg2_convert_init_t convert_init;
+ int error;
+
+ error = convert (MPEG2_CONVERT_SET, NULL, &mpeg2dec->sequence, 0,
+ arg, &convert_init);
+
+ if (!error)
+ {
+ mpeg2dec->convert = convert;
+ mpeg2dec->convert_arg = arg;
+ mpeg2dec->convert_id_size = convert_init.id_size;
+ mpeg2dec->convert_stride = 0;
+ }
+
+ return error;
+}
+
+int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride)
+{
+ if (!mpeg2dec->convert)
+ {
+ if (stride < (int) mpeg2dec->sequence.width)
+ stride = mpeg2dec->sequence.width;
+
+ mpeg2dec->decoder.stride_frame = stride;
+ }
+ else
+ {
+ mpeg2_convert_init_t convert_init;
+
+ stride = mpeg2dec->convert(MPEG2_CONVERT_STRIDE, NULL,
+ &mpeg2dec->sequence, stride,
+ mpeg2dec->convert_arg,
+ &convert_init);
+
+ mpeg2dec->convert_id_size = convert_init.id_size;
+ mpeg2dec->convert_stride = stride;
+ }
+
+ return stride;
+}
+
+void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[MPEG2_COMPONENTS], void * id)
+{
+ mpeg2_fbuf_t * fbuf;
+
+ if (mpeg2dec->custom_fbuf)
+ {
+ if (mpeg2dec->state == STATE_SEQUENCE)
+ {
+ mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
+ mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
+ }
+
+ mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type ==
+ PIC_FLAG_CODING_TYPE_B));
+
+ fbuf = mpeg2dec->fbuf[0];
+ }
+ else
+ {
+ fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf;
+ mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index;
+ }
+
+ fbuf->buf[0] = buf[0];
+#if MPEG2_COLOR
+ fbuf->buf[1] = buf[1];
+ fbuf->buf[2] = buf[2];
+#endif
+
+ fbuf->id = id;
+}
+
+void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf)
+{
+ mpeg2dec->custom_fbuf = custom_fbuf;
+}
+
+void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip)
+{
+ mpeg2dec->first_decode_slice = 1;
+ mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1);
+}
+
+void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end)
+{
+ start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start;
+ end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end;
+ mpeg2dec->first_decode_slice = start;
+ mpeg2dec->nb_decode_slices = end - start;
+}
+
+void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2)
+{
+ mpeg2dec->tag_previous = mpeg2dec->tag_current;
+ mpeg2dec->tag2_previous = mpeg2dec->tag2_current;
+ mpeg2dec->tag_current = tag;
+ mpeg2dec->tag2_current = tag2;
+ mpeg2dec->num_tags++;
+ mpeg2dec->bytes_since_tag = 0;
+}
+
+void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset)
+{
+ mpeg2dec->buf_start = mpeg2dec->buf_end = NULL;
+ mpeg2dec->num_tags = 0;
+ mpeg2dec->shift = 0xffffff00;
+ mpeg2dec->code = 0xb4;
+ mpeg2dec->action = mpeg2_seek_header;
+ mpeg2dec->state = STATE_INVALID;
+ mpeg2dec->first = 1;
+
+ mpeg2_reset_info(&mpeg2dec->info);
+ mpeg2dec->info.gop = NULL;
+ mpeg2dec->info.user_data = NULL;
+ mpeg2dec->info.user_data_len = 0;
+
+ if (full_reset)
+ {
+ mpeg2dec->info.sequence = NULL;
+ mpeg2_header_state_init (mpeg2dec);
+ }
+}
+
+mpeg2dec_t * mpeg2_init (void)
+{
+ mpeg2dec_t * mpeg2dec;
+
+ mpeg2_idct_init ();
+
+ mpeg2dec = (mpeg2dec_t *)mpeg2_bufalloc(sizeof (mpeg2dec_t),
+ MPEG2_ALLOC_MPEG2DEC);
+ if (mpeg2dec == NULL)
+ return NULL;
+
+ mpeg2dec->decoder.DCTblock = static_dct_block;
+
+ rb->memset (mpeg2dec->decoder.DCTblock, 0, DCT_BLOCKSIZE);
+
+ DEBUGF("DCTblock: %p\n", mpeg2dec->decoder.DCTblock);
+
+ mpeg2dec->chunk_buffer = (uint8_t *)mpeg2_bufalloc(BUFFER_SIZE + 4,
+ MPEG2_ALLOC_CHUNK);
+
+ mpeg2dec->sequence.width = (unsigned)-1;
+ mpeg2_reset (mpeg2dec, 1);
+
+ return mpeg2dec;
+}
+
+void mpeg2_close (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_header_state_init (mpeg2dec);
+#if 0
+ /* These are dedicated buffers in rockbox */
+ mpeg2_free (mpeg2dec->chunk_buffer);
+ mpeg2_free (mpeg2dec);
+#endif
+}
diff --git a/apps/plugins/mpegplayer/libmpeg2/header.c b/apps/plugins/mpegplayer/libmpeg2/header.c
new file mode 100644
index 0000000000..001cafe7d5
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/header.c
@@ -0,0 +1,1286 @@
+/*
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.101
+ */
+
+#include "plugin.h"
+
+#include "mpeg2dec_config.h"
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+#define SEQ_EXT 2
+#define SEQ_DISPLAY_EXT 4
+#define QUANT_MATRIX_EXT 8
+#define COPYRIGHT_EXT 0x10
+#define PIC_DISPLAY_EXT 0x80
+#define PIC_CODING_EXT 0x100
+
+/* default intra quant matrix, in zig-zag order */
+static const uint8_t default_intra_quantizer_matrix[64] =
+{
+ 8,
+ 16, 16,
+ 19, 16, 19,
+ 22, 22, 22, 22,
+ 22, 22, 26, 24, 26,
+ 27, 27, 27, 26, 26, 26,
+ 26, 27, 27, 27, 29, 29, 29,
+ 34, 34, 34, 29, 29, 29, 27, 27,
+ 29, 29, 32, 32, 34, 34, 37,
+ 38, 37, 35, 35, 34, 35,
+ 38, 38, 40, 40, 40,
+ 48, 48, 46, 46,
+ 56, 56, 58,
+ 69, 69,
+ 83
+};
+
+const uint8_t default_mpeg2_scan_norm[64] =
+{
+ /* Zig-Zag scan pattern */
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+const uint8_t default_mpeg2_scan_alt[64] =
+{
+ /* Alternate scan pattern */
+ 0, 8, 16, 24, 1, 9, 2, 10,
+ 17, 25, 32, 40, 48, 56, 57, 49,
+ 41, 33, 26, 18, 3, 11, 4, 12,
+ 19, 27, 34, 42, 50, 58, 35, 43,
+ 51, 59, 20, 28, 5, 13, 6, 14,
+ 21, 29, 36, 44, 52, 60, 37, 45,
+ 53, 61, 22, 30, 7, 15, 23, 31,
+ 38, 46, 54, 62, 39, 47, 55, 63
+};
+
+uint8_t mpeg2_scan_norm[64] IDATA_ATTR;
+uint8_t mpeg2_scan_alt[64] IDATA_ATTR;
+
+void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec)
+{
+ if (mpeg2dec->sequence.width != (unsigned)-1)
+ {
+ mpeg2dec->sequence.width = (unsigned)-1;
+ mpeg2_mem_reset(); /* Clean the memory slate */
+#if 0
+ if (!mpeg2dec->custom_fbuf)
+ {
+ int i;
+ for (i = mpeg2dec->alloc_index_user;
+ i < mpeg2dec->alloc_index; i++)
+ {
+ mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[0]);
+#if MPEG2_COLOR
+ mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[1]);
+ mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[2]);
+#endif
+ }
+ }
+
+ if (mpeg2dec->convert_start)
+ {
+ int i;
+ for (i = 0; i < 3; i++)
+ {
+ mpeg2_free(mpeg2dec->yuv_buf[i][0]);
+#if MPEG2_COLOR
+ mpeg2_free(mpeg2dec->yuv_buf[i][1]);
+ mpeg2_free(mpeg2dec->yuv_buf[i][2]);
+#endif
+ }
+ }
+
+ if (mpeg2dec->decoder.convert_id)
+ {
+ mpeg2_free(mpeg2dec->decoder.convert_id);
+ }
+#endif
+ }
+
+ mpeg2dec->decoder.coding_type = I_TYPE;
+ mpeg2dec->decoder.convert = NULL;
+ mpeg2dec->decoder.convert_id = NULL;
+
+ mpeg2dec->picture = mpeg2dec->pictures;
+
+ mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[0].fbuf;
+ mpeg2dec->fbuf[1] = &mpeg2dec->fbuf_alloc[1].fbuf;
+ mpeg2dec->fbuf[2] = &mpeg2dec->fbuf_alloc[2].fbuf;
+
+ mpeg2dec->first = 1;
+ mpeg2dec->alloc_index = 0;
+ mpeg2dec->alloc_index_user = 0;
+ mpeg2dec->first_decode_slice = 1;
+ mpeg2dec->nb_decode_slices = 0xb0 - 1;
+ mpeg2dec->convert = NULL;
+ mpeg2dec->convert_start = NULL;
+ mpeg2dec->custom_fbuf = 0;
+ mpeg2dec->yuv_index = 0;
+}
+
+void mpeg2_reset_info (mpeg2_info_t * info)
+{
+ info->current_picture =
+ info->current_picture_2nd = NULL;
+
+ info->display_picture =
+ info->display_picture_2nd = NULL;
+
+ info->current_fbuf =
+ info->display_fbuf =
+ info->discard_fbuf = NULL;
+}
+
+static void info_user_data (mpeg2dec_t * mpeg2dec)
+{
+ if (mpeg2dec->user_data_len)
+ {
+ mpeg2dec->info.user_data = mpeg2dec->chunk_buffer;
+ mpeg2dec->info.user_data_len = mpeg2dec->user_data_len - 3;
+ }
+}
+
+int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec)
+{
+ static const unsigned int frame_period[16] =
+ {
+ 0, 1126125, 1125000, 1080000, 900900, 900000, 540000, 450450, 450000,
+ /* unofficial: xing 15 fps */
+ 1800000,
+ /* unofficial: libmpeg3 "Unofficial economy rates" 5/10/12/15 fps */
+ 5400000, 2700000, 2250000, 1800000, 0, 0
+ };
+
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence;
+ int i;
+
+ if ((buffer[6] & 0x20) != 0x20) /* missing marker_bit */
+ return 1;
+
+ i = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
+
+ if (!(sequence->display_width = sequence->picture_width = i >> 12))
+ return 1;
+
+ if (!(sequence->display_height = sequence->picture_height = i & 0xfff))
+ return 1;
+
+ sequence->width = (sequence->picture_width + 15) & ~15;
+ sequence->height = (sequence->picture_height + 15) & ~15;
+ sequence->chroma_width = sequence->width >> 1;
+ sequence->chroma_height = sequence->height >> 1;
+
+ sequence->flags = SEQ_FLAG_PROGRESSIVE_SEQUENCE |
+ SEQ_VIDEO_FORMAT_UNSPECIFIED;
+
+ sequence->pixel_width = buffer[3] >> 4; /* aspect ratio */
+ sequence->frame_period = frame_period[buffer[3] & 15];
+
+ sequence->byte_rate = (buffer[4]<<10) | (buffer[5]<<2) | (buffer[6]>>6);
+
+ sequence->vbv_buffer_size = ((buffer[6]<<16) | (buffer[7]<<8)) & 0x1ff800;
+
+ if (buffer[7] & 4)
+ sequence->flags |= SEQ_FLAG_CONSTRAINED_PARAMETERS;
+
+ mpeg2dec->copy_matrix = 3;
+
+ if (buffer[7] & 2)
+ {
+ for (i = 0; i < 64; i++)
+ {
+ mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] =
+ (buffer[i+7] << 7) | (buffer[i+8] >> 1);
+ }
+
+ buffer += 64;
+ }
+ else
+ {
+ for (i = 0; i < 64; i++)
+ {
+ mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] =
+ default_intra_quantizer_matrix[i];
+ }
+ }
+
+ if (buffer[7] & 1)
+ {
+ for (i = 0; i < 64; i++)
+ {
+ mpeg2dec->new_quantizer_matrix[1][mpeg2_scan_norm[i]] =
+ buffer[i+8];
+ }
+ }
+ else
+ {
+ rb->memset (mpeg2dec->new_quantizer_matrix[1], 16, 64);
+ }
+
+ sequence->profile_level_id = 0x80;
+ sequence->colour_primaries = 0;
+ sequence->transfer_characteristics = 0;
+ sequence->matrix_coefficients = 0;
+
+ mpeg2dec->ext_state = SEQ_EXT;
+ mpeg2dec->state = STATE_SEQUENCE;
+
+ mpeg2dec->display_offset_x =
+ mpeg2dec->display_offset_y = 0;
+
+ return 0;
+}
+
+static int sequence_ext (mpeg2dec_t * mpeg2dec)
+{
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence;
+ uint32_t flags;
+
+ if (!(buffer[3] & 1))
+ return 1;
+
+ sequence->profile_level_id = (buffer[0] << 4) | (buffer[1] >> 4);
+
+ sequence->picture_width += ((buffer[1] << 13) | (buffer[2] << 5)) & 0x3000;
+ sequence->display_width = sequence->picture_width;
+
+ sequence->picture_height += (buffer[2] << 7) & 0x3000;
+ sequence->display_height = sequence->picture_height;
+
+ sequence->width = (sequence->picture_width + 15) & ~15;
+ sequence->height = (sequence->picture_height + 15) & ~15;
+
+ flags = sequence->flags | SEQ_FLAG_MPEG2;
+
+ if (!(buffer[1] & 8))
+ {
+ flags &= ~SEQ_FLAG_PROGRESSIVE_SEQUENCE;
+ sequence->height = (sequence->height + 31) & ~31;
+ }
+
+ if (buffer[5] & 0x80)
+ flags |= SEQ_FLAG_LOW_DELAY;
+
+ sequence->flags = flags;
+ sequence->chroma_width = sequence->width;
+ sequence->chroma_height = sequence->height;
+
+ switch (buffer[1] & 6)
+ {
+ case 0: /* invalid */
+ return 1;
+ case 2: /* 4:2:0 */
+ sequence->chroma_height >>= 1;
+ case 4: /* 4:2:2 */
+ sequence->chroma_width >>= 1;
+ }
+
+ sequence->byte_rate += ((buffer[2]<<25) | (buffer[3]<<17)) & 0x3ffc0000;
+
+ sequence->vbv_buffer_size |= buffer[4] << 21;
+
+ sequence->frame_period =
+ sequence->frame_period * ((buffer[5]&31)+1) / (((buffer[5]>>2)&3)+1);
+
+ mpeg2dec->ext_state = SEQ_DISPLAY_EXT;
+
+ return 0;
+}
+
+static int sequence_display_ext (mpeg2dec_t * mpeg2dec)
+{
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence;
+ int x;
+
+ sequence->flags = (sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) |
+ ((buffer[0] << 4) & SEQ_MASK_VIDEO_FORMAT);
+
+ if (buffer[0] & 1)
+ {
+ sequence->flags |= SEQ_FLAG_COLOUR_DESCRIPTION;
+ sequence->colour_primaries = buffer[1];
+ sequence->transfer_characteristics = buffer[2];
+ sequence->matrix_coefficients = buffer[3];
+ buffer += 3;
+ }
+
+ if (!(buffer[2] & 2)) /* missing marker_bit */
+ return 1;
+
+ x = (buffer[1] << 6) | (buffer[2] >> 2);
+ if (x)
+ sequence->display_width = x;
+
+ x = ((buffer[2] & 1) << 13) | (buffer[3] << 5) | (buffer[4] >> 3);
+ if (x)
+ sequence->display_height = x;
+
+ return 0;
+}
+
+static inline void simplify (unsigned int * u, unsigned int * v)
+{
+ unsigned int a, b, tmp;
+
+ a = *u;
+ b = *v;
+
+ /* find greatest common divisor */
+ while (a)
+ {
+ tmp = a;
+ a = b % tmp;
+ b = tmp;
+ }
+
+ *u /= b;
+ *v /= b;
+}
+
+static inline void finalize_sequence (mpeg2_sequence_t * sequence)
+{
+ int width;
+ int height;
+
+ sequence->byte_rate *= 50;
+
+ if (sequence->flags & SEQ_FLAG_MPEG2)
+ {
+ switch (sequence->pixel_width)
+ {
+ case 1: /* square pixels */
+ sequence->pixel_width =
+ sequence->pixel_height = 1;
+ return;
+ case 2: /* 4:3 aspect ratio */
+ width = 4;
+ height = 3;
+ break;
+ case 3: /* 16:9 aspect ratio */
+ width = 16;
+ height = 9;
+ break;
+ case 4: /* 2.21:1 aspect ratio */
+ width = 221;
+ height = 100;
+ break;
+ default: /* illegal */
+ sequence->pixel_width =
+ sequence->pixel_height = 0;
+ return;
+ }
+
+ width *= sequence->display_height;
+ height *= sequence->display_width;
+ }
+ else
+ {
+ if (sequence->byte_rate == 50 * 0x3ffff)
+ sequence->byte_rate = 0; /* mpeg-1 VBR */
+
+ switch (sequence->pixel_width)
+ {
+ case 0:
+ case 15: /* illegal */
+ sequence->pixel_width =
+ sequence->pixel_height = 0;
+ return;
+ case 1: /* square pixels */
+ sequence->pixel_width =
+ sequence->pixel_height = 1;
+ return;
+ case 3: /* 720x576 16:9 */
+ sequence->pixel_width = 64;
+ sequence->pixel_height = 45;
+ return;
+ case 6: /* 720x480 16:9 */
+ sequence->pixel_width = 32;
+ sequence->pixel_height = 27;
+ return;
+ case 8: /* BT.601 625 lines 4:3 */
+ sequence->pixel_width = 59;
+ sequence->pixel_height = 54;
+ return;
+ case 12: /* BT.601 525 lines 4:3 */
+ sequence->pixel_width = 10;
+ sequence->pixel_height = 11;
+ return;
+ default:
+ height = 88 * sequence->pixel_width + 1171;
+ width = 2000;
+ }
+ }
+
+ sequence->pixel_width = width;
+ sequence->pixel_height = height;
+
+ simplify(&sequence->pixel_width, &sequence->pixel_height);
+}
+
+int mpeg2_guess_aspect (const mpeg2_sequence_t * sequence,
+ unsigned int * pixel_width,
+ unsigned int * pixel_height)
+{
+ static const struct
+ {
+ unsigned int width, height;
+ } video_modes[] =
+ {
+ {720, 576}, /* 625 lines, 13.5 MHz (D1, DV, DVB, DVD) */
+ {704, 576}, /* 625 lines, 13.5 MHz (1/1 D1, DVB, DVD, 4CIF) */
+ {544, 576}, /* 625 lines, 10.125 MHz (DVB, laserdisc) */
+ {528, 576}, /* 625 lines, 10.125 MHz (3/4 D1, DVB, laserdisc) */
+ {480, 576}, /* 625 lines, 9 MHz (2/3 D1, DVB, SVCD) */
+ {352, 576}, /* 625 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVB, DVD) */
+ {352, 288}, /* 625 lines, 6.75 MHz, 1 field (D4, VCD, DVB, DVD, CIF) */
+ {176, 144}, /* 625 lines, 3.375 MHz, half field (QCIF) */
+ {720, 486}, /* 525 lines, 13.5 MHz (D1) */
+ {704, 486}, /* 525 lines, 13.5 MHz */
+ {720, 480}, /* 525 lines, 13.5 MHz (DV, DSS, DVD) */
+ {704, 480}, /* 525 lines, 13.5 MHz (1/1 D1, ATSC, DVD) */
+ {544, 480}, /* 525 lines. 10.125 MHz (DSS, laserdisc) */
+ {528, 480}, /* 525 lines. 10.125 MHz (3/4 D1, laserdisc) */
+ {480, 480}, /* 525 lines, 9 MHz (2/3 D1, SVCD) */
+ {352, 480}, /* 525 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVD) */
+ {352, 240} /* 525 lines. 6.75 MHz, 1 field (D4, VCD, DSS, DVD) */
+ };
+ unsigned int width, height, pix_width, pix_height, i, DAR_16_9;
+
+ *pixel_width = sequence->pixel_width;
+ *pixel_height = sequence->pixel_height;
+ width = sequence->picture_width;
+ height = sequence->picture_height;
+
+ for (i = 0; i < sizeof (video_modes) / sizeof (video_modes[0]); i++)
+ {
+ if (width == video_modes[i].width && height == video_modes[i].height)
+ break;
+ }
+
+ if (i == ARRAYLEN(video_modes) ||
+ (sequence->pixel_width == 1 && sequence->pixel_height == 1) ||
+ width != sequence->display_width || height != sequence->display_height)
+ {
+ return 0;
+ }
+
+ for (pix_height = 1; height * pix_height < 480; pix_height <<= 1);
+ height *= pix_height;
+
+ for (pix_width = 1; width * pix_width <= 352; pix_width <<= 1);
+ width *= pix_width;
+
+ if (!(sequence->flags & SEQ_FLAG_MPEG2))
+ {
+ static unsigned int mpeg1_check[2][2] = {{11, 54}, {27, 45}};
+ DAR_16_9 = (sequence->pixel_height == 27 ||
+ sequence->pixel_height == 45);
+ if (width < 704 ||
+ sequence->pixel_height != mpeg1_check[DAR_16_9][height == 576])
+ return 0;
+ }
+ else
+ {
+ DAR_16_9 = (3 * sequence->picture_width * sequence->pixel_width >
+ 4 * sequence->picture_height * sequence->pixel_height);
+ switch (width)
+ {
+ case 528:
+ case 544:
+ pix_width *= 4;
+ pix_height *= 3;
+ break;
+ case 480:
+ pix_width *= 3;
+ pix_height *= 2;
+ break;
+ }
+ }
+
+ if (DAR_16_9)
+ {
+ pix_width *= 4;
+ pix_height *= 3;
+ }
+
+ if (height == 576)
+ {
+ pix_width *= 59;
+ pix_height *= 54;
+ }
+ else
+ {
+ pix_width *= 10;
+ pix_height *= 11;
+ }
+
+ *pixel_width = pix_width;
+ *pixel_height = pix_height;
+
+ simplify (pixel_width, pixel_height);
+
+ return (height == 576) ? 1 : 2;
+}
+
+static void copy_matrix (mpeg2dec_t * mpeg2dec, int index)
+{
+ if (rb->memcmp (mpeg2dec->quantizer_matrix[index],
+ mpeg2dec->new_quantizer_matrix[index], 64))
+ {
+ rb->memcpy (mpeg2dec->quantizer_matrix[index],
+ mpeg2dec->new_quantizer_matrix[index], 64);
+
+ mpeg2dec->scaled[index] = -1;
+ }
+}
+
+static void finalize_matrix (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_decoder_t *decoder = &mpeg2dec->decoder;
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (mpeg2dec->copy_matrix & (1 << i))
+ copy_matrix (mpeg2dec, i);
+
+ if ((mpeg2dec->copy_matrix & (4 << i)) &&
+ rb->memcmp(mpeg2dec->quantizer_matrix[i],
+ mpeg2dec->new_quantizer_matrix[i+2], 64))
+ {
+ copy_matrix (mpeg2dec, i + 2);
+ decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i+2];
+ }
+ else if (mpeg2dec->copy_matrix & (5 << i))
+ {
+ decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i];
+ }
+ }
+}
+
+static mpeg2_state_t invalid_end_action (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_reset_info (&mpeg2dec->info);
+
+ mpeg2dec->info.gop = NULL;
+
+ info_user_data (mpeg2dec);
+
+ mpeg2_header_state_init (mpeg2dec);
+
+ mpeg2dec->sequence = mpeg2dec->new_sequence;
+ mpeg2dec->action = mpeg2_seek_header;
+ mpeg2dec->state = STATE_SEQUENCE;
+
+ return STATE_SEQUENCE;
+}
+
+void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence;
+ mpeg2_decoder_t * decoder = &mpeg2dec->decoder;
+
+ finalize_sequence(sequence);
+ finalize_matrix(mpeg2dec);
+
+ decoder->mpeg1 = !(sequence->flags & SEQ_FLAG_MPEG2);
+ decoder->width = sequence->width;
+ decoder->height = sequence->height;
+ decoder->vertical_position_extension = sequence->picture_height > 2800;
+ decoder->chroma_format = (sequence->chroma_width == sequence->width) +
+ (sequence->chroma_height == sequence->height);
+
+ if (mpeg2dec->sequence.width != (unsigned)-1)
+ {
+ /*
+ * According to 6.1.1.6, repeat sequence headers should be
+ * identical to the original. However some encoders don't
+ * respect that and change various fields (including bitrate
+ * and aspect ratio) in the repeat sequence headers. So we
+ * choose to be as conservative as possible and only restart
+ * the decoder if the width, height, chroma_width,
+ * chroma_height or low_delay flag are modified.
+ */
+ if (sequence->width != mpeg2dec->sequence.width ||
+ sequence->height != mpeg2dec->sequence.height ||
+ sequence->chroma_width != mpeg2dec->sequence.chroma_width ||
+ sequence->chroma_height != mpeg2dec->sequence.chroma_height ||
+ ((sequence->flags ^ mpeg2dec->sequence.flags) &
+ SEQ_FLAG_LOW_DELAY))
+ {
+ decoder->stride_frame = sequence->width;
+ mpeg2_header_end (mpeg2dec);
+ mpeg2dec->action = invalid_end_action;
+ mpeg2dec->state = STATE_INVALID_END;
+ return;
+ }
+
+ mpeg2dec->state = rb->memcmp(&mpeg2dec->sequence, sequence,
+ sizeof (mpeg2_sequence_t)) ?
+ STATE_SEQUENCE_MODIFIED :
+ STATE_SEQUENCE_REPEATED;
+ }
+ else
+ {
+ decoder->stride_frame = sequence->width;
+ }
+
+ mpeg2dec->sequence = *sequence;
+ mpeg2_reset_info(&mpeg2dec->info);
+ mpeg2dec->info.sequence = &mpeg2dec->sequence;
+ mpeg2dec->info.gop = NULL;
+
+ info_user_data (mpeg2dec);
+}
+
+int mpeg2_header_gop (mpeg2dec_t * mpeg2dec)
+{
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ mpeg2_gop_t * gop = &mpeg2dec->new_gop;
+
+ if (!(buffer[1] & 8))
+ return 1;
+
+ gop->hours = (buffer[0] >> 2) & 31;
+ gop->minutes = ((buffer[0] << 4) | (buffer[1] >> 4)) & 63;
+ gop->seconds = ((buffer[1] << 3) | (buffer[2] >> 5)) & 63;
+ gop->pictures = ((buffer[2] << 1) | (buffer[3] >> 7)) & 63;
+ gop->flags = (buffer[0] >> 7) | ((buffer[3] >> 4) & 6);
+
+ mpeg2dec->state = STATE_GOP;
+ return 0;
+}
+
+void mpeg2_header_gop_finalize (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2dec->gop = mpeg2dec->new_gop;
+ mpeg2_reset_info (&mpeg2dec->info);
+ mpeg2dec->info.gop = &mpeg2dec->gop;
+ info_user_data (mpeg2dec);
+}
+
+void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (mpeg2dec->fbuf[1] != &mpeg2dec->fbuf_alloc[i].fbuf &&
+ mpeg2dec->fbuf[2] != &mpeg2dec->fbuf_alloc[i].fbuf)
+ {
+ mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[i].fbuf;
+ mpeg2dec->info.current_fbuf = mpeg2dec->fbuf[0];
+
+ if (b_type || (mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY))
+ {
+ if (b_type || mpeg2dec->convert)
+ mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[0];
+
+ mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[0];
+ }
+
+ break;
+ }
+ }
+}
+
+int mpeg2_header_picture (mpeg2dec_t * mpeg2dec)
+{
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ mpeg2_picture_t * picture = &mpeg2dec->new_picture;
+ mpeg2_decoder_t * decoder = &mpeg2dec->decoder;
+ int type;
+
+ mpeg2dec->state = (mpeg2dec->state != STATE_SLICE_1ST) ?
+ STATE_PICTURE : STATE_PICTURE_2ND;
+ mpeg2dec->ext_state = PIC_CODING_EXT;
+
+ picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6);
+
+ type = (buffer [1] >> 3) & 7;
+
+ if (type == PIC_FLAG_CODING_TYPE_P || type == PIC_FLAG_CODING_TYPE_B)
+ {
+ /* forward_f_code and backward_f_code - used in mpeg1 only */
+ decoder->f_motion.f_code[1] = (buffer[3] >> 2) & 1;
+ decoder->f_motion.f_code[0] =
+ (((buffer[3] << 1) | (buffer[4] >> 7)) & 7) - 1;
+ decoder->b_motion.f_code[1] = (buffer[4] >> 6) & 1;
+ decoder->b_motion.f_code[0] = ((buffer[4] >> 3) & 7) - 1;
+ }
+
+ picture->flags = PIC_FLAG_PROGRESSIVE_FRAME | type;
+ picture->tag = picture->tag2 = 0;
+
+ if (mpeg2dec->num_tags)
+ {
+ if (mpeg2dec->bytes_since_tag >= mpeg2dec->chunk_ptr - buffer + 4)
+ {
+ mpeg2dec->num_tags = 0;
+ picture->tag = mpeg2dec->tag_current;
+ picture->tag2 = mpeg2dec->tag2_current;
+ picture->flags |= PIC_FLAG_TAGS;
+ }
+ else if (mpeg2dec->num_tags > 1)
+ {
+ mpeg2dec->num_tags = 1;
+ picture->tag = mpeg2dec->tag_previous;
+ picture->tag2 = mpeg2dec->tag2_previous;
+ picture->flags |= PIC_FLAG_TAGS;
+ }
+ }
+
+ picture->nb_fields = 2;
+ picture->display_offset[0].x = picture->display_offset[1].x =
+ picture->display_offset[2].x = mpeg2dec->display_offset_x;
+
+ picture->display_offset[0].y = picture->display_offset[1].y =
+ picture->display_offset[2].y = mpeg2dec->display_offset_y;
+
+ /* XXXXXX decode extra_information_picture as well */
+
+ mpeg2dec->q_scale_type = 0;
+ decoder->intra_dc_precision = 7;
+ decoder->frame_pred_frame_dct = 1;
+ decoder->concealment_motion_vectors = 0;
+ decoder->scan = mpeg2_scan_norm;
+ decoder->picture_structure = FRAME_PICTURE;
+ mpeg2dec->copy_matrix = 0;
+
+ return 0;
+}
+
+static int picture_coding_ext (mpeg2dec_t * mpeg2dec)
+{
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ mpeg2_picture_t * picture = &mpeg2dec->new_picture;
+ mpeg2_decoder_t * decoder = &mpeg2dec->decoder;
+ uint32_t flags;
+
+ /* pre subtract 1 for use later in compute_motion_vector */
+ decoder->f_motion.f_code[0] = (buffer[0] & 15) - 1;
+ decoder->f_motion.f_code[1] = (buffer[1] >> 4) - 1;
+ decoder->b_motion.f_code[0] = (buffer[1] & 15) - 1;
+ decoder->b_motion.f_code[1] = (buffer[2] >> 4) - 1;
+
+ flags = picture->flags;
+
+ decoder->intra_dc_precision = 7 - ((buffer[2] >> 2) & 3);
+ decoder->picture_structure = buffer[2] & 3;
+
+ switch (decoder->picture_structure)
+ {
+ case TOP_FIELD:
+ flags |= PIC_FLAG_TOP_FIELD_FIRST;
+ case BOTTOM_FIELD:
+ picture->nb_fields = 1;
+ break;
+ case FRAME_PICTURE:
+ if (!(mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE))
+ {
+ picture->nb_fields = (buffer[3] & 2) ? 3 : 2;
+ flags |= (buffer[3] & 128) ? PIC_FLAG_TOP_FIELD_FIRST : 0;
+ }
+ else
+ {
+ picture->nb_fields = (buffer[3]&2) ? ((buffer[3]&128) ? 6 : 4) : 2;
+ }
+ break;
+ default:
+ return 1;
+ }
+
+ decoder->top_field_first = buffer[3] >> 7;
+ decoder->frame_pred_frame_dct = (buffer[3] >> 6) & 1;
+ decoder->concealment_motion_vectors = (buffer[3] >> 5) & 1;
+ mpeg2dec->q_scale_type = buffer[3] & 16;
+ decoder->intra_vlc_format = (buffer[3] >> 3) & 1;
+ decoder->scan = (buffer[3] & 4) ? mpeg2_scan_alt : mpeg2_scan_norm;
+
+ if (!(buffer[4] & 0x80))
+ flags &= ~PIC_FLAG_PROGRESSIVE_FRAME;
+
+ if (buffer[4] & 0x40)
+ {
+ flags |= (((buffer[4]<<26) | (buffer[5]<<18) | (buffer[6]<<10)) &
+ PIC_MASK_COMPOSITE_DISPLAY) | PIC_FLAG_COMPOSITE_DISPLAY;
+ }
+
+ picture->flags = flags;
+
+ mpeg2dec->ext_state = PIC_DISPLAY_EXT | COPYRIGHT_EXT | QUANT_MATRIX_EXT;
+
+ return 0;
+}
+
+static int picture_display_ext (mpeg2dec_t * mpeg2dec)
+{
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ mpeg2_picture_t * picture = &mpeg2dec->new_picture;
+ int i, nb_pos;
+
+ nb_pos = picture->nb_fields;
+
+ if (mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE)
+ nb_pos >>= 1;
+
+ for (i = 0; i < nb_pos; i++)
+ {
+ int x, y;
+
+ x = ((buffer[4*i] << 24) | (buffer[4*i+1] << 16) |
+ (buffer[4*i+2] << 8) | buffer[4*i+3]) >> (11-2*i);
+
+ y = ((buffer[4*i+2] << 24) | (buffer[4*i+3] << 16) |
+ (buffer[4*i+4] << 8) | buffer[4*i+5]) >> (10-2*i);
+
+ if (! (x & y & 1))
+ return 1;
+
+ picture->display_offset[i].x = mpeg2dec->display_offset_x = x >> 1;
+ picture->display_offset[i].y = mpeg2dec->display_offset_y = y >> 1;
+ }
+
+ for (; i < 3; i++)
+ {
+ picture->display_offset[i].x = mpeg2dec->display_offset_x;
+ picture->display_offset[i].y = mpeg2dec->display_offset_y;
+ }
+
+ return 0;
+}
+
+void mpeg2_header_picture_finalize (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_decoder_t * decoder = &mpeg2dec->decoder;
+ int old_type_b = decoder->coding_type == B_TYPE;
+ int low_delay = mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY;
+
+ finalize_matrix (mpeg2dec);
+ decoder->coding_type = mpeg2dec->new_picture.flags & PIC_MASK_CODING_TYPE;
+
+ if (mpeg2dec->state == STATE_PICTURE)
+ {
+ mpeg2_picture_t * picture;
+ mpeg2_picture_t * other;
+
+ decoder->second_field = 0;
+
+ picture = other = mpeg2dec->pictures;
+
+ if (old_type_b ^ (mpeg2dec->picture < mpeg2dec->pictures + 2))
+ picture += 2;
+ else
+ other += 2;
+
+ mpeg2dec->picture = picture;
+ *picture = mpeg2dec->new_picture;
+
+ if (!old_type_b)
+ {
+ mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
+ mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
+ }
+
+ mpeg2dec->fbuf[0] = NULL;
+ mpeg2_reset_info (&mpeg2dec->info);
+ mpeg2dec->info.current_picture = picture;
+ mpeg2dec->info.display_picture = picture;
+
+ if (decoder->coding_type != B_TYPE)
+ {
+ if (!low_delay)
+ {
+ if (mpeg2dec->first)
+ {
+ mpeg2dec->info.display_picture = NULL;
+ mpeg2dec->first = 0;
+ }
+ else
+ {
+ mpeg2dec->info.display_picture = other;
+
+ if (other->nb_fields == 1)
+ mpeg2dec->info.display_picture_2nd = other + 1;
+
+ mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[1];
+ }
+ }
+
+ if (!low_delay + !mpeg2dec->convert)
+ {
+ mpeg2dec->info.discard_fbuf =
+ mpeg2dec->fbuf[!low_delay + !mpeg2dec->convert];
+ }
+ }
+
+ if (mpeg2dec->convert)
+ {
+ mpeg2_convert_init_t convert_init;
+
+ if (!mpeg2dec->convert_start)
+ {
+ mpeg2dec->decoder.convert_id =
+ mpeg2_malloc (mpeg2dec->convert_id_size,
+ MPEG2_ALLOC_CONVERT_ID);
+
+ mpeg2dec->convert (MPEG2_CONVERT_START,
+ mpeg2dec->decoder.convert_id,
+ &mpeg2dec->sequence,
+ mpeg2dec->convert_stride,
+ mpeg2dec->convert_arg, &convert_init);
+
+ mpeg2dec->convert_start = convert_init.start;
+ mpeg2dec->decoder.convert = convert_init.copy;
+
+ int y_size = decoder->stride_frame * mpeg2dec->sequence.height;
+
+ mpeg2dec->yuv_buf[0][0] =
+ (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV);
+#if MPEG2_COLOR
+ int uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format);
+
+ mpeg2dec->yuv_buf[0][1] =
+ (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV);
+ mpeg2dec->yuv_buf[0][2] =
+ (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV);
+#endif
+
+ mpeg2dec->yuv_buf[1][0] =
+ (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV);
+#if MPEG2_COLOR
+ mpeg2dec->yuv_buf[1][1] =
+ (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV);
+ mpeg2dec->yuv_buf[1][2] =
+ (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV);
+#endif
+ y_size = decoder->stride_frame * 32;
+
+ mpeg2dec->yuv_buf[2][0] =
+ (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV);
+#if MPEG2_COLOR
+ uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format);
+
+ mpeg2dec->yuv_buf[2][1] =
+ (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV);
+ mpeg2dec->yuv_buf[2][2] =
+ (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV);
+#endif
+ }
+
+ if (!mpeg2dec->custom_fbuf)
+ {
+ while (mpeg2dec->alloc_index < 3)
+ {
+ mpeg2_fbuf_t * fbuf;
+
+ fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf;
+ fbuf->id = NULL;
+
+ fbuf->buf[0] =
+ (uint8_t *) mpeg2_malloc (convert_init.buf_size[0],
+ MPEG2_ALLOC_CONVERTED);
+#if MPEG2_COLOR
+ fbuf->buf[1] =
+ (uint8_t *) mpeg2_malloc (convert_init.buf_size[1],
+ MPEG2_ALLOC_CONVERTED);
+ fbuf->buf[2] =
+ (uint8_t *) mpeg2_malloc (convert_init.buf_size[2],
+ MPEG2_ALLOC_CONVERTED);
+#endif
+ }
+
+ mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE));
+ }
+ }
+ else if (!mpeg2dec->custom_fbuf)
+ {
+ while (mpeg2dec->alloc_index < 3)
+ {
+ mpeg2_fbuf_t * fbuf;
+
+ fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf;
+
+ fbuf->id = NULL;
+
+ int y_size = decoder->stride_frame * mpeg2dec->sequence.height;
+
+ fbuf->buf[0] = (uint8_t *) mpeg2_malloc (y_size,
+ MPEG2_ALLOC_YUV);
+#if MPEG2_COLOR
+ int uv_size = y_size >> (2 - decoder->chroma_format);
+
+ fbuf->buf[1] = (uint8_t *) mpeg2_malloc (uv_size,
+ MPEG2_ALLOC_YUV);
+ fbuf->buf[2] = (uint8_t *) mpeg2_malloc (uv_size,
+ MPEG2_ALLOC_YUV);
+#endif
+ }
+
+ mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE));
+ }
+ }
+ else
+ {
+ decoder->second_field = 1;
+ mpeg2dec->picture++; /* second field picture */
+
+ *(mpeg2dec->picture) = mpeg2dec->new_picture;
+
+ mpeg2dec->info.current_picture_2nd = mpeg2dec->picture;
+
+ if (low_delay || decoder->coding_type == B_TYPE)
+ mpeg2dec->info.display_picture_2nd = mpeg2dec->picture;
+ }
+
+ info_user_data (mpeg2dec);
+}
+
+static int copyright_ext (mpeg2dec_t * mpeg2dec)
+{
+ (void)mpeg2dec;
+ return 0;
+}
+
+static int quant_matrix_ext (mpeg2dec_t * mpeg2dec)
+{
+ uint8_t * buffer = mpeg2dec->chunk_start;
+ int i, j;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (buffer[0] & (8 >> i))
+ {
+ for (j = 0; j < 64; j++)
+ {
+ mpeg2dec->new_quantizer_matrix[i][mpeg2_scan_norm[j]] =
+ (buffer[j] << (i+5)) | (buffer[j+1] >> (3-i));
+ }
+
+ mpeg2dec->copy_matrix |= 1 << i;
+ buffer += 64;
+ }
+ }
+
+ return 0;
+}
+
+int mpeg2_header_extension (mpeg2dec_t * mpeg2dec)
+{
+ static int (* const parser[9]) (mpeg2dec_t *) =
+ {
+ NULL,
+ sequence_ext,
+ sequence_display_ext,
+ quant_matrix_ext,
+ copyright_ext,
+ NULL,
+ NULL,
+ picture_display_ext,
+ picture_coding_ext
+ };
+
+ int ext, ext_bit;
+
+ ext = mpeg2dec->chunk_start[0] >> 4;
+ ext_bit = 1 << ext;
+
+ if (!(mpeg2dec->ext_state & ext_bit))
+ return 0; /* ignore illegal extensions */
+
+ mpeg2dec->ext_state &= ~ext_bit;
+
+ return parser[ext] (mpeg2dec);
+}
+
+int mpeg2_header_user_data (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2dec->user_data_len += mpeg2dec->chunk_ptr - 1 - mpeg2dec->chunk_start;
+ mpeg2dec->chunk_start = mpeg2dec->chunk_ptr - 1;
+
+ return 0;
+}
+
+static void prescale (mpeg2dec_t * mpeg2dec, int index)
+{
+ static const int non_linear_scale[32] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 28, 32, 36, 40, 44, 48, 52,
+ 56, 64, 72, 80, 88, 96, 104, 112
+ };
+
+ int i, j, k;
+ mpeg2_decoder_t * decoder = &mpeg2dec->decoder;
+
+ if (mpeg2dec->scaled[index] != mpeg2dec->q_scale_type)
+ {
+ mpeg2dec->scaled[index] = mpeg2dec->q_scale_type;
+
+ for (i = 0; i < 32; i++)
+ {
+ k = mpeg2dec->q_scale_type ? non_linear_scale[i] : (i << 1);
+
+ for (j = 0; j < 64; j++)
+ {
+ decoder->quantizer_prescale[index][i][j] =
+ k * mpeg2dec->quantizer_matrix[index][j];
+ }
+ }
+ }
+}
+
+mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_decoder_t * decoder = &mpeg2dec->decoder;
+
+ mpeg2dec->info.user_data = NULL;
+ mpeg2dec->info.user_data_len = 0;
+ mpeg2dec->state = (mpeg2dec->picture->nb_fields > 1 ||
+ mpeg2dec->state == STATE_PICTURE_2ND) ?
+ STATE_SLICE : STATE_SLICE_1ST;
+
+ if (mpeg2dec->decoder.coding_type != D_TYPE)
+ {
+ prescale (mpeg2dec, 0);
+
+ if (decoder->chroma_quantizer[0] == decoder->quantizer_prescale[2])
+ prescale (mpeg2dec, 2);
+
+ if (mpeg2dec->decoder.coding_type != I_TYPE)
+ {
+ prescale (mpeg2dec, 1);
+
+ if (decoder->chroma_quantizer[1] == decoder->quantizer_prescale[3])
+ prescale (mpeg2dec, 3);
+ }
+ }
+
+ if (!(mpeg2dec->nb_decode_slices))
+ {
+ mpeg2dec->picture->flags |= PIC_FLAG_SKIP;
+ }
+ else if (mpeg2dec->convert_start)
+ {
+ mpeg2dec->convert_start (decoder->convert_id, mpeg2dec->fbuf[0],
+ mpeg2dec->picture, mpeg2dec->info.gop);
+
+ if (mpeg2dec->decoder.coding_type == B_TYPE)
+ {
+ mpeg2_init_fbuf (&mpeg2dec->decoder, mpeg2dec->yuv_buf[2],
+ mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1],
+ mpeg2dec->yuv_buf[mpeg2dec->yuv_index]);
+ }
+ else
+ {
+ mpeg2_init_fbuf (&mpeg2dec->decoder,
+ mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1],
+ mpeg2dec->yuv_buf[mpeg2dec->yuv_index],
+ mpeg2dec->yuv_buf[mpeg2dec->yuv_index]);
+
+ if (mpeg2dec->state == STATE_SLICE)
+ mpeg2dec->yuv_index ^= 1;
+ }
+ }
+ else
+ {
+ int b_type;
+
+ b_type = (mpeg2dec->decoder.coding_type == B_TYPE);
+
+ mpeg2_init_fbuf (&mpeg2dec->decoder, mpeg2dec->fbuf[0]->buf,
+ mpeg2dec->fbuf[b_type + 1]->buf,
+ mpeg2dec->fbuf[b_type]->buf);
+ }
+
+ mpeg2dec->action = NULL;
+
+ return STATE_INTERNAL_NORETURN;
+}
+
+static mpeg2_state_t seek_sequence (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_reset_info (&mpeg2dec->info);
+
+ mpeg2dec->info.sequence = NULL;
+ mpeg2dec->info.gop = NULL;
+
+ mpeg2_header_state_init (mpeg2dec);
+
+ mpeg2dec->action = mpeg2_seek_header;
+
+ return mpeg2_seek_header (mpeg2dec);
+}
+
+mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec)
+{
+ mpeg2_picture_t * picture;
+ int b_type;
+
+ b_type = (mpeg2dec->decoder.coding_type == B_TYPE);
+ picture = mpeg2dec->pictures;
+
+ if ((mpeg2dec->picture >= picture + 2) ^ b_type)
+ picture = mpeg2dec->pictures + 2;
+
+ mpeg2_reset_info (&mpeg2dec->info);
+
+ if (!(mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY))
+ {
+ mpeg2dec->info.display_picture = picture;
+
+ if (picture->nb_fields == 1)
+ mpeg2dec->info.display_picture_2nd = picture + 1;
+
+ mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[b_type];
+
+ if (!mpeg2dec->convert)
+ mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type + 1];
+ }
+ else if (!mpeg2dec->convert)
+ {
+ mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type];
+ }
+
+ mpeg2dec->action = seek_sequence;
+
+ return STATE_END;
+}
diff --git a/apps/plugins/mpegplayer/libmpeg2/idct.c b/apps/plugins/mpegplayer/libmpeg2/idct.c
new file mode 100644
index 0000000000..7f0b9a3c12
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/idct.c
@@ -0,0 +1,274 @@
+/*
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.36
+ */
+
+#include "plugin.h"
+
+#include "mpeg2dec_config.h"
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+#if defined(CPU_COLDFIRE) || defined (CPU_ARM)
+#define IDCT_ASM
+#endif
+
+#ifndef IDCT_ASM
+
+#define W1 2841 /* 2048 * sqrt (2) * cos (1 * pi / 16) */
+#define W2 2676 /* 2048 * sqrt (2) * cos (2 * pi / 16) */
+#define W3 2408 /* 2048 * sqrt (2) * cos (3 * pi / 16) */
+#define W5 1609 /* 2048 * sqrt (2) * cos (5 * pi / 16) */
+#define W6 1108 /* 2048 * sqrt (2) * cos (6 * pi / 16) */
+#define W7 565 /* 2048 * sqrt (2) * cos (7 * pi / 16) */
+
+/*
+ * In legal streams, the IDCT output should be between -384 and +384.
+ * In corrupted streams, it is possible to force the IDCT output to go
+ * to +-3826 - this is the worst case for a column IDCT where the
+ * column inputs are 16-bit values.
+ */
+#define CLIP(i) \
+ ({ typeof (i) _i = (i); \
+ if ((_i & 0xff) != _i) \
+ _i = ~(_i >> (8*sizeof(_i) - 1)); \
+ _i; })
+
+#if 0
+#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \
+ do { \
+ t0 = W0 * d0 + W1 * d1; \
+ t1 = W0 * d1 - W1 * d0; \
+ } while (0)
+#else
+#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \
+ do { \
+ int tmp = W0 * (d0 + d1); \
+ t0 = tmp + (W1 - W0) * d1; \
+ t1 = tmp - (W1 + W0) * d0; \
+ } while (0)
+#endif
+
+static inline void idct_row (int16_t * const block)
+{
+ int d0, d1, d2, d3;
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+ int t0, t1, t2, t3;
+
+ /* shortcut */
+ if (likely (!(block[1] | ((int32_t *)block)[1] | ((int32_t *)block)[2] |
+ ((int32_t *)block)[3])))
+ {
+ uint32_t tmp = (uint16_t) (block[0] >> 1);
+ tmp |= tmp << 16;
+ ((int32_t *)block)[0] = tmp;
+ ((int32_t *)block)[1] = tmp;
+ ((int32_t *)block)[2] = tmp;
+ ((int32_t *)block)[3] = tmp;
+ return;
+ }
+
+ d0 = (block[0] << 11) + 2048;
+ d1 = block[1];
+ d2 = block[2] << 11;
+ d3 = block[3];
+ t0 = d0 + d2;
+ t1 = d0 - d2;
+ BUTTERFLY (t2, t3, W6, W2, d3, d1);
+ a0 = t0 + t2;
+ a1 = t1 + t3;
+ a2 = t1 - t3;
+ a3 = t0 - t2;
+
+ d0 = block[4];
+ d1 = block[5];
+ d2 = block[6];
+ d3 = block[7];
+ BUTTERFLY (t0, t1, W7, W1, d3, d0);
+ BUTTERFLY (t2, t3, W3, W5, d1, d2);
+ b0 = t0 + t2;
+ b3 = t1 + t3;
+ t0 -= t2;
+ t1 -= t3;
+ b1 = ((t0 + t1) >> 8) * 181;
+ b2 = ((t0 - t1) >> 8) * 181;
+
+ block[0] = (a0 + b0) >> 12;
+ block[1] = (a1 + b1) >> 12;
+ block[2] = (a2 + b2) >> 12;
+ block[3] = (a3 + b3) >> 12;
+ block[4] = (a3 - b3) >> 12;
+ block[5] = (a2 - b2) >> 12;
+ block[6] = (a1 - b1) >> 12;
+ block[7] = (a0 - b0) >> 12;
+}
+
+static inline void idct_col (int16_t * const block)
+{
+ int d0, d1, d2, d3;
+ int a0, a1, a2, a3, b0, b1, b2, b3;
+ int t0, t1, t2, t3;
+
+ d0 = (block[8*0] << 11) + 65536;
+ d1 = block[8*1];
+ d2 = block[8*2] << 11;
+ d3 = block[8*3];
+ t0 = d0 + d2;
+ t1 = d0 - d2;
+ BUTTERFLY (t2, t3, W6, W2, d3, d1);
+ a0 = t0 + t2;
+ a1 = t1 + t3;
+ a2 = t1 - t3;
+ a3 = t0 - t2;
+
+ d0 = block[8*4];
+ d1 = block[8*5];
+ d2 = block[8*6];
+ d3 = block[8*7];
+ BUTTERFLY (t0, t1, W7, W1, d3, d0);
+ BUTTERFLY (t2, t3, W3, W5, d1, d2);
+ b0 = t0 + t2;
+ b3 = t1 + t3;
+ t0 -= t2;
+ t1 -= t3;
+ b1 = ((t0 + t1) >> 8) * 181;
+ b2 = ((t0 - t1) >> 8) * 181;
+
+ block[8*0] = (a0 + b0) >> 17;
+ block[8*1] = (a1 + b1) >> 17;
+ block[8*2] = (a2 + b2) >> 17;
+ block[8*3] = (a3 + b3) >> 17;
+ block[8*4] = (a3 - b3) >> 17;
+ block[8*5] = (a2 - b2) >> 17;
+ block[8*6] = (a1 - b1) >> 17;
+ block[8*7] = (a0 - b0) >> 17;
+}
+
+void mpeg2_idct_copy (int16_t * block, uint8_t * dest,
+ const int stride)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ idct_row (block + 8 * i);
+
+ for (i = 0; i < 8; i++)
+ idct_col (block + i);
+
+ do
+ {
+ dest[0] = CLIP (block[0]);
+ dest[1] = CLIP (block[1]);
+ dest[2] = CLIP (block[2]);
+ dest[3] = CLIP (block[3]);
+ dest[4] = CLIP (block[4]);
+ dest[5] = CLIP (block[5]);
+ dest[6] = CLIP (block[6]);
+ dest[7] = CLIP (block[7]);
+
+ ((int32_t *)block)[0] = 0;
+ ((int32_t *)block)[1] = 0;
+ ((int32_t *)block)[2] = 0;
+ ((int32_t *)block)[3] = 0;
+
+ dest += stride;
+ block += 8;
+ }
+ while (--i);
+}
+
+void mpeg2_idct_add (const int last, int16_t * block,
+ uint8_t * dest, const int stride)
+{
+ int i;
+
+ if (last != 129 || (block[0] & (7 << 4)) == (4 << 4))
+ {
+ for (i = 0; i < 8; i++)
+ idct_row (block + 8 * i);
+
+ for (i = 0; i < 8; i++)
+ idct_col (block + i);
+
+ do
+ {
+ dest[0] = CLIP (block[0] + dest[0]);
+ dest[1] = CLIP (block[1] + dest[1]);
+ dest[2] = CLIP (block[2] + dest[2]);
+ dest[3] = CLIP (block[3] + dest[3]);
+ dest[4] = CLIP (block[4] + dest[4]);
+ dest[5] = CLIP (block[5] + dest[5]);
+ dest[6] = CLIP (block[6] + dest[6]);
+ dest[7] = CLIP (block[7] + dest[7]);
+
+ ((int32_t *)block)[0] = 0;
+ ((int32_t *)block)[1] = 0;
+ ((int32_t *)block)[2] = 0;
+ ((int32_t *)block)[3] = 0;
+
+ dest += stride;
+ block += 8;
+ }
+ while (--i);
+ }
+ else
+ {
+ int DC = (block[0] + 64) >> 7;
+ block[0] = block[63] = 0;
+ i = 8;
+
+ do
+ {
+ dest[0] = CLIP (DC + dest[0]);
+ dest[1] = CLIP (DC + dest[1]);
+ dest[2] = CLIP (DC + dest[2]);
+ dest[3] = CLIP (DC + dest[3]);
+ dest[4] = CLIP (DC + dest[4]);
+ dest[5] = CLIP (DC + dest[5]);
+ dest[6] = CLIP (DC + dest[6]);
+ dest[7] = CLIP (DC + dest[7]);
+ dest += stride;
+ }
+ while (--i);
+ }
+}
+
+#endif /* IDCT_ASM */
+
+void mpeg2_idct_init (void)
+{
+ int i, j;
+
+ for (i = 0; i < 64; i++)
+ {
+ j = default_mpeg2_scan_norm[i];
+ mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
+
+ j = default_mpeg2_scan_alt[i];
+ mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
+ }
+}
diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_arm.S b/apps/plugins/mpegplayer/libmpeg2/idct_arm.S
new file mode 100644
index 0000000000..97a87a8b59
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/idct_arm.S
@@ -0,0 +1,443 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+
+ .global mpeg2_idct_copy
+ .type mpeg2_idct_copy, %function
+ .global mpeg2_idct_add
+ .type mpeg2_idct_add, %function
+
+
+/* Custom calling convention:
+ * r0 contains block pointer and is non-volatile
+ * all non-volatile c context saved and restored on its behalf
+ */
+.idct:
+ add r12, r0, #128
+1:
+ ldrsh r1, [r0, #0] /* d0 */
+ ldrsh r2, [r0, #2] /* d1 */
+ ldrsh r3, [r0, #4] /* d2 */
+ ldrsh r4, [r0, #6] /* d3 */
+ ldrsh r5, [r0, #8] /* d0 */
+ ldrsh r6, [r0, #10] /* d1 */
+ ldrsh r7, [r0, #12] /* d2 */
+ ldrsh r8, [r0, #14] /* d3 */
+ orrs r9, r2, r3
+ orreqs r9, r4, r5
+ orreqs r9, r6, r7
+ cmpeq r8, #0
+ bne 2f
+ mov r1, r1, asl #15
+ bic r1, r1, #0x8000
+ orr r1, r1, r1, lsr #16
+ str r1, [r0], #4
+ str r1, [r0], #4
+ str r1, [r0], #4
+ str r1, [r0], #4
+ cmp r0, r12
+ blo 1b
+ b 3f
+2:
+ mov r1, r1, asl #11 /* r1 = d0 = (block[0] << 11) + 2048 */
+ add r1, r1, #2048
+ add r1, r1, r3, asl #11 /* r1 = t0 = d0 + (block[2] << 11) */
+ sub r3, r1, r3, asl #12 /* r3 = t1 = d0 - (block[2] << 11) */
+
+ add r9, r2, r4 /* r9 = tmp = (d1+d3)*(1108/4) */
+ add r10, r9, r9, asl #2
+ add r10, r10, r9, asl #4
+ add r9, r10, r9, asl #8
+
+ add r10, r2, r2, asl #4 /* r2 = t2 = tmp + (d1*(1568/32)*8) */
+ add r2, r10, r2, asl #5
+ add r2, r9, r2, asl #3
+
+ add r10, r4, r4, asl #2 /* r4 = t3 = tmp - (d3*(3784/8)*2) */
+ rsb r10, r10, r4, asl #6
+ add r4, r4, r10, asl #3
+ sub r4, r9, r4, asl #1
+ /* t2 & t3 are 1/4 final value here */
+ add r1, r1, r2, asl #2 /* r1 = a0 = t0 + t2 */
+ sub r2, r1, r2, asl #3 /* r2 = a3 = t0 - t2 */
+ add r3, r3, r4, asl #2 /* r3 = a1 = t1 + t3 */
+ sub r4, r3, r4, asl #3 /* r4 = a2 = t1 - t3 */
+
+ add r9, r8, r5 /* r9 = tmp = 565*(d3 + d0) */
+ add r10, r9, r9, asl #4
+ add r10, r10, r10, asl #5
+ add r9, r10, r9, asl #2
+
+ add r10, r5, r5, asl #4 /* r5 = t0 = tmp + (((2276/4)*d0)*4) */
+ add r10, r10, r10, asl #5
+ add r5, r10, r5, asl #3
+ add r5, r9, r5, asl #2
+
+ add r10, r8, r8, asl #2 /* r8 = t1 = tmp - (((3406/2)*d3)*2) */
+ add r10, r10, r10, asl #4
+ add r10, r10, r8, asl #7
+ rsb r8, r8, r10, asl #3
+ sub r8, r9, r8, asl #1
+
+ add r9, r6, r7 /* r9 = tmp = (2408/8)*(d1 + d2) */
+ add r10, r9, r9, asl #3
+ add r10, r10, r10, asl #5
+ add r9, r10, r9, asl #2
+
+ add r10, r7, r7, asl #3 /* r7 = t2 = (tmp*8) - 799*d2 */
+ add r10, r10, r7, asl #4
+ rsb r7, r7, r10, asl #5
+ rsb r7, r7, r9, asl #3
+
+ sub r10, r6, r6, asl #4 /* r6 = t3 = (tmp*8) - 4017*d1 */
+ sub r10, r10, r6, asl #6
+ add r10, r10, r6, asl #12
+ add r6, r10, r6
+ rsb r6, r6, r9, asl #3
+ /* t0 = r5, t1 = r8, t2 = r7, t3 = r6*/
+ add r9, r5, r7 /* r9 = b0 = t0 + t2 */
+ add r10, r8, r6 /* r10 = b3 = t1 + t3 */
+ sub r5, r5, r7 /* t0 -= t2 */
+ sub r8, r8, r6 /* t1 -= t3 */
+ add r6, r5, r8 /* r6 = t0 + t1 */
+ sub r7, r5, r8 /* r7 = t0 - t1 */
+
+ add r11, r6, r6, asr #2 /* r6 = b1 = r6*(181/128) */
+ add r11, r11, r11, asr #5
+ add r6, r11, r6, asr #3
+ add r11, r7, r7, asr #2 /* r7 = b2 = r7*(181/128) */
+ add r11, r11, r11, asr #5
+ add r7, r11, r7, asr #3
+ /* r1 = a0, r3 = a1, r4 = a2, r2 = a3 */
+ /* r9 = b0, r6 = b1*2, r7 = b2*2, r10 = b3 */
+ add r5, r1, r9 /* block[0] = (a0 + b0) >> 12 */
+ mov r5, r5, asr #12
+ strh r5, [r0], #2
+ add r8, r3, r6, asr #1 /* block[1] = (a1 + b1) >> 12 */
+ mov r8, r8, asr #12
+ strh r8, [r0], #2
+ add r5, r4, r7, asr #1 /* block[2] = (a2 + b2) >> 12 */
+ mov r5, r5, asr #12
+ strh r5, [r0], #2
+ add r8, r2, r10 /* block[3] = (a3 + b3) >> 12 */
+ mov r8, r8, asr #12
+ strh r8, [r0], #2
+ sub r5, r2, r10 /* block[4] = (a3 - b3) >> 12 */
+ mov r5, r5, asr #12
+ strh r5, [r0], #2
+ sub r8, r4, r7, asr #1 /* block[5] = (a2 - b2) >> 12 */
+ mov r8, r8, asr #12
+ strh r8, [r0], #2
+ sub r5, r3, r6, asr #1 /* block[6] = (a1 - b1) >> 12 */
+ mov r5, r5, asr #12
+ strh r5, [r0], #2
+ sub r8, r1, r9 /* block[7] = (a0 - b0) >> 12 */
+ mov r8, r8, asr #12
+ strh r8, [r0], #2
+ cmp r0, r12
+ blo 1b
+3:
+ sub r0, r0, #128
+ add r12, r0, #16
+4:
+ ldrsh r1, [r0, #0*8] /* d0 */
+ ldrsh r2, [r0, #2*8] /* d1 */
+ ldrsh r3, [r0, #4*8] /* d2 */
+ ldrsh r4, [r0, #6*8] /* d3 */
+ ldrsh r5, [r0, #8*8] /* d0 */
+ ldrsh r6, [r0, #10*8] /* d1 */
+ ldrsh r7, [r0, #12*8] /* d2 */
+ ldrsh r8, [r0, #14*8] /* d3 */
+
+ mov r1, r1, asl #11 /* r1 = d0 = (block[0] << 11) + 2048 */
+ add r1, r1, #65536
+ add r1, r1, r3, asl #11 /* r1 = t0 = d0 + d2:(block[2] << 11) */
+ sub r3, r1, r3, asl #12 /* r3 = t1 = d0 - d2:(block[2] << 11) */
+
+ add r9, r2, r4 /* r9 = tmp = (d1+d3)*(1108/4) */
+ add r10, r9, r9, asl #2
+ add r10, r10, r9, asl #4
+ add r9, r10, r9, asl #8
+
+ add r11, r2, r2, asl #4 /* r2 = t2 = tmp + (d1*(1568/32)*8) */
+ add r2, r11, r2, asl #5
+ add r2, r9, r2, asl #3
+
+ add r10, r4, r4, asl #2 /* r4 = t3 = tmp - (d3*(3784/8)*2) */
+ rsb r10, r10, r4, asl #6
+ add r4, r4, r10, asl #3
+ sub r4, r9, r4, asl #1
+ /* t2 & t3 are 1/4 final value here */
+ add r1, r1, r2, asl #2 /* r1 = a0 = t0 + t2 */
+ sub r2, r1, r2, asl #3 /* r2 = a3 = t0 - t2 */
+ add r3, r3, r4, asl #2 /* r3 = a1 = t1 + t3 */
+ sub r4, r3, r4, asl #3 /* r4 = a2 = t1 - t3 */
+
+ add r9, r8, r5 /* r9 = tmp = 565*(d3 + d0) */
+ add r10, r9, r9, asl #4
+ add r10, r10, r10, asl #5
+ add r9, r10, r9, asl #2
+
+ add r10, r5, r5, asl #4 /* r5 = t0 = tmp + (((2276/4)*d0)*4) */
+ add r10, r10, r10, asl #5
+ add r5, r10, r5, asl #3
+ add r5, r9, r5, asl #2
+
+ add r10, r8, r8, asl #2 /* r8 = t1 = tmp - (((3406/2)*d3)*2) */
+ add r10, r10, r10, asl #4
+ add r10, r10, r8, asl #7
+ rsb r8, r8, r10, asl #3
+ sub r8, r9, r8, asl #1
+
+ add r9, r6, r7 /* r9 = tmp = (2408/8)*(d1 + d2) */
+ add r10, r9, r9, asl #3
+ add r10, r10, r10, asl #5
+ add r9, r10, r9, asl #2
+
+ add r10, r7, r7, asl #3 /* r7 = t2 = (tmp*8) - 799*d2 */
+ add r10, r10, r7, asl #4
+ rsb r7, r7, r10, asl #5
+ rsb r7, r7, r9, asl #3
+
+ sub r10, r6, r6, asl #4 /* r6 = t3 = (tmp*8) - 4017*d1 */
+ sub r10, r10, r6, asl #6
+ add r10, r10, r6, asl #12
+ add r6, r10, r6
+ rsb r6, r6, r9, asl #3
+ /* t0=r5, t1=r8, t2=r7, t3=r6*/
+ add r9, r5, r7 /* r9 = b0 = t0 + t2 */
+ add r10, r8, r6 /* r10 = b3 = t1 + t3 */
+ sub r5, r5, r7 /* t0 -= t2 */
+ sub r8, r8, r6 /* t1 -= t3 */
+ add r6, r5, r8 /* r6 = t0 + t1 */
+ sub r7, r5, r8 /* r7 = t0 - t1 */
+
+ add r11, r6, r6, asr #2 /* r6 = b1 = r5*(181/128) */
+ add r11, r11, r11, asr #5
+ add r6, r11, r6, asr #3
+ add r11, r7, r7, asr #2 /* r7 = b2 = r6*(181/128) */
+ add r11, r11, r11, asr #5
+ add r7, r11, r7, asr #3
+ /* r1 = a0, r3 = a1, r4 = a2, r2 = a3 */
+ /* r9 = b0, r6 = b1*2, r7 = b2*2, r10 = b3 */
+ add r5, r1, r9 /* block[0] = (a0 + b0) >> 17 */
+ mov r5, r5, asr #17
+ strh r5, [r0, #0*8]
+ add r8, r3, r6, asr #1 /* block[1] = (a1 + b1) >> 17 */
+ mov r8, r8, asr #17
+ strh r8, [r0, #2*8]
+ add r5, r4, r7, asr #1 /* block[2] = (a2 + b2) >> 17 */
+ mov r5, r5, asr #17
+ strh r5, [r0, #4*8]
+ add r8, r2, r10 /* block[3] = (a3 + b3) >> 17 */
+ mov r8, r8, asr #17
+ strh r8, [r0, #6*8]
+ sub r5, r2, r10 /* block[4] = (a3 - b3) >> 17 */
+ mov r5, r5, asr #17
+ strh r5, [r0, #8*8]
+ sub r8, r4, r7, asr #1 /* block[5] = (a2 - b2) >> 17 */
+ mov r8, r8, asr #17
+ strh r8, [r0, #10*8]
+ sub r5, r3, r6, asr #1 /* block[6] = (a1 - b1) >> 17 */
+ mov r5, r5, asr #17
+ strh r5, [r0, #12*8]
+ sub r8, r1, r9 /* block[7] = (a0 - b0) >> 17 */
+ mov r8, r8, asr #17
+ strh r8, [r0, #14*8]
+ add r0, r0, #2
+ cmp r0, r12
+ blo 4b
+ sub r0, r0, #16
+ bx lr
+
+mpeg2_idct_copy:
+ stmfd sp!, { r1-r2, r4-r11, lr }
+ bl .idct
+ ldmfd sp!, { r1-r2 }
+ mov r11, #0
+ add r12, r0, #128
+1:
+ ldrsh r3, [r0, #0]
+ ldrsh r4, [r0, #2]
+ ldrsh r5, [r0, #4]
+ ldrsh r6, [r0, #6]
+ ldrsh r7, [r0, #8]
+ ldrsh r8, [r0, #10]
+ ldrsh r9, [r0, #12]
+ ldrsh r10, [r0, #14]
+ cmp r3, #255
+ mvnhi r3, r3, asr #31
+ strb r3, [r1, #0]
+ str r11, [r0], #4
+ cmp r4, #255
+ mvnhi r4, r4, asr #31
+ strb r4, [r1, #1]
+ cmp r5, #255
+ mvnhi r5, r5, asr #31
+ strb r5, [r1, #2]
+ str r11, [r0], #4
+ cmp r6, #255
+ mvnhi r6, r6, asr #31
+ strb r6, [r1, #3]
+ cmp r7, #255
+ mvnhi r7, r7, asr #31
+ strb r7, [r1, #4]
+ str r11, [r0], #4
+ cmp r8, #255
+ mvnhi r8, r8, asr #31
+ strb r8, [r1, #5]
+ cmp r9, #255
+ mvnhi r9, r9, asr #31
+ strb r9, [r1, #6]
+ str r11, [r0], #4
+ cmp r10, #255
+ mvnhi r10, r10, asr #31
+ strb r10, [r1, #7]
+ add r1, r1, r2
+ cmp r0, r12
+ blo 1b
+ ldmpc regs=r4-r11
+
+mpeg2_idct_add:
+ cmp r0, #129
+ mov r0, r1
+ ldreqsh r1, [r0, #0]
+ bne 1f
+ and r1, r1, #0x70
+ cmp r1, #0x40
+ bne 3f
+1:
+ stmfd sp!, { r2-r11, lr }
+ bl .idct
+ ldmfd sp!, { r1-r2 }
+ mov r11, #0
+ add r12, r0, #128
+2:
+ ldrb r3, [r1, #0]
+ ldrb r4, [r1, #1]
+ ldrb r5, [r1, #2]
+ ldrb r6, [r1, #3]
+ ldrsh r7, [r0, #0]
+ ldrsh r8, [r0, #2]
+ ldrsh r9, [r0, #4]
+ ldrsh r10, [r0, #6]
+ add r7, r7, r3
+ ldrb r3, [r1, #4]
+ cmp r7, #255
+ mvnhi r7, r7, asr #31
+ strb r7, [r1, #0]
+ ldrsh r7, [r0, #8]
+ add r8, r8, r4
+ ldrb r4, [r1, #5]
+ cmp r8, #255
+ mvnhi r8, r8, asr #31
+ strb r8, [r1, #1]
+ ldrsh r8, [r0, #10]
+ add r9, r9, r5
+ ldrb r5, [r1, #6]
+ cmp r9, #255
+ mvnhi r9, r9, asr #31
+ strb r9, [r1, #2]
+ ldrsh r9, [r0, #12]
+ add r10, r10, r6
+ ldrb r6, [r1, #7]
+ cmp r10, #255
+ mvnhi r10, r10, asr #31
+ strb r10, [r1, #3]
+ ldrsh r10, [r0, #14]
+ str r11, [r0], #4
+ add r7, r7, r3
+ cmp r7, #255
+ mvnhi r7, r7, asr #31
+ strb r7, [r1, #4]
+ str r11, [r0], #4
+ add r8, r8, r4
+ cmp r8, #255
+ mvnhi r8, r8, asr #31
+ strb r8, [r1, #5]
+ str r11, [r0], #4
+ add r9, r9, r5
+ cmp r9, #255
+ mvnhi r9, r9, asr #31
+ strb r9, [r1, #6]
+ add r10, r10, r6
+ cmp r10, #255
+ mvnhi r10, r10, asr #31
+ strb r10, [r1, #7]
+ str r11, [r0], #4
+ add r1, r1, r2
+ cmp r0, r12
+ blo 2b
+ ldmpc regs=r4-r11
+3:
+ stmfd sp!, { r4-r5, lr }
+ ldrsh r1, [r0, #0] /* r1 = block[0] */
+ mov r4, #0
+ strh r4, [r0, #0] /* block[0] = 0 */
+ strh r4, [r0, #126] /* block[63] = 0 */
+ add r1, r1, #64 /* r1 = DC << 7 */
+ add r0, r2, r3, asl #3
+4:
+ ldrb r4, [r2, #0]
+ ldrb r5, [r2, #1]
+ ldrb r12, [r2, #2]
+ ldrb lr, [r2, #3]
+ add r4, r4, r1, asr #7
+ cmp r4, #255
+ mvnhi r4, r4, asr #31
+ strb r4, [r2, #0]
+ add r5, r5, r1, asr #7
+ cmp r5, #255
+ mvnhi r5, r5, asr #31
+ strb r5, [r2, #1]
+ add r12, r12, r1, asr #7
+ cmp r12, #255
+ mvnhi r12, r12, asr #31
+ strb r12, [r2, #2]
+ add lr, lr, r1, asr #7
+ cmp lr, #255
+ mvnhi lr, lr, asr #31
+ strb lr, [r2, #3]
+ ldrb r4, [r2, #4]
+ ldrb r5, [r2, #5]
+ ldrb r12, [r2, #6]
+ ldrb lr, [r2, #7]
+ add r4, r4, r1, asr #7
+ cmp r4, #255
+ mvnhi r4, r4, asr #31
+ strb r4, [r2, #4]
+ add r5, r5, r1, asr #7
+ cmp r5, #255
+ mvnhi r5, r5, asr #31
+ strb r5, [r2, #5]
+ add r12, r12, r1, asr #7
+ cmp r12, #255
+ mvnhi r12, r12, asr #31
+ strb r12, [r2, #6]
+ add lr, lr, r1, asr #7
+ cmp lr, #255
+ mvnhi lr, lr, asr #31
+ strb lr, [r2, #7]
+ add r2, r2, r3
+ cmp r2, r0
+ blo 4b
+ ldmpc regs=r4-r5
diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S b/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S
new file mode 100644
index 0000000000..dc53cbd7bd
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S
@@ -0,0 +1,297 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Jens Arnold
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+ .global mpeg2_idct_copy
+ .type mpeg2_idct_copy, %function
+ .global mpeg2_idct_add
+ .type mpeg2_idct_add, %function
+
+/* Custom calling convention:
+ * r0 contains block pointer and is non-volatile
+ * all non-volatile c context saved and restored on its behalf
+ */
+.idct:
+ str lr, [sp, #-4]! @ lr is used
+ add r1, r0, #128 @ secondary, transposed temp buffer
+ mov r14, #8 @ loop counter
+
+.row_loop:
+ ldmia r0!, {r2, r3, r10, r11} @ fetch f0, f2, f4, f6, f1, f3, f5, f7
+ ldrd r4, L_W1357 @ load W1, W3, W5, W7
+
+ smuad r6, r4, r10 @ b0 = W1 * f1 + W3 * f3
+ smultt r7, r5, r10 @ -b1 = W7 * f3
+ smulbt r8, r4, r10 @ -b2 = W1 * f3
+
+ smusdx r9, r10, r5 @ b3 = f1 * W7 - f3 * W5
+ smlabb r7, r4, r11, r7 @ -b1 += W1 * f5
+ rsb r8, r8, #0 @ b2 = -b2
+ smlabb r8, r5, r10, r8 @ b2 += W5 * f1
+
+ smlad r6, r5, r11, r6 @ b0 += W5 * f5 + W7 * f7
+ smlabt r7, r5, r11, r7 @ -b1 += W5 * f7
+ smlatb r8, r5, r11, r8 @ b2 += W7 * f5
+
+ smlsdx r9, r11, r4, r9 @ b3 += f5 * W3 - f7 * W1
+ rsb r7, r7, #0 @ b1 = -b1
+ smlatb r7, r4, r10, r7 @ b1 += W3 * f1
+ smlatt r8, r4, r11, r8 @ b2 += W3 * f7
+
+ ldrd r4, L_W0246 @ load W0, W2, W4, W6
+ add r2, r2, #1 @ f0 += 1
+
+ smulbb r10, r5, r3 @ a0' = W4 * f4
+ smultt r12, r5, r3 @ a3' = W6 * f6
+ smultt r3, r4, r3 @ -a2' = W2 * f6
+
+ rsb r11, r10, #0 @ a1' = -W4 * f4
+ smlabb r10, r4, r2, r10 @ a0' += W0 * f0
+ smlabb r11, r4, r2, r11 @ a1' += W0 * f0
+ smlatt r12, r4, r2, r12 @ a3' += W2 * f2
+ rsb r3, r3, #0 @ a2' = -a2'
+ smlatt r3, r5, r2, r3 @ a2' += W6 * f2
+
+ add r10, r10, r12 @ a0 = a0' + a3'
+ sub r12, r10, r12, lsl #1 @ a3 = a0 - 2 * a3'
+ add r11, r11, r3 @ a1 = a1' + a2'
+ sub r3, r11, r3, lsl #1 @ a2 = a1 - 2 * a2'
+
+ subs r14, r14, #1 @ decrease loop count
+
+ @ Special store order for making the column pass calculate columns in
+ @ the order 0-2-1-3-4-6-5-7, allowing for uxtab16 use in later stages.
+ sub r2, r10, r6 @ block[7] = (a0 - b0)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1, #7*16]
+ sub r2, r11, r7 @ block[6] = (a1 - b1)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1, #5*16]
+ sub r2, r3, r8 @ block[5] = (a2 - b2)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1, #6*16]
+ sub r2, r12, r9 @ block[4] = (a3 - b3)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1, #4*16]
+ add r2, r12, r9 @ block[3] = (a3 + b3)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1, #3*16]
+ add r2, r3, r8 @ block[2] = (a2 + b2)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1, #1*16]
+ add r2, r11, r7 @ block[1] = (a1 + b1)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1, #2*16]
+ add r2, r10, r6 @ block[0] = (a0 + b0)
+ mov r2, r2, asr #12 @ >> 12
+ strh r2, [r1], #2 @ advance to next temp column
+
+ bne .row_loop
+ b .col_start
+
+ @placed here because of ldrd's offset limit
+L_W1357:
+ .short 2841
+ .short 2408
+ .short 1609
+ .short 565
+
+L_W0246:
+ .short 2048
+ .short 2676
+ .short 2048
+ .short 1108
+
+.col_start:
+ @ r0 now points to the temp buffer, where we need it.
+ sub r1, r1, #128+16 @ point r1 back to the input block
+ mov r14, #8 @ loop counter
+
+.col_loop:
+ ldmia r0!, {r2, r3, r10, r11} @ fetch f0, f2, f4, f6, f1, f3, f5, f7
+ ldrd r4, L_W1357 @ load W1, W3, W5, W7
+
+ smuad r6, r4, r10 @ b0 = W1 * f1 + W3 * f3
+ smultt r7, r5, r10 @ -b1 = W7 * f3
+ smulbt r8, r4, r10 @ -b2 = W1 * f3
+
+ smusdx r9, r10, r5 @ b3 = f1 * W7 - f3 * W5
+ smlabb r7, r4, r11, r7 @ -b1 += W1 * f5
+ rsb r8, r8, #0 @ b2 = -b2
+ smlabb r8, r5, r10, r8 @ b2 += W5 * f1
+
+ smlad r6, r5, r11, r6 @ b0 += W5 * f5 + W7 * f7
+ smlabt r7, r5, r11, r7 @ -b1 += W5 * f7
+ smlatb r8, r5, r11, r8 @ b2 += W7 * f5
+
+ smlsdx r9, r11, r4, r9 @ b3 += f5 * W3 - f7 * W1
+ rsb r7, r7, #0 @ b1 = -b1
+ smlatb r7, r4, r10, r7 @ b1 += W3 * f1
+ smlatt r8, r4, r11, r8 @ b2 += W3 * f7
+
+ ldrd r4, L_W0246 @ load W0, W2, W4, W6
+ add r2, r2, #32 @ DC offset: 0.5
+
+ smulbb r10, r5, r3 @ a0' = W4 * f4
+ smultt r12, r5, r3 @ a3' = W6 * f6
+ smultt r3, r4, r3 @ -a2' = W2 * f6
+
+ rsb r11, r10, #0 @ a1' = -W4 * f4
+ smlabb r10, r4, r2, r10 @ a0' += W0 * f0
+ smlabb r11, r4, r2, r11 @ a1' += W0 * f0
+ smlatt r12, r4, r2, r12 @ a3' += W2 * f2
+ rsb r3, r3, #0 @ a2' = -a2'
+ smlatt r3, r5, r2, r3 @ a2' += W6 * f2
+
+ add r10, r10, r12 @ a0 = a0' + a3'
+ sub r12, r10, r12, lsl #1 @ a3 = a0 - 2 * a3'
+ add r11, r11, r3 @ a1 = a1' + a2'
+ sub r3, r11, r3, lsl #1 @ a2 = a1 - 2 * a2'
+
+ subs r14, r14, #1 @ decrease loop count
+
+ sub r2, r10, r6 @ block[7] = (a0 - b0)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1, #7*16]
+ sub r2, r11, r7 @ block[6] = (a1 - b1)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1, #6*16]
+ sub r2, r3, r8 @ block[5] = (a2 - b2)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1, #5*16]
+ sub r2, r12, r9 @ block[4] = (a3 - b3)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1, #4*16]
+ add r2, r12, r9 @ block[3] = (a3 + b3)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1, #3*16]
+ add r2, r3, r8 @ block[2] = (a2 + b2)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1, #2*16]
+ add r2, r11, r7 @ block[1] = (a1 + b1)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1, #1*16]
+ add r2, r10, r6 @ block[0] = (a0 + b0)
+ mov r2, r2, asr #17 @ >> 17
+ strh r2, [r1], #2 @ advance to next column
+
+ bne .col_loop
+
+ sub r0, r0, #256 @ point r0 back to the input block
+ ldr pc, [sp], #4
+
+
+mpeg2_idct_copy:
+ stmfd sp!, {r1-r2, r4-r11, lr}
+ bl .idct
+ ldmfd sp!, {r1-r2}
+
+ add r3, r0, #128
+ mov r8, #0
+ mov r9, #0
+ mov r10, #0
+ mov r11, #0
+1: @ idct data is in order 0-2-1-3-4-6-5-7,
+ ldmia r0, {r4-r7} @ see above
+ stmia r0!, {r8-r11}
+ usat16 r4, #8, r4
+ usat16 r5, #8, r5
+ orr r4, r4, r5, lsl #8
+ usat16 r6, #8, r6
+ usat16 r7, #8, r7
+ orr r5, r6, r7, lsl #8
+ strd r4, [r1] @ r4, r5
+ add r1, r1, r2
+ cmp r0, r3
+ blo 1b
+
+ ldmfd sp!, {r4-r11, pc}
+
+mpeg2_idct_add:
+ cmp r0, #129
+ mov r0, r1
+ ldreqsh r1, [r0, #0]
+ bne 1f
+ and r1, r1, #0x70
+ cmp r1, #0x40
+ bne 3f
+1:
+ stmfd sp!, {r2-r11, lr}
+ bl .idct
+ ldmfd sp!, {r1-r2}
+
+ add r3, r0, #128
+ mov r10, #0
+ mov r11, #0
+ mov r12, #0
+ mov lr, #0
+ ldrd r8, [r1] @ r8, r9
+2: @ idct data is in order 0-2-1-3-4-6-5-7,
+ ldmia r0, {r4-r7} @ see above
+ stmia r0!, {r10-r12, lr}
+ uxtab16 r4, r4, r8
+ uxtab16 r5, r5, r8, ror #8
+ usat16 r4, #8, r4
+ usat16 r5, #8, r5
+ orr r4, r4, r5, lsl #8
+ uxtab16 r6, r6, r9
+ uxtab16 r7, r7, r9, ror #8
+ usat16 r6, #8, r6
+ usat16 r7, #8, r7
+ orr r5, r6, r7, lsl #8
+ strd r4, [r1] @ r4, r5
+ add r1, r1, r2
+ cmp r0, r3
+ ldrlod r8, [r1] @ r8, r9
+ blo 2b
+
+ ldmfd sp!, {r4-r11, pc}
+
+3:
+ stmfd sp!, {r4, lr}
+ ldrsh r4, [r0, #0] @ r4 = block[0]
+ mov r12, #0
+ strh r12, [r0, #0] @ block[0] = 0
+ strh r12, [r0, #126] @ block[63] = 0
+ add r4, r4, #64
+ mov r4, r4, asr #7 @ r4 = DC
+ mov r4, r4, lsl #16 @ spread to 2 halfwords
+ orr r4, r4, r4, lsr #16
+ ldrd r0, [r2] @ r0, r1
+ add r12, r2, r3, asl #3
+4:
+ uxtab16 lr, r4, r0, ror #8
+ uxtab16 r0, r4, r0
+ usat16 lr, #8, lr
+ usat16 r0, #8, r0
+ orr r0, r0, lr, lsl #8
+ uxtab16 lr, r4, r1, ror #8
+ uxtab16 r1, r4, r1
+ usat16 lr, #8, lr
+ usat16 r1, #8, r1
+ orr r1, r1, lr, lsl #8
+ strd r0, [r2] @ r0, r1
+ add r2, r2, r3
+ cmp r2, r12
+ ldrlod r0, [r2] @ r0, r1
+ blo 4b
+
+ ldmfd sp!, {r4, pc}
diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S b/apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S
new file mode 100644
index 0000000000..abc54b16cb
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S
@@ -0,0 +1,575 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 Jens Arnold
+ * Based on the work of Karim Boucher and Rani Hod
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+ .global mpeg2_idct_copy
+ .type mpeg2_idct_copy, @function
+ .global mpeg2_idct_add
+ .type mpeg2_idct_add, @function
+
+ /* The IDCT itself.
+ * Input: %a0: block pointer
+ * Caller must save all registers. */
+ .align 2
+.idct:
+ move.l %a0, %a6
+
+ move.l #0, %macsr | signed integer mode
+
+ move.l #((2048<<16)+2841), %a0 | W0, W1
+ move.l #((2676<<16)+2408), %a1 | W2, W3
+ move.l #((2048<<16)+1609), %a2 | W4, W5
+ move.l #((1108<<16)+ 565), %a3 | W6, W7
+
+ lea.l (128,%a6), %a4 | secondary, transposed temp buffer
+ moveq.l #8, %d3 | loop counter
+
+.row_loop:
+ movem.l (%a6), %d0-%d2/%a5 | fetch (f0, f2, f4, f6, f1, f3, f5, f7)
+
+ mac.w %a0l, %d2u, %acc0 | %acc0 = W1 * f1
+ mac.w %a1l, %d2l, %acc0 | + W3 * f3
+ mac.w %a2l, %a5u, %acc0 | + W5 * f5
+ mac.w %a3l, %a5l, %acc0 | + W7 * f7
+
+ mac.w %a1l, %d2u, %acc1 | %acc1 = W3 * f1
+ msac.w %a3l, %d2l, %acc1 | - W7 * f3
+ msac.w %a0l, %a5u, %acc1 | - W1 * f5
+ msac.w %a2l, %a5l, %acc1 | - W5 * f7
+
+ mac.w %a2l, %d2u, %acc2 | %acc2 = W5 * f1
+ msac.w %a0l, %d2l, %acc2 | - W1 * f3
+ mac.w %a3l, %a5u, %acc2 | + W7 * f5
+ mac.w %a1l, %a5l, %acc2 | + W3 * f7
+
+ mac.w %a3l, %d2u, %acc3 | %acc3 = W7 * f1
+ msac.w %a2l, %d2l, %acc3 | - W5 * f3
+ mac.w %a1l, %a5u, %acc3 | + W3 * f5
+ msac.w %a0l, %a5l, %acc3 | - W1 * f7
+
+ lea.l (16,%a6), %a6 | Advance to next row; put here to fill EMAC latency
+ add.l #(1<<16), %d0 | f0 += 1;
+
+ movclr.l %acc0, %d4 | b0
+ movclr.l %acc1, %d5 | b1
+ movclr.l %acc2, %d6 | b2
+ movclr.l %acc3, %d7 | b3
+
+ mac.w %a0u, %d0u, %acc0 | %acc0 = W0 * f0
+ mac.w %a2u, %d1u, %acc0 | + W4 * f4
+ move.l %acc0, %acc3
+ mac.w %a1u, %d0l, %acc0 | + W2 * f2
+ mac.w %a3u, %d1l, %acc0 | + W6 * f6
+
+ mac.w %a0u, %d0u, %acc1 | %acc1 = W0 * f0
+ msac.w %a2u, %d1u, %acc1 | - W4 * f4
+ move.l %acc1, %acc2
+ mac.w %a3u, %d0l, %acc1 | + W6 * f2
+ msac.w %a1u, %d1l, %acc1 | - W2 * f6
+
+ | ^ move.l %acc1, %acc2 %acc2 = W0 * f0 - W4 * f4
+ msac.w %a3u, %d0l, %acc2 | - W6 * f2
+ mac.w %a1u, %d1l, %acc2 | + W2 * f6
+
+ | ^ move.l %acc0, %acc3 %acc3 = W0 * f0 + W4 * f4
+ msac.w %a1u, %d0l, %acc3 | - W2 * f2
+ msac.w %a3u, %d1l, %acc3 | - W6 * f6
+
+ moveq.l #12, %d1 | shift amount
+
+ move.l %acc0, %d0 | block[7] = (a0
+ sub.l %d4,%d0 | - b0)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (7*16,%a4)
+
+ move.l %acc1, %d0 | block[6] = (a1
+ sub.l %d5,%d0 | - b1)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (6*16,%a4)
+
+ move.l %acc2, %d0 | block[5] = (a2
+ sub.l %d6,%d0 | - b2)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (5*16,%a4)
+
+ move.l %acc3, %d0 | block[4] = (a3
+ sub.l %d7,%d0 | - b3)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (4*16,%a4)
+
+ movclr.l %acc3, %d0 | block[3] = (a3
+ add.l %d7, %d0 | + b3)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (3*16,%a4)
+
+ movclr.l %acc2, %d0 | block[2] = (a2
+ add.l %d6, %d0 | + b2)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (2*16,%a4)
+
+ movclr.l %acc1, %d0 | block[1] = (a1
+ add.l %d5, %d0 | + b1)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (1*16,%a4)
+
+ movclr.l %acc0, %d0 | block[0] = (a0
+ add.l %d4, %d0 | + b0)
+ asr.l %d1, %d0 | >> 12
+ move.w %d0, (%a4)+ | advance to next temp column
+
+ subq.l #1, %d3 | loop 8 times
+ bne.w .row_loop
+
+ | %a6 now points to the temp buffer, where we need it.
+ lea.l (-16-128,%a4), %a4 | point %a4 back to the input block
+ moveq.l #8, %d3 | loop counter
+
+.col_loop:
+ movem.l (%a6), %d0-%d2/%a5 | fetch (f0, f2, f4, f6, f1, f3, f5, f7)
+
+ mac.w %a0l, %d2u, %acc0 | %acc0 = W1 * f1
+ mac.w %a1l, %d2l, %acc0 | + W3 * f3
+ mac.w %a2l, %a5u, %acc0 | + W5 * f5
+ mac.w %a3l, %a5l, %acc0 | + W7 * f7
+
+ mac.w %a1l, %d2u, %acc1 | %acc1 = W3 * f1
+ msac.w %a3l, %d2l, %acc1 | - W7 * f3
+ msac.w %a0l, %a5u, %acc1 | - W1 * f5
+ msac.w %a2l, %a5l, %acc1 | - W5 * f7
+
+ mac.w %a2l, %d2u, %acc2 | %acc2 = W5 * f1
+ msac.w %a0l, %d2l, %acc2 | - W1 * f3
+ mac.w %a3l, %a5u, %acc2 | + W7 * f5
+ mac.w %a1l, %a5l, %acc2 | + W3 * f7
+
+ mac.w %a3l, %d2u, %acc3 | %acc3 = W7 * f1
+ msac.w %a2l, %d2l, %acc3 | - W5 * f3
+ mac.w %a1l, %a5u, %acc3 | + W3 * f5
+ msac.w %a0l, %a5l, %acc3 | - W1 * f7
+
+ lea.l (16,%a6), %a6 | Advance to next row; put here to fill EMAC latency
+ add.l #(32<<16), %d0 | DC offset: 0.5
+
+ movclr.l %acc0, %d4 | b0
+ movclr.l %acc1, %d5 | b1
+ movclr.l %acc2, %d6 | b2
+ movclr.l %acc3, %d7 | b3
+
+ mac.w %a0u, %d0u, %acc0 | %acc0 = W0 * f0
+ mac.w %a2u, %d1u, %acc0 | + W4 * f4
+ move.l %acc0, %acc3
+ mac.w %a1u, %d0l, %acc0 | + W2 * f2
+ mac.w %a3u, %d1l, %acc0 | + W6 * f6
+
+ mac.w %a0u, %d0u, %acc1 | %acc1 = W0 * f0
+ msac.w %a2u, %d1u, %acc1 | - W4 * f4
+ move.l %acc1, %acc2
+ mac.w %a3u, %d0l, %acc1 | + W6 * f2
+ msac.w %a1u, %d1l, %acc1 | - W2 * f6
+
+ | ^ move.l %acc1, %acc2 %acc2 = W0 * f0 - W4 * f4
+ msac.w %a3u, %d0l, %acc2 | - W6 * f2
+ mac.w %a1u, %d1l, %acc2 | + W2 * f6
+
+ | ^ move.l %acc0, %acc3 %acc3 = W0 * f0 + W4 * f4
+ msac.w %a1u, %d0l, %acc3 | - W2 * f2
+ msac.w %a3u, %d1l, %acc3 | - W6 * f6
+
+ moveq.l #17, %d1 | shift amount
+
+ move.l %acc0, %d0 | block[7] = (a0
+ sub.l %d4,%d0 | - b0)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (7*16,%a4)
+
+ move.l %acc1, %d0 | block[6] = (a1
+ sub.l %d5,%d0 | - b1)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (6*16,%a4)
+
+ move.l %acc2, %d0 | block[5] = (a2
+ sub.l %d6,%d0 | - b2)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (5*16,%a4)
+
+ move.l %acc3, %d0 | block[4] = (a3
+ sub.l %d7,%d0 | - b3)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (4*16,%a4)
+
+ movclr.l %acc3, %d0 | block[3] = (a3
+ add.l %d7, %d0 | + b3)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (3*16,%a4)
+
+ movclr.l %acc2, %d0 | block[2] = (a2
+ add.l %d6, %d0 | + b2)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (2*16,%a4)
+
+ movclr.l %acc1, %d0 | block[1] = (a1
+ add.l %d5, %d0 | + b1)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (1*16,%a4)
+
+ movclr.l %acc0, %d0 | block[0] = (a0
+ add.l %d4, %d0 | + b0)
+ asr.l %d1, %d0 | >> 17
+ move.w %d0, (%a4)+ | advance to next column
+
+ subq.l #1, %d3 | loop 8 times
+ bne.w .col_loop
+
+ rts
+
+ .align 2
+
+mpeg2_idct_copy:
+ lea.l (-11*4,%sp), %sp
+ movem.l %d2-%d7/%a2-%a6, (%sp) | save some registers
+ move.l (11*4+4,%sp), %a0 | %a0 - block pointer for idct
+
+ bsr.w .idct | apply idct to block
+ movem.l (11*4+4,%sp), %a0-%a2 | %a0 - block pointer
+ | %a1 - destination pointer
+ | %a2 - stride
+
+ move.l #255, %d1 | preload constant for clipping
+ moveq.l #8, %d4 | loop counter
+
+.copy_clip_loop:
+ move.w (%a0), %d0 | load block[0]
+ ext.l %d0 | sign extend
+ cmp.l %d1, %d0 | overflow?
+ bls.b 1f
+ spl.b %d0 | yes: set appropriate limit value in low byte
+1:
+ move.b %d0, %d2 | collect output bytes 0..3 in %d2
+ lsl.l #8, %d2
+
+ move.w (2,%a0), %d0 | load block[1]
+ ext.l %d0 | sign extend
+ cmp.l %d1, %d0 | overflow?
+ bls.b 1f
+ spl.b %d0 | yes: set appropriate limit value in low byte
+1:
+ move.b %d0, %d2 | collect output bytes 0..3 in %d2
+ lsl.l #8, %d2
+ clr.l (%a0)+ | clear block[0] and block[1],
+ | %a0 now pointing to block[2]
+ move.w (%a0), %d0 | do b2 and b3
+ ext.l %d0
+ cmp.l %d1, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.b %d0, %d2
+ lsl.l #8, %d2
+
+ move.w (2,%a0), %d0
+ ext.l %d0
+ cmp.l %d1, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.b %d0, %d2
+ clr.l (%a0)+
+
+ move.w (%a0), %d0 | do b4 and b5
+ ext.l %d0
+ cmp.l %d1, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.b %d0, %d3
+ lsl.l #8, %d3
+
+ move.w (2,%a0), %d0
+ ext.l %d0
+ cmp.l %d1, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.b %d0, %d3
+ lsl.l #8, %d3
+ clr.l (%a0)+
+
+ move.w (%a0), %d0 | do b6 and b7
+ ext.l %d0
+ cmp.l %d1, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.b %d0, %d3
+ lsl.l #8, %d3
+
+ move.w (2,%a0), %d0
+ ext.l %d0
+ cmp.l %d1, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.b %d0, %d3
+ clr.l (%a0)+
+
+ movem.l %d2-%d3, (%a1) | write all 8 output bytes at once
+ add.l %a2, %a1 | advance output pointer
+ subq.l #1, %d4 | loop 8 times
+ bne.w .copy_clip_loop
+
+ movem.l (%sp), %d2-%d7/%a2-%a6
+ lea.l (11*4,%sp), %sp
+ rts
+
+ .align 2
+
+mpeg2_idct_add:
+ lea.l (-11*4,%sp), %sp
+ movem.l %d2-%d7/%a2-%a6, (%sp)
+ movem.l (11*4+4,%sp), %d0/%a0-%a2 | %d0 - last value
+ | %a0 - block pointer
+ | %a1 - destination pointer
+ | %a2 - stride
+
+ cmp.l #129, %d0 | last == 129 ?
+ bne.b .idct_add | no: perform idct + addition
+ move.w (%a0), %d0
+ ext.l %d0 | ((block[0]
+ asr.l #4, %d0 | >> 4)
+ and.l #7, %d0 | & 7)
+ subq.l #4, %d0 | - 4 == 0 ?
+ bne.w .dc_add | no: just perform addition
+
+.idct_add:
+ bsr.w .idct | apply idct
+ movem.l (11*4+8,%sp), %a0-%a2 | reload arguments %a0..%a2
+
+ move.l #255, %d2 | preload constant for clipping
+ clr.l %d3 | used for splitting input words into bytes
+ moveq.l #8, %d4 | loop counter
+
+.add_clip_loop:
+ movem.l (%a1), %d6-%d7 | fetch (b0 b1 b2 b3) (b4 b5 b6 b7)
+ swap %d6 | (b2 b3 b0 b1)
+ swap %d7 | (b6 b7 b4 b5)
+
+ move.w (2,%a0), %d0 | load block[1]
+ ext.l %d0 | sign extend
+ move.b %d6, %d3 | copy b1
+ lsr.l #8, %d6 | prepare 1st buffer for next byte
+ add.l %d3, %d0 | add b1
+ cmp.l %d2, %d0 | overflow ?
+ bls.b 1f
+ spl.b %d0 | yes: set appropriate limit value in low byte
+1:
+ move.w (%a0), %d1 | load block[0]
+ ext.l %d1 | sign extend
+ move.b %d6, %d3 | copy b0
+ lsr.l #8, %d6 | prepare 1st buffer for next byte
+ add.l %d3, %d1 | add b0
+ cmp.l %d2, %d1 | overflow ?
+ bls.b 1f
+ spl.b %d1 | yes: set appropriate limit value in low byte
+1:
+ move.b %d1, %d5 | collect output bytes 0..3 in %d5
+ lsl.l #8, %d5
+ move.b %d0, %d5
+ lsl.l #8, %d5
+ clr.l (%a0)+ | clear block[0] and block[1]
+ | %a0 now pointing to block[2]
+ move.w (2,%a0), %d0 | do b3 and b2
+ ext.l %d0
+ move.b %d6, %d3
+ lsr.l #8, %d6
+ add.l %d3, %d0
+ cmp.l %d2, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.w (%a0), %d1
+ ext.l %d1
+ add.l %d6, %d1
+ cmp.l %d2, %d1
+ bls.b 1f
+ spl.b %d1
+1:
+ move.b %d1, %d5
+ lsl.l #8, %d5
+ move.b %d0, %d5
+ clr.l (%a0)+
+
+ move.w (2,%a0), %d0 | do b5 and b4
+ ext.l %d0
+ move.b %d7, %d3
+ lsr.l #8, %d7
+ add.l %d3, %d0
+ cmp.l %d2, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.w (%a0), %d1
+ ext.l %d1
+ move.b %d7, %d3
+ lsr.l #8, %d7
+ add.l %d3, %d1
+ cmp.l %d2, %d1
+ bls.b 1f
+ spl.b %d1
+1:
+ move.b %d1, %d6
+ lsl.l #8, %d6
+ move.b %d0, %d6
+ lsl.l #8, %d6
+ clr.l (%a0)+
+
+ move.w (2,%a0), %d0 | do b7 and b6
+ ext.l %d0
+ move.b %d7, %d3
+ lsr.l #8, %d7
+ add.l %d3, %d0
+ cmp.l %d2, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.w (%a0), %d1
+ ext.l %d1
+ add.l %d7, %d1
+ cmp.l %d2, %d1
+ bls.b 1f
+ spl.b %d1
+1:
+ move.b %d1, %d6
+ lsl.l #8, %d6
+ move.b %d0, %d6
+ clr.l (%a0)+
+
+ movem.l %d5-%d6, (%a1) | write all 8 output bytes at once
+ add.l %a2, %a1 | advance output pointer
+ subq.l #1, %d4 | loop 8 times
+ bne.w .add_clip_loop
+
+ bra.w .idct_add_end
+
+.dc_add:
+ move.w (%a0), %d0
+ ext.l %d0 | %d0 = (block[0]
+ add.l #64, %d0 | + 64)
+ asr.l #7, %d0 | >> 7
+ clr.w (%a0) | clear block[0]
+ clr.w (63*2,%a0) | and block[63]
+ move.l %d0, %a0 | DC value in %a0
+
+ move.l #255, %d2 | preload constant for clipping
+ clr.l %d3 | for splitting input words into bytes
+ moveq.l #8, %d4 | loop counter
+
+.dc_clip_loop:
+ movem.l (%a1), %d6-%d7 | (b0 b1 b2 b3) (b4 b5 b6 b7)
+ swap %d6 | (b2 b3 b0 b1)
+ swap %d7 | (b6 b7 b4 b5)
+
+ move.l %a0, %d0 | copy DC
+ move.b %d6, %d3 | copy b1
+ lsr.l #8, %d6 | prepare 1st buffer for next byte
+ add.l %d3, %d0 | add b1
+ cmp.l %d2, %d0 | overflow ?
+ bls.b 1f
+ spl.b %d0 | yes: set appropriate limit value in low byte
+1:
+ move.l %a0, %d1 | copy DC
+ move.b %d6, %d3 | copy b0
+ lsr.l #8, %d6 | prepare 1st buffer for next byte
+ add.l %d3, %d1 | add b0
+ cmp.l %d2, %d1 | overflow ?
+ bls.b 1f
+ spl.b %d1 | yes: set appropriate limit value in low byte
+1:
+ move.b %d1, %d5 | collect output bytes 0..3 in %d5
+ lsl.l #8, %d5
+ move.b %d0, %d5
+ lsl.l #8, %d5
+
+ move.l %a0, %d0 | do b3 and b2
+ move.b %d6, %d3
+ lsr.l #8, %d6
+ add.l %d3, %d0
+ cmp.l %d2, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.l %a0, %d1
+ add.l %d6, %d1
+ cmp.l %d2, %d1
+ bls.b 1f
+ spl.b %d1
+1:
+ move.b %d1, %d5
+ lsl.l #8, %d5
+ move.b %d0, %d5
+
+ move.l %a0, %d0 | do b5 and b4
+ move.b %d7, %d3
+ lsr.l #8, %d7
+ add.l %d3, %d0
+ cmp.l %d2, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.l %a0, %d1
+ move.b %d7, %d3
+ lsr.l #8, %d7
+ add.l %d3, %d1
+ cmp.l %d2, %d1
+ bls.b 1f
+ spl.b %d1
+1:
+ move.b %d1, %d6 | do b7 and b6
+ lsl.l #8, %d6
+ move.b %d0, %d6
+ lsl.l #8, %d6
+
+ move.l %a0, %d0
+ move.b %d7, %d3
+ lsr.l #8, %d7
+ add.l %d3, %d0
+ cmp.l %d2, %d0
+ bls.b 1f
+ spl.b %d0
+1:
+ move.l %a0, %d1
+ add.l %d7, %d1
+ cmp.l %d2, %d1
+ bls.b 1f
+ spl.b %d1
+1:
+ move.b %d1, %d6
+ lsl.l #8, %d6
+ move.b %d0, %d6
+
+ movem.l %d5-%d6, (%a1) | write all 8 output bytes at once
+ add.l %a2, %a1 | advance output pointer
+ subq.l #1, %d4 | loop 8 times
+ bne.w .dc_clip_loop
+
+.idct_add_end:
+ movem.l (%sp), %d2-%d7/%a2-%a6
+ lea.l (11*4,%sp), %sp
+ rts
diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp.c
new file mode 100644
index 0000000000..d6968f68ce
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/motion_comp.c
@@ -0,0 +1,66 @@
+/*
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.17 - lost compatibility previously to
+ * provide simplified and CPU-optimized motion compensation.
+ */
+
+#include "plugin.h"
+
+#include "mpeg2dec_config.h"
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+/* These are defined in their respective target files - motion_comp_X.c */
+extern mpeg2_mc_fct MC_put_o_16;
+extern mpeg2_mc_fct MC_put_o_8;
+extern mpeg2_mc_fct MC_put_x_16;
+extern mpeg2_mc_fct MC_put_x_8;
+extern mpeg2_mc_fct MC_put_y_16;
+extern mpeg2_mc_fct MC_put_y_8;
+extern mpeg2_mc_fct MC_put_xy_16;
+extern mpeg2_mc_fct MC_put_xy_8;
+
+extern mpeg2_mc_fct MC_avg_o_16;
+extern mpeg2_mc_fct MC_avg_o_8;
+extern mpeg2_mc_fct MC_avg_x_16;
+extern mpeg2_mc_fct MC_avg_x_8;
+extern mpeg2_mc_fct MC_avg_y_16;
+extern mpeg2_mc_fct MC_avg_y_8;
+extern mpeg2_mc_fct MC_avg_xy_16;
+extern mpeg2_mc_fct MC_avg_xy_8;
+
+const mpeg2_mc_t mpeg2_mc =
+{
+ {
+ MC_put_o_16, MC_put_x_16, MC_put_y_16, MC_put_xy_16,
+ MC_put_o_8, MC_put_x_8, MC_put_y_8, MC_put_xy_8
+ },
+ {
+ MC_avg_o_16, MC_avg_x_16, MC_avg_y_16, MC_avg_xy_16,
+ MC_avg_o_8, MC_avg_x_8, MC_avg_y_8, MC_avg_xy_8
+ }
+};
diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp.h b/apps/plugins/mpegplayer/libmpeg2/motion_comp.h
new file mode 100644
index 0000000000..4737e72cab
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/motion_comp.h
@@ -0,0 +1,86 @@
+/*
+ * motion_comp.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
+ *
+ * $Id$
+ */
+
+
+#define avg2(a,b) ((a+b+1)>>1)
+#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
+
+#define predict_o(i) (ref[i])
+#define predict_x(i) (avg2 (ref[i], ref[i+1]))
+#define predict_y(i) (avg2 (ref[i], (ref+stride)[i]))
+#define predict_xy(i) (avg4 (ref[i], ref[i+1], \
+ (ref+stride)[i], (ref+stride)[i+1]))
+
+#define put(predictor,i) dest[i] = predictor (i)
+#define avg(predictor,i) dest[i] = avg2 (predictor (i), dest[i])
+
+/* mc function template */
+#define MC_FUNC(op, xy) \
+ MC_FUNC_16(op, xy) \
+ MC_FUNC_8(op, xy)
+
+#define MC_FUNC_16(op, xy) \
+ void MC_##op##_##xy##_16 (uint8_t * dest, const uint8_t * ref, \
+ const int stride, int height) \
+ { \
+ do { \
+ op (predict_##xy, 0); \
+ op (predict_##xy, 1); \
+ op (predict_##xy, 2); \
+ op (predict_##xy, 3); \
+ op (predict_##xy, 4); \
+ op (predict_##xy, 5); \
+ op (predict_##xy, 6); \
+ op (predict_##xy, 7); \
+ op (predict_##xy, 8); \
+ op (predict_##xy, 9); \
+ op (predict_##xy, 10); \
+ op (predict_##xy, 11); \
+ op (predict_##xy, 12); \
+ op (predict_##xy, 13); \
+ op (predict_##xy, 14); \
+ op (predict_##xy, 15); \
+ ref += stride; \
+ dest += stride; \
+ } while (--height); \
+ }
+
+#define MC_FUNC_8(op, xy) \
+ void MC_##op##_##xy##_8 (uint8_t * dest, const uint8_t * ref, \
+ const int stride, int height) \
+ { \
+ do { \
+ op (predict_##xy, 0); \
+ op (predict_##xy, 1); \
+ op (predict_##xy, 2); \
+ op (predict_##xy, 3); \
+ op (predict_##xy, 4); \
+ op (predict_##xy, 5); \
+ op (predict_##xy, 6); \
+ op (predict_##xy, 7); \
+ ref += stride; \
+ dest += stride; \
+ } while (--height); \
+ }
diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c
new file mode 100644
index 0000000000..dcf1df53e9
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c
@@ -0,0 +1,39 @@
+/*
+ * motion_comp_arm.c
+ * Copyright (C) 2004 AGAWA Koji <i (AT) atty (DOT) jp>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ * See http://libmpeg2.sourceforge.net/ for updates.
+ *
+ * mpeg2dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+#include <inttypes.h>
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+#include "motion_comp.h"
+
+/* definitions of the actual mc functions */
+
+/* MC_FUNC (put, o) <= ASM */
+MC_FUNC (avg, o)
+/* MC_FUNC (put, x) <= ASM */
+MC_FUNC (avg, x)
+MC_FUNC (put, y)
+MC_FUNC (avg, y)
+MC_FUNC (put, xy)
+MC_FUNC (avg, xy)
diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S
new file mode 100644
index 0000000000..1ec1b0686e
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S
@@ -0,0 +1,342 @@
+@ motion_comp_arm_s.S
+@ Copyright (C) 2004 AGAWA Koji <i (AT) atty (DOT) jp>
+@
+@ This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+@ See http://libmpeg2.sourceforge.net/ for updates.
+@
+@ mpeg2dec is free software; you can redistribute it and/or modify
+@ it under the terms of the GNU General Public License as published by
+@ the Free Software Foundation; either version 2 of the License, or
+@ (at your option) any later version.
+@
+@ mpeg2dec is distributed in the hope that it will be useful,
+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+@ GNU General Public License for more details.
+@
+@ You should have received a copy of the GNU General Public License
+@ along with this program; if not, write to the Free Software
+@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+@
+@ $Id$
+
+#include "config.h" /* Rockbox: ARM architecture version */
+
+ .text
+
+@ ----------------------------------------------------------------
+ .align
+ .global MC_put_o_16
+MC_put_o_16:
+ @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height)
+ @@ pld [r1]
+ stmfd sp!, {r4-r7, lr} @ R14 is also called LR
+ and r4, r1, #3
+ ldr pc, [pc, r4, lsl #2]
+ .word 0
+ .word MC_put_o_16_align0
+ .word MC_put_o_16_align1
+ .word MC_put_o_16_align2
+ .word MC_put_o_16_align3
+
+MC_put_o_16_align0:
+ ldmia r1, {r4-r7}
+ add r1, r1, r2
+ @@ pld [r1]
+ stmia r0, {r4-r7}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne MC_put_o_16_align0
+ ldmpc regs=r4-r7 @@ update PC with LR content.
+
+.macro ADJ_ALIGN_QW shift, R0, R1, R2, R3, R4
+ mov \R0, \R0, lsr #(\shift)
+ orr \R0, \R0, \R1, lsl #(32 - \shift)
+ mov \R1, \R1, lsr #(\shift)
+ orr \R1, \R1, \R2, lsl #(32 - \shift)
+ mov \R2, \R2, lsr #(\shift)
+ orr \R2, \R2, \R3, lsl #(32 - \shift)
+ mov \R3, \R3, lsr #(\shift)
+ orr \R3, \R3, \R4, lsl #(32 - \shift)
+ mov \R4, \R4, lsr #(\shift)
+.endm
+
+MC_put_o_16_align1:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4-r7, r12}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_QW 8, r4, r5, r6, r7, r12
+ stmia r0, {r4-r7}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-r7 @@ update PC with LR content.
+
+MC_put_o_16_align2:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4-r7, r12}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_QW 16, r4, r5, r6, r7, r12
+ stmia r0, {r4-r7}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-r7 @@ update PC with LR content.
+
+MC_put_o_16_align3:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4-r7, r12}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_QW 24, r4, r5, r6, r7, r12
+ stmia r0, {r4-r7}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-r7 @@ update PC with LR content.
+
+@ ----------------------------------------------------------------
+ .align
+ .global MC_put_o_8
+MC_put_o_8:
+ @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height)
+ @@ pld [r1]
+ stmfd sp!, {r4, r5, lr} @ R14 is also called LR
+ and r4, r1, #3
+ ldr pc, [pc, r4, lsl #2]
+ .word 0
+ .word MC_put_o_8_align0
+ .word MC_put_o_8_align1
+ .word MC_put_o_8_align2
+ .word MC_put_o_8_align3
+
+MC_put_o_8_align0:
+ ldmia r1, {r4, r5}
+ add r1, r1, r2
+ @@ pld [r1]
+ stmia r0, {r4, r5}
+ add r0, r0, r2
+ subs r3, r3, #1
+ bne MC_put_o_8_align0
+ ldmpc regs=r4-r5 @@ update PC with LR content.
+
+.macro ADJ_ALIGN_DW shift, R0, R1, R2
+ mov \R0, \R0, lsr #(\shift)
+ orr \R0, \R0, \R1, lsl #(32 - \shift)
+ mov \R1, \R1, lsr #(\shift)
+ orr \R1, \R1, \R2, lsl #(32 - \shift)
+ mov \R2, \R2, lsr #(\shift)
+.endm
+
+MC_put_o_8_align1:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4, r5, r12}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_DW 8, r4, r5, r12
+ stmia r0, {r4, r5}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-r5 @@ update PC with LR content.
+
+MC_put_o_8_align2:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4, r5, r12}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_DW 16, r4, r5, r12
+ stmia r0, {r4, r5}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-r5 @@ update PC with LR content.
+
+MC_put_o_8_align3:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4, r5, r12}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_DW 24, r4, r5, r12
+ stmia r0, {r4, r5}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-r5 @@ update PC with LR content.
+
+@ ----------------------------------------------------------------
+.macro AVG_PW rW1, rW2
+ mov \rW2, \rW2, lsl #24
+ orr \rW2, \rW2, \rW1, lsr #8
+ eor r9, \rW1, \rW2
+#if ARM_ARCH >= 6
+ uhadd8 \rW2, \rW1, \rW2
+#else
+ and \rW2, \rW1, \rW2
+ and r10, r9, r11
+ add \rW2, \rW2, r10, lsr #1
+#endif
+ and r9, r9, r12
+ add \rW2, \rW2, r9
+.endm
+
+#if ARM_ARCH >= 6
+#define HIGHEST_REG r9
+#else
+#define HIGHEST_REG r11
+#endif
+
+ .align
+ .global MC_put_x_16
+MC_put_x_16:
+ @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height)
+ @@ pld [r1]
+ stmfd sp!, {r4-HIGHEST_REG, lr} @ R14 is also called LR
+ and r4, r1, #3
+ ldr r12, 2f
+#if ARM_ARCH < 6
+ mvn r11, r12
+#endif
+ ldr pc, [pc, r4, lsl #2]
+2: .word 0x01010101
+ .word MC_put_x_16_align0
+ .word MC_put_x_16_align1
+ .word MC_put_x_16_align2
+ .word MC_put_x_16_align3
+
+MC_put_x_16_align0:
+ ldmia r1, {r4-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ AVG_PW r5, r6
+ AVG_PW r4, r5
+ stmia r0, {r5-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne MC_put_x_16_align0
+ ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content.
+
+MC_put_x_16_align1:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_QW 8, r4, r5, r6, r7, r8
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ AVG_PW r5, r6
+ AVG_PW r4, r5
+ stmia r0, {r5-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content.
+
+MC_put_x_16_align2:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_QW 16, r4, r5, r6, r7, r8
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ AVG_PW r5, r6
+ AVG_PW r4, r5
+ stmia r0, {r5-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content.
+
+MC_put_x_16_align3:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r4-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_QW 24, r4, r5, r6, r7, r8
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ AVG_PW r5, r6
+ AVG_PW r4, r5
+ stmia r0, {r5-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r4-HIGHEST_REG @@ update PC with LR content.
+
+@ ----------------------------------------------------------------
+ .align
+ .global MC_put_x_8
+MC_put_x_8:
+ @@ void func(uint8_t * dest, const uint8_t * ref, int stride, int height)
+ @@ pld [r1]
+ stmfd sp!, {r6-HIGHEST_REG, lr} @ R14 is also called LR
+ and r6, r1, #3
+ ldr r12, 2f
+#if ARM_ARCH < 6
+ mvn r11, r12
+#endif
+ ldr pc, [pc, r6, lsl #2]
+2: .word 0x01010101
+ .word MC_put_x_8_align0
+ .word MC_put_x_8_align1
+ .word MC_put_x_8_align2
+ .word MC_put_x_8_align3
+
+MC_put_x_8_align0:
+ ldmia r1, {r6-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ stmia r0, {r7-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne MC_put_x_8_align0
+ ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content.
+
+MC_put_x_8_align1:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r6-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_DW 8, r6, r7, r8
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ stmia r0, {r7-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content.
+
+MC_put_x_8_align2:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r6-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_DW 16, r6, r7, r8
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ stmia r0, {r7-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content.
+
+MC_put_x_8_align3:
+ and r1, r1, #0xFFFFFFFC
+1: ldmia r1, {r6-r8}
+ add r1, r1, r2
+ @@ pld [r1]
+ ADJ_ALIGN_DW 24, r6, r7, r8
+ AVG_PW r7, r8
+ AVG_PW r6, r7
+ stmia r0, {r7-r8}
+ subs r3, r3, #1
+ add r0, r0, r2
+ bne 1b
+ ldmpc regs=r6-HIGHEST_REG @@ update PC with LR content.
diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c
new file mode 100644
index 0000000000..9a8640e7e6
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c
@@ -0,0 +1,40 @@
+/*
+ * 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
+ *
+ * $Id$
+ */
+#include <inttypes.h>
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+#include "motion_comp.h"
+
+/* definitions of the actual mc functions */
+
+MC_FUNC (put, o)
+MC_FUNC (avg, o)
+MC_FUNC (put, x)
+MC_FUNC (avg, x)
+MC_FUNC (put, y)
+MC_FUNC (avg, y)
+MC_FUNC (put, xy)
+MC_FUNC (avg, xy)
diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c
new file mode 100644
index 0000000000..b97e3510e7
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c
@@ -0,0 +1,38 @@
+/*
+ * Based on:
+ * motion_comp_arm.c
+ * Copyright (C) 2004 AGAWA Koji <i (AT) atty (DOT) jp>
+ *
+ * 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 <inttypes.h>
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+#include "motion_comp.h"
+
+/* definitions of the actual mc functions */
+
+/* MC_FUNC (put, o) <= ASM */
+MC_FUNC (avg, o)
+/* MC_FUNC (put, x) <= ASM */
+MC_FUNC (avg, x)
+MC_FUNC (put, y)
+MC_FUNC (avg, y)
+MC_FUNC (put, xy)
+MC_FUNC (avg, xy)
diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S
new file mode 100644
index 0000000000..55d87cb708
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S
@@ -0,0 +1,436 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 Jens Arnold
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+.macro LEFT8_PW dW1, dW2 | needs %d0 == 24, clobbers %d2
+ lsl.l #8, \dW1 | changes dW1, keeps dW2
+ move.l \dW2, %d2
+ lsr.l %d0, %d2
+ or.l %d2, \dW1
+.endm
+
+.macro LEFT24_PW dW1, dW2 | needs %d0 == 24, clobbers %d2
+ lsl.l %d0, \dW1 | changes dW1, keeps dW2
+ move.l \dW2, %d2
+ lsr.l #8, %d2
+ or.l %d2, \dW1
+.endm
+
+/*****************************************************************************/
+
+ .align 2
+ .global MC_put_o_8
+ .type MC_put_o_8, @function
+
+MC_put_o_8:
+ movem.l (4,%sp), %a0-%a1 | dest, source
+ move.l %a1, %d0
+ and.l #3, %d0
+ sub.l %d0, %a1 | align source
+ jmp.l (2, %pc, %d0.l*4)
+ bra.w .po8_0
+ bra.w .po8_1
+ bra.w .po8_2
+ | last table entry coincides with target
+
+.po8_3:
+ lea.l (-5*4,%sp), %sp
+ movem.l %d2-%d5/%a2, (%sp) | save some registers
+ move.l (5*4+12,%sp), %a2 | stride
+ move.l (5*4+16,%sp), %d1 | height
+ moveq.l #24, %d0 | shift amount
+1:
+ movem.l (%a1), %d3-%d5
+ add.l %a2, %a1
+ LEFT24_PW %d3, %d4
+ lsl.l %d0, %d4
+ lsr.l #8, %d5
+ or.l %d5, %d4
+ movem.l %d3-%d4, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d1
+ bne.s 1b
+ movem.l (%sp), %d2-%d5/%a2
+ lea.l (5*4,%sp), %sp
+ rts
+
+.po8_2:
+ lea.l (-3*4,%sp), %sp
+ movem.l %d2-%d4, (%sp) | save some registers
+ movem.l (3*4+12,%sp), %d0-%d1 | stride, height
+1:
+ movem.l (%a1), %d2-%d4
+ add.l %d0, %a1
+ swap %d2
+ swap %d3
+ move.w %d3, %d2
+ swap %d4
+ move.w %d4, %d3
+ movem.l %d2-%d3, (%a0)
+ add.l %d0, %a0
+ subq.l #1, %d1
+ bne.s 1b
+ movem.l (%sp), %d2-%d4
+ lea.l (3*4,%sp), %sp
+ rts
+
+.po8_1:
+ lea.l (-5*4,%sp), %sp
+ movem.l %d2-%d5/%a2, (%sp) | save some registers
+ move.l (5*4+12,%sp), %a2 | stride
+ move.l (5*4+16,%sp), %d1 | height
+ moveq.l #24, %d0 | shift amount
+1:
+ movem.l (%a1), %d3-%d5
+ add.l %a2, %a1
+ LEFT8_PW %d3, %d4
+ lsl.l #8, %d4
+ lsr.l %d0, %d5
+ or.l %d5, %d4
+ movem.l %d3-%d4, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d1
+ bne.s 1b
+ movem.l (%sp), %d2-%d5/%a2
+ lea.l (5*4,%sp), %sp
+ rts
+
+.po8_0:
+ movem.l (12,%sp), %d0-%d1 | stride, height
+ subq.l #4, %d0 | adjust for increment within the loop
+1:
+ move.l (%a1)+, (%a0)+
+ move.l (%a1), (%a0)
+ add.l %d0, %a0
+ add.l %d0, %a1
+ subq.l #1, %d1
+ bne.s 1b
+ rts
+
+/*****************************************************************************/
+
+ .align 2
+ .global MC_put_o_16
+ .type MC_put_o_16, @function
+
+MC_put_o_16:
+ lea.l (-7*4,%sp), %sp
+ movem.l %d2-%d7/%a2, (%sp) | save some registers
+ movem.l (7*4+4,%sp), %a0-%a2| dest, source, stride
+ move.l (7*4+16,%sp), %d1 | height
+ move.l %a1, %d0
+ and.l #3, %d0
+ sub.l %d0, %a1
+ jmp.l (2, %pc, %d0.l*4)
+ bra.w .po16_0
+ bra.w .po16_1
+ bra.w .po16_2
+ | last table entry coincides with target
+
+.po16_3:
+ moveq.l #24, %d0 | shift amount
+1:
+ movem.l (%a1), %d3-%d7
+ add.l %a2, %a1
+ LEFT24_PW %d3, %d4
+ LEFT24_PW %d4, %d5
+ LEFT24_PW %d5, %d6
+ lsl.l %d0, %d6
+ lsr.l #8, %d7
+ or.l %d7, %d6
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d1
+ bne.s 1b
+ movem.l (%sp), %d2-%d7/%a2
+ lea.l (7*4,%sp), %sp
+ rts
+
+.po16_2:
+1:
+ movem.l (%a1), %d3-%d7
+ add.l %a2, %a1
+ swap %d3
+ swap %d4
+ move.w %d4, %d3
+ swap %d5
+ move.w %d5, %d4
+ swap %d6
+ move.w %d6, %d5
+ swap %d7
+ move.w %d7, %d6
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d1
+ bne.s 1b
+ movem.l (%sp), %d2-%d7/%a2
+ lea.l (7*4,%sp), %sp
+ rts
+
+.po16_1:
+ moveq.l #24, %d0 | shift amount
+1:
+ movem.l (%a1), %d3-%d7
+ add.l %a2, %a1
+ LEFT8_PW %d3, %d4
+ LEFT8_PW %d4, %d5
+ LEFT8_PW %d5, %d6
+ lsl.l #8, %d6
+ lsr.l %d0, %d7
+ or.l %d7, %d6
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d1
+ bne.s 1b
+ movem.l (%sp), %d2-%d7/%a2
+ lea.l (7*4,%sp), %sp
+ rts
+
+.po16_0:
+1:
+ movem.l (%a1), %d3-%d6
+ add.l %a2, %a1
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d1
+ bne.s 1b
+ movem.l (%sp), %d2-%d7/%a2
+ lea.l (7*4,%sp), %sp
+ rts
+
+/*****************************************************************************/
+
+.macro AVG_PW dW1, dW2 | needs %d0 == 24, clobbers %d1, %d2,
+ move.l \dW1, %d1 | changes dW1, keeps dW2
+ lsl.l #8, \dW1
+ move.l \dW2, %d2
+ lsr.l %d0, %d2
+ or.l %d2, \dW1
+ move.l %d1, %d2
+ eor.l \dW1, %d1
+ and.l %d2, \dW1
+ move.l #0xfefefefe, %d2
+ and.l %d1, %d2
+ eor.l %d2, %d1
+ lsr.l #1, %d2
+ add.l %d2, \dW1
+ add.l %d1, \dW1
+.endm
+
+/*****************************************************************************/
+
+ .align 2
+ .global MC_put_x_8
+ .type MC_put_x_8, @function
+
+MC_put_x_8:
+ lea.l (-6*4,%sp), %sp
+ movem.l %d2-%d6/%a2, (%sp) | save some registers
+ movem.l (6*4+4,%sp), %a0-%a2| dest, source, stride
+ move.l (6*4+16,%sp), %d6 | height
+ move.l %a1, %d0
+ and.l #3, %d0
+ sub.l %d0, %a1
+ jmp.l (2, %pc, %d0.l*4)
+ bra.w .px8_0
+ bra.w .px8_1
+ bra.w .px8_2
+ | last table entry coincides with target
+
+.px8_3:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d5
+ add.l %a2, %a1
+ LEFT24_PW %d3, %d4
+ LEFT24_PW %d4, %d5
+ lsl.l %d0, %d5
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ movem.l %d3-%d4, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d6
+ bne.s 1b
+ movem.l (%sp), %d2-%d6/%a2
+ lea.l (6*4,%sp), %sp
+ rts
+
+.px8_2:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d5
+ add.l %a2, %a1
+ swap %d3
+ swap %d4
+ move.w %d4, %d3
+ swap %d5
+ move.w %d5, %d4
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ movem.l %d3-%d4, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d6
+ bne.s 1b
+ movem.l (%sp), %d2-%d6/%a2
+ lea.l (6*4,%sp), %sp
+ rts
+
+.px8_1:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d5
+ add.l %a2, %a1
+ LEFT8_PW %d3, %d4
+ LEFT8_PW %d4, %d5
+ lsl.l #8, %d5
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ movem.l %d3-%d4, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d6
+ bne.s 1b
+ movem.l (%sp), %d2-%d6/%a2
+ lea.l (6*4,%sp), %sp
+ rts
+
+.px8_0:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d5
+ add.l %a2, %a1
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ movem.l %d3-%d4, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %d6
+ bne.s 1b
+ movem.l (%sp), %d2-%d6/%a2
+ lea.l (6*4,%sp), %sp
+ rts
+
+/*****************************************************************************/
+
+ .align 2
+ .global MC_put_x_16
+ .type MC_put_x_16, @function
+
+MC_put_x_16:
+ lea.l (-8*4,%sp), %sp
+ movem.l %d2-%d7/%a2-%a3, (%sp) | save some registers
+ movem.l (8*4+4,%sp), %a0-%a3 | dest, source, stride, height
+ move.l %a1, %d0
+ and.l #3, %d0
+ sub.l %d0, %a1
+ jmp.l (2, %pc, %d0.l*4)
+ bra.w .px16_0
+ bra.w .px16_1
+ bra.w .px16_2
+ | last table entry coincides with target
+
+.px16_3:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d7
+ add.l %a2, %a1
+ LEFT24_PW %d3, %d4
+ LEFT24_PW %d4, %d5
+ LEFT24_PW %d5, %d6
+ LEFT24_PW %d6, %d7
+ lsl.l %d0, %d7
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ AVG_PW %d5, %d6
+ AVG_PW %d6, %d7
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %a3
+ tst.l %a3
+ bne.w 1b
+ movem.l (%sp), %d2-%d7/%a2-%a3
+ lea.l (8*4,%sp), %sp
+ rts
+
+.px16_2:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d7
+ add.l %a2, %a1
+ swap %d3
+ swap %d4
+ move.w %d4, %d3
+ swap %d5
+ move.w %d5, %d4
+ swap %d6
+ move.w %d6, %d5
+ swap %d7
+ move.w %d7, %d6
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ AVG_PW %d5, %d6
+ AVG_PW %d6, %d7
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %a3
+ tst.l %a3
+ bne.w 1b
+ movem.l (%sp), %d2-%d7/%a2-%a3
+ lea.l (8*4,%sp), %sp
+ rts
+
+.px16_1:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d7
+ add.l %a2, %a1
+ LEFT8_PW %d3, %d4
+ LEFT8_PW %d4, %d5
+ LEFT8_PW %d5, %d6
+ LEFT8_PW %d6, %d7
+ lsl.l #8, %d7
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ AVG_PW %d5, %d6
+ AVG_PW %d6, %d7
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %a3
+ tst.l %a3
+ bne.w 1b
+ movem.l (%sp), %d2-%d7/%a2-%a3
+ lea.l (8*4,%sp), %sp
+ rts
+
+.px16_0:
+ moveq.l #24, %d0
+1:
+ movem.l (%a1), %d3-%d7
+ add.l %a2, %a1
+ AVG_PW %d3, %d4
+ AVG_PW %d4, %d5
+ AVG_PW %d5, %d6
+ AVG_PW %d6, %d7
+ movem.l %d3-%d6, (%a0)
+ add.l %a2, %a0
+ subq.l #1, %a3
+ tst.l %a3
+ bne.w 1b
+ movem.l (%sp), %d2-%d7/%a2-%a3
+ lea.l (8*4,%sp), %sp
+ rts
diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2.h
new file mode 100644
index 0000000000..bd14ead96e
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/mpeg2.h
@@ -0,0 +1,223 @@
+/*
+ * mpeg2.h
+ * Copyright (C) 2000-2004 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.67
+ */
+
+#ifndef MPEG2_H
+#define MPEG2_H
+
+#include "mpeg2dec_config.h"
+
+#define MPEG2_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
+#define MPEG2_RELEASE MPEG2_VERSION (0, 5, 0) /* 0.5.0 */
+
+#define SEQ_FLAG_MPEG2 1
+#define SEQ_FLAG_CONSTRAINED_PARAMETERS 2
+#define SEQ_FLAG_PROGRESSIVE_SEQUENCE 4
+#define SEQ_FLAG_LOW_DELAY 8
+#define SEQ_FLAG_COLOUR_DESCRIPTION 16
+
+#define SEQ_MASK_VIDEO_FORMAT 0xe0
+#define SEQ_VIDEO_FORMAT_COMPONENT 0x00
+#define SEQ_VIDEO_FORMAT_PAL 0x20
+#define SEQ_VIDEO_FORMAT_NTSC 0x40
+#define SEQ_VIDEO_FORMAT_SECAM 0x60
+#define SEQ_VIDEO_FORMAT_MAC 0x80
+#define SEQ_VIDEO_FORMAT_UNSPECIFIED 0xa0
+
+typedef struct mpeg2_sequence_s
+{
+ unsigned int width, height;
+ unsigned int chroma_width, chroma_height;
+ unsigned int byte_rate;
+ unsigned int vbv_buffer_size;
+ uint32_t flags;
+
+ unsigned int picture_width, picture_height;
+ unsigned int display_width, display_height;
+ unsigned int pixel_width, pixel_height;
+ unsigned int frame_period;
+
+ uint8_t profile_level_id;
+ uint8_t colour_primaries;
+ uint8_t transfer_characteristics;
+ uint8_t matrix_coefficients;
+} mpeg2_sequence_t;
+
+#define GOP_FLAG_DROP_FRAME 1
+#define GOP_FLAG_BROKEN_LINK 2
+#define GOP_FLAG_CLOSED_GOP 4
+
+typedef struct mpeg2_gop_s
+{
+ uint8_t hours;
+ uint8_t minutes;
+ uint8_t seconds;
+ uint8_t pictures;
+ uint32_t flags;
+} mpeg2_gop_t;
+
+#define PIC_MASK_CODING_TYPE 7
+#define PIC_FLAG_CODING_TYPE_I 1
+#define PIC_FLAG_CODING_TYPE_P 2
+#define PIC_FLAG_CODING_TYPE_B 3
+#define PIC_FLAG_CODING_TYPE_D 4
+
+#define PIC_FLAG_TOP_FIELD_FIRST 8
+#define PIC_FLAG_PROGRESSIVE_FRAME 16
+#define PIC_FLAG_COMPOSITE_DISPLAY 32
+#define PIC_FLAG_SKIP 64
+#define PIC_FLAG_TAGS 128
+#define PIC_MASK_COMPOSITE_DISPLAY 0xfffff000
+
+typedef struct mpeg2_picture_s
+{
+ unsigned int temporal_reference;
+ unsigned int nb_fields;
+ uint32_t tag, tag2;
+ uint32_t flags;
+ struct
+ {
+ int x, y;
+ } display_offset[3];
+} mpeg2_picture_t;
+
+typedef struct mpeg2_fbuf_s
+{
+ uint8_t * buf[MPEG2_COMPONENTS];
+ void * id;
+} mpeg2_fbuf_t;
+
+typedef struct mpeg2_info_s
+{
+ const mpeg2_sequence_t * sequence;
+ const mpeg2_gop_t * gop;
+ const mpeg2_picture_t * current_picture;
+ const mpeg2_picture_t * current_picture_2nd;
+ const mpeg2_fbuf_t * current_fbuf;
+ const mpeg2_picture_t * display_picture;
+ const mpeg2_picture_t * display_picture_2nd;
+ const mpeg2_fbuf_t * display_fbuf;
+ const mpeg2_fbuf_t * discard_fbuf;
+ const uint8_t * user_data;
+ unsigned int user_data_len;
+} mpeg2_info_t;
+
+typedef struct mpeg2dec_s mpeg2dec_t;
+typedef struct mpeg2_decoder_s mpeg2_decoder_t;
+
+typedef enum
+{
+ STATE_INTERNAL_NORETURN = -1,
+ STATE_BUFFER = 0,
+ STATE_SEQUENCE = 1,
+ STATE_SEQUENCE_REPEATED = 2,
+ STATE_SEQUENCE_MODIFIED = 3,
+ STATE_GOP = 4,
+ STATE_PICTURE = 5,
+ STATE_SLICE_1ST = 6,
+ STATE_PICTURE_2ND = 7,
+ STATE_SLICE = 8,
+ STATE_END = 9,
+ STATE_INVALID = 10,
+ STATE_INVALID_END = 11,
+} mpeg2_state_t;
+
+typedef struct mpeg2_convert_init_s
+{
+ unsigned int id_size;
+ unsigned int buf_size[MPEG2_COMPONENTS];
+ void (* start)(void * id, const mpeg2_fbuf_t * fbuf,
+ const mpeg2_picture_t * picture, const mpeg2_gop_t * gop);
+ void (* copy)(void * id, uint8_t * const * src, unsigned int v_offset);
+} mpeg2_convert_init_t;
+
+typedef enum
+{
+ MPEG2_CONVERT_SET = 0,
+ MPEG2_CONVERT_STRIDE = 1,
+ MPEG2_CONVERT_START = 2
+} mpeg2_convert_stage_t;
+
+typedef int mpeg2_convert_t (int stage, void * id,
+ const mpeg2_sequence_t * sequence, int stride,
+ void * arg, mpeg2_convert_init_t * result);
+int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg);
+int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride);
+void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[MPEG2_COMPONENTS],
+ void * id);
+void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf);
+
+mpeg2dec_t * mpeg2_init (void);
+const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec);
+void mpeg2_close (mpeg2dec_t * mpeg2dec);
+
+void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end);
+int mpeg2_getpos (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec);
+
+void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset);
+void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip);
+void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end);
+
+void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2);
+
+void mpeg2_init_fbuf (mpeg2_decoder_t * decoder,
+ uint8_t * current_fbuf[MPEG2_COMPONENTS],
+ uint8_t * forward_fbuf[MPEG2_COMPONENTS],
+ uint8_t * backward_fbuf[MPEG2_COMPONENTS]);
+void mpeg2_slice (mpeg2_decoder_t * decoder, int code, const uint8_t * buffer);
+
+int mpeg2_guess_aspect (const mpeg2_sequence_t * sequence,
+ unsigned int * pixel_width,
+ unsigned int * pixel_height);
+
+typedef enum
+{
+ MPEG2_ALLOC_MPEG2DEC = 0,
+ MPEG2_ALLOC_CHUNK = 1,
+ MPEG2_ALLOC_YUV = 2,
+ MPEG2_ALLOC_CONVERT_ID = 3,
+ MPEG2_ALLOC_CONVERTED = 4,
+ MPEG_ALLOC_CODEC_MALLOC,
+ MPEG_ALLOC_CODEC_CALLOC,
+ MPEG_ALLOC_MPEG2_BUFFER,
+ MPEG_ALLOC_AUDIOBUF,
+ MPEG_ALLOC_PCMOUT,
+ MPEG_ALLOC_DISKBUF,
+ __MPEG_ALLOC_FIRST = -256,
+} mpeg2_alloc_t;
+
+void * mpeg2_malloc (unsigned size, mpeg2_alloc_t reason);
+#if 0
+void mpeg2_free (void * buf);
+#endif
+/* allocates a dedicated buffer and locks all previous allocation in place */
+void * mpeg2_bufalloc(unsigned size, mpeg2_alloc_t reason);
+/* clears all non-dedicated buffer space */
+void mpeg2_mem_reset(void);
+void mpeg2_alloc_init(unsigned char* buf, int mallocsize);
+
+#endif /* MPEG2_H */
diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h
new file mode 100644
index 0000000000..e04562e18d
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h
@@ -0,0 +1,274 @@
+/*
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.89
+ */
+#ifndef MPEG2_INTERNAL_H
+#define MPEG2_INTERNAL_H
+
+#include "config.h" /* for Rockbox CPU_ #defines */
+
+/* macroblock modes */
+#define MACROBLOCK_INTRA 1
+#define MACROBLOCK_PATTERN 2
+#define MACROBLOCK_MOTION_BACKWARD 4
+#define MACROBLOCK_MOTION_FORWARD 8
+#define MACROBLOCK_QUANT 16
+#define DCT_TYPE_INTERLACED 32
+/* motion_type */
+#define MOTION_TYPE_SHIFT 6
+#define MC_FIELD 1
+#define MC_FRAME 2
+#define MC_16X8 2
+#define MC_DMV 3
+
+/* picture structure */
+#define TOP_FIELD 1
+#define BOTTOM_FIELD 2
+#define FRAME_PICTURE 3
+
+/* picture coding type */
+#define I_TYPE 1
+#define P_TYPE 2
+#define B_TYPE 3
+#define D_TYPE 4
+
+typedef void mpeg2_mc_fct (uint8_t *, const uint8_t *, int, int);
+
+typedef struct
+{
+ uint8_t * ref[2][MPEG2_COMPONENTS];
+ uint8_t ** ref2[2];
+ int pmv[2][2];
+ int f_code[2];
+} motion_t;
+
+typedef void motion_parser_t(mpeg2_decoder_t * decoder,
+ motion_t * motion,
+ mpeg2_mc_fct * const * table);
+
+struct mpeg2_decoder_s
+{
+ /* first, state that carries information from one macroblock to the */
+ /* next inside a slice, and is never used outside of mpeg2_slice() */
+
+ /* bit parsing stuff */
+ uint32_t bitstream_buf; /* current 32 bit working set */
+ int bitstream_bits; /* used bits in working set */
+ const uint8_t * bitstream_ptr; /* buffer with stream data */
+
+ uint8_t * dest[MPEG2_COMPONENTS];
+
+ int offset;
+ int stride;
+ int uv_stride;
+ int slice_stride;
+ int slice_uv_stride;
+ int stride_frame;
+ unsigned int limit_x;
+ unsigned int limit_y_16;
+ unsigned int limit_y_8;
+ unsigned int limit_y;
+
+ /* Motion vectors */
+ /* The f_ and b_ correspond to the forward and backward motion */
+ /* predictors */
+ motion_t b_motion;
+ motion_t f_motion;
+ motion_parser_t * motion_parser[5];
+
+ /* predictor for DC coefficients in intra blocks */
+ int16_t dc_dct_pred[MPEG2_COMPONENTS];
+
+ /* DCT coefficients */
+ int16_t * DCTblock; /* put buffer separately to have it in IRAM */
+
+ uint8_t * picture_dest[MPEG2_COMPONENTS];
+ void (* convert) (void * convert_id, uint8_t * const * src,
+ unsigned int v_offset);
+ void * convert_id;
+
+ int dmv_offset;
+ unsigned int v_offset;
+
+ /* now non-slice-specific information */
+
+ /* sequence header stuff */
+ uint16_t * quantizer_matrix[4];
+ uint16_t (* chroma_quantizer[2])[64];
+ uint16_t quantizer_prescale[4][32][64];
+
+ /* The width and height of the picture snapped to macroblock units */
+ int width;
+ int height;
+ int vertical_position_extension;
+ int chroma_format;
+
+ /* picture header stuff */
+
+ /* what type of picture this is (I, P, B, D) */
+ int coding_type;
+
+ /* picture coding extension stuff */
+
+ /* quantization factor for intra dc coefficients */
+ int intra_dc_precision;
+ /* top/bottom/both fields */
+ int picture_structure;
+ /* bool to indicate all predictions are frame based */
+ int frame_pred_frame_dct;
+ /* bool to indicate whether intra blocks have motion vectors */
+ /* (for concealment) */
+ int concealment_motion_vectors;
+ /* bool to use different vlc tables */
+ int intra_vlc_format;
+ /* used for DMV MC */
+ int top_field_first;
+
+ /* stuff derived from bitstream */
+
+ /* pointer to the zigzag scan we're supposed to be using */
+ const uint8_t * scan;
+
+ int second_field;
+
+ int mpeg1;
+};
+
+typedef struct
+{
+ mpeg2_fbuf_t fbuf;
+} fbuf_alloc_t;
+
+struct mpeg2dec_s
+{
+ mpeg2_decoder_t decoder;
+
+ mpeg2_info_t info;
+
+ uint32_t shift;
+ int is_display_initialized;
+ mpeg2_state_t (* action) (struct mpeg2dec_s * mpeg2dec);
+ mpeg2_state_t state;
+ uint32_t ext_state;
+
+ /* allocated in init - gcc has problems allocating such big structures */
+ uint8_t * ATTR_ALIGN(4) chunk_buffer;
+ /* pointer to start of the current chunk */
+ uint8_t * chunk_start;
+ /* pointer to current position in chunk_buffer */
+ uint8_t * chunk_ptr;
+ /* last start code ? */
+ uint8_t code;
+
+ /* picture tags */
+ uint32_t tag_current, tag2_current, tag_previous, tag2_previous;
+ int num_tags;
+ int bytes_since_tag;
+
+ int first;
+ int alloc_index_user;
+ int alloc_index;
+ uint8_t first_decode_slice;
+ uint8_t nb_decode_slices;
+
+ unsigned int user_data_len;
+
+ mpeg2_sequence_t new_sequence;
+ mpeg2_sequence_t sequence;
+ mpeg2_gop_t new_gop;
+ mpeg2_gop_t gop;
+ mpeg2_picture_t new_picture;
+ mpeg2_picture_t pictures[4];
+ mpeg2_picture_t * picture;
+ /*const*/ mpeg2_fbuf_t * fbuf[3]; /* 0: current fbuf, 1-2: prediction fbufs */
+
+ fbuf_alloc_t fbuf_alloc[3];
+ int custom_fbuf;
+
+ uint8_t * yuv_buf[3][MPEG2_COMPONENTS];
+ int yuv_index;
+ mpeg2_convert_t * convert;
+ void * convert_arg;
+ unsigned int convert_id_size;
+ int convert_stride;
+ void (* convert_start) (void * id, const mpeg2_fbuf_t * fbuf,
+ const mpeg2_picture_t * picture,
+ const mpeg2_gop_t * gop);
+
+ uint8_t * buf_start;
+ uint8_t * buf_end;
+
+ int16_t display_offset_x, display_offset_y;
+
+ int copy_matrix;
+ int8_t q_scale_type, scaled[4];
+ uint8_t quantizer_matrix[4][64];
+ uint8_t new_quantizer_matrix[4][64];
+};
+
+/* decode.c */
+mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec);
+
+/* header.c */
+void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec);
+void mpeg2_reset_info (mpeg2_info_t * info);
+int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_gop (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_picture (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_extension (mpeg2dec_t * mpeg2dec);
+int mpeg2_header_user_data (mpeg2dec_t * mpeg2dec);
+void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec);
+void mpeg2_header_gop_finalize (mpeg2dec_t * mpeg2dec);
+void mpeg2_header_picture_finalize (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec);
+mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec);
+void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type);
+
+/* idct.c */
+void mpeg2_idct_init (void);
+void mpeg2_idct_copy(int16_t * block, uint8_t * dest,
+ const int stride);
+void mpeg2_idct_add(const int last, int16_t * block,
+ uint8_t * dest, const int stride);
+
+extern const uint8_t default_mpeg2_scan_norm[64];
+extern const uint8_t default_mpeg2_scan_alt[64];
+extern uint8_t mpeg2_scan_norm[64];
+extern uint8_t mpeg2_scan_alt[64];
+
+/* motion_comp.c */
+void mpeg2_mc_init (void);
+
+typedef struct
+{
+ mpeg2_mc_fct * put [8];
+ mpeg2_mc_fct * avg [8];
+} mpeg2_mc_t;
+
+extern const mpeg2_mc_t mpeg2_mc;
+
+#endif /* MPEG2_INTERNAL_H */
+
diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h
new file mode 100644
index 0000000000..c34ee374df
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h
@@ -0,0 +1,15 @@
+/* $Id$ */
+#ifndef MPEG2DEC_CONFIG_H
+#define MPEG2DEC_CONFIG_H
+
+#define ATTRIBUTE_ALIGNED_MAX 16
+
+#ifdef HAVE_LCD_COLOR
+#define MPEG2_COLOR 1
+#define MPEG2_COMPONENTS 3
+#else
+#define MPEG2_COLOR 0
+#define MPEG2_COMPONENTS 1
+#endif
+
+#endif /* MPEG2DEC_CONFIG_H */
diff --git a/apps/plugins/mpegplayer/libmpeg2/slice.c b/apps/plugins/mpegplayer/libmpeg2/slice.c
new file mode 100644
index 0000000000..926333d5d0
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/slice.c
@@ -0,0 +1,2898 @@
+/*
+ * slice.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 2003 Peter Gubanov <peter@elecard.net.ru>
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.55
+ */
+
+#include "plugin.h"
+
+#include "mpeg2dec_config.h"
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+#include "vlc.h"
+
+static inline int get_macroblock_modes (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ int macroblock_modes;
+ const MBtab * tab;
+
+ switch (decoder->coding_type)
+ {
+ case I_TYPE:
+ tab = MB_I + UBITS (bit_buf, 1);
+ DUMPBITS (bit_buf, bits, tab->len);
+ macroblock_modes = tab->modes;
+
+ if (!(decoder->frame_pred_frame_dct) &&
+ decoder->picture_structure == FRAME_PICTURE)
+ {
+ macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED;
+ DUMPBITS (bit_buf, bits, 1);
+ }
+
+ return macroblock_modes;
+
+ case P_TYPE:
+ tab = MB_P + UBITS (bit_buf, 5);
+ DUMPBITS (bit_buf, bits, tab->len);
+ macroblock_modes = tab->modes;
+
+ if (decoder->picture_structure != FRAME_PICTURE)
+ {
+ if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
+ {
+ macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT;
+ DUMPBITS (bit_buf, bits, 2);
+ }
+
+ return macroblock_modes | MACROBLOCK_MOTION_FORWARD;
+ }
+ else if (decoder->frame_pred_frame_dct)
+ {
+ if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
+ macroblock_modes |= MC_FRAME << MOTION_TYPE_SHIFT;
+
+ return macroblock_modes | MACROBLOCK_MOTION_FORWARD;
+ }
+ else
+ {
+ if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
+ {
+ macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT;
+ DUMPBITS (bit_buf, bits, 2);
+ }
+
+ if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))
+ {
+ macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED;
+ DUMPBITS (bit_buf, bits, 1);
+ }
+
+ return macroblock_modes | MACROBLOCK_MOTION_FORWARD;
+ }
+
+ case B_TYPE:
+ tab = MB_B + UBITS (bit_buf, 6);
+ DUMPBITS (bit_buf, bits, tab->len);
+ macroblock_modes = tab->modes;
+
+ if (decoder->picture_structure != FRAME_PICTURE)
+ {
+ if (! (macroblock_modes & MACROBLOCK_INTRA))
+ {
+ macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT;
+ DUMPBITS (bit_buf, bits, 2);
+ }
+
+ return macroblock_modes;
+ }
+ else if (decoder->frame_pred_frame_dct)
+ {
+ /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */
+ macroblock_modes |= MC_FRAME << MOTION_TYPE_SHIFT;
+ return macroblock_modes;
+ }
+ else
+ {
+ if (macroblock_modes & MACROBLOCK_INTRA)
+ goto intra;
+
+ macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT;
+ DUMPBITS (bit_buf, bits, 2);
+
+ if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))
+ {
+ intra:
+ macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED;
+ DUMPBITS (bit_buf, bits, 1);
+ }
+ return macroblock_modes;
+ }
+
+ case D_TYPE:
+ DUMPBITS (bit_buf, bits, 1);
+ return MACROBLOCK_INTRA;
+
+ default:
+ return 0;
+ }
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+static inline void get_quantizer_scale (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ int quantizer_scale_code;
+
+ quantizer_scale_code = UBITS (bit_buf, 5);
+ DUMPBITS (bit_buf, bits, 5);
+
+ decoder->quantizer_matrix[0] =
+ decoder->quantizer_prescale[0][quantizer_scale_code];
+
+ decoder->quantizer_matrix[1] =
+ decoder->quantizer_prescale[1][quantizer_scale_code];
+
+ decoder->quantizer_matrix[2] =
+ decoder->chroma_quantizer[0][quantizer_scale_code];
+
+ decoder->quantizer_matrix[3] =
+ decoder->chroma_quantizer[1][quantizer_scale_code];
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+static inline int get_motion_delta (mpeg2_decoder_t * const decoder,
+ const int f_code)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ int delta;
+ int sign;
+ const MVtab * tab;
+
+ if (bit_buf & 0x80000000)
+ {
+ DUMPBITS (bit_buf, bits, 1);
+ return 0;
+ }
+ else if (bit_buf >= 0x0c000000)
+ {
+ tab = MV_4 + UBITS (bit_buf, 4);
+ delta = (tab->delta << f_code) + 1;
+ bits += tab->len + f_code + 1;
+ bit_buf <<= tab->len;
+
+ sign = SBITS (bit_buf, 1);
+ bit_buf <<= 1;
+
+ if (f_code)
+ delta += UBITS (bit_buf, f_code);
+ bit_buf <<= f_code;
+
+ return (delta ^ sign) - sign;
+ }
+ else
+ {
+ tab = MV_10 + UBITS (bit_buf, 10);
+ delta = (tab->delta << f_code) + 1;
+ bits += tab->len + 1;
+ bit_buf <<= tab->len;
+
+ sign = SBITS (bit_buf, 1);
+ bit_buf <<= 1;
+
+ if (f_code)
+ {
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ delta += UBITS (bit_buf, f_code);
+ DUMPBITS (bit_buf, bits, f_code);
+ }
+
+ return (delta ^ sign) - sign;
+
+ }
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+static inline int bound_motion_vector (const int vector, const int f_code)
+{
+ return ((int32_t)vector << (27 - f_code)) >> (27 - f_code);
+}
+
+static inline int get_dmv (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ const DMVtab * tab;
+
+ tab = DMV_2 + UBITS (bit_buf, 2);
+ DUMPBITS (bit_buf, bits, tab->len);
+ return tab->dmv;
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+static inline int get_coded_block_pattern (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ const CBPtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ if (bit_buf >= 0x20000000)
+ {
+ tab = CBP_7 + (UBITS (bit_buf, 7) - 16);
+ DUMPBITS (bit_buf, bits, tab->len);
+ return tab->cbp;
+ }
+ else
+ {
+ tab = CBP_9 + UBITS (bit_buf, 9);
+ DUMPBITS (bit_buf, bits, tab->len);
+ return tab->cbp;
+ }
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+static inline int get_luma_dc_dct_diff (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ const DCtab * tab;
+ int size;
+ int dc_diff;
+
+ if (bit_buf < 0xf8000000)
+ {
+ tab = DC_lum_5 + UBITS (bit_buf, 5);
+ size = tab->size;
+
+ if (size)
+ {
+ bits += tab->len + size;
+ bit_buf <<= tab->len;
+ dc_diff =
+ UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
+ bit_buf <<= size;
+ return dc_diff << decoder->intra_dc_precision;
+ }
+ else
+ {
+ DUMPBITS (bit_buf, bits, 3);
+ return 0;
+ }
+ }
+ else
+ {
+ tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0);
+ size = tab->size;
+ DUMPBITS (bit_buf, bits, tab->len);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
+ DUMPBITS (bit_buf, bits, size);
+ return dc_diff << decoder->intra_dc_precision;
+ }
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+#if MPEG2_COLOR
+static inline int get_chroma_dc_dct_diff (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ const DCtab * tab;
+ int size;
+ int dc_diff;
+
+ if (bit_buf < 0xf8000000)
+ {
+ tab = DC_chrom_5 + UBITS (bit_buf, 5);
+ size = tab->size;
+
+ if (size)
+ {
+ bits += tab->len + size;
+ bit_buf <<= tab->len;
+ dc_diff =
+ UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
+ bit_buf <<= size;
+ return dc_diff << decoder->intra_dc_precision;
+ }
+ else
+ {
+ DUMPBITS (bit_buf, bits, 2);
+ return 0;
+ }
+ }
+ else
+ {
+ tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0);
+ size = tab->size;
+ DUMPBITS (bit_buf, bits, tab->len + 1);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size);
+ DUMPBITS (bit_buf, bits, size);
+ return dc_diff << decoder->intra_dc_precision;
+ }
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+#endif /* MPEG2_COLOR */
+
+#define SATURATE(val) \
+ do { \
+ val <<= 4; \
+ if (unlikely (val != (int16_t) val)) \
+ val = (SBITS (val, 1) ^ 2047) << 4; \
+ } while (0)
+
+static void get_intra_block_B14 (mpeg2_decoder_t * const decoder,
+ const uint16_t * const quant_matrix)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ const uint8_t * const scan = decoder->scan;
+ int16_t * const dest = decoder->DCTblock;
+ int mismatch = ~dest[0];
+ int i = 0;
+ int j;
+ int val;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ while (1)
+ {
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
+
+ i += tab->run;
+ if (i >= 64)
+ break; /* end of block */
+
+ normal_code:
+ j = scan[i];
+ bit_buf <<= tab->len;
+ bits += tab->len + 1;
+ val = (tab->level * quant_matrix[j]) >> 4;
+
+ /* if (bitstream_get (1)) val = -val; */
+ val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
+
+ SATURATE (val);
+ dest[j] = val;
+ mismatch ^= val;
+
+ bit_buf <<= 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ else if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check needed to avoid buffer overflow */
+
+ j = scan[i];
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ val = (SBITS (bit_buf, 12) * quant_matrix[j]) / 16;
+
+ SATURATE (val);
+ dest[j] = val;
+ mismatch ^= val;
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ dest[63] ^= mismatch & 16;
+ DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+}
+
+static void get_intra_block_B15 (mpeg2_decoder_t * const decoder,
+ const uint16_t * const quant_matrix)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ const uint8_t * const scan = decoder->scan;
+ int16_t * const dest = decoder->DCTblock;
+ int mismatch = ~dest[0];
+ int i = 0;
+ int j;
+ int val;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ while (1)
+ {
+ if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+
+ if (i < 64)
+ {
+ normal_code:
+ j = scan[i];
+ bit_buf <<= tab->len;
+ bits += tab->len + 1;
+ val = (tab->level * quant_matrix[j]) >> 4;
+
+ /* if (bitstream_get (1)) val = -val; */
+ val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
+
+ SATURATE (val);
+ dest[j] = val;
+ mismatch ^= val;
+
+ bit_buf <<= 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ else
+ {
+ /* end of block. I commented out this code because if we */
+ /* dont exit here we will still exit at the later test :) */
+
+ /* if (i >= 128) break; */ /* end of block */
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check against buffer overflow */
+
+ j = scan[i];
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ val = (SBITS (bit_buf, 12) * quant_matrix[j]) / 16;
+
+ SATURATE (val);
+ dest[j] = val;
+ mismatch ^= val;
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ dest[63] ^= mismatch & 16;
+ DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+}
+
+static int get_non_intra_block (mpeg2_decoder_t * const decoder,
+ const uint16_t * const quant_matrix)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ const uint8_t * const scan = decoder->scan;
+ int16_t * const dest = decoder->DCTblock;
+ int mismatch = -1;
+ int i = -1;
+ int j;
+ int val;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5);
+ goto entry_1;
+ }
+ else
+ {
+ goto entry_2;
+ }
+
+ while (1)
+ {
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
+
+ entry_1:
+ i += tab->run;
+ if (i >= 64)
+ break; /* end of block */
+
+ normal_code:
+ j = scan[i];
+ bit_buf <<= tab->len;
+ bits += tab->len + 1;
+ val = ((2 * tab->level + 1) * quant_matrix[j]) >> 5;
+
+ /* if (bitstream_get (1)) val = -val; */
+ val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
+
+ SATURATE (val);
+ dest[j] = val;
+ mismatch ^= val;
+
+ bit_buf <<= 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+
+ entry_2:
+ if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check needed to avoid buffer overflow */
+
+ j = scan[i];
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1;
+ val = (val * quant_matrix[j]) / 32;
+
+ SATURATE (val);
+ dest[j] = val;
+ mismatch ^= val;
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ dest[63] ^= mismatch & 16;
+ DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+ return i;
+}
+
+static void get_mpeg1_intra_block (mpeg2_decoder_t * const decoder)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ const uint8_t * const scan = decoder->scan;
+ const uint16_t * const quant_matrix = decoder->quantizer_matrix[0];
+ int16_t * const dest = decoder->DCTblock;
+ int i = 0;
+ int j;
+ int val;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ while (1)
+ {
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
+
+ i += tab->run;
+ if (i >= 64)
+ break; /* end of block */
+
+ normal_code:
+ j = scan[i];
+ bit_buf <<= tab->len;
+ bits += tab->len + 1;
+ val = (tab->level * quant_matrix[j]) >> 4;
+
+ /* oddification */
+ val = (val - 1) | 1;
+
+ /* if (bitstream_get (1)) val = -val; */
+ val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
+
+ SATURATE (val);
+ dest[j] = val;
+
+ bit_buf <<= 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ else if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check needed to avoid buffer overflow */
+
+ j = scan[i];
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ val = SBITS (bit_buf, 8);
+
+ if (! (val & 0x7f))
+ {
+ DUMPBITS (bit_buf, bits, 8);
+ val = UBITS (bit_buf, 8) + 2 * val;
+ }
+
+ val = (val * quant_matrix[j]) / 16;
+
+ /* oddification */
+ val = (val + ~SBITS (val, 1)) | 1;
+
+ SATURATE (val);
+ dest[j] = val;
+
+ DUMPBITS (bit_buf, bits, 8);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+}
+
+static int get_mpeg1_non_intra_block (mpeg2_decoder_t * const decoder)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ const uint8_t * const scan = decoder->scan;
+ const uint16_t * const quant_matrix = decoder->quantizer_matrix[1];
+ int16_t * const dest = decoder->DCTblock;
+ int i = -1;
+ int j;
+ int val;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5);
+ goto entry_1;
+ }
+ else
+ {
+ goto entry_2;
+ }
+
+ while (1)
+ {
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
+
+ entry_1:
+ i += tab->run;
+ if (i >= 64)
+ break; /* end of block */
+
+ normal_code:
+ j = scan[i];
+ bit_buf <<= tab->len;
+ bits += tab->len + 1;
+ val = ((2 * tab->level + 1) * quant_matrix[j]) >> 5;
+
+ /* oddification */
+ val = (val - 1) | 1;
+
+ /* if (bitstream_get (1)) val = -val; */
+ val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);
+
+ SATURATE (val);
+ dest[j] = val;
+
+ bit_buf <<= 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+
+ entry_2:
+ if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check needed to avoid buffer overflow */
+
+ j = scan[i];
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ val = SBITS (bit_buf, 8);
+
+ if (! (val & 0x7f))
+ {
+ DUMPBITS (bit_buf, bits, 8);
+ val = UBITS (bit_buf, 8) + 2 * val;
+ }
+
+ val = 2 * (val + SBITS (val, 1)) + 1;
+ val = (val * quant_matrix[j]) / 32;
+
+ /* oddification */
+ val = (val + ~SBITS (val, 1)) | 1;
+
+ SATURATE (val);
+ dest[j] = val;
+
+ DUMPBITS (bit_buf, bits, 8);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+ return i;
+}
+
+static inline void slice_intra_DCT (mpeg2_decoder_t * const decoder,
+ const int cc,
+ uint8_t * const dest, const int stride)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ /* Get the intra DC coefficient and inverse quantize it */
+ if (cc == 0)
+ {
+ decoder->dc_dct_pred[0] += get_luma_dc_dct_diff (decoder);
+ decoder->DCTblock[0] = decoder->dc_dct_pred[0];
+
+ }
+#if MPEG2_COLOR
+ else
+ {
+ decoder->dc_dct_pred[cc] += get_chroma_dc_dct_diff (decoder);
+ decoder->DCTblock[0] = decoder->dc_dct_pred[cc];
+ }
+#endif
+
+ if (decoder->mpeg1)
+ {
+ if (decoder->coding_type != D_TYPE)
+ get_mpeg1_intra_block (decoder);
+ }
+ else if (decoder->intra_vlc_format)
+ {
+ get_intra_block_B15 (decoder, decoder->quantizer_matrix[cc ? 2 : 0]);
+ }
+ else
+ {
+ get_intra_block_B14 (decoder, decoder->quantizer_matrix[cc ? 2 : 0]);
+ }
+
+ mpeg2_idct_copy (decoder->DCTblock, dest, stride);
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+static inline void slice_non_intra_DCT (mpeg2_decoder_t * const decoder,
+ const int cc,
+ uint8_t * const dest, const int stride)
+{
+ int last;
+
+ if (decoder->mpeg1)
+ {
+ last = get_mpeg1_non_intra_block (decoder);
+ }
+ else
+ {
+ last = get_non_intra_block (decoder,
+ decoder->quantizer_matrix[cc ? 3 : 1]);
+ }
+
+ mpeg2_idct_add (last, decoder->DCTblock, dest, stride);
+}
+
+#if !MPEG2_COLOR
+static void skip_mpeg1_intra_block (mpeg2_decoder_t * const decoder)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ int i = 0;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ while (1)
+ {
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
+
+ i += tab->run;
+ if (i >= 64)
+ break; /* end of block */
+
+ normal_code:
+ bit_buf <<= tab->len + 1;
+ bits += tab->len + 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ }
+ else if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check needed to avoid buffer overflow */
+
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ if (!(SBITS (bit_buf, 8) & 0x7f))
+ DUMPBITS (bit_buf, bits, 8);
+
+ DUMPBITS (bit_buf, bits, 8);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ DUMPBITS (bit_buf, bits, 2); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+}
+
+static void skip_intra_block_B14 (mpeg2_decoder_t * const decoder)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ int i = 0;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ while (1)
+ {
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
+
+ i += tab->run;
+ if (i >= 64)
+ break; /* end of block */
+
+ normal_code:
+ bit_buf <<= tab->len + 1;
+ bits += tab->len + 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ }
+ else if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check needed to avoid buffer overflow */
+
+ DUMPBITS (bit_buf, bits, 12); /* Can't dump more than 16 atm */
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ DUMPBITS (bit_buf, bits, 2); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+}
+
+static void skip_intra_block_B15 (mpeg2_decoder_t * const decoder)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ int i = 0;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ while (1)
+ {
+ if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+
+ if (i < 64)
+ {
+ normal_code:
+ bit_buf <<= tab->len + 1;
+ bits += tab->len + 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ }
+ else
+ {
+ /* end of block. I commented out this code because if we */
+ /* dont exit here we will still exit at the later test :) */
+
+ /* if (i >= 128) break; */ /* end of block */
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check against buffer overflow */
+
+ DUMPBITS (bit_buf, bits, 12); /* Can't dump more than 16 atm */
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ }
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ DUMPBITS (bit_buf, bits, 4); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+}
+
+static void skip_non_intra_block (mpeg2_decoder_t * const decoder)
+{
+ uint32_t bit_buf = decoder->bitstream_buf;
+ int bits = decoder->bitstream_bits;
+ const uint8_t * bit_ptr = decoder->bitstream_ptr;
+ int i = -1;
+ const DCTtab * tab;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5);
+ goto entry_1;
+ }
+ else
+ {
+ goto entry_2;
+ }
+
+ while (1)
+ {
+ if (bit_buf >= 0x28000000)
+ {
+ tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5);
+
+ entry_1:
+ i += tab->run;
+ if (i >= 64)
+ break; /* end of block */
+
+ normal_code:
+ bit_buf <<= tab->len + 1;
+ bits += tab->len + 1;
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ continue;
+ }
+
+ entry_2:
+ if (bit_buf >= 0x04000000)
+ {
+ tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4);
+
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+
+ /* escape code */
+
+ i += UBITS (bit_buf << 6, 6) - 64;
+ if (i >= 64)
+ break; /* illegal, check needed to avoid buffer overflow */
+
+ if (decoder->mpeg1)
+ {
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ if (!(SBITS (bit_buf, 8) & 0x7f))
+ DUMPBITS (bit_buf, bits, 8);
+
+ DUMPBITS (bit_buf, bits, 8);
+ }
+ else
+ {
+ DUMPBITS (bit_buf, bits, 12);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ DUMPBITS (bit_buf, bits, 12);
+ }
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ }
+ else if (bit_buf >= 0x02000000)
+ {
+ tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00800000)
+ {
+ tab = DCT_13 + (UBITS (bit_buf, 13) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else if (bit_buf >= 0x00200000)
+ {
+ tab = DCT_15 + (UBITS (bit_buf, 15) - 16);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ else
+ {
+ tab = DCT_16 + UBITS (bit_buf, 16);
+ bit_buf <<= 16;
+ GETWORD (bit_buf, bits + 16, bit_ptr);
+ i += tab->run;
+ if (i < 64)
+ goto normal_code;
+ }
+ break; /* illegal, check needed to avoid buffer overflow */
+ }
+
+ DUMPBITS (bit_buf, bits, 2); /* dump end of block code */
+ decoder->bitstream_buf = bit_buf;
+ decoder->bitstream_bits = bits;
+ decoder->bitstream_ptr = bit_ptr;
+}
+
+static void skip_chroma_dc_dct_diff (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ const DCtab * tab;
+ int size;
+
+ if (bit_buf < 0xf8000000)
+ {
+ tab = DC_chrom_5 + UBITS (bit_buf, 5);
+ size = tab->size;
+
+ if (size)
+ {
+ bits += tab->len + size;
+ bit_buf <<= tab->len;
+ bit_buf <<= size;
+ }
+ else
+ {
+ DUMPBITS (bit_buf, bits, 2);
+ }
+ }
+ else
+ {
+ tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0);
+ size = tab->size;
+ DUMPBITS (bit_buf, bits, tab->len + 1);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ DUMPBITS (bit_buf, bits, size);
+ }
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+static void skip_chroma_non_intra (mpeg2_decoder_t * const decoder,
+ uint32_t coded_block_pattern)
+{
+ static const uint32_t cbp_mask[3] =
+ {
+ 0x00000030,
+ 0xc0000030,
+ 0xfc000030,
+ };
+
+ uint32_t cbp = coded_block_pattern &
+ cbp_mask[MIN((unsigned)decoder->chroma_format, 2u)];
+
+ while (cbp)
+ {
+ skip_non_intra_block (decoder);
+ cbp &= (cbp - 1);
+ }
+}
+
+static void skip_chroma_intra (mpeg2_decoder_t * const decoder)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+ int i = 2 << decoder->chroma_format;
+
+ if ((unsigned)i > 8)
+ i = 8;
+
+ while (i-- > 0)
+ {
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ skip_chroma_dc_dct_diff (decoder);
+
+ if (decoder->mpeg1)
+ {
+ if (decoder->coding_type != D_TYPE)
+ skip_mpeg1_intra_block (decoder);
+ }
+ else if (decoder->intra_vlc_format)
+ {
+ skip_intra_block_B15 (decoder);
+ }
+ else
+ {
+ skip_intra_block_B14 (decoder);
+ }
+ }
+
+ if (decoder->chroma_format == 0 && decoder->coding_type == D_TYPE)
+ {
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ DUMPBITS (bit_buf, bits, 1);
+ }
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+#endif /* !MPEG2_COLOR */
+
+#define MOTION_420(table, ref, motion_x, motion_y, size, y) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y_ ## size)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \
+ motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \
+ ref[0] + (pos_x >> 1) + (pos_y >> 1) * decoder->stride, \
+ decoder->stride, size); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ motion_x /= 2; \
+ motion_y /= 2; \
+ xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \
+ offset = ((decoder->offset + motion_x) >> 1) + \
+ ((((decoder->v_offset + motion_y) >> 1) + y/2) * \
+ decoder->uv_stride); \
+ \
+ table[4+xy_half] (decoder->dest[1] + y/2 * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[1] + offset, \
+ decoder->uv_stride, size/2); \
+ table[4+xy_half] (decoder->dest[2] + y/2 * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[2] + offset, \
+ decoder->uv_stride, size/2); \
+ }
+
+#define MOTION_FIELD_420(table, ref, motion_x, motion_y, \
+ dest_field, op, src_field) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = decoder->v_offset + motion_y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \
+ motion_y = pos_y - decoder->v_offset; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \
+ decoder->offset, \
+ (ref[0] + (pos_x >> 1) + \
+ ((pos_y op) + src_field) * decoder->stride), \
+ 2 * decoder->stride, 8); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ motion_x /= 2; \
+ motion_y /= 2; \
+ xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \
+ offset = ((decoder->offset + motion_x) >> 1) + \
+ (((decoder->v_offset >> 1) + (motion_y op) + src_field) * \
+ decoder->uv_stride); \
+ \
+ table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[1] + offset, \
+ 2 * decoder->uv_stride, 4); \
+ table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[2] + offset, \
+ 2 * decoder->uv_stride, 4); \
+ }
+
+#define MOTION_DMV_420(table, ref, motion_x, motion_y) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = decoder->v_offset + motion_y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \
+ motion_y = pos_y - decoder->v_offset; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \
+ table[xy_half] (decoder->dest[0] + decoder->offset, \
+ ref[0] + offset, 2 * decoder->stride, 8); \
+ table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \
+ ref[0] + decoder->stride + offset, \
+ 2 * decoder->stride, 8); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ motion_x /= 2; \
+ motion_y /= 2; \
+ xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \
+ offset = ((decoder->offset + motion_x) >> 1) + \
+ (((decoder->v_offset >> 1) + (motion_y & ~1)) * \
+ decoder->uv_stride); \
+ \
+ table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1), \
+ ref[1] + offset, 2 * decoder->uv_stride, 4); \
+ table[4+xy_half] (decoder->dest[1] + decoder->uv_stride + \
+ (decoder->offset >> 1), \
+ ref[1] + decoder->uv_stride + offset, \
+ 2 * decoder->uv_stride, 4); \
+ table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1), \
+ ref[2] + offset, 2 * decoder->uv_stride, 4); \
+ table[4+xy_half] (decoder->dest[2] + decoder->uv_stride + \
+ (decoder->offset >> 1), \
+ ref[2] + decoder->uv_stride + offset, \
+ 2 * decoder->uv_stride, 4); \
+ }
+
+#define MOTION_ZERO_420(table, ref) \
+ table[0] (decoder->dest[0] + decoder->offset, \
+ (ref[0] + decoder->offset + \
+ decoder->v_offset * decoder->stride), decoder->stride, 16); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ offset = ((decoder->offset >> 1) + \
+ (decoder->v_offset >> 1) * decoder->uv_stride); \
+ \
+ table[4] (decoder->dest[1] + (decoder->offset >> 1), \
+ ref[1] + offset, decoder->uv_stride, 8); \
+ table[4] (decoder->dest[2] + (decoder->offset >> 1), \
+ ref[2] + offset, decoder->uv_stride, 8); \
+ }
+
+#define MOTION_422(table, ref, motion_x, motion_y, size, y) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y_ ## size)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \
+ motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride; \
+ \
+ table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \
+ ref[0] + offset, decoder->stride, size); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ offset = (offset + (motion_x & (motion_x < 0))) >> 1; \
+ motion_x /= 2; \
+ xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \
+ \
+ table[4+xy_half] (decoder->dest[1] + y * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[1] + offset, \
+ decoder->uv_stride, size); \
+ table[4+xy_half] (decoder->dest[2] + y * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[2] + offset, \
+ decoder->uv_stride, size); \
+ }
+
+#define MOTION_FIELD_422(table, ref, motion_x, motion_y, \
+ dest_field, op, src_field) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = decoder->v_offset + motion_y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \
+ motion_y = pos_y - decoder->v_offset; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride; \
+ \
+ table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \
+ decoder->offset, ref[0] + offset, \
+ 2 * decoder->stride, 8); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ offset = (offset + (motion_x & (motion_x < 0))) >> 1; \
+ motion_x /= 2; \
+ xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \
+ \
+ table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[1] + offset, \
+ 2 * decoder->uv_stride, 8); \
+ table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride + \
+ (decoder->offset >> 1), ref[2] + offset, \
+ 2 * decoder->uv_stride, 8); \
+ }
+
+#define MOTION_DMV_422(table, ref, motion_x, motion_y) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = decoder->v_offset + motion_y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \
+ motion_y = pos_y - decoder->v_offset; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \
+ \
+ table[xy_half] (decoder->dest[0] + decoder->offset, \
+ ref[0] + offset, 2 * decoder->stride, 8); \
+ table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \
+ ref[0] + decoder->stride + offset, \
+ 2 * decoder->stride, 8); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ offset = (offset + (motion_x & (motion_x < 0))) >> 1; \
+ motion_x /= 2; \
+ xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \
+ \
+ table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1), \
+ ref[1] + offset, 2 * decoder->uv_stride, 8); \
+ table[4+xy_half] (decoder->dest[1] + decoder->uv_stride + \
+ (decoder->offset >> 1), \
+ ref[1] + decoder->uv_stride + offset, \
+ 2 * decoder->uv_stride, 8); \
+ table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1), \
+ ref[2] + offset, 2 * decoder->uv_stride, 8); \
+ table[4+xy_half] (decoder->dest[2] + decoder->uv_stride + \
+ (decoder->offset >> 1), \
+ ref[2] + decoder->uv_stride + offset, \
+ 2 * decoder->uv_stride, 8); \
+ }
+
+#define MOTION_ZERO_422(table, ref) \
+ offset = decoder->offset + decoder->v_offset * decoder->stride; \
+ table[0] (decoder->dest[0] + decoder->offset, \
+ ref[0] + offset, decoder->stride, 16); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ offset >>= 1; \
+ table[4] (decoder->dest[1] + (decoder->offset >> 1), \
+ ref[1] + offset, decoder->uv_stride, 16); \
+ table[4] (decoder->dest[2] + (decoder->offset >> 1), \
+ ref[2] + offset, decoder->uv_stride, 16); \
+ }
+
+#define MOTION_444(table, ref, motion_x, motion_y, size, y) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y_ ## size)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \
+ motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride; \
+ \
+ table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \
+ ref[0] + offset, decoder->stride, size); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ table[xy_half] (decoder->dest[1] + y * decoder->stride + decoder->offset, \
+ ref[1] + offset, decoder->stride, size); \
+ table[xy_half] (decoder->dest[2] + y * decoder->stride + decoder->offset, \
+ ref[2] + offset, decoder->stride, size); \
+ }
+
+#define MOTION_FIELD_444(table, ref, motion_x, motion_y, \
+ dest_field, op, src_field) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = decoder->v_offset + motion_y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \
+ motion_y = pos_y - decoder->v_offset; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride; \
+ \
+ table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \
+ decoder->offset, ref[0] + offset, \
+ 2 * decoder->stride, 8); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ table[xy_half] (decoder->dest[1] + dest_field * decoder->stride + \
+ decoder->offset, ref[1] + offset, \
+ 2 * decoder->stride, 8); \
+ table[xy_half] (decoder->dest[2] + dest_field * decoder->stride + \
+ decoder->offset, ref[2] + offset, \
+ 2 * decoder->stride, 8); \
+ }
+
+#define MOTION_DMV_444(table, ref, motion_x, motion_y) \
+ pos_x = 2 * decoder->offset + motion_x; \
+ pos_y = decoder->v_offset + motion_y; \
+ \
+ if (unlikely (pos_x > decoder->limit_x)) \
+ { \
+ pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \
+ motion_x = pos_x - 2 * decoder->offset; \
+ } \
+ \
+ if (unlikely (pos_y > decoder->limit_y)) \
+ { \
+ pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \
+ motion_y = pos_y - decoder->v_offset; \
+ } \
+ \
+ xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \
+ offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \
+ \
+ table[xy_half] (decoder->dest[0] + decoder->offset, \
+ ref[0] + offset, 2 * decoder->stride, 8); \
+ table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \
+ ref[0] + decoder->stride + offset, \
+ 2 * decoder->stride, 8); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ table[xy_half] (decoder->dest[1] + decoder->offset, \
+ ref[1] + offset, 2 * decoder->stride, 8); \
+ table[xy_half] (decoder->dest[1] + decoder->stride + decoder->offset, \
+ ref[1] + decoder->stride + offset, \
+ 2 * decoder->stride, 8); \
+ table[xy_half] (decoder->dest[2] + decoder->offset, \
+ ref[2] + offset, 2 * decoder->stride, 8); \
+ table[xy_half] (decoder->dest[2] + decoder->stride + decoder->offset, \
+ ref[2] + decoder->stride + offset, \
+ 2 * decoder->stride, 8); \
+ }
+
+#define MOTION_ZERO_444(table, ref) \
+ offset = decoder->offset + decoder->v_offset * decoder->stride; \
+ \
+ table[0] (decoder->dest[0] + decoder->offset, \
+ ref[0] + offset, decoder->stride, 16); \
+ \
+ if (MPEG2_COLOR) \
+ { \
+ table[4] (decoder->dest[1] + decoder->offset, \
+ ref[1] + offset, decoder->stride, 16); \
+ table[4] (decoder->dest[2] + decoder->offset, \
+ ref[2] + offset, decoder->stride, 16); \
+ }
+
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+static void motion_mp1 (mpeg2_decoder_t * const decoder,
+ motion_t * const motion,
+ mpeg2_mc_fct * const * const table)
+{
+ int motion_x, motion_y;
+ unsigned int pos_x, pos_y, xy_half, offset;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ motion_x = motion->pmv[0][0] +
+ (get_motion_delta (decoder,
+ motion->f_code[0]) << motion->f_code[1]);
+ motion_x = bound_motion_vector (motion_x,
+ motion->f_code[0] + motion->f_code[1]);
+ motion->pmv[0][0] = motion_x;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ motion_y = motion->pmv[0][1] +
+ (get_motion_delta (decoder,
+ motion->f_code[0]) << motion->f_code[1]);
+ motion_y = bound_motion_vector (motion_y,
+ motion->f_code[0] + motion->f_code[1]);
+ motion->pmv[0][1] = motion_y;
+
+ MOTION_420 (table, motion->ref[0], motion_x, motion_y, 16, 0);
+}
+
+#define MOTION_FUNCTIONS(FORMAT, MOTION, MOTION_FIELD, \
+ MOTION_DMV, MOTION_ZERO) \
+ \
+static void motion_fr_frame_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ int motion_x, motion_y; \
+ unsigned int pos_x, pos_y, xy_half, offset; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \
+ motion->f_code[1]); \
+ motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \
+ motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \
+ \
+ MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); \
+} \
+ \
+static void motion_fr_field_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ int motion_x, motion_y, field; \
+ unsigned int pos_x, pos_y, xy_half, offset; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ field = UBITS (bit_buf, 1); \
+ DUMPBITS (bit_buf, bits, 1); \
+ \
+ motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[0][0] = motion_x; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_y = ((motion->pmv[0][1] >> 1) + \
+ get_motion_delta (decoder, motion->f_code[1])); \
+ /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \
+ motion->pmv[0][1] = motion_y << 1; \
+ \
+ MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 0, & ~1, field); \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ field = UBITS (bit_buf, 1); \
+ DUMPBITS (bit_buf, bits, 1); \
+ \
+ motion_x = motion->pmv[1][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[1][0] = motion_x; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_y = ((motion->pmv[1][1] >> 1) + \
+ get_motion_delta (decoder, motion->f_code[1])); \
+ /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \
+ motion->pmv[1][1] = motion_y << 1; \
+ \
+ MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 1, & ~1, field); \
+} \
+ \
+static void motion_fr_dmv_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ int motion_x, motion_y, dmv_x, dmv_y, m, other_x, other_y; \
+ unsigned int pos_x, pos_y, xy_half, offset; \
+ \
+ (void)table; \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ dmv_x = get_dmv (decoder); \
+ \
+ motion_y = ((motion->pmv[0][1] >> 1) + \
+ get_motion_delta (decoder, motion->f_code[1])); \
+ /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \
+ motion->pmv[1][1] = motion->pmv[0][1] = motion_y << 1; \
+ dmv_y = get_dmv (decoder); \
+ \
+ m = decoder->top_field_first ? 1 : 3; \
+ other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; \
+ other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y - 1; \
+ MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 0, | 1, 0); \
+ \
+ m = decoder->top_field_first ? 3 : 1; \
+ other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; \
+ other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y + 1; \
+ MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 1, & ~1, 0);\
+ \
+ MOTION_DMV (mpeg2_mc.avg, motion->ref[0], motion_x, motion_y); \
+} \
+ \
+static void motion_reuse_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ int motion_x, motion_y; \
+ unsigned int pos_x, pos_y, xy_half, offset; \
+ \
+ motion_x = motion->pmv[0][0]; \
+ motion_y = motion->pmv[0][1]; \
+ \
+ MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); \
+} \
+ \
+static void motion_zero_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ unsigned int offset; \
+ \
+ motion->pmv[0][0] = motion->pmv[0][1] = 0; \
+ motion->pmv[1][0] = motion->pmv[1][1] = 0; \
+ \
+ MOTION_ZERO (table, motion->ref[0]); \
+} \
+ \
+static void motion_fi_field_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ int motion_x, motion_y; \
+ uint8_t ** ref_field; \
+ unsigned int pos_x, pos_y, xy_half, offset; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ ref_field = motion->ref2[UBITS (bit_buf, 1)]; \
+ DUMPBITS (bit_buf, bits, 1); \
+ \
+ motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \
+ motion->f_code[1]); \
+ motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \
+ motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \
+ \
+ MOTION (table, ref_field, motion_x, motion_y, 16, 0); \
+} \
+ \
+static void motion_fi_16x8_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ int motion_x, motion_y; \
+ uint8_t ** ref_field; \
+ unsigned int pos_x, pos_y, xy_half, offset; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ ref_field = motion->ref2[UBITS (bit_buf, 1)]; \
+ DUMPBITS (bit_buf, bits, 1); \
+ \
+ motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[0][0] = motion_x; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \
+ motion->f_code[1]); \
+ motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \
+ motion->pmv[0][1] = motion_y; \
+ \
+ MOTION (table, ref_field, motion_x, motion_y, 8, 0); \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ ref_field = motion->ref2[UBITS (bit_buf, 1)]; \
+ DUMPBITS (bit_buf, bits, 1); \
+ \
+ motion_x = motion->pmv[1][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[1][0] = motion_x; \
+ \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_y = motion->pmv[1][1] + get_motion_delta (decoder, \
+ motion->f_code[1]); \
+ motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \
+ motion->pmv[1][1] = motion_y; \
+ \
+ MOTION (table, ref_field, motion_x, motion_y, 8, 8); \
+} \
+ \
+static void motion_fi_dmv_##FORMAT (mpeg2_decoder_t * const decoder, \
+ motion_t * const motion, \
+ mpeg2_mc_fct * const * const table) \
+{ \
+ int motion_x, motion_y, other_x, other_y; \
+ unsigned int pos_x, pos_y, xy_half, offset; \
+ \
+ (void)table; \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \
+ motion->f_code[0]); \
+ motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \
+ motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \
+ NEEDBITS (bit_buf, bits, bit_ptr); \
+ other_x = ((motion_x + (motion_x > 0)) >> 1) + get_dmv (decoder); \
+ \
+ motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \
+ motion->f_code[1]); \
+ motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \
+ motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \
+ other_y = (((motion_y + (motion_y > 0)) >> 1) + get_dmv (decoder) + \
+ decoder->dmv_offset); \
+ \
+ MOTION (mpeg2_mc.put, motion->ref[0], motion_x, motion_y, 16, 0); \
+ MOTION (mpeg2_mc.avg, motion->ref[1], other_x, other_y, 16, 0); \
+} \
+
+MOTION_FUNCTIONS (420, MOTION_420, MOTION_FIELD_420, MOTION_DMV_420,
+ MOTION_ZERO_420)
+MOTION_FUNCTIONS (422, MOTION_422, MOTION_FIELD_422, MOTION_DMV_422,
+ MOTION_ZERO_422)
+MOTION_FUNCTIONS (444, MOTION_444, MOTION_FIELD_444, MOTION_DMV_444,
+ MOTION_ZERO_444)
+
+/* like motion_frame, but parsing without actual motion compensation */
+static void motion_fr_conceal (mpeg2_decoder_t * const decoder)
+{
+ int tmp;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ tmp = (decoder->f_motion.pmv[0][0] +
+ get_motion_delta (decoder, decoder->f_motion.f_code[0]));
+ tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]);
+ decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[0][0] = tmp;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ tmp = (decoder->f_motion.pmv[0][1] +
+ get_motion_delta (decoder, decoder->f_motion.f_code[1]));
+ tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]);
+ decoder->f_motion.pmv[1][1] = decoder->f_motion.pmv[0][1] = tmp;
+
+ DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */
+}
+
+static void motion_fi_conceal (mpeg2_decoder_t * const decoder)
+{
+ int tmp;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ DUMPBITS (bit_buf, bits, 1); /* remove field_select */
+
+ tmp = decoder->f_motion.pmv[0][0] +
+ get_motion_delta (decoder, decoder->f_motion.f_code[0]);
+ tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]);
+
+ decoder->f_motion.pmv[1][0] =
+ decoder->f_motion.pmv[0][0] = tmp;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ tmp = (decoder->f_motion.pmv[0][1] +
+ get_motion_delta (decoder, decoder->f_motion.f_code[1]));
+ tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]);
+
+ decoder->f_motion.pmv[1][1] =
+ decoder->f_motion.pmv[0][1] = tmp;
+
+ DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */
+}
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+
+#define MOTION_CALL(routine, direction) \
+do { \
+ if ((direction) & MACROBLOCK_MOTION_FORWARD) \
+ routine (decoder, &decoder->f_motion, mpeg2_mc.put); \
+ \
+ if ((direction) & MACROBLOCK_MOTION_BACKWARD) \
+ { \
+ routine (decoder, &decoder->b_motion, \
+ ((direction) & MACROBLOCK_MOTION_FORWARD ? \
+ mpeg2_mc.avg : mpeg2_mc.put)); \
+ } \
+} while (0)
+
+#define NEXT_MACROBLOCK \
+do { \
+ decoder->offset += 16; \
+ \
+ if (decoder->offset == decoder->width) \
+ { \
+ do { /* just so we can use the break statement */ \
+ if (decoder->convert) \
+ { \
+ decoder->convert (decoder->convert_id, decoder->dest, \
+ decoder->v_offset); \
+ if (decoder->coding_type == B_TYPE) \
+ break; \
+ } \
+ \
+ decoder->dest[0] += decoder->slice_stride; \
+ if (MPEG2_COLOR) \
+ { \
+ decoder->dest[1] += decoder->slice_uv_stride; \
+ decoder->dest[2] += decoder->slice_uv_stride; \
+ } \
+ } while (0); \
+ \
+ decoder->v_offset += 16; \
+ \
+ if (decoder->v_offset > decoder->limit_y) \
+ return; \
+ \
+ decoder->offset = 0; \
+ } \
+} while (0)
+
+void mpeg2_init_fbuf (mpeg2_decoder_t * decoder,
+ uint8_t * current_fbuf[MPEG2_COMPONENTS],
+ uint8_t * forward_fbuf[MPEG2_COMPONENTS],
+ uint8_t * backward_fbuf[MPEG2_COMPONENTS])
+{
+ int offset, stride, height, bottom_field;
+
+ stride = decoder->stride_frame;
+ bottom_field = (decoder->picture_structure == BOTTOM_FIELD);
+ offset = bottom_field ? stride : 0;
+ height = decoder->height;
+
+ decoder->picture_dest[0] = current_fbuf[0] + offset;
+#if MPEG2_COLOR
+ decoder->picture_dest[1] = current_fbuf[1] + (offset >> 1);
+ decoder->picture_dest[2] = current_fbuf[2] + (offset >> 1);
+#endif
+
+ decoder->f_motion.ref[0][0] = forward_fbuf[0] + offset;
+#if MPEG2_COLOR
+ decoder->f_motion.ref[0][1] = forward_fbuf[1] + (offset >> 1);
+ decoder->f_motion.ref[0][2] = forward_fbuf[2] + (offset >> 1);
+#endif
+
+ decoder->b_motion.ref[0][0] = backward_fbuf[0] + offset;
+#if MPEG2_COLOR
+ decoder->b_motion.ref[0][1] = backward_fbuf[1] + (offset >> 1);
+ decoder->b_motion.ref[0][2] = backward_fbuf[2] + (offset >> 1);
+#endif
+
+ if (decoder->picture_structure != FRAME_PICTURE)
+ {
+ decoder->dmv_offset = bottom_field ? 1 : -1;
+ decoder->f_motion.ref2[0] = decoder->f_motion.ref[bottom_field];
+ decoder->f_motion.ref2[1] = decoder->f_motion.ref[!bottom_field];
+ decoder->b_motion.ref2[0] = decoder->b_motion.ref[bottom_field];
+ decoder->b_motion.ref2[1] = decoder->b_motion.ref[!bottom_field];
+ offset = stride - offset;
+
+ if (decoder->second_field && (decoder->coding_type != B_TYPE))
+ forward_fbuf = current_fbuf;
+
+ decoder->f_motion.ref[1][0] = forward_fbuf[0] + offset;
+#if MPEG2_COLOR
+ decoder->f_motion.ref[1][1] = forward_fbuf[1] + (offset >> 1);
+ decoder->f_motion.ref[1][2] = forward_fbuf[2] + (offset >> 1);
+#endif
+ decoder->b_motion.ref[1][0] = backward_fbuf[0] + offset;
+#if MPEG2_COLOR
+ decoder->b_motion.ref[1][1] = backward_fbuf[1] + (offset >> 1);
+ decoder->b_motion.ref[1][2] = backward_fbuf[2] + (offset >> 1);
+#endif
+ stride <<= 1;
+ height >>= 1;
+ }
+
+ decoder->stride = stride;
+ decoder->slice_stride = 16 * stride;
+#if MPEG2_COLOR
+ decoder->uv_stride = stride >> 1;
+ decoder->slice_uv_stride =
+ decoder->slice_stride >> (2 - decoder->chroma_format);
+#endif
+ decoder->limit_x = 2 * decoder->width - 32;
+ decoder->limit_y_16 = 2 * height - 32;
+ decoder->limit_y_8 = 2 * height - 16;
+ decoder->limit_y = height - 16;
+
+ if (decoder->mpeg1)
+ {
+ decoder->motion_parser[0] = motion_zero_420;
+ decoder->motion_parser[MC_FRAME] = motion_mp1;
+ decoder->motion_parser[4] = motion_reuse_420;
+ }
+ else if (decoder->picture_structure == FRAME_PICTURE)
+ {
+ if (decoder->chroma_format == 0)
+ {
+ decoder->motion_parser[0] = motion_zero_420;
+ decoder->motion_parser[MC_FIELD] = motion_fr_field_420;
+ decoder->motion_parser[MC_FRAME] = motion_fr_frame_420;
+ decoder->motion_parser[MC_DMV] = motion_fr_dmv_420;
+ decoder->motion_parser[4] = motion_reuse_420;
+ }
+ else if (decoder->chroma_format == 1)
+ {
+ decoder->motion_parser[0] = motion_zero_422;
+ decoder->motion_parser[MC_FIELD] = motion_fr_field_422;
+ decoder->motion_parser[MC_FRAME] = motion_fr_frame_422;
+ decoder->motion_parser[MC_DMV] = motion_fr_dmv_422;
+ decoder->motion_parser[4] = motion_reuse_422;
+ }
+ else
+ {
+ decoder->motion_parser[0] = motion_zero_444;
+ decoder->motion_parser[MC_FIELD] = motion_fr_field_444;
+ decoder->motion_parser[MC_FRAME] = motion_fr_frame_444;
+ decoder->motion_parser[MC_DMV] = motion_fr_dmv_444;
+ decoder->motion_parser[4] = motion_reuse_444;
+ }
+ }
+ else
+ {
+ if (decoder->chroma_format == 0)
+ {
+ decoder->motion_parser[0] = motion_zero_420;
+ decoder->motion_parser[MC_FIELD] = motion_fi_field_420;
+ decoder->motion_parser[MC_16X8] = motion_fi_16x8_420;
+ decoder->motion_parser[MC_DMV] = motion_fi_dmv_420;
+ decoder->motion_parser[4] = motion_reuse_420;
+ }
+ else if (decoder->chroma_format == 1)
+ {
+ decoder->motion_parser[0] = motion_zero_422;
+ decoder->motion_parser[MC_FIELD] = motion_fi_field_422;
+ decoder->motion_parser[MC_16X8] = motion_fi_16x8_422;
+ decoder->motion_parser[MC_DMV] = motion_fi_dmv_422;
+ decoder->motion_parser[4] = motion_reuse_422;
+ }
+ else
+ {
+ decoder->motion_parser[0] = motion_zero_444;
+ decoder->motion_parser[MC_FIELD] = motion_fi_field_444;
+ decoder->motion_parser[MC_16X8] = motion_fi_16x8_444;
+ decoder->motion_parser[MC_DMV] = motion_fi_dmv_444;
+ decoder->motion_parser[4] = motion_reuse_444;
+ }
+ }
+}
+
+static inline int slice_init (mpeg2_decoder_t * const decoder, int code)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ int offset;
+ const MBAtab * mba;
+
+#if MPEG2_COLOR
+ decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] =
+ decoder->dc_dct_pred[2] = 16384;
+#else
+ decoder->dc_dct_pred[0] = 16384;
+#endif
+
+ decoder->f_motion.pmv[0][0] = decoder->f_motion.pmv[0][1] = 0;
+ decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[1][1] = 0;
+ decoder->b_motion.pmv[0][0] = decoder->b_motion.pmv[0][1] = 0;
+ decoder->b_motion.pmv[1][0] = decoder->b_motion.pmv[1][1] = 0;
+
+ if (decoder->vertical_position_extension)
+ {
+ code += UBITS (bit_buf, 3) << 7;
+ DUMPBITS (bit_buf, bits, 3);
+ }
+
+ decoder->v_offset = (code - 1) * 16;
+ offset = 0;
+
+ if (!(decoder->convert) || decoder->coding_type != B_TYPE)
+ {
+ offset = (code - 1) * decoder->slice_stride;
+ }
+
+ decoder->dest[0] = decoder->picture_dest[0] + offset;
+#if MPEG2_COLOR
+ offset >>= (2 - decoder->chroma_format);
+ decoder->dest[1] = decoder->picture_dest[1] + offset;
+ decoder->dest[2] = decoder->picture_dest[2] + offset;
+#endif
+
+ get_quantizer_scale (decoder);
+
+ /* ignore intra_slice and all the extra data */
+ while (bit_buf & 0x80000000)
+ {
+ DUMPBITS (bit_buf, bits, 9);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ }
+
+ /* decode initial macroblock address increment */
+ offset = 0;
+ while (1)
+ {
+ if (bit_buf >= 0x08000000)
+ {
+ mba = MBA_5 + (UBITS (bit_buf, 6) - 2);
+ break;
+ }
+ else if (bit_buf >= 0x01800000)
+ {
+ mba = MBA_11 + (UBITS (bit_buf, 12) - 24);
+ break;
+ }
+ else
+ {
+ switch (UBITS (bit_buf, 12))
+ {
+ case 8: /* macroblock_escape */
+ offset += 33;
+ DUMPBITS (bit_buf, bits, 11);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ case 15: /* macroblock_stuffing (MPEG1 only) */
+ bit_buf &= 0xfffff;
+ DUMPBITS (bit_buf, bits, 11);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ default: /* error */
+ return 1;
+ }
+ }
+ }
+
+ DUMPBITS (bit_buf, bits, mba->len + 1);
+ decoder->offset = (offset + mba->mba) << 4;
+
+ while (decoder->offset - decoder->width >= 0)
+ {
+ decoder->offset -= decoder->width;
+
+ if (!(decoder->convert) || decoder->coding_type != B_TYPE)
+ {
+ decoder->dest[0] += decoder->slice_stride;
+#if MPEG2_COLOR
+ decoder->dest[1] += decoder->slice_uv_stride;
+ decoder->dest[2] += decoder->slice_uv_stride;
+#endif
+ }
+
+ decoder->v_offset += 16;
+ }
+
+ if (decoder->v_offset > decoder->limit_y)
+ return 1;
+
+ return 0;
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
+
+void mpeg2_slice (mpeg2_decoder_t * const decoder, const int code,
+ const uint8_t * const buffer)
+{
+#define bit_buf (decoder->bitstream_buf)
+#define bits (decoder->bitstream_bits)
+#define bit_ptr (decoder->bitstream_ptr)
+
+ bitstream_init (decoder, buffer);
+
+ if (slice_init (decoder, code))
+ return;
+
+ while (1)
+ {
+ int macroblock_modes;
+ int mba_inc;
+ const MBAtab * mba;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+
+ macroblock_modes = get_macroblock_modes (decoder);
+
+ /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */
+ if (macroblock_modes & MACROBLOCK_QUANT)
+ get_quantizer_scale (decoder);
+
+ if (macroblock_modes & MACROBLOCK_INTRA)
+ {
+ int DCT_offset, DCT_stride;
+ int offset;
+ uint8_t * dest_y;
+
+ if (decoder->concealment_motion_vectors)
+ {
+ if (decoder->picture_structure == FRAME_PICTURE)
+ motion_fr_conceal (decoder);
+ else
+ motion_fi_conceal (decoder);
+ }
+ else
+ {
+ decoder->f_motion.pmv[0][0] = decoder->f_motion.pmv[0][1] = 0;
+ decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[1][1] = 0;
+ decoder->b_motion.pmv[0][0] = decoder->b_motion.pmv[0][1] = 0;
+ decoder->b_motion.pmv[1][0] = decoder->b_motion.pmv[1][1] = 0;
+ }
+
+ if (macroblock_modes & DCT_TYPE_INTERLACED)
+ {
+ DCT_offset = decoder->stride;
+ DCT_stride = decoder->stride * 2;
+ }
+ else
+ {
+ DCT_offset = decoder->stride * 8;
+ DCT_stride = decoder->stride;
+ }
+
+ offset = decoder->offset;
+ dest_y = decoder->dest[0] + offset;
+ slice_intra_DCT (decoder, 0, dest_y, DCT_stride);
+ slice_intra_DCT (decoder, 0, dest_y + 8, DCT_stride);
+ slice_intra_DCT (decoder, 0, dest_y + DCT_offset, DCT_stride);
+ slice_intra_DCT (decoder, 0, dest_y + DCT_offset + 8, DCT_stride);
+
+#if MPEG2_COLOR
+ if (likely (decoder->chroma_format == 0))
+ {
+ slice_intra_DCT (decoder, 1, decoder->dest[1] + (offset >> 1),
+ decoder->uv_stride);
+ slice_intra_DCT (decoder, 2, decoder->dest[2] + (offset >> 1),
+ decoder->uv_stride);
+
+ if (decoder->coding_type == D_TYPE)
+ {
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ DUMPBITS (bit_buf, bits, 1);
+ }
+ }
+ else if (likely (decoder->chroma_format == 1))
+ {
+ uint8_t * dest_u = decoder->dest[1] + (offset >> 1);
+ uint8_t * dest_v = decoder->dest[2] + (offset >> 1);
+
+ DCT_stride >>= 1;
+ DCT_offset >>= 1;
+
+ slice_intra_DCT (decoder, 1, dest_u, DCT_stride);
+ slice_intra_DCT (decoder, 2, dest_v, DCT_stride);
+ slice_intra_DCT (decoder, 1, dest_u + DCT_offset, DCT_stride);
+ slice_intra_DCT (decoder, 2, dest_v + DCT_offset, DCT_stride);
+ }
+ else
+ {
+ uint8_t * dest_u = decoder->dest[1] + offset;
+ uint8_t * dest_v = decoder->dest[2] + offset;
+
+ slice_intra_DCT (decoder, 1, dest_u, DCT_stride);
+ slice_intra_DCT (decoder, 2, dest_v, DCT_stride);
+ slice_intra_DCT (decoder, 1, dest_u + DCT_offset, DCT_stride);
+ slice_intra_DCT (decoder, 2, dest_v + DCT_offset, DCT_stride);
+ slice_intra_DCT (decoder, 1, dest_u + 8, DCT_stride);
+ slice_intra_DCT (decoder, 2, dest_v + 8, DCT_stride);
+ slice_intra_DCT (decoder, 1, dest_u + DCT_offset + 8,
+ DCT_stride);
+ slice_intra_DCT (decoder, 2, dest_v + DCT_offset + 8,
+ DCT_stride);
+ }
+#else
+ skip_chroma_intra(decoder);
+#endif /* MPEG2_COLOR */
+ }
+ else
+ {
+ motion_parser_t * parser;
+
+ parser =
+ decoder->motion_parser[macroblock_modes >> MOTION_TYPE_SHIFT];
+ MOTION_CALL (parser, macroblock_modes);
+
+ if (macroblock_modes & MACROBLOCK_PATTERN)
+ {
+ int coded_block_pattern;
+ int DCT_offset, DCT_stride;
+
+ if (macroblock_modes & DCT_TYPE_INTERLACED)
+ {
+ DCT_offset = decoder->stride;
+ DCT_stride = decoder->stride * 2;
+ }
+ else
+ {
+ DCT_offset = decoder->stride * 8;
+ DCT_stride = decoder->stride;
+ }
+
+ coded_block_pattern = get_coded_block_pattern (decoder);
+
+ if (likely (decoder->chroma_format == 0))
+ {
+ int offset = decoder->offset;
+ uint8_t * dest_y = decoder->dest[0] + offset;
+
+ if (coded_block_pattern & 1)
+ slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride);
+
+ if (coded_block_pattern & 2)
+ slice_non_intra_DCT (decoder, 0, dest_y + 8,
+ DCT_stride);
+
+ if (coded_block_pattern & 4)
+ slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset,
+ DCT_stride);
+
+ if (coded_block_pattern & 8)
+ slice_non_intra_DCT (decoder, 0,
+ dest_y + DCT_offset + 8,
+ DCT_stride);
+#if MPEG2_COLOR
+ if (coded_block_pattern & 16)
+ slice_non_intra_DCT (decoder, 1,
+ decoder->dest[1] + (offset >> 1),
+ decoder->uv_stride);
+
+ if (coded_block_pattern & 32)
+ slice_non_intra_DCT (decoder, 2,
+ decoder->dest[2] + (offset >> 1),
+ decoder->uv_stride);
+#endif /* MPEG2_COLOR */
+ }
+ else if (likely (decoder->chroma_format == 1))
+ {
+ int offset;
+ uint8_t * dest_y;
+
+ coded_block_pattern |= bit_buf & (3 << 30);
+ DUMPBITS (bit_buf, bits, 2);
+
+ offset = decoder->offset;
+ dest_y = decoder->dest[0] + offset;
+
+ if (coded_block_pattern & 1)
+ slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride);
+
+ if (coded_block_pattern & 2)
+ slice_non_intra_DCT (decoder, 0, dest_y + 8,
+ DCT_stride);
+
+ if (coded_block_pattern & 4)
+ slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset,
+ DCT_stride);
+
+ if (coded_block_pattern & 8)
+ slice_non_intra_DCT (decoder, 0,
+ dest_y + DCT_offset + 8,
+ DCT_stride);
+#if MPEG2_COLOR
+ DCT_stride >>= 1;
+ DCT_offset = (DCT_offset + offset) >> 1;
+
+ if (coded_block_pattern & 16)
+ slice_non_intra_DCT (decoder, 1,
+ decoder->dest[1] + (offset >> 1),
+ DCT_stride);
+
+ if (coded_block_pattern & 32)
+ slice_non_intra_DCT (decoder, 2,
+ decoder->dest[2] + (offset >> 1),
+ DCT_stride);
+
+ if (coded_block_pattern & (2 << 30))
+ slice_non_intra_DCT (decoder, 1,
+ decoder->dest[1] + DCT_offset,
+ DCT_stride);
+
+ if (coded_block_pattern & (1 << 30))
+ slice_non_intra_DCT (decoder, 2,
+ decoder->dest[2] + DCT_offset,
+ DCT_stride);
+#endif /* MPEG2_COLOR */
+ }
+ else
+ {
+ int offset = decoder->offset;
+ uint8_t * dest_y = decoder->dest[0] + offset;
+#if MPEG2_COLOR
+ uint8_t * dest_u = decoder->dest[1] + offset;
+ uint8_t * dest_v = decoder->dest[2] + offset;
+#endif
+ coded_block_pattern |= bit_buf & (63 << 26);
+ DUMPBITS (bit_buf, bits, 6);
+
+ if (coded_block_pattern & 1)
+ slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride);
+
+ if (coded_block_pattern & 2)
+ slice_non_intra_DCT (decoder, 0, dest_y + 8,
+ DCT_stride);
+
+ if (coded_block_pattern & 4)
+ slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset,
+ DCT_stride);
+
+ if (coded_block_pattern & 8)
+ slice_non_intra_DCT (decoder, 0,
+ dest_y + DCT_offset + 8,
+ DCT_stride);
+#if MPEG2_COLOR
+ if (coded_block_pattern & 16)
+ slice_non_intra_DCT (decoder, 1, dest_u, DCT_stride);
+
+ if (coded_block_pattern & 32)
+ slice_non_intra_DCT (decoder, 2, dest_v, DCT_stride);
+
+ if (coded_block_pattern & (32 << 26))
+ slice_non_intra_DCT (decoder, 1, dest_u + DCT_offset,
+ DCT_stride);
+
+ if (coded_block_pattern & (16 << 26))
+ slice_non_intra_DCT (decoder, 2, dest_v + DCT_offset,
+ DCT_stride);
+
+ if (coded_block_pattern & (8 << 26))
+ slice_non_intra_DCT (decoder, 1, dest_u + 8,
+ DCT_stride);
+
+ if (coded_block_pattern & (4 << 26))
+ slice_non_intra_DCT (decoder, 2, dest_v + 8,
+ DCT_stride);
+
+ if (coded_block_pattern & (2 << 26))
+ slice_non_intra_DCT (decoder, 1,
+ dest_u + DCT_offset + 8,
+ DCT_stride);
+
+ if (coded_block_pattern & (1 << 26))
+ slice_non_intra_DCT (decoder, 2,
+ dest_v + DCT_offset + 8,
+ DCT_stride);
+#endif /* MPEG2_COLOR */
+ }
+#if !MPEG2_COLOR
+ skip_chroma_non_intra(decoder, coded_block_pattern);
+#endif
+ }
+
+#if MPEG2_COLOR
+ decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] =
+ decoder->dc_dct_pred[2] = 16384;
+#else
+ decoder->dc_dct_pred[0] = 16384;
+#endif
+ }
+
+ NEXT_MACROBLOCK;
+
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ mba_inc = 0;
+
+ while (1)
+ {
+ if (bit_buf >= 0x10000000)
+ {
+ mba = MBA_5 + (UBITS (bit_buf, 5) - 2);
+ break;
+ }
+ else if (bit_buf >= 0x03000000)
+ {
+ mba = MBA_11 + (UBITS (bit_buf, 11) - 24);
+ break;
+ }
+ else
+ {
+ switch (UBITS (bit_buf, 11))
+ {
+ case 8: /* macroblock_escape */
+ mba_inc += 33;
+ /* pass through */
+ case 15: /* macroblock_stuffing (MPEG1 only) */
+ DUMPBITS (bit_buf, bits, 11);
+ NEEDBITS (bit_buf, bits, bit_ptr);
+ continue;
+ default: /* end of slice, or error */
+ return;
+ }
+ }
+ }
+
+ DUMPBITS (bit_buf, bits, mba->len);
+ mba_inc += mba->mba;
+
+ if (mba_inc)
+ {
+#if MPEG2_COLOR
+ decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] =
+ decoder->dc_dct_pred[2] = 16384;
+#else
+ decoder->dc_dct_pred[0] = 16384;
+#endif
+ if (decoder->coding_type == P_TYPE)
+ {
+ do
+ {
+ MOTION_CALL (decoder->motion_parser[0],
+ MACROBLOCK_MOTION_FORWARD);
+ NEXT_MACROBLOCK;
+ }
+ while (--mba_inc);
+ }
+ else
+ {
+ do
+ {
+ MOTION_CALL (decoder->motion_parser[4], macroblock_modes);
+ NEXT_MACROBLOCK;
+ }
+ while (--mba_inc);
+ }
+ }
+ }
+
+#undef bit_buf
+#undef bits
+#undef bit_ptr
+}
diff --git a/apps/plugins/mpegplayer/libmpeg2/vlc.h b/apps/plugins/mpegplayer/libmpeg2/vlc.h
new file mode 100644
index 0000000000..d1b6a98cde
--- /dev/null
+++ b/apps/plugins/mpegplayer/libmpeg2/vlc.h
@@ -0,0 +1,433 @@
+/*
+ * 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
+ *
+ * $Id$
+ * libmpeg2 sync history:
+ * 2008-07-01 - CVS revision 1.12
+ */
+
+#define GETWORD(bit_buf, shift, bit_ptr) \
+do { \
+ bit_buf |= ((bit_ptr[0] << 8) | bit_ptr[1]) << (shift); \
+ bit_ptr += 2; \
+} while (0)
+
+static inline void bitstream_init (mpeg2_decoder_t * decoder,
+ const uint8_t * start)
+{
+ decoder->bitstream_buf =
+ (start[0] << 24) | (start[1] << 16) | (start[2] << 8) | start[3];
+ decoder->bitstream_ptr = start + 4;
+ decoder->bitstream_bits = -16;
+}
+
+/* make sure that there are at least 16 valid bits in bit_buf */
+#define NEEDBITS(bit_buf, bits, bit_ptr) \
+do { \
+ if (unlikely (bits > 0)) { \
+ GETWORD (bit_buf, bits, bit_ptr); \
+ bits -= 16; \
+ } \
+} while (0)
+
+/* remove num valid bits from bit_buf */
+#define DUMPBITS(bit_buf, bits, num) \
+do { \
+ bit_buf <<= (num); \
+ bits += (num); \
+} while (0)
+
+/* take num bits from the high part of bit_buf and zero extend them */
+#define UBITS(bit_buf,num) (((uint32_t)(bit_buf)) >> (32 - (num)))
+
+/* take num bits from the high part of bit_buf and sign extend them */
+#define SBITS(bit_buf,num) (((int32_t)(bit_buf)) >> (32 - (num)))
+
+typedef struct {
+ uint8_t modes;
+ uint8_t len;
+} MBtab;
+
+typedef struct {
+ uint8_t delta;
+ uint8_t len;
+} MVtab;
+
+typedef struct {
+ int8_t dmv;
+ uint8_t len;
+} DMVtab;
+
+typedef struct {
+ uint8_t cbp;
+ uint8_t len;
+} CBPtab;
+
+typedef struct {
+ uint8_t size;
+ uint8_t len;
+} DCtab;
+
+typedef struct {
+ uint8_t run;
+ uint8_t level;
+ uint8_t len;
+} DCTtab;
+
+typedef struct {
+ uint8_t mba;
+ uint8_t len;
+} MBAtab;
+
+
+#define INTRA MACROBLOCK_INTRA
+#define QUANT MACROBLOCK_QUANT
+
+static const MBtab MB_I [] ICONST_ATTR = {
+ {INTRA|QUANT, 2}, {INTRA, 1}
+};
+
+#define MC MACROBLOCK_MOTION_FORWARD
+#define CODED MACROBLOCK_PATTERN
+
+static const MBtab MB_P [] ICONST_ATTR = {
+ {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5},
+ {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3},
+ {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
+ {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
+ {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}
+};
+
+#define FWD MACROBLOCK_MOTION_FORWARD
+#define BWD MACROBLOCK_MOTION_BACKWARD
+#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD
+
+static const MBtab MB_B [] ICONST_ATTR = {
+ {0, 6}, {INTRA|QUANT, 6},
+ {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6},
+ {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5},
+ {INTRA, 5}, {INTRA, 5},
+ {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4},
+ {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4},
+ {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
+ {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
+ {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
+ {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
+ {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}
+};
+
+#undef INTRA
+#undef QUANT
+#undef MC
+#undef CODED
+#undef FWD
+#undef BWD
+#undef INTER
+
+
+static const MVtab MV_4 [] ICONST_ATTR = {
+ { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
+};
+
+static const MVtab MV_10 [] ICONST_ATTR = {
+ { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10},
+ { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10},
+ {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9},
+ { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7},
+ { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7},
+ { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}
+};
+
+
+static const DMVtab DMV_2 [] ICONST_ATTR = {
+ { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
+};
+
+
+static const CBPtab CBP_7 [] ICONST_ATTR = {
+ {0x11, 7}, {0x12, 7}, {0x14, 7}, {0x18, 7},
+ {0x21, 7}, {0x22, 7}, {0x24, 7}, {0x28, 7},
+ {0x3f, 6}, {0x3f, 6}, {0x30, 6}, {0x30, 6},
+ {0x09, 6}, {0x09, 6}, {0x06, 6}, {0x06, 6},
+ {0x1f, 5}, {0x1f, 5}, {0x1f, 5}, {0x1f, 5},
+ {0x10, 5}, {0x10, 5}, {0x10, 5}, {0x10, 5},
+ {0x2f, 5}, {0x2f, 5}, {0x2f, 5}, {0x2f, 5},
+ {0x20, 5}, {0x20, 5}, {0x20, 5}, {0x20, 5},
+ {0x07, 5}, {0x07, 5}, {0x07, 5}, {0x07, 5},
+ {0x0b, 5}, {0x0b, 5}, {0x0b, 5}, {0x0b, 5},
+ {0x0d, 5}, {0x0d, 5}, {0x0d, 5}, {0x0d, 5},
+ {0x0e, 5}, {0x0e, 5}, {0x0e, 5}, {0x0e, 5},
+ {0x05, 5}, {0x05, 5}, {0x05, 5}, {0x05, 5},
+ {0x0a, 5}, {0x0a, 5}, {0x0a, 5}, {0x0a, 5},
+ {0x03, 5}, {0x03, 5}, {0x03, 5}, {0x03, 5},
+ {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5},
+ {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4},
+ {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4},
+ {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4},
+ {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4},
+ {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
+ {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
+ {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
+ {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
+ {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3},
+ {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3},
+ {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3},
+ {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}
+};
+
+static const CBPtab CBP_9 [] ICONST_ATTR = {
+ {0, 9}, {0x00, 9}, {0x39, 9}, {0x36, 9},
+ {0x37, 9}, {0x3b, 9}, {0x3d, 9}, {0x3e, 9},
+ {0x17, 8}, {0x17, 8}, {0x1b, 8}, {0x1b, 8},
+ {0x1d, 8}, {0x1d, 8}, {0x1e, 8}, {0x1e, 8},
+ {0x27, 8}, {0x27, 8}, {0x2b, 8}, {0x2b, 8},
+ {0x2d, 8}, {0x2d, 8}, {0x2e, 8}, {0x2e, 8},
+ {0x19, 8}, {0x19, 8}, {0x16, 8}, {0x16, 8},
+ {0x29, 8}, {0x29, 8}, {0x26, 8}, {0x26, 8},
+ {0x35, 8}, {0x35, 8}, {0x3a, 8}, {0x3a, 8},
+ {0x33, 8}, {0x33, 8}, {0x3c, 8}, {0x3c, 8},
+ {0x15, 8}, {0x15, 8}, {0x1a, 8}, {0x1a, 8},
+ {0x13, 8}, {0x13, 8}, {0x1c, 8}, {0x1c, 8},
+ {0x25, 8}, {0x25, 8}, {0x2a, 8}, {0x2a, 8},
+ {0x23, 8}, {0x23, 8}, {0x2c, 8}, {0x2c, 8},
+ {0x31, 8}, {0x31, 8}, {0x32, 8}, {0x32, 8},
+ {0x34, 8}, {0x34, 8}, {0x38, 8}, {0x38, 8}
+};
+
+
+static const DCtab DC_lum_5 [] ICONST_ATTR = {
+ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}
+};
+
+static const DCtab DC_chrom_5 [] ICONST_ATTR = {
+ {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
+ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}
+};
+
+static const DCtab DC_long [] ICONST_ATTR = {
+ {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
+ {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
+ {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6},
+ {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
+};
+
+
+static const DCTtab DCT_16 [] ICONST_ATTR = {
+ {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+ {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+ {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+ {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
+ { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0},
+ { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0},
+ { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0},
+ { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0}
+};
+
+static const DCTtab DCT_15 [] ICONST_ATTR = {
+ { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15},
+ { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15},
+ { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15},
+ { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15},
+ { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14},
+ { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14},
+ { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14},
+ { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14},
+ { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14},
+ { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14},
+ { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14},
+ { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14}
+};
+
+static const DCTtab DCT_13 [] ICONST_ATTR = {
+ { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13},
+ { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13},
+ { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13},
+ { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13},
+ { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12},
+ { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12},
+ { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12},
+ { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12},
+ { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12},
+ { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12},
+ { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12},
+ { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12}
+};
+
+static const DCTtab DCT_B14_10 [] ICONST_ATTR = {
+ { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10},
+ { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10}
+};
+
+static const DCTtab DCT_B14_8 [] ICONST_ATTR = {
+ { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12},
+ { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7},
+ { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7},
+ { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6},
+ { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6},
+ { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6},
+ { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
+ { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8},
+ { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8}
+};
+
+static const DCTtab DCT_B14AC_5 [] ICONST_ATTR = {
+ { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
+ { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
+ {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}
+};
+
+static const DCTtab DCT_B14DC_5 [] ICONST_ATTR = {
+ { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
+ { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
+ { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}
+};
+
+static const DCTtab DCT_B15_10 [] ICONST_ATTR = {
+ { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9},
+ { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9}
+};
+
+static const DCTtab DCT_B15_8 [] ICONST_ATTR = {
+ { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12},
+ { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7},
+ { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7},
+ { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6},
+ { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6},
+ { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6},
+ { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
+ { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8},
+ { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8},
+ { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
+ { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
+ { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
+ { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
+ { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
+ { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
+ { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
+ { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
+ { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
+ { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
+ { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7},
+ { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7},
+ { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8},
+ { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8}
+};
+
+
+static const MBAtab MBA_5 [] ICONST_ATTR = {
+ {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
+ {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}
+};
+
+static const MBAtab MBA_11 [] ICONST_ATTR = {
+ {32, 11}, {31, 11}, {30, 11}, {29, 11},
+ {28, 11}, {27, 11}, {26, 11}, {25, 11},
+ {24, 11}, {23, 11}, {22, 11}, {21, 11},
+ {20, 10}, {20, 10}, {19, 10}, {19, 10},
+ {18, 10}, {18, 10}, {17, 10}, {17, 10},
+ {16, 10}, {16, 10}, {15, 10}, {15, 10},
+ {14, 8}, {14, 8}, {14, 8}, {14, 8},
+ {14, 8}, {14, 8}, {14, 8}, {14, 8},
+ {13, 8}, {13, 8}, {13, 8}, {13, 8},
+ {13, 8}, {13, 8}, {13, 8}, {13, 8},
+ {12, 8}, {12, 8}, {12, 8}, {12, 8},
+ {12, 8}, {12, 8}, {12, 8}, {12, 8},
+ {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ {10, 8}, {10, 8}, {10, 8}, {10, 8},
+ {10, 8}, {10, 8}, {10, 8}, {10, 8},
+ { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
+ { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
+ { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}
+};