From 9d3d925295112a0080bc1d70fad170db9e1af2a9 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 13 Oct 2022 11:04:12 -0400 Subject: Revert "RFC: Get rid of mpegplayer plugin" This reverts commit d25d24812e8120c0eb133a412287ac030eb185c9. Change-Id: I1563223e343fb1e2eda72a45823b38350025ff93 --- apps/plugins/mpegplayer/libmpeg2/AUTHORS | 33 + apps/plugins/mpegplayer/libmpeg2/README | 204 ++ apps/plugins/mpegplayer/libmpeg2/README.rockbox | 44 + apps/plugins/mpegplayer/libmpeg2/attributes.h | 42 + apps/plugins/mpegplayer/libmpeg2/decode.c | 527 ++++ apps/plugins/mpegplayer/libmpeg2/header.c | 1287 +++++++++ apps/plugins/mpegplayer/libmpeg2/idct.c | 274 ++ apps/plugins/mpegplayer/libmpeg2/idct_arm.S | 443 +++ apps/plugins/mpegplayer/libmpeg2/idct_armv6.S | 297 ++ apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S | 575 ++++ apps/plugins/mpegplayer/libmpeg2/motion_comp.c | 66 + apps/plugins/mpegplayer/libmpeg2/motion_comp.h | 86 + .../mpegplayer/libmpeg2/motion_comp_arm_c.c | 39 + .../mpegplayer/libmpeg2/motion_comp_arm_s.S | 342 +++ apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c | 40 + .../mpegplayer/libmpeg2/motion_comp_coldfire_c.c | 38 + .../mpegplayer/libmpeg2/motion_comp_coldfire_s.S | 436 +++ apps/plugins/mpegplayer/libmpeg2/mpeg2.h | 223 ++ apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h | 274 ++ apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h | 15 + apps/plugins/mpegplayer/libmpeg2/slice.c | 2898 ++++++++++++++++++++ apps/plugins/mpegplayer/libmpeg2/vlc.h | 433 +++ 22 files changed, 8616 insertions(+) create mode 100644 apps/plugins/mpegplayer/libmpeg2/AUTHORS create mode 100644 apps/plugins/mpegplayer/libmpeg2/README create mode 100644 apps/plugins/mpegplayer/libmpeg2/README.rockbox create mode 100644 apps/plugins/mpegplayer/libmpeg2/attributes.h create mode 100644 apps/plugins/mpegplayer/libmpeg2/decode.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/header.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/idct.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/idct_arm.S create mode 100644 apps/plugins/mpegplayer/libmpeg2/idct_armv6.S create mode 100644 apps/plugins/mpegplayer/libmpeg2/idct_coldfire.S create mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp.h create mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S create mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_c.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S create mode 100644 apps/plugins/mpegplayer/libmpeg2/mpeg2.h create mode 100644 apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h create mode 100644 apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h create mode 100644 apps/plugins/mpegplayer/libmpeg2/slice.c create mode 100644 apps/plugins/mpegplayer/libmpeg2/vlc.h (limited to 'apps/plugins/mpegplayer/libmpeg2') 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 started the project and +made the initial working implementation. + +Michel Lespinasse did major changes for speed and +mpeg conformance and is the current maintainer. Most of the current +code was (re)written by him. + +Other contributors include: + Bruno Barreyra - build fixes + Gildas Bazin - mingw32 port + Alexander W. Chin - progressive_seq fix + Stephen Crowley - build fixes + Didier Gautheron - bug fixes + Ryan C. Gordon - SDL support + Peter Gubanov - MMX IDCT scheduling + HÃ¥kan Hjort - Solaris fixes, mlib code + Nicolas Joly - assorted bug fixes + Gerd Knorr - Xv support + David I. Lehn - motion_comp mmx code + Olie Lho - MMX yuv2rgb routine + David S. Miller - sparc VIS optimizations + Rick Niles - build fixes + Real Ouellet - g200 fixes + Bajusz Peter - motion comp fixes + Franck Sicard - x11 fixes + Brion Vibber - x11 fixes + Martin Vogt - reentrancy fixes + Fredrik Vraalsen - general hackage and stuff + +(let me know if I forgot anyone) + +Thanks to David Schleef for creating me an account on his ppc g4 +machine and making it possible for me to work on the altivec code. diff --git a/apps/plugins/mpegplayer/libmpeg2/README b/apps/plugins/mpegplayer/libmpeg2/README 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.5 + */ + +/* use gcc attribs to align critical data structures */ +#ifdef ATTRIBUTE_ALIGNED_MAX +#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align))) +#else +#define ATTR_ALIGN(align) +#endif + +#if defined(LIKELY) && defined (UNLIKELY) +#define likely(x) LIKELY(x) +#define unlikely(x) UNLIKELY(x) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + diff --git a/apps/plugins/mpegplayer/libmpeg2/decode.c b/apps/plugins/mpegplayer/libmpeg2/decode.c 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.114 + */ + +#include "plugin.h" + +#include "mpeg2dec_config.h" + +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" + +#define BUFFER_SIZE (1194 * 1024) + +#if defined(CPU_COLDFIRE) || (defined(CPU_ARM) && ARM_ARCH >= 6) +/* twice as large as on other targets because coldfire uses + * a secondary, transposed buffer for optimisation */ +static int16_t static_dct_block[128] IBSS_ATTR ATTR_ALIGN(16); +#define DCT_BLOCKSIZE (128 * sizeof (int16_t)) +#else +static int16_t static_dct_block[64] IBSS_ATTR ATTR_ALIGN(16); +#define DCT_BLOCKSIZE (64 * sizeof (int16_t)) +#endif + +const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec) +{ + return &mpeg2dec->info; +} + +static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes) +{ + uint8_t * current; + uint32_t shift; + uint8_t * limit; + uint8_t byte; + + if (!bytes) + return 0; + + current = mpeg2dec->buf_start; + shift = mpeg2dec->shift; + limit = current + bytes; + + do + { + byte = *current++; + + if (shift == 0x00000100) + { + int skipped; + + mpeg2dec->shift = 0xffffff00; + skipped = current - mpeg2dec->buf_start; + mpeg2dec->buf_start = current; + + return skipped; + } + + shift = (shift | byte) << 8; + } + while (current < limit); + + mpeg2dec->shift = shift; + mpeg2dec->buf_start = current; + + return 0; +} + +static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes) +{ + uint8_t * current; + uint32_t shift; + uint8_t * chunk_ptr; + uint8_t * limit; + uint8_t byte; + + if (!bytes) + return 0; + + current = mpeg2dec->buf_start; + shift = mpeg2dec->shift; + chunk_ptr = mpeg2dec->chunk_ptr; + limit = current + bytes; + + do + { + byte = *current++; + + if (shift == 0x00000100) + { + int copied; + + mpeg2dec->shift = 0xffffff00; + mpeg2dec->chunk_ptr = chunk_ptr + 1; + copied = current - mpeg2dec->buf_start; + mpeg2dec->buf_start = current; + return copied; + } + + shift = (shift | byte) << 8; + *chunk_ptr++ = byte; + } + while (current < limit); + + mpeg2dec->shift = shift; + mpeg2dec->buf_start = current; + return 0; +} + +void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end) +{ + mpeg2dec->buf_start = start; + mpeg2dec->buf_end = end; +} + +int mpeg2_getpos (mpeg2dec_t * mpeg2dec) +{ + return mpeg2dec->buf_end - mpeg2dec->buf_start; +} + +static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec) +{ + int size, skipped; + + size = mpeg2dec->buf_end - mpeg2dec->buf_start; + skipped = skip_chunk (mpeg2dec, size); + + if (!skipped) + { + mpeg2dec->bytes_since_tag += size; + return STATE_BUFFER; + } + + mpeg2dec->bytes_since_tag += skipped; + mpeg2dec->code = mpeg2dec->buf_start[-1]; + + return STATE_INTERNAL_NORETURN; +} + +mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec) +{ + while (!(mpeg2dec->code == 0xb3 || + ((mpeg2dec->code == 0xb7 || mpeg2dec->code == 0xb8 || + !mpeg2dec->code) && mpeg2dec->sequence.width != (unsigned)-1))) + { + if (seek_chunk (mpeg2dec) == STATE_BUFFER) + return STATE_BUFFER; + } + + mpeg2dec->chunk_start = + mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; + + mpeg2dec->user_data_len = 0; + + return ((mpeg2dec->code == 0xb7) ? + mpeg2_header_end(mpeg2dec) : mpeg2_parse_header(mpeg2dec)); +} + +#define RECEIVED(code,state) (((state) << 8) + (code)) + +mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec) +{ + int size_buffer, size_chunk, copied; + + if (mpeg2dec->action) + { + mpeg2_state_t state; + + state = mpeg2dec->action (mpeg2dec); + + if (state > STATE_INTERNAL_NORETURN) + return state; + } + + while (1) + { + while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) < + mpeg2dec->nb_decode_slices) + { + size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; + size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE - + mpeg2dec->chunk_ptr; + + if (size_buffer <= size_chunk) + { + copied = copy_chunk (mpeg2dec, size_buffer); + + if (!copied) + { + mpeg2dec->bytes_since_tag += size_buffer; + mpeg2dec->chunk_ptr += size_buffer; + return STATE_BUFFER; + } + } + else + { + copied = copy_chunk (mpeg2dec, size_chunk); + + if (!copied) + { + /* filled the chunk buffer without finding a start code */ + mpeg2dec->bytes_since_tag += size_chunk; + mpeg2dec->action = seek_chunk; + return STATE_INVALID; + } + } + + mpeg2dec->bytes_since_tag += copied; + + mpeg2_slice (&mpeg2dec->decoder, mpeg2dec->code, + mpeg2dec->chunk_start); + mpeg2dec->code = mpeg2dec->buf_start[-1]; + mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; + } + + if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1) + break; + + if (seek_chunk (mpeg2dec) == STATE_BUFFER) + return STATE_BUFFER; + } + + mpeg2dec->action = mpeg2_seek_header; + + switch (mpeg2dec->code) + { + case 0x00: + return mpeg2dec->state; + case 0xb3: + case 0xb7: + case 0xb8: + return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID; + default: + mpeg2dec->action = seek_chunk; + return STATE_INVALID; + } +} + +mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec) +{ + static int (* const process_header[9]) (mpeg2dec_t *) = + { + mpeg2_header_picture, + mpeg2_header_extension, + mpeg2_header_user_data, + mpeg2_header_sequence, + NULL, + NULL, + NULL, + NULL, + mpeg2_header_gop + }; + + int size_buffer, size_chunk, copied; + + mpeg2dec->action = mpeg2_parse_header; + mpeg2dec->info.user_data = NULL; + mpeg2dec->info.user_data_len = 0; + + while (1) + { + size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; + size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE - + mpeg2dec->chunk_ptr; + + if (size_buffer <= size_chunk) + { + copied = copy_chunk (mpeg2dec, size_buffer); + + if (!copied) + { + mpeg2dec->bytes_since_tag += size_buffer; + mpeg2dec->chunk_ptr += size_buffer; + return STATE_BUFFER; + } + } + else + { + copied = copy_chunk (mpeg2dec, size_chunk); + + if (!copied) + { + /* filled the chunk buffer without finding a start code */ + mpeg2dec->bytes_since_tag += size_chunk; + mpeg2dec->code = 0xb4; + mpeg2dec->action = mpeg2_seek_header; + return STATE_INVALID; + } + } + + mpeg2dec->bytes_since_tag += copied; + + if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) + { + mpeg2dec->code = mpeg2dec->buf_start[-1]; + mpeg2dec->action = mpeg2_seek_header; + return STATE_INVALID; + } + + mpeg2dec->code = mpeg2dec->buf_start[-1]; + + switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) + { + /* state transition after a sequence header */ + case RECEIVED (0x00, STATE_SEQUENCE): + case RECEIVED (0xb8, STATE_SEQUENCE): + mpeg2_header_sequence_finalize (mpeg2dec); + break; + + /* other legal state transitions */ + case RECEIVED (0x00, STATE_GOP): + mpeg2_header_gop_finalize (mpeg2dec); + break; + case RECEIVED (0x01, STATE_PICTURE): + case RECEIVED (0x01, STATE_PICTURE_2ND): + mpeg2_header_picture_finalize (mpeg2dec); + mpeg2dec->action = mpeg2_header_slice_start; + break; + + /* legal headers within a given state */ + case RECEIVED (0xb2, STATE_SEQUENCE): + case RECEIVED (0xb2, STATE_GOP): + case RECEIVED (0xb2, STATE_PICTURE): + case RECEIVED (0xb2, STATE_PICTURE_2ND): + case RECEIVED (0xb5, STATE_SEQUENCE): + case RECEIVED (0xb5, STATE_PICTURE): + case RECEIVED (0xb5, STATE_PICTURE_2ND): + mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; + continue; + + default: + mpeg2dec->action = mpeg2_seek_header; + return STATE_INVALID; + } + + mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; + mpeg2dec->user_data_len = 0; + + return mpeg2dec->state; + } +} + +int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg) +{ + mpeg2_convert_init_t convert_init; + int error; + + error = convert (MPEG2_CONVERT_SET, NULL, &mpeg2dec->sequence, 0, + arg, &convert_init); + + if (!error) + { + mpeg2dec->convert = convert; + mpeg2dec->convert_arg = arg; + mpeg2dec->convert_id_size = convert_init.id_size; + mpeg2dec->convert_stride = 0; + } + + return error; +} + +int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride) +{ + if (!mpeg2dec->convert) + { + if (stride < (int) mpeg2dec->sequence.width) + stride = mpeg2dec->sequence.width; + + mpeg2dec->decoder.stride_frame = stride; + } + else + { + mpeg2_convert_init_t convert_init; + + stride = mpeg2dec->convert(MPEG2_CONVERT_STRIDE, NULL, + &mpeg2dec->sequence, stride, + mpeg2dec->convert_arg, + &convert_init); + + mpeg2dec->convert_id_size = convert_init.id_size; + mpeg2dec->convert_stride = stride; + } + + return stride; +} + +void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[MPEG2_COMPONENTS], void * id) +{ + mpeg2_fbuf_t * fbuf; + + if (mpeg2dec->custom_fbuf) + { + if (mpeg2dec->state == STATE_SEQUENCE) + { + mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; + mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; + } + + mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type == + PIC_FLAG_CODING_TYPE_B)); + + fbuf = mpeg2dec->fbuf[0]; + } + else + { + fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf; + mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index; + } + + fbuf->buf[0] = buf[0]; +#if MPEG2_COLOR + fbuf->buf[1] = buf[1]; + fbuf->buf[2] = buf[2]; +#endif + + fbuf->id = id; +} + +void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf) +{ + mpeg2dec->custom_fbuf = custom_fbuf; +} + +void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip) +{ + mpeg2dec->first_decode_slice = 1; + mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1); +} + +void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end) +{ + start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start; + end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end; + mpeg2dec->first_decode_slice = start; + mpeg2dec->nb_decode_slices = end - start; +} + +void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2) +{ + mpeg2dec->tag_previous = mpeg2dec->tag_current; + mpeg2dec->tag2_previous = mpeg2dec->tag2_current; + mpeg2dec->tag_current = tag; + mpeg2dec->tag2_current = tag2; + mpeg2dec->num_tags++; + mpeg2dec->bytes_since_tag = 0; +} + +void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset) +{ + mpeg2dec->buf_start = mpeg2dec->buf_end = NULL; + mpeg2dec->num_tags = 0; + mpeg2dec->shift = 0xffffff00; + mpeg2dec->code = 0xb4; + mpeg2dec->action = mpeg2_seek_header; + mpeg2dec->state = STATE_INVALID; + mpeg2dec->first = 1; + + mpeg2_reset_info(&mpeg2dec->info); + mpeg2dec->info.gop = NULL; + mpeg2dec->info.user_data = NULL; + mpeg2dec->info.user_data_len = 0; + + if (full_reset) + { + mpeg2dec->info.sequence = NULL; + mpeg2_header_state_init (mpeg2dec); + } +} + +mpeg2dec_t * mpeg2_init (void) +{ + mpeg2dec_t * mpeg2dec; + + mpeg2_idct_init (); + + mpeg2dec = (mpeg2dec_t *)mpeg2_bufalloc(sizeof (mpeg2dec_t), + MPEG2_ALLOC_MPEG2DEC); + if (mpeg2dec == NULL) + return NULL; + + mpeg2dec->decoder.DCTblock = static_dct_block; + + rb->memset (mpeg2dec->decoder.DCTblock, 0, DCT_BLOCKSIZE); + + DEBUGF("DCTblock: %p\n", mpeg2dec->decoder.DCTblock); + + mpeg2dec->chunk_buffer = (uint8_t *)mpeg2_bufalloc(BUFFER_SIZE + 4, + MPEG2_ALLOC_CHUNK); + + mpeg2dec->sequence.width = (unsigned)-1; + mpeg2_reset (mpeg2dec, 1); + + return mpeg2dec; +} + +void mpeg2_close (mpeg2dec_t * mpeg2dec) +{ + mpeg2_header_state_init (mpeg2dec); +#if 0 + /* These are dedicated buffers in rockbox */ + mpeg2_free (mpeg2dec->chunk_buffer); + mpeg2_free (mpeg2dec); +#endif +} diff --git a/apps/plugins/mpegplayer/libmpeg2/header.c b/apps/plugins/mpegplayer/libmpeg2/header.c new file mode 100644 index 0000000000..b40193a338 --- /dev/null +++ b/apps/plugins/mpegplayer/libmpeg2/header.c @@ -0,0 +1,1287 @@ +/* + * header.c + * Copyright (C) 2000-2003 Michel Lespinasse + * Copyright (C) 2003 Regis Duchesne + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.101 + */ + +#include "plugin.h" + +#include "mpeg2dec_config.h" + +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" + +#define SEQ_EXT 2 +#define SEQ_DISPLAY_EXT 4 +#define QUANT_MATRIX_EXT 8 +#define COPYRIGHT_EXT 0x10 +#define PIC_DISPLAY_EXT 0x80 +#define PIC_CODING_EXT 0x100 + +/* default intra quant matrix, in zig-zag order */ +static const uint8_t default_intra_quantizer_matrix[64] = +{ + 8, + 16, 16, + 19, 16, 19, + 22, 22, 22, 22, + 22, 22, 26, 24, 26, + 27, 27, 27, 26, 26, 26, + 26, 27, 27, 27, 29, 29, 29, + 34, 34, 34, 29, 29, 29, 27, 27, + 29, 29, 32, 32, 34, 34, 37, + 38, 37, 35, 35, 34, 35, + 38, 38, 40, 40, 40, + 48, 48, 46, 46, + 56, 56, 58, + 69, 69, + 83 +}; + +const uint8_t default_mpeg2_scan_norm[64] = +{ + /* Zig-Zag scan pattern */ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +const uint8_t default_mpeg2_scan_alt[64] = +{ + /* Alternate scan pattern */ + 0, 8, 16, 24, 1, 9, 2, 10, + 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, + 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, + 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, + 38, 46, 54, 62, 39, 47, 55, 63 +}; + +uint8_t mpeg2_scan_norm[64] IDATA_ATTR; +uint8_t mpeg2_scan_alt[64] IDATA_ATTR; + +void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec) +{ + if (mpeg2dec->sequence.width != (unsigned)-1) + { + mpeg2dec->sequence.width = (unsigned)-1; + mpeg2_mem_reset(); /* Clean the memory slate */ +#if 0 + if (!mpeg2dec->custom_fbuf) + { + int i; + for (i = mpeg2dec->alloc_index_user; + i < mpeg2dec->alloc_index; i++) + { + mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[0]); +#if MPEG2_COLOR + mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[1]); + mpeg2_free(mpeg2dec->fbuf_alloc[i].fbuf.buf[2]); +#endif + } + } + + if (mpeg2dec->convert_start) + { + int i; + for (i = 0; i < 3; i++) + { + mpeg2_free(mpeg2dec->yuv_buf[i][0]); +#if MPEG2_COLOR + mpeg2_free(mpeg2dec->yuv_buf[i][1]); + mpeg2_free(mpeg2dec->yuv_buf[i][2]); +#endif + } + } + + if (mpeg2dec->decoder.convert_id) + { + mpeg2_free(mpeg2dec->decoder.convert_id); + } +#endif + } + + mpeg2dec->decoder.coding_type = I_TYPE; + mpeg2dec->decoder.convert = NULL; + mpeg2dec->decoder.convert_id = NULL; + + mpeg2dec->picture = mpeg2dec->pictures; + + mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[0].fbuf; + mpeg2dec->fbuf[1] = &mpeg2dec->fbuf_alloc[1].fbuf; + mpeg2dec->fbuf[2] = &mpeg2dec->fbuf_alloc[2].fbuf; + + mpeg2dec->first = 1; + mpeg2dec->alloc_index = 0; + mpeg2dec->alloc_index_user = 0; + mpeg2dec->first_decode_slice = 1; + mpeg2dec->nb_decode_slices = 0xb0 - 1; + mpeg2dec->convert = NULL; + mpeg2dec->convert_start = NULL; + mpeg2dec->custom_fbuf = 0; + mpeg2dec->yuv_index = 0; +} + +void mpeg2_reset_info (mpeg2_info_t * info) +{ + info->current_picture = + info->current_picture_2nd = NULL; + + info->display_picture = + info->display_picture_2nd = NULL; + + info->current_fbuf = + info->display_fbuf = + info->discard_fbuf = NULL; +} + +static void info_user_data (mpeg2dec_t * mpeg2dec) +{ + if (mpeg2dec->user_data_len) + { + mpeg2dec->info.user_data = mpeg2dec->chunk_buffer; + mpeg2dec->info.user_data_len = mpeg2dec->user_data_len - 3; + } +} + +int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec) +{ + static const unsigned int frame_period[16] = + { + 0, 1126125, 1125000, 1080000, 900900, 900000, 540000, 450450, 450000, + /* unofficial: xing 15 fps */ + 1800000, + /* unofficial: libmpeg3 "Unofficial economy rates" 5/10/12/15 fps */ + 5400000, 2700000, 2250000, 1800000, 0, 0 + }; + + uint8_t * buffer = mpeg2dec->chunk_start; + mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; + int i; + + if ((buffer[6] & 0x20) != 0x20) /* missing marker_bit */ + return 1; + + i = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; + + if (!(sequence->display_width = sequence->picture_width = i >> 12)) + return 1; + + if (!(sequence->display_height = sequence->picture_height = i & 0xfff)) + return 1; + + sequence->width = (sequence->picture_width + 15) & ~15; + sequence->height = (sequence->picture_height + 15) & ~15; + sequence->chroma_width = sequence->width >> 1; + sequence->chroma_height = sequence->height >> 1; + + sequence->flags = SEQ_FLAG_PROGRESSIVE_SEQUENCE | + SEQ_VIDEO_FORMAT_UNSPECIFIED; + + sequence->pixel_width = buffer[3] >> 4; /* aspect ratio */ + sequence->frame_period = frame_period[buffer[3] & 15]; + + sequence->byte_rate = (buffer[4]<<10) | (buffer[5]<<2) | (buffer[6]>>6); + + sequence->vbv_buffer_size = ((buffer[6]<<16) | (buffer[7]<<8)) & 0x1ff800; + + if (buffer[7] & 4) + sequence->flags |= SEQ_FLAG_CONSTRAINED_PARAMETERS; + + mpeg2dec->copy_matrix = 3; + + if (buffer[7] & 2) + { + for (i = 0; i < 64; i++) + { + mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] = + (buffer[i+7] << 7) | (buffer[i+8] >> 1); + } + + buffer += 64; + } + else + { + for (i = 0; i < 64; i++) + { + mpeg2dec->new_quantizer_matrix[0][mpeg2_scan_norm[i]] = + default_intra_quantizer_matrix[i]; + } + } + + if (buffer[7] & 1) + { + for (i = 0; i < 64; i++) + { + mpeg2dec->new_quantizer_matrix[1][mpeg2_scan_norm[i]] = + buffer[i+8]; + } + } + else + { + rb->memset (mpeg2dec->new_quantizer_matrix[1], 16, 64); + } + + sequence->profile_level_id = 0x80; + sequence->colour_primaries = 0; + sequence->transfer_characteristics = 0; + sequence->matrix_coefficients = 0; + + mpeg2dec->ext_state = SEQ_EXT; + mpeg2dec->state = STATE_SEQUENCE; + + mpeg2dec->display_offset_x = + mpeg2dec->display_offset_y = 0; + + return 0; +} + +static int sequence_ext (mpeg2dec_t * mpeg2dec) +{ + uint8_t * buffer = mpeg2dec->chunk_start; + mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; + uint32_t flags; + + if (!(buffer[3] & 1)) + return 1; + + sequence->profile_level_id = (buffer[0] << 4) | (buffer[1] >> 4); + + sequence->picture_width += ((buffer[1] << 13) | (buffer[2] << 5)) & 0x3000; + sequence->display_width = sequence->picture_width; + + sequence->picture_height += (buffer[2] << 7) & 0x3000; + sequence->display_height = sequence->picture_height; + + sequence->width = (sequence->picture_width + 15) & ~15; + sequence->height = (sequence->picture_height + 15) & ~15; + + flags = sequence->flags | SEQ_FLAG_MPEG2; + + if (!(buffer[1] & 8)) + { + flags &= ~SEQ_FLAG_PROGRESSIVE_SEQUENCE; + sequence->height = (sequence->height + 31) & ~31; + } + + if (buffer[5] & 0x80) + flags |= SEQ_FLAG_LOW_DELAY; + + sequence->flags = flags; + sequence->chroma_width = sequence->width; + sequence->chroma_height = sequence->height; + + switch (buffer[1] & 6) + { + case 0: /* invalid */ + return 1; + case 2: /* 4:2:0 */ + sequence->chroma_height >>= 1; + /* fallthrough */ + case 4: /* 4:2:2 */ + sequence->chroma_width >>= 1; + } + + sequence->byte_rate += ((buffer[2]<<25) | (buffer[3]<<17)) & 0x3ffc0000; + + sequence->vbv_buffer_size |= buffer[4] << 21; + + sequence->frame_period = + sequence->frame_period * ((buffer[5]&31)+1) / (((buffer[5]>>2)&3)+1); + + mpeg2dec->ext_state = SEQ_DISPLAY_EXT; + + return 0; +} + +static int sequence_display_ext (mpeg2dec_t * mpeg2dec) +{ + uint8_t * buffer = mpeg2dec->chunk_start; + mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; + int x; + + sequence->flags = (sequence->flags & ~SEQ_MASK_VIDEO_FORMAT) | + ((buffer[0] << 4) & SEQ_MASK_VIDEO_FORMAT); + + if (buffer[0] & 1) + { + sequence->flags |= SEQ_FLAG_COLOUR_DESCRIPTION; + sequence->colour_primaries = buffer[1]; + sequence->transfer_characteristics = buffer[2]; + sequence->matrix_coefficients = buffer[3]; + buffer += 3; + } + + if (!(buffer[2] & 2)) /* missing marker_bit */ + return 1; + + x = (buffer[1] << 6) | (buffer[2] >> 2); + if (x) + sequence->display_width = x; + + x = ((buffer[2] & 1) << 13) | (buffer[3] << 5) | (buffer[4] >> 3); + if (x) + sequence->display_height = x; + + return 0; +} + +static inline void simplify (unsigned int * u, unsigned int * v) +{ + unsigned int a, b, tmp; + + a = *u; + b = *v; + + /* find greatest common divisor */ + while (a) + { + tmp = a; + a = b % tmp; + b = tmp; + } + + *u /= b; + *v /= b; +} + +static inline void finalize_sequence (mpeg2_sequence_t * sequence) +{ + int width; + int height; + + sequence->byte_rate *= 50; + + if (sequence->flags & SEQ_FLAG_MPEG2) + { + switch (sequence->pixel_width) + { + case 1: /* square pixels */ + sequence->pixel_width = + sequence->pixel_height = 1; + return; + case 2: /* 4:3 aspect ratio */ + width = 4; + height = 3; + break; + case 3: /* 16:9 aspect ratio */ + width = 16; + height = 9; + break; + case 4: /* 2.21:1 aspect ratio */ + width = 221; + height = 100; + break; + default: /* illegal */ + sequence->pixel_width = + sequence->pixel_height = 0; + return; + } + + width *= sequence->display_height; + height *= sequence->display_width; + } + else + { + if (sequence->byte_rate == 50 * 0x3ffff) + sequence->byte_rate = 0; /* mpeg-1 VBR */ + + switch (sequence->pixel_width) + { + case 0: + case 15: /* illegal */ + sequence->pixel_width = + sequence->pixel_height = 0; + return; + case 1: /* square pixels */ + sequence->pixel_width = + sequence->pixel_height = 1; + return; + case 3: /* 720x576 16:9 */ + sequence->pixel_width = 64; + sequence->pixel_height = 45; + return; + case 6: /* 720x480 16:9 */ + sequence->pixel_width = 32; + sequence->pixel_height = 27; + return; + case 8: /* BT.601 625 lines 4:3 */ + sequence->pixel_width = 59; + sequence->pixel_height = 54; + return; + case 12: /* BT.601 525 lines 4:3 */ + sequence->pixel_width = 10; + sequence->pixel_height = 11; + return; + default: + height = 88 * sequence->pixel_width + 1171; + width = 2000; + } + } + + sequence->pixel_width = width; + sequence->pixel_height = height; + + simplify(&sequence->pixel_width, &sequence->pixel_height); +} + +int mpeg2_guess_aspect (const mpeg2_sequence_t * sequence, + unsigned int * pixel_width, + unsigned int * pixel_height) +{ + static const struct + { + unsigned int width, height; + } video_modes[] = + { + {720, 576}, /* 625 lines, 13.5 MHz (D1, DV, DVB, DVD) */ + {704, 576}, /* 625 lines, 13.5 MHz (1/1 D1, DVB, DVD, 4CIF) */ + {544, 576}, /* 625 lines, 10.125 MHz (DVB, laserdisc) */ + {528, 576}, /* 625 lines, 10.125 MHz (3/4 D1, DVB, laserdisc) */ + {480, 576}, /* 625 lines, 9 MHz (2/3 D1, DVB, SVCD) */ + {352, 576}, /* 625 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVB, DVD) */ + {352, 288}, /* 625 lines, 6.75 MHz, 1 field (D4, VCD, DVB, DVD, CIF) */ + {176, 144}, /* 625 lines, 3.375 MHz, half field (QCIF) */ + {720, 486}, /* 525 lines, 13.5 MHz (D1) */ + {704, 486}, /* 525 lines, 13.5 MHz */ + {720, 480}, /* 525 lines, 13.5 MHz (DV, DSS, DVD) */ + {704, 480}, /* 525 lines, 13.5 MHz (1/1 D1, ATSC, DVD) */ + {544, 480}, /* 525 lines. 10.125 MHz (DSS, laserdisc) */ + {528, 480}, /* 525 lines. 10.125 MHz (3/4 D1, laserdisc) */ + {480, 480}, /* 525 lines, 9 MHz (2/3 D1, SVCD) */ + {352, 480}, /* 525 lines, 6.75 MHz (D2, 1/2 D1, CVD, DVD) */ + {352, 240} /* 525 lines. 6.75 MHz, 1 field (D4, VCD, DSS, DVD) */ + }; + unsigned int width, height, pix_width, pix_height, i, DAR_16_9; + + *pixel_width = sequence->pixel_width; + *pixel_height = sequence->pixel_height; + width = sequence->picture_width; + height = sequence->picture_height; + + for (i = 0; i < sizeof (video_modes) / sizeof (video_modes[0]); i++) + { + if (width == video_modes[i].width && height == video_modes[i].height) + break; + } + + if (i == ARRAYLEN(video_modes) || + (sequence->pixel_width == 1 && sequence->pixel_height == 1) || + width != sequence->display_width || height != sequence->display_height) + { + return 0; + } + + for (pix_height = 1; height * pix_height < 480; pix_height <<= 1); + height *= pix_height; + + for (pix_width = 1; width * pix_width <= 352; pix_width <<= 1); + width *= pix_width; + + if (!(sequence->flags & SEQ_FLAG_MPEG2)) + { + static unsigned int mpeg1_check[2][2] = {{11, 54}, {27, 45}}; + DAR_16_9 = (sequence->pixel_height == 27 || + sequence->pixel_height == 45); + if (width < 704 || + sequence->pixel_height != mpeg1_check[DAR_16_9][height == 576]) + return 0; + } + else + { + DAR_16_9 = (3 * sequence->picture_width * sequence->pixel_width > + 4 * sequence->picture_height * sequence->pixel_height); + switch (width) + { + case 528: + case 544: + pix_width *= 4; + pix_height *= 3; + break; + case 480: + pix_width *= 3; + pix_height *= 2; + break; + } + } + + if (DAR_16_9) + { + pix_width *= 4; + pix_height *= 3; + } + + if (height == 576) + { + pix_width *= 59; + pix_height *= 54; + } + else + { + pix_width *= 10; + pix_height *= 11; + } + + *pixel_width = pix_width; + *pixel_height = pix_height; + + simplify (pixel_width, pixel_height); + + return (height == 576) ? 1 : 2; +} + +static void copy_matrix (mpeg2dec_t * mpeg2dec, int index) +{ + if (rb->memcmp (mpeg2dec->quantizer_matrix[index], + mpeg2dec->new_quantizer_matrix[index], 64)) + { + rb->memcpy (mpeg2dec->quantizer_matrix[index], + mpeg2dec->new_quantizer_matrix[index], 64); + + mpeg2dec->scaled[index] = -1; + } +} + +static void finalize_matrix (mpeg2dec_t * mpeg2dec) +{ + mpeg2_decoder_t *decoder = &mpeg2dec->decoder; + int i; + + for (i = 0; i < 2; i++) + { + if (mpeg2dec->copy_matrix & (1 << i)) + copy_matrix (mpeg2dec, i); + + if ((mpeg2dec->copy_matrix & (4 << i)) && + rb->memcmp(mpeg2dec->quantizer_matrix[i], + mpeg2dec->new_quantizer_matrix[i+2], 64)) + { + copy_matrix (mpeg2dec, i + 2); + decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i+2]; + } + else if (mpeg2dec->copy_matrix & (5 << i)) + { + decoder->chroma_quantizer[i] = decoder->quantizer_prescale[i]; + } + } +} + +static mpeg2_state_t invalid_end_action (mpeg2dec_t * mpeg2dec) +{ + mpeg2_reset_info (&mpeg2dec->info); + + mpeg2dec->info.gop = NULL; + + info_user_data (mpeg2dec); + + mpeg2_header_state_init (mpeg2dec); + + mpeg2dec->sequence = mpeg2dec->new_sequence; + mpeg2dec->action = mpeg2_seek_header; + mpeg2dec->state = STATE_SEQUENCE; + + return STATE_SEQUENCE; +} + +void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec) +{ + mpeg2_sequence_t * sequence = &mpeg2dec->new_sequence; + mpeg2_decoder_t * decoder = &mpeg2dec->decoder; + + finalize_sequence(sequence); + finalize_matrix(mpeg2dec); + + decoder->mpeg1 = !(sequence->flags & SEQ_FLAG_MPEG2); + decoder->width = sequence->width; + decoder->height = sequence->height; + decoder->vertical_position_extension = sequence->picture_height > 2800; + decoder->chroma_format = (sequence->chroma_width == sequence->width) + + (sequence->chroma_height == sequence->height); + + if (mpeg2dec->sequence.width != (unsigned)-1) + { + /* + * According to 6.1.1.6, repeat sequence headers should be + * identical to the original. However some encoders don't + * respect that and change various fields (including bitrate + * and aspect ratio) in the repeat sequence headers. So we + * choose to be as conservative as possible and only restart + * the decoder if the width, height, chroma_width, + * chroma_height or low_delay flag are modified. + */ + if (sequence->width != mpeg2dec->sequence.width || + sequence->height != mpeg2dec->sequence.height || + sequence->chroma_width != mpeg2dec->sequence.chroma_width || + sequence->chroma_height != mpeg2dec->sequence.chroma_height || + ((sequence->flags ^ mpeg2dec->sequence.flags) & + SEQ_FLAG_LOW_DELAY)) + { + decoder->stride_frame = sequence->width; + mpeg2_header_end (mpeg2dec); + mpeg2dec->action = invalid_end_action; + mpeg2dec->state = STATE_INVALID_END; + return; + } + + mpeg2dec->state = rb->memcmp(&mpeg2dec->sequence, sequence, + sizeof (mpeg2_sequence_t)) ? + STATE_SEQUENCE_MODIFIED : + STATE_SEQUENCE_REPEATED; + } + else + { + decoder->stride_frame = sequence->width; + } + + mpeg2dec->sequence = *sequence; + mpeg2_reset_info(&mpeg2dec->info); + mpeg2dec->info.sequence = &mpeg2dec->sequence; + mpeg2dec->info.gop = NULL; + + info_user_data (mpeg2dec); +} + +int mpeg2_header_gop (mpeg2dec_t * mpeg2dec) +{ + uint8_t * buffer = mpeg2dec->chunk_start; + mpeg2_gop_t * gop = &mpeg2dec->new_gop; + + if (!(buffer[1] & 8)) + return 1; + + gop->hours = (buffer[0] >> 2) & 31; + gop->minutes = ((buffer[0] << 4) | (buffer[1] >> 4)) & 63; + gop->seconds = ((buffer[1] << 3) | (buffer[2] >> 5)) & 63; + gop->pictures = ((buffer[2] << 1) | (buffer[3] >> 7)) & 63; + gop->flags = (buffer[0] >> 7) | ((buffer[3] >> 4) & 6); + + mpeg2dec->state = STATE_GOP; + return 0; +} + +void mpeg2_header_gop_finalize (mpeg2dec_t * mpeg2dec) +{ + mpeg2dec->gop = mpeg2dec->new_gop; + mpeg2_reset_info (&mpeg2dec->info); + mpeg2dec->info.gop = &mpeg2dec->gop; + info_user_data (mpeg2dec); +} + +void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type) +{ + int i; + + for (i = 0; i < 3; i++) + { + if (mpeg2dec->fbuf[1] != &mpeg2dec->fbuf_alloc[i].fbuf && + mpeg2dec->fbuf[2] != &mpeg2dec->fbuf_alloc[i].fbuf) + { + mpeg2dec->fbuf[0] = &mpeg2dec->fbuf_alloc[i].fbuf; + mpeg2dec->info.current_fbuf = mpeg2dec->fbuf[0]; + + if (b_type || (mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY)) + { + if (b_type || mpeg2dec->convert) + mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[0]; + + mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[0]; + } + + break; + } + } +} + +int mpeg2_header_picture (mpeg2dec_t * mpeg2dec) +{ + uint8_t * buffer = mpeg2dec->chunk_start; + mpeg2_picture_t * picture = &mpeg2dec->new_picture; + mpeg2_decoder_t * decoder = &mpeg2dec->decoder; + int type; + + mpeg2dec->state = (mpeg2dec->state != STATE_SLICE_1ST) ? + STATE_PICTURE : STATE_PICTURE_2ND; + mpeg2dec->ext_state = PIC_CODING_EXT; + + picture->temporal_reference = (buffer[0] << 2) | (buffer[1] >> 6); + + type = (buffer [1] >> 3) & 7; + + if (type == PIC_FLAG_CODING_TYPE_P || type == PIC_FLAG_CODING_TYPE_B) + { + /* forward_f_code and backward_f_code - used in mpeg1 only */ + decoder->f_motion.f_code[1] = (buffer[3] >> 2) & 1; + decoder->f_motion.f_code[0] = + (((buffer[3] << 1) | (buffer[4] >> 7)) & 7) - 1; + decoder->b_motion.f_code[1] = (buffer[4] >> 6) & 1; + decoder->b_motion.f_code[0] = ((buffer[4] >> 3) & 7) - 1; + } + + picture->flags = PIC_FLAG_PROGRESSIVE_FRAME | type; + picture->tag = picture->tag2 = 0; + + if (mpeg2dec->num_tags) + { + if (mpeg2dec->bytes_since_tag >= mpeg2dec->chunk_ptr - buffer + 4) + { + mpeg2dec->num_tags = 0; + picture->tag = mpeg2dec->tag_current; + picture->tag2 = mpeg2dec->tag2_current; + picture->flags |= PIC_FLAG_TAGS; + } + else if (mpeg2dec->num_tags > 1) + { + mpeg2dec->num_tags = 1; + picture->tag = mpeg2dec->tag_previous; + picture->tag2 = mpeg2dec->tag2_previous; + picture->flags |= PIC_FLAG_TAGS; + } + } + + picture->nb_fields = 2; + picture->display_offset[0].x = picture->display_offset[1].x = + picture->display_offset[2].x = mpeg2dec->display_offset_x; + + picture->display_offset[0].y = picture->display_offset[1].y = + picture->display_offset[2].y = mpeg2dec->display_offset_y; + + /* XXXXXX decode extra_information_picture as well */ + + mpeg2dec->q_scale_type = 0; + decoder->intra_dc_precision = 7; + decoder->frame_pred_frame_dct = 1; + decoder->concealment_motion_vectors = 0; + decoder->scan = mpeg2_scan_norm; + decoder->picture_structure = FRAME_PICTURE; + mpeg2dec->copy_matrix = 0; + + return 0; +} + +static int picture_coding_ext (mpeg2dec_t * mpeg2dec) +{ + uint8_t * buffer = mpeg2dec->chunk_start; + mpeg2_picture_t * picture = &mpeg2dec->new_picture; + mpeg2_decoder_t * decoder = &mpeg2dec->decoder; + uint32_t flags; + + /* pre subtract 1 for use later in compute_motion_vector */ + decoder->f_motion.f_code[0] = (buffer[0] & 15) - 1; + decoder->f_motion.f_code[1] = (buffer[1] >> 4) - 1; + decoder->b_motion.f_code[0] = (buffer[1] & 15) - 1; + decoder->b_motion.f_code[1] = (buffer[2] >> 4) - 1; + + flags = picture->flags; + + decoder->intra_dc_precision = 7 - ((buffer[2] >> 2) & 3); + decoder->picture_structure = buffer[2] & 3; + + switch (decoder->picture_structure) + { + case TOP_FIELD: + flags |= PIC_FLAG_TOP_FIELD_FIRST; + case BOTTOM_FIELD: + picture->nb_fields = 1; + break; + case FRAME_PICTURE: + if (!(mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE)) + { + picture->nb_fields = (buffer[3] & 2) ? 3 : 2; + flags |= (buffer[3] & 128) ? PIC_FLAG_TOP_FIELD_FIRST : 0; + } + else + { + picture->nb_fields = (buffer[3]&2) ? ((buffer[3]&128) ? 6 : 4) : 2; + } + break; + default: + return 1; + } + + decoder->top_field_first = buffer[3] >> 7; + decoder->frame_pred_frame_dct = (buffer[3] >> 6) & 1; + decoder->concealment_motion_vectors = (buffer[3] >> 5) & 1; + mpeg2dec->q_scale_type = buffer[3] & 16; + decoder->intra_vlc_format = (buffer[3] >> 3) & 1; + decoder->scan = (buffer[3] & 4) ? mpeg2_scan_alt : mpeg2_scan_norm; + + if (!(buffer[4] & 0x80)) + flags &= ~PIC_FLAG_PROGRESSIVE_FRAME; + + if (buffer[4] & 0x40) + { + flags |= (((buffer[4]<<26) | (buffer[5]<<18) | (buffer[6]<<10)) & + PIC_MASK_COMPOSITE_DISPLAY) | PIC_FLAG_COMPOSITE_DISPLAY; + } + + picture->flags = flags; + + mpeg2dec->ext_state = PIC_DISPLAY_EXT | COPYRIGHT_EXT | QUANT_MATRIX_EXT; + + return 0; +} + +static int picture_display_ext (mpeg2dec_t * mpeg2dec) +{ + uint8_t * buffer = mpeg2dec->chunk_start; + mpeg2_picture_t * picture = &mpeg2dec->new_picture; + int i, nb_pos; + + nb_pos = picture->nb_fields; + + if (mpeg2dec->sequence.flags & SEQ_FLAG_PROGRESSIVE_SEQUENCE) + nb_pos >>= 1; + + for (i = 0; i < nb_pos; i++) + { + int x, y; + + x = ((buffer[4*i] << 24) | (buffer[4*i+1] << 16) | + (buffer[4*i+2] << 8) | buffer[4*i+3]) >> (11-2*i); + + y = ((buffer[4*i+2] << 24) | (buffer[4*i+3] << 16) | + (buffer[4*i+4] << 8) | buffer[4*i+5]) >> (10-2*i); + + if (! (x & y & 1)) + return 1; + + picture->display_offset[i].x = mpeg2dec->display_offset_x = x >> 1; + picture->display_offset[i].y = mpeg2dec->display_offset_y = y >> 1; + } + + for (; i < 3; i++) + { + picture->display_offset[i].x = mpeg2dec->display_offset_x; + picture->display_offset[i].y = mpeg2dec->display_offset_y; + } + + return 0; +} + +void mpeg2_header_picture_finalize (mpeg2dec_t * mpeg2dec) +{ + mpeg2_decoder_t * decoder = &mpeg2dec->decoder; + int old_type_b = decoder->coding_type == B_TYPE; + int low_delay = mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY; + + finalize_matrix (mpeg2dec); + decoder->coding_type = mpeg2dec->new_picture.flags & PIC_MASK_CODING_TYPE; + + if (mpeg2dec->state == STATE_PICTURE) + { + mpeg2_picture_t * picture; + mpeg2_picture_t * other; + + decoder->second_field = 0; + + picture = other = mpeg2dec->pictures; + + if (old_type_b ^ (mpeg2dec->picture < mpeg2dec->pictures + 2)) + picture += 2; + else + other += 2; + + mpeg2dec->picture = picture; + *picture = mpeg2dec->new_picture; + + if (!old_type_b) + { + mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; + mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; + } + + mpeg2dec->fbuf[0] = NULL; + mpeg2_reset_info (&mpeg2dec->info); + mpeg2dec->info.current_picture = picture; + mpeg2dec->info.display_picture = picture; + + if (decoder->coding_type != B_TYPE) + { + if (!low_delay) + { + if (mpeg2dec->first) + { + mpeg2dec->info.display_picture = NULL; + mpeg2dec->first = 0; + } + else + { + mpeg2dec->info.display_picture = other; + + if (other->nb_fields == 1) + mpeg2dec->info.display_picture_2nd = other + 1; + + mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[1]; + } + } + + if (!low_delay + !mpeg2dec->convert) + { + mpeg2dec->info.discard_fbuf = + mpeg2dec->fbuf[!low_delay + !mpeg2dec->convert]; + } + } + + if (mpeg2dec->convert) + { + mpeg2_convert_init_t convert_init; + + if (!mpeg2dec->convert_start) + { + mpeg2dec->decoder.convert_id = + mpeg2_malloc (mpeg2dec->convert_id_size, + MPEG2_ALLOC_CONVERT_ID); + + mpeg2dec->convert (MPEG2_CONVERT_START, + mpeg2dec->decoder.convert_id, + &mpeg2dec->sequence, + mpeg2dec->convert_stride, + mpeg2dec->convert_arg, &convert_init); + + mpeg2dec->convert_start = convert_init.start; + mpeg2dec->decoder.convert = convert_init.copy; + + int y_size = decoder->stride_frame * mpeg2dec->sequence.height; + + mpeg2dec->yuv_buf[0][0] = + (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV); +#if MPEG2_COLOR + int uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format); + + mpeg2dec->yuv_buf[0][1] = + (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); + mpeg2dec->yuv_buf[0][2] = + (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); +#endif + + mpeg2dec->yuv_buf[1][0] = + (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV); +#if MPEG2_COLOR + mpeg2dec->yuv_buf[1][1] = + (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); + mpeg2dec->yuv_buf[1][2] = + (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); +#endif + y_size = decoder->stride_frame * 32; + + mpeg2dec->yuv_buf[2][0] = + (uint8_t *) mpeg2_malloc(y_size, MPEG2_ALLOC_YUV); +#if MPEG2_COLOR + uv_size = y_size >> (2 - mpeg2dec->decoder.chroma_format); + + mpeg2dec->yuv_buf[2][1] = + (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); + mpeg2dec->yuv_buf[2][2] = + (uint8_t *) mpeg2_malloc(uv_size, MPEG2_ALLOC_YUV); +#endif + } + + if (!mpeg2dec->custom_fbuf) + { + while (mpeg2dec->alloc_index < 3) + { + mpeg2_fbuf_t * fbuf; + + fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf; + fbuf->id = NULL; + + fbuf->buf[0] = + (uint8_t *) mpeg2_malloc (convert_init.buf_size[0], + MPEG2_ALLOC_CONVERTED); +#if MPEG2_COLOR + fbuf->buf[1] = + (uint8_t *) mpeg2_malloc (convert_init.buf_size[1], + MPEG2_ALLOC_CONVERTED); + fbuf->buf[2] = + (uint8_t *) mpeg2_malloc (convert_init.buf_size[2], + MPEG2_ALLOC_CONVERTED); +#endif + } + + mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE)); + } + } + else if (!mpeg2dec->custom_fbuf) + { + while (mpeg2dec->alloc_index < 3) + { + mpeg2_fbuf_t * fbuf; + + fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index++].fbuf; + + fbuf->id = NULL; + + int y_size = decoder->stride_frame * mpeg2dec->sequence.height; + + fbuf->buf[0] = (uint8_t *) mpeg2_malloc (y_size, + MPEG2_ALLOC_YUV); +#if MPEG2_COLOR + int uv_size = y_size >> (2 - decoder->chroma_format); + + fbuf->buf[1] = (uint8_t *) mpeg2_malloc (uv_size, + MPEG2_ALLOC_YUV); + fbuf->buf[2] = (uint8_t *) mpeg2_malloc (uv_size, + MPEG2_ALLOC_YUV); +#endif + } + + mpeg2_set_fbuf (mpeg2dec, (decoder->coding_type == B_TYPE)); + } + } + else + { + decoder->second_field = 1; + mpeg2dec->picture++; /* second field picture */ + + *(mpeg2dec->picture) = mpeg2dec->new_picture; + + mpeg2dec->info.current_picture_2nd = mpeg2dec->picture; + + if (low_delay || decoder->coding_type == B_TYPE) + mpeg2dec->info.display_picture_2nd = mpeg2dec->picture; + } + + info_user_data (mpeg2dec); +} + +static int copyright_ext (mpeg2dec_t * mpeg2dec) +{ + (void)mpeg2dec; + return 0; +} + +static int quant_matrix_ext (mpeg2dec_t * mpeg2dec) +{ + uint8_t * buffer = mpeg2dec->chunk_start; + int i, j; + + for (i = 0; i < 4; i++) + { + if (buffer[0] & (8 >> i)) + { + for (j = 0; j < 64; j++) + { + mpeg2dec->new_quantizer_matrix[i][mpeg2_scan_norm[j]] = + (buffer[j] << (i+5)) | (buffer[j+1] >> (3-i)); + } + + mpeg2dec->copy_matrix |= 1 << i; + buffer += 64; + } + } + + return 0; +} + +int mpeg2_header_extension (mpeg2dec_t * mpeg2dec) +{ + static int (* const parser[9]) (mpeg2dec_t *) = + { + NULL, + sequence_ext, + sequence_display_ext, + quant_matrix_ext, + copyright_ext, + NULL, + NULL, + picture_display_ext, + picture_coding_ext + }; + + int ext, ext_bit; + + ext = mpeg2dec->chunk_start[0] >> 4; + ext_bit = 1 << ext; + + if (!(mpeg2dec->ext_state & ext_bit)) + return 0; /* ignore illegal extensions */ + + mpeg2dec->ext_state &= ~ext_bit; + + return parser[ext] (mpeg2dec); +} + +int mpeg2_header_user_data (mpeg2dec_t * mpeg2dec) +{ + mpeg2dec->user_data_len += mpeg2dec->chunk_ptr - 1 - mpeg2dec->chunk_start; + mpeg2dec->chunk_start = mpeg2dec->chunk_ptr - 1; + + return 0; +} + +static void prescale (mpeg2dec_t * mpeg2dec, int index) +{ + static const int non_linear_scale[32] = + { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 18, 20, 22, + 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 104, 112 + }; + + int i, j, k; + mpeg2_decoder_t * decoder = &mpeg2dec->decoder; + + if (mpeg2dec->scaled[index] != mpeg2dec->q_scale_type) + { + mpeg2dec->scaled[index] = mpeg2dec->q_scale_type; + + for (i = 0; i < 32; i++) + { + k = mpeg2dec->q_scale_type ? non_linear_scale[i] : (i << 1); + + for (j = 0; j < 64; j++) + { + decoder->quantizer_prescale[index][i][j] = + k * mpeg2dec->quantizer_matrix[index][j]; + } + } + } +} + +mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec) +{ + mpeg2_decoder_t * decoder = &mpeg2dec->decoder; + + mpeg2dec->info.user_data = NULL; + mpeg2dec->info.user_data_len = 0; + mpeg2dec->state = (mpeg2dec->picture->nb_fields > 1 || + mpeg2dec->state == STATE_PICTURE_2ND) ? + STATE_SLICE : STATE_SLICE_1ST; + + if (mpeg2dec->decoder.coding_type != D_TYPE) + { + prescale (mpeg2dec, 0); + + if (decoder->chroma_quantizer[0] == decoder->quantizer_prescale[2]) + prescale (mpeg2dec, 2); + + if (mpeg2dec->decoder.coding_type != I_TYPE) + { + prescale (mpeg2dec, 1); + + if (decoder->chroma_quantizer[1] == decoder->quantizer_prescale[3]) + prescale (mpeg2dec, 3); + } + } + + if (!(mpeg2dec->nb_decode_slices)) + { + mpeg2dec->picture->flags |= PIC_FLAG_SKIP; + } + else if (mpeg2dec->convert_start) + { + mpeg2dec->convert_start (decoder->convert_id, mpeg2dec->fbuf[0], + mpeg2dec->picture, mpeg2dec->info.gop); + + if (mpeg2dec->decoder.coding_type == B_TYPE) + { + mpeg2_init_fbuf (&mpeg2dec->decoder, mpeg2dec->yuv_buf[2], + mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1], + mpeg2dec->yuv_buf[mpeg2dec->yuv_index]); + } + else + { + mpeg2_init_fbuf (&mpeg2dec->decoder, + mpeg2dec->yuv_buf[mpeg2dec->yuv_index ^ 1], + mpeg2dec->yuv_buf[mpeg2dec->yuv_index], + mpeg2dec->yuv_buf[mpeg2dec->yuv_index]); + + if (mpeg2dec->state == STATE_SLICE) + mpeg2dec->yuv_index ^= 1; + } + } + else + { + int b_type; + + b_type = (mpeg2dec->decoder.coding_type == B_TYPE); + + mpeg2_init_fbuf (&mpeg2dec->decoder, mpeg2dec->fbuf[0]->buf, + mpeg2dec->fbuf[b_type + 1]->buf, + mpeg2dec->fbuf[b_type]->buf); + } + + mpeg2dec->action = NULL; + + return STATE_INTERNAL_NORETURN; +} + +static mpeg2_state_t seek_sequence (mpeg2dec_t * mpeg2dec) +{ + mpeg2_reset_info (&mpeg2dec->info); + + mpeg2dec->info.sequence = NULL; + mpeg2dec->info.gop = NULL; + + mpeg2_header_state_init (mpeg2dec); + + mpeg2dec->action = mpeg2_seek_header; + + return mpeg2_seek_header (mpeg2dec); +} + +mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec) +{ + mpeg2_picture_t * picture; + int b_type; + + b_type = (mpeg2dec->decoder.coding_type == B_TYPE); + picture = mpeg2dec->pictures; + + if ((mpeg2dec->picture >= picture + 2) ^ b_type) + picture = mpeg2dec->pictures + 2; + + mpeg2_reset_info (&mpeg2dec->info); + + if (!(mpeg2dec->sequence.flags & SEQ_FLAG_LOW_DELAY)) + { + mpeg2dec->info.display_picture = picture; + + if (picture->nb_fields == 1) + mpeg2dec->info.display_picture_2nd = picture + 1; + + mpeg2dec->info.display_fbuf = mpeg2dec->fbuf[b_type]; + + if (!mpeg2dec->convert) + mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type + 1]; + } + else if (!mpeg2dec->convert) + { + mpeg2dec->info.discard_fbuf = mpeg2dec->fbuf[b_type]; + } + + mpeg2dec->action = seek_sequence; + + return STATE_END; +} diff --git a/apps/plugins/mpegplayer/libmpeg2/idct.c b/apps/plugins/mpegplayer/libmpeg2/idct.c 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.36 + */ + +#include "plugin.h" + +#include "mpeg2dec_config.h" + +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" + +#if defined(CPU_COLDFIRE) || defined (CPU_ARM) +#define IDCT_ASM +#endif + +#ifndef IDCT_ASM + +#define W1 2841 /* 2048 * sqrt (2) * cos (1 * pi / 16) */ +#define W2 2676 /* 2048 * sqrt (2) * cos (2 * pi / 16) */ +#define W3 2408 /* 2048 * sqrt (2) * cos (3 * pi / 16) */ +#define W5 1609 /* 2048 * sqrt (2) * cos (5 * pi / 16) */ +#define W6 1108 /* 2048 * sqrt (2) * cos (6 * pi / 16) */ +#define W7 565 /* 2048 * sqrt (2) * cos (7 * pi / 16) */ + +/* + * In legal streams, the IDCT output should be between -384 and +384. + * In corrupted streams, it is possible to force the IDCT output to go + * to +-3826 - this is the worst case for a column IDCT where the + * column inputs are 16-bit values. + */ +#define CLIP(i) \ + ({ typeof (i) _i = (i); \ + if ((_i & 0xff) != _i) \ + _i = ~(_i >> (8*sizeof(_i) - 1)); \ + _i; }) + +#if 0 +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ + do { \ + t0 = W0 * d0 + W1 * d1; \ + t1 = W0 * d1 - W1 * d0; \ + } while (0) +#else +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ + do { \ + int tmp = W0 * (d0 + d1); \ + t0 = tmp + (W1 - W0) * d1; \ + t1 = tmp - (W1 + W0) * d0; \ + } while (0) +#endif + +static inline void idct_row (int16_t * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + /* shortcut */ + if (likely (!(block[1] | ((int32_t *)block)[1] | ((int32_t *)block)[2] | + ((int32_t *)block)[3]))) + { + uint32_t tmp = (uint16_t) (block[0] >> 1); + tmp |= tmp << 16; + ((int32_t *)block)[0] = tmp; + ((int32_t *)block)[1] = tmp; + ((int32_t *)block)[2] = tmp; + ((int32_t *)block)[3] = tmp; + return; + } + + d0 = (block[0] << 11) + 2048; + d1 = block[1]; + d2 = block[2] << 11; + d3 = block[3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[4]; + d1 = block[5]; + d2 = block[6]; + d3 = block[7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 -= t2; + t1 -= t3; + b1 = ((t0 + t1) >> 8) * 181; + b2 = ((t0 - t1) >> 8) * 181; + + block[0] = (a0 + b0) >> 12; + block[1] = (a1 + b1) >> 12; + block[2] = (a2 + b2) >> 12; + block[3] = (a3 + b3) >> 12; + block[4] = (a3 - b3) >> 12; + block[5] = (a2 - b2) >> 12; + block[6] = (a1 - b1) >> 12; + block[7] = (a0 - b0) >> 12; +} + +static inline void idct_col (int16_t * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + d0 = (block[8*0] << 11) + 65536; + d1 = block[8*1]; + d2 = block[8*2] << 11; + d3 = block[8*3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[8*4]; + d1 = block[8*5]; + d2 = block[8*6]; + d3 = block[8*7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 -= t2; + t1 -= t3; + b1 = ((t0 + t1) >> 8) * 181; + b2 = ((t0 - t1) >> 8) * 181; + + block[8*0] = (a0 + b0) >> 17; + block[8*1] = (a1 + b1) >> 17; + block[8*2] = (a2 + b2) >> 17; + block[8*3] = (a3 + b3) >> 17; + block[8*4] = (a3 - b3) >> 17; + block[8*5] = (a2 - b2) >> 17; + block[8*6] = (a1 - b1) >> 17; + block[8*7] = (a0 - b0) >> 17; +} + +void mpeg2_idct_copy (int16_t * block, uint8_t * dest, + const int stride) +{ + int i; + + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + + for (i = 0; i < 8; i++) + idct_col (block + i); + + do + { + dest[0] = CLIP (block[0]); + dest[1] = CLIP (block[1]); + dest[2] = CLIP (block[2]); + dest[3] = CLIP (block[3]); + dest[4] = CLIP (block[4]); + dest[5] = CLIP (block[5]); + dest[6] = CLIP (block[6]); + dest[7] = CLIP (block[7]); + + ((int32_t *)block)[0] = 0; + ((int32_t *)block)[1] = 0; + ((int32_t *)block)[2] = 0; + ((int32_t *)block)[3] = 0; + + dest += stride; + block += 8; + } + while (--i); +} + +void mpeg2_idct_add (const int last, int16_t * block, + uint8_t * dest, const int stride) +{ + int i; + + if (last != 129 || (block[0] & (7 << 4)) == (4 << 4)) + { + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + + for (i = 0; i < 8; i++) + idct_col (block + i); + + do + { + dest[0] = CLIP (block[0] + dest[0]); + dest[1] = CLIP (block[1] + dest[1]); + dest[2] = CLIP (block[2] + dest[2]); + dest[3] = CLIP (block[3] + dest[3]); + dest[4] = CLIP (block[4] + dest[4]); + dest[5] = CLIP (block[5] + dest[5]); + dest[6] = CLIP (block[6] + dest[6]); + dest[7] = CLIP (block[7] + dest[7]); + + ((int32_t *)block)[0] = 0; + ((int32_t *)block)[1] = 0; + ((int32_t *)block)[2] = 0; + ((int32_t *)block)[3] = 0; + + dest += stride; + block += 8; + } + while (--i); + } + else + { + int DC = (block[0] + 64) >> 7; + block[0] = block[63] = 0; + i = 8; + + do + { + dest[0] = CLIP (DC + dest[0]); + dest[1] = CLIP (DC + dest[1]); + dest[2] = CLIP (DC + dest[2]); + dest[3] = CLIP (DC + dest[3]); + dest[4] = CLIP (DC + dest[4]); + dest[5] = CLIP (DC + dest[5]); + dest[6] = CLIP (DC + dest[6]); + dest[7] = CLIP (DC + dest[7]); + dest += stride; + } + while (--i); + } +} + +#endif /* IDCT_ASM */ + +void mpeg2_idct_init (void) +{ + int i, j; + + for (i = 0; i < 64; i++) + { + j = default_mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + + j = default_mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } +} diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_arm.S b/apps/plugins/mpegplayer/libmpeg2/idct_arm.S 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.17 - lost compatibility previously to + * provide simplified and CPU-optimized motion compensation. + */ + +#include "plugin.h" + +#include "mpeg2dec_config.h" + +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" + +/* These are defined in their respective target files - motion_comp_X.c */ +extern mpeg2_mc_fct MC_put_o_16; +extern mpeg2_mc_fct MC_put_o_8; +extern mpeg2_mc_fct MC_put_x_16; +extern mpeg2_mc_fct MC_put_x_8; +extern mpeg2_mc_fct MC_put_y_16; +extern mpeg2_mc_fct MC_put_y_8; +extern mpeg2_mc_fct MC_put_xy_16; +extern mpeg2_mc_fct MC_put_xy_8; + +extern mpeg2_mc_fct MC_avg_o_16; +extern mpeg2_mc_fct MC_avg_o_8; +extern mpeg2_mc_fct MC_avg_x_16; +extern mpeg2_mc_fct MC_avg_x_8; +extern mpeg2_mc_fct MC_avg_y_16; +extern mpeg2_mc_fct MC_avg_y_8; +extern mpeg2_mc_fct MC_avg_xy_16; +extern mpeg2_mc_fct MC_avg_xy_8; + +const mpeg2_mc_t mpeg2_mc = +{ + { + MC_put_o_16, MC_put_x_16, MC_put_y_16, MC_put_xy_16, + MC_put_o_8, MC_put_x_8, MC_put_y_8, MC_put_xy_8 + }, + { + MC_avg_o_16, MC_avg_x_16, MC_avg_y_16, MC_avg_xy_16, + MC_avg_o_8, MC_avg_x_8, MC_avg_y_8, MC_avg_xy_8 + } +}; diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp.h b/apps/plugins/mpegplayer/libmpeg2/motion_comp.h 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + + +#define avg2(a,b) ((a+b+1)>>1) +#define avg4(a,b,c,d) ((a+b+c+d+2)>>2) + +#define predict_o(i) (ref[i]) +#define predict_x(i) (avg2 (ref[i], ref[i+1])) +#define predict_y(i) (avg2 (ref[i], (ref+stride)[i])) +#define predict_xy(i) (avg4 (ref[i], ref[i+1], \ + (ref+stride)[i], (ref+stride)[i+1])) + +#define put(predictor,i) dest[i] = predictor (i) +#define avg(predictor,i) dest[i] = avg2 (predictor (i), dest[i]) + +/* mc function template */ +#define MC_FUNC(op, xy) \ + MC_FUNC_16(op, xy) \ + MC_FUNC_8(op, xy) + +#define MC_FUNC_16(op, xy) \ + void MC_##op##_##xy##_16 (uint8_t * dest, const uint8_t * ref, \ + const int stride, int height) \ + { \ + do { \ + op (predict_##xy, 0); \ + op (predict_##xy, 1); \ + op (predict_##xy, 2); \ + op (predict_##xy, 3); \ + op (predict_##xy, 4); \ + op (predict_##xy, 5); \ + op (predict_##xy, 6); \ + op (predict_##xy, 7); \ + op (predict_##xy, 8); \ + op (predict_##xy, 9); \ + op (predict_##xy, 10); \ + op (predict_##xy, 11); \ + op (predict_##xy, 12); \ + op (predict_##xy, 13); \ + op (predict_##xy, 14); \ + op (predict_##xy, 15); \ + ref += stride; \ + dest += stride; \ + } while (--height); \ + } + +#define MC_FUNC_8(op, xy) \ + void MC_##op##_##xy##_8 (uint8_t * dest, const uint8_t * ref, \ + const int stride, int height) \ + { \ + do { \ + op (predict_##xy, 0); \ + op (predict_##xy, 1); \ + op (predict_##xy, 2); \ + op (predict_##xy, 3); \ + op (predict_##xy, 4); \ + op (predict_##xy, 5); \ + op (predict_##xy, 6); \ + op (predict_##xy, 7); \ + ref += stride; \ + dest += stride; \ + } while (--height); \ + } diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_c.c 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 + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ +#include +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" +#include "motion_comp.h" + +/* definitions of the actual mc functions */ + +/* MC_FUNC (put, o) <= ASM */ +MC_FUNC (avg, o) +/* MC_FUNC (put, x) <= ASM */ +MC_FUNC (avg, x) +MC_FUNC (put, y) +MC_FUNC (avg, y) +MC_FUNC (put, xy) +MC_FUNC (avg, xy) diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S b/apps/plugins/mpegplayer/libmpeg2/motion_comp_arm_s.S 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 +@ +@ 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ +#include +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" +#include "motion_comp.h" + +/* definitions of the actual mc functions */ + +MC_FUNC (put, o) +MC_FUNC (avg, o) +MC_FUNC (put, x) +MC_FUNC (avg, x) +MC_FUNC (put, y) +MC_FUNC (avg, y) +MC_FUNC (put, xy) +MC_FUNC (avg, xy) diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_c.c 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 + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" +#include "motion_comp.h" + +/* definitions of the actual mc functions */ + +/* MC_FUNC (put, o) <= ASM */ +MC_FUNC (avg, o) +/* MC_FUNC (put, x) <= ASM */ +MC_FUNC (avg, x) +MC_FUNC (put, y) +MC_FUNC (avg, y) +MC_FUNC (put, xy) +MC_FUNC (avg, xy) diff --git a/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S b/apps/plugins/mpegplayer/libmpeg2/motion_comp_coldfire_s.S 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.67 + */ + +#ifndef MPEG2_H +#define MPEG2_H + +#include "mpeg2dec_config.h" + +#define MPEG2_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c)) +#define MPEG2_RELEASE MPEG2_VERSION (0, 5, 0) /* 0.5.0 */ + +#define SEQ_FLAG_MPEG2 1 +#define SEQ_FLAG_CONSTRAINED_PARAMETERS 2 +#define SEQ_FLAG_PROGRESSIVE_SEQUENCE 4 +#define SEQ_FLAG_LOW_DELAY 8 +#define SEQ_FLAG_COLOUR_DESCRIPTION 16 + +#define SEQ_MASK_VIDEO_FORMAT 0xe0 +#define SEQ_VIDEO_FORMAT_COMPONENT 0x00 +#define SEQ_VIDEO_FORMAT_PAL 0x20 +#define SEQ_VIDEO_FORMAT_NTSC 0x40 +#define SEQ_VIDEO_FORMAT_SECAM 0x60 +#define SEQ_VIDEO_FORMAT_MAC 0x80 +#define SEQ_VIDEO_FORMAT_UNSPECIFIED 0xa0 + +typedef struct mpeg2_sequence_s +{ + unsigned int width, height; + unsigned int chroma_width, chroma_height; + unsigned int byte_rate; + unsigned int vbv_buffer_size; + uint32_t flags; + + unsigned int picture_width, picture_height; + unsigned int display_width, display_height; + unsigned int pixel_width, pixel_height; + unsigned int frame_period; + + uint8_t profile_level_id; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; +} mpeg2_sequence_t; + +#define GOP_FLAG_DROP_FRAME 1 +#define GOP_FLAG_BROKEN_LINK 2 +#define GOP_FLAG_CLOSED_GOP 4 + +typedef struct mpeg2_gop_s +{ + uint8_t hours; + uint8_t minutes; + uint8_t seconds; + uint8_t pictures; + uint32_t flags; +} mpeg2_gop_t; + +#define PIC_MASK_CODING_TYPE 7 +#define PIC_FLAG_CODING_TYPE_I 1 +#define PIC_FLAG_CODING_TYPE_P 2 +#define PIC_FLAG_CODING_TYPE_B 3 +#define PIC_FLAG_CODING_TYPE_D 4 + +#define PIC_FLAG_TOP_FIELD_FIRST 8 +#define PIC_FLAG_PROGRESSIVE_FRAME 16 +#define PIC_FLAG_COMPOSITE_DISPLAY 32 +#define PIC_FLAG_SKIP 64 +#define PIC_FLAG_TAGS 128 +#define PIC_MASK_COMPOSITE_DISPLAY 0xfffff000 + +typedef struct mpeg2_picture_s +{ + unsigned int temporal_reference; + unsigned int nb_fields; + uint32_t tag, tag2; + uint32_t flags; + struct + { + int x, y; + } display_offset[3]; +} mpeg2_picture_t; + +typedef struct mpeg2_fbuf_s +{ + uint8_t * buf[MPEG2_COMPONENTS]; + void * id; +} mpeg2_fbuf_t; + +typedef struct mpeg2_info_s +{ + const mpeg2_sequence_t * sequence; + const mpeg2_gop_t * gop; + const mpeg2_picture_t * current_picture; + const mpeg2_picture_t * current_picture_2nd; + const mpeg2_fbuf_t * current_fbuf; + const mpeg2_picture_t * display_picture; + const mpeg2_picture_t * display_picture_2nd; + const mpeg2_fbuf_t * display_fbuf; + const mpeg2_fbuf_t * discard_fbuf; + const uint8_t * user_data; + unsigned int user_data_len; +} mpeg2_info_t; + +typedef struct mpeg2dec_s mpeg2dec_t; +typedef struct mpeg2_decoder_s mpeg2_decoder_t; + +typedef enum +{ + STATE_INTERNAL_NORETURN = -1, + STATE_BUFFER = 0, + STATE_SEQUENCE = 1, + STATE_SEQUENCE_REPEATED = 2, + STATE_SEQUENCE_MODIFIED = 3, + STATE_GOP = 4, + STATE_PICTURE = 5, + STATE_SLICE_1ST = 6, + STATE_PICTURE_2ND = 7, + STATE_SLICE = 8, + STATE_END = 9, + STATE_INVALID = 10, + STATE_INVALID_END = 11, +} mpeg2_state_t; + +typedef struct mpeg2_convert_init_s +{ + unsigned int id_size; + unsigned int buf_size[MPEG2_COMPONENTS]; + void (* start)(void * id, const mpeg2_fbuf_t * fbuf, + const mpeg2_picture_t * picture, const mpeg2_gop_t * gop); + void (* copy)(void * id, uint8_t * const * src, unsigned int v_offset); +} mpeg2_convert_init_t; + +typedef enum +{ + MPEG2_CONVERT_SET = 0, + MPEG2_CONVERT_STRIDE = 1, + MPEG2_CONVERT_START = 2 +} mpeg2_convert_stage_t; + +typedef int mpeg2_convert_t (int stage, void * id, + const mpeg2_sequence_t * sequence, int stride, + void * arg, mpeg2_convert_init_t * result); +int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg); +int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride); +void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[MPEG2_COMPONENTS], + void * id); +void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf); + +mpeg2dec_t * mpeg2_init (void); +const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec); +void mpeg2_close (mpeg2dec_t * mpeg2dec); + +void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end); +int mpeg2_getpos (mpeg2dec_t * mpeg2dec); +mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec); + +void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset); +void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip); +void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end); + +void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2); + +void mpeg2_init_fbuf (mpeg2_decoder_t * decoder, + uint8_t * current_fbuf[MPEG2_COMPONENTS], + uint8_t * forward_fbuf[MPEG2_COMPONENTS], + uint8_t * backward_fbuf[MPEG2_COMPONENTS]); +void mpeg2_slice (mpeg2_decoder_t * decoder, int code, const uint8_t * buffer); + +int mpeg2_guess_aspect (const mpeg2_sequence_t * sequence, + unsigned int * pixel_width, + unsigned int * pixel_height); + +typedef enum +{ + MPEG2_ALLOC_MPEG2DEC = 0, + MPEG2_ALLOC_CHUNK = 1, + MPEG2_ALLOC_YUV = 2, + MPEG2_ALLOC_CONVERT_ID = 3, + MPEG2_ALLOC_CONVERTED = 4, + MPEG_ALLOC_CODEC_MALLOC, + MPEG_ALLOC_CODEC_CALLOC, + MPEG_ALLOC_MPEG2_BUFFER, + MPEG_ALLOC_AUDIOBUF, + MPEG_ALLOC_PCMOUT, + MPEG_ALLOC_DISKBUF, + __MPEG_ALLOC_FIRST = -256, +} mpeg2_alloc_t; + +void * mpeg2_malloc (unsigned size, mpeg2_alloc_t reason); +#if 0 +void mpeg2_free (void * buf); +#endif +/* allocates a dedicated buffer and locks all previous allocation in place */ +void * mpeg2_bufalloc(unsigned size, mpeg2_alloc_t reason); +/* clears all non-dedicated buffer space */ +void mpeg2_mem_reset(void); +void mpeg2_alloc_init(unsigned char* buf, int mallocsize); + +#endif /* MPEG2_H */ diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2_internal.h 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.89 + */ +#ifndef MPEG2_INTERNAL_H +#define MPEG2_INTERNAL_H + +#include "config.h" /* for Rockbox CPU_ #defines */ + +/* macroblock modes */ +#define MACROBLOCK_INTRA 1 +#define MACROBLOCK_PATTERN 2 +#define MACROBLOCK_MOTION_BACKWARD 4 +#define MACROBLOCK_MOTION_FORWARD 8 +#define MACROBLOCK_QUANT 16 +#define DCT_TYPE_INTERLACED 32 +/* motion_type */ +#define MOTION_TYPE_SHIFT 6 +#define MC_FIELD 1 +#define MC_FRAME 2 +#define MC_16X8 2 +#define MC_DMV 3 + +/* picture structure */ +#define TOP_FIELD 1 +#define BOTTOM_FIELD 2 +#define FRAME_PICTURE 3 + +/* picture coding type */ +#define I_TYPE 1 +#define P_TYPE 2 +#define B_TYPE 3 +#define D_TYPE 4 + +typedef void mpeg2_mc_fct (uint8_t *, const uint8_t *, int, int); + +typedef struct +{ + uint8_t * ref[2][MPEG2_COMPONENTS]; + uint8_t ** ref2[2]; + int pmv[2][2]; + int f_code[2]; +} motion_t; + +typedef void motion_parser_t(mpeg2_decoder_t * decoder, + motion_t * motion, + mpeg2_mc_fct * const * table); + +struct mpeg2_decoder_s +{ + /* first, state that carries information from one macroblock to the */ + /* next inside a slice, and is never used outside of mpeg2_slice() */ + + /* bit parsing stuff */ + uint32_t bitstream_buf; /* current 32 bit working set */ + int bitstream_bits; /* used bits in working set */ + const uint8_t * bitstream_ptr; /* buffer with stream data */ + + uint8_t * dest[MPEG2_COMPONENTS]; + + int offset; + int stride; + int uv_stride; + int slice_stride; + int slice_uv_stride; + int stride_frame; + unsigned int limit_x; + unsigned int limit_y_16; + unsigned int limit_y_8; + unsigned int limit_y; + + /* Motion vectors */ + /* The f_ and b_ correspond to the forward and backward motion */ + /* predictors */ + motion_t b_motion; + motion_t f_motion; + motion_parser_t * motion_parser[5]; + + /* predictor for DC coefficients in intra blocks */ + int16_t dc_dct_pred[MPEG2_COMPONENTS]; + + /* DCT coefficients */ + int16_t * DCTblock; /* put buffer separately to have it in IRAM */ + + uint8_t * picture_dest[MPEG2_COMPONENTS]; + void (* convert) (void * convert_id, uint8_t * const * src, + unsigned int v_offset); + void * convert_id; + + int dmv_offset; + unsigned int v_offset; + + /* now non-slice-specific information */ + + /* sequence header stuff */ + uint16_t * quantizer_matrix[4]; + uint16_t (* chroma_quantizer[2])[64]; + uint16_t quantizer_prescale[4][32][64]; + + /* The width and height of the picture snapped to macroblock units */ + int width; + int height; + int vertical_position_extension; + int chroma_format; + + /* picture header stuff */ + + /* what type of picture this is (I, P, B, D) */ + int coding_type; + + /* picture coding extension stuff */ + + /* quantization factor for intra dc coefficients */ + int intra_dc_precision; + /* top/bottom/both fields */ + int picture_structure; + /* bool to indicate all predictions are frame based */ + int frame_pred_frame_dct; + /* bool to indicate whether intra blocks have motion vectors */ + /* (for concealment) */ + int concealment_motion_vectors; + /* bool to use different vlc tables */ + int intra_vlc_format; + /* used for DMV MC */ + int top_field_first; + + /* stuff derived from bitstream */ + + /* pointer to the zigzag scan we're supposed to be using */ + const uint8_t * scan; + + int second_field; + + int mpeg1; +}; + +typedef struct +{ + mpeg2_fbuf_t fbuf; +} fbuf_alloc_t; + +struct mpeg2dec_s +{ + mpeg2_decoder_t decoder; + + mpeg2_info_t info; + + uint32_t shift; + int is_display_initialized; + mpeg2_state_t (* action) (struct mpeg2dec_s * mpeg2dec); + mpeg2_state_t state; + uint32_t ext_state; + + /* allocated in init - gcc has problems allocating such big structures */ + uint8_t * ATTR_ALIGN(4) chunk_buffer; + /* pointer to start of the current chunk */ + uint8_t * chunk_start; + /* pointer to current position in chunk_buffer */ + uint8_t * chunk_ptr; + /* last start code ? */ + uint8_t code; + + /* picture tags */ + uint32_t tag_current, tag2_current, tag_previous, tag2_previous; + int num_tags; + int bytes_since_tag; + + int first; + int alloc_index_user; + int alloc_index; + uint8_t first_decode_slice; + uint8_t nb_decode_slices; + + unsigned int user_data_len; + + mpeg2_sequence_t new_sequence; + mpeg2_sequence_t sequence; + mpeg2_gop_t new_gop; + mpeg2_gop_t gop; + mpeg2_picture_t new_picture; + mpeg2_picture_t pictures[4]; + mpeg2_picture_t * picture; + /*const*/ mpeg2_fbuf_t * fbuf[3]; /* 0: current fbuf, 1-2: prediction fbufs */ + + fbuf_alloc_t fbuf_alloc[3]; + int custom_fbuf; + + uint8_t * yuv_buf[3][MPEG2_COMPONENTS]; + int yuv_index; + mpeg2_convert_t * convert; + void * convert_arg; + unsigned int convert_id_size; + int convert_stride; + void (* convert_start) (void * id, const mpeg2_fbuf_t * fbuf, + const mpeg2_picture_t * picture, + const mpeg2_gop_t * gop); + + uint8_t * buf_start; + uint8_t * buf_end; + + int16_t display_offset_x, display_offset_y; + + int copy_matrix; + int8_t q_scale_type, scaled[4]; + uint8_t quantizer_matrix[4][64]; + uint8_t new_quantizer_matrix[4][64]; +}; + +/* decode.c */ +mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec); +mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec); + +/* header.c */ +void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec); +void mpeg2_reset_info (mpeg2_info_t * info); +int mpeg2_header_sequence (mpeg2dec_t * mpeg2dec); +int mpeg2_header_gop (mpeg2dec_t * mpeg2dec); +int mpeg2_header_picture (mpeg2dec_t * mpeg2dec); +int mpeg2_header_extension (mpeg2dec_t * mpeg2dec); +int mpeg2_header_user_data (mpeg2dec_t * mpeg2dec); +void mpeg2_header_sequence_finalize (mpeg2dec_t * mpeg2dec); +void mpeg2_header_gop_finalize (mpeg2dec_t * mpeg2dec); +void mpeg2_header_picture_finalize (mpeg2dec_t * mpeg2dec); +mpeg2_state_t mpeg2_header_slice_start (mpeg2dec_t * mpeg2dec); +mpeg2_state_t mpeg2_header_end (mpeg2dec_t * mpeg2dec); +void mpeg2_set_fbuf (mpeg2dec_t * mpeg2dec, int b_type); + +/* idct.c */ +void mpeg2_idct_init (void); +void mpeg2_idct_copy(int16_t * block, uint8_t * dest, + const int stride); +void mpeg2_idct_add(const int last, int16_t * block, + uint8_t * dest, const int stride); + +extern const uint8_t default_mpeg2_scan_norm[64]; +extern const uint8_t default_mpeg2_scan_alt[64]; +extern uint8_t mpeg2_scan_norm[64]; +extern uint8_t mpeg2_scan_alt[64]; + +/* motion_comp.c */ +void mpeg2_mc_init (void); + +typedef struct +{ + mpeg2_mc_fct * put [8]; + mpeg2_mc_fct * avg [8]; +} mpeg2_mc_t; + +extern const mpeg2_mc_t mpeg2_mc; + +#endif /* MPEG2_INTERNAL_H */ + diff --git a/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h b/apps/plugins/mpegplayer/libmpeg2/mpeg2dec_config.h 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 + * Copyright (C) 2003 Peter Gubanov + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.55 + */ + +#include "plugin.h" + +#include "mpeg2dec_config.h" + +#include "mpeg2.h" +#include "attributes.h" +#include "mpeg2_internal.h" + +#include "vlc.h" + +static inline int get_macroblock_modes (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int macroblock_modes; + const MBtab * tab; + + switch (decoder->coding_type) + { + case I_TYPE: + tab = MB_I + UBITS (bit_buf, 1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (!(decoder->frame_pred_frame_dct) && + decoder->picture_structure == FRAME_PICTURE) + { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + + return macroblock_modes; + + case P_TYPE: + tab = MB_P + UBITS (bit_buf, 5); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) + { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) + { + macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; + DUMPBITS (bit_buf, bits, 2); + } + + return macroblock_modes | MACROBLOCK_MOTION_FORWARD; + } + else if (decoder->frame_pred_frame_dct) + { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) + macroblock_modes |= MC_FRAME << MOTION_TYPE_SHIFT; + + return macroblock_modes | MACROBLOCK_MOTION_FORWARD; + } + else + { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) + { + macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; + DUMPBITS (bit_buf, bits, 2); + } + + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) + { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + + return macroblock_modes | MACROBLOCK_MOTION_FORWARD; + } + + case B_TYPE: + tab = MB_B + UBITS (bit_buf, 6); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) + { + if (! (macroblock_modes & MACROBLOCK_INTRA)) + { + macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; + DUMPBITS (bit_buf, bits, 2); + } + + return macroblock_modes; + } + else if (decoder->frame_pred_frame_dct) + { + /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ + macroblock_modes |= MC_FRAME << MOTION_TYPE_SHIFT; + return macroblock_modes; + } + else + { + if (macroblock_modes & MACROBLOCK_INTRA) + goto intra; + + macroblock_modes |= UBITS (bit_buf, 2) << MOTION_TYPE_SHIFT; + DUMPBITS (bit_buf, bits, 2); + + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) + { + intra: + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case D_TYPE: + DUMPBITS (bit_buf, bits, 1); + return MACROBLOCK_INTRA; + + default: + return 0; + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline void get_quantizer_scale (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int quantizer_scale_code; + + quantizer_scale_code = UBITS (bit_buf, 5); + DUMPBITS (bit_buf, bits, 5); + + decoder->quantizer_matrix[0] = + decoder->quantizer_prescale[0][quantizer_scale_code]; + + decoder->quantizer_matrix[1] = + decoder->quantizer_prescale[1][quantizer_scale_code]; + + decoder->quantizer_matrix[2] = + decoder->chroma_quantizer[0][quantizer_scale_code]; + + decoder->quantizer_matrix[3] = + decoder->chroma_quantizer[1][quantizer_scale_code]; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_motion_delta (mpeg2_decoder_t * const decoder, + const int f_code) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int delta; + int sign; + const MVtab * tab; + + if (bit_buf & 0x80000000) + { + DUMPBITS (bit_buf, bits, 1); + return 0; + } + else if (bit_buf >= 0x0c000000) + { + tab = MV_4 + UBITS (bit_buf, 4); + delta = (tab->delta << f_code) + 1; + bits += tab->len + f_code + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) + delta += UBITS (bit_buf, f_code); + bit_buf <<= f_code; + + return (delta ^ sign) - sign; + } + else + { + tab = MV_10 + UBITS (bit_buf, 10); + delta = (tab->delta << f_code) + 1; + bits += tab->len + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) + { + NEEDBITS (bit_buf, bits, bit_ptr); + delta += UBITS (bit_buf, f_code); + DUMPBITS (bit_buf, bits, f_code); + } + + return (delta ^ sign) - sign; + + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int bound_motion_vector (const int vector, const int f_code) +{ + return ((int32_t)vector << (27 - f_code)) >> (27 - f_code); +} + +static inline int get_dmv (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DMVtab * tab; + + tab = DMV_2 + UBITS (bit_buf, 2); + DUMPBITS (bit_buf, bits, tab->len); + return tab->dmv; + +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_coded_block_pattern (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const CBPtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + if (bit_buf >= 0x20000000) + { + tab = CBP_7 + (UBITS (bit_buf, 7) - 16); + DUMPBITS (bit_buf, bits, tab->len); + return tab->cbp; + } + else + { + tab = CBP_9 + UBITS (bit_buf, 9); + DUMPBITS (bit_buf, bits, tab->len); + return tab->cbp; + } + +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline int get_luma_dc_dct_diff (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) + { + tab = DC_lum_5 + UBITS (bit_buf, 5); + size = tab->size; + + if (size) + { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff << decoder->intra_dc_precision; + } + else + { + DUMPBITS (bit_buf, bits, 3); + return 0; + } + } + else + { + tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff << decoder->intra_dc_precision; + } + +#undef bit_buf +#undef bits +#undef bit_ptr +} + +#if MPEG2_COLOR +static inline int get_chroma_dc_dct_diff (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) + { + tab = DC_chrom_5 + UBITS (bit_buf, 5); + size = tab->size; + + if (size) + { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff << decoder->intra_dc_precision; + } + else + { + DUMPBITS (bit_buf, bits, 2); + return 0; + } + } + else + { + tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len + 1); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff << decoder->intra_dc_precision; + } + +#undef bit_buf +#undef bits +#undef bit_ptr +} +#endif /* MPEG2_COLOR */ + +#define SATURATE(val) \ + do { \ + val <<= 4; \ + if (unlikely (val != (int16_t) val)) \ + val = (SBITS (val, 1) ^ 2047) << 4; \ + } while (0) + +static void get_intra_block_B14 (mpeg2_decoder_t * const decoder, + const uint16_t * const quant_matrix) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + const uint8_t * const scan = decoder->scan; + int16_t * const dest = decoder->DCTblock; + int mismatch = ~dest[0]; + int i = 0; + int j; + int val; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) + { + if (bit_buf >= 0x28000000) + { + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + val = (tab->level * quant_matrix[j]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + else if (bit_buf >= 0x04000000) + { + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = (SBITS (bit_buf, 12) * quant_matrix[j]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + dest[63] ^= mismatch & 16; + DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; +} + +static void get_intra_block_B15 (mpeg2_decoder_t * const decoder, + const uint16_t * const quant_matrix) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + const uint8_t * const scan = decoder->scan; + int16_t * const dest = decoder->DCTblock; + int mismatch = ~dest[0]; + int i = 0; + int j; + int val; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) + { + if (bit_buf >= 0x04000000) + { + tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + + if (i < 64) + { + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + val = (tab->level * quant_matrix[j]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + else + { + /* end of block. I commented out this code because if we */ + /* dont exit here we will still exit at the later test :) */ + + /* if (i >= 128) break; */ /* end of block */ + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check against buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = (SBITS (bit_buf, 12) * quant_matrix[j]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + dest[63] ^= mismatch & 16; + DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; +} + +static int get_non_intra_block (mpeg2_decoder_t * const decoder, + const uint16_t * const quant_matrix) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + const uint8_t * const scan = decoder->scan; + int16_t * const dest = decoder->DCTblock; + int mismatch = -1; + int i = -1; + int j; + int val; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + if (bit_buf >= 0x28000000) + { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } + else + { + goto entry_2; + } + + while (1) + { + if (bit_buf >= 0x28000000) + { + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + val = ((2 * tab->level + 1) * quant_matrix[j]) >> 5; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + + entry_2: + if (bit_buf >= 0x04000000) + { + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1; + val = (val * quant_matrix[j]) / 32; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + dest[63] ^= mismatch & 16; + DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; + return i; +} + +static void get_mpeg1_intra_block (mpeg2_decoder_t * const decoder) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + const uint8_t * const scan = decoder->scan; + const uint16_t * const quant_matrix = decoder->quantizer_matrix[0]; + int16_t * const dest = decoder->DCTblock; + int i = 0; + int j; + int val; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) + { + if (bit_buf >= 0x28000000) + { + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + val = (tab->level * quant_matrix[j]) >> 4; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + else if (bit_buf >= 0x04000000) + { + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + + if (! (val & 0x7f)) + { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + + val = (val * quant_matrix[j]) / 16; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; +} + +static int get_mpeg1_non_intra_block (mpeg2_decoder_t * const decoder) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + const uint8_t * const scan = decoder->scan; + const uint16_t * const quant_matrix = decoder->quantizer_matrix[1]; + int16_t * const dest = decoder->DCTblock; + int i = -1; + int j; + int val; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) + { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } + else + { + goto entry_2; + } + + while (1) + { + if (bit_buf >= 0x28000000) + { + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + val = ((2 * tab->level + 1) * quant_matrix[j]) >> 5; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + + entry_2: + if (bit_buf >= 0x04000000) + { + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + + if (! (val & 0x7f)) + { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + + val = 2 * (val + SBITS (val, 1)) + 1; + val = (val * quant_matrix[j]) / 32; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + DUMPBITS (bit_buf, bits, tab->len); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; + return i; +} + +static inline void slice_intra_DCT (mpeg2_decoder_t * const decoder, + const int cc, + uint8_t * const dest, const int stride) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + NEEDBITS (bit_buf, bits, bit_ptr); + /* Get the intra DC coefficient and inverse quantize it */ + if (cc == 0) + { + decoder->dc_dct_pred[0] += get_luma_dc_dct_diff (decoder); + decoder->DCTblock[0] = decoder->dc_dct_pred[0]; + + } +#if MPEG2_COLOR + else + { + decoder->dc_dct_pred[cc] += get_chroma_dc_dct_diff (decoder); + decoder->DCTblock[0] = decoder->dc_dct_pred[cc]; + } +#endif + + if (decoder->mpeg1) + { + if (decoder->coding_type != D_TYPE) + get_mpeg1_intra_block (decoder); + } + else if (decoder->intra_vlc_format) + { + get_intra_block_B15 (decoder, decoder->quantizer_matrix[cc ? 2 : 0]); + } + else + { + get_intra_block_B14 (decoder, decoder->quantizer_matrix[cc ? 2 : 0]); + } + + mpeg2_idct_copy (decoder->DCTblock, dest, stride); + +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static inline void slice_non_intra_DCT (mpeg2_decoder_t * const decoder, + const int cc, + uint8_t * const dest, const int stride) +{ + int last; + + if (decoder->mpeg1) + { + last = get_mpeg1_non_intra_block (decoder); + } + else + { + last = get_non_intra_block (decoder, + decoder->quantizer_matrix[cc ? 3 : 1]); + } + + mpeg2_idct_add (last, decoder->DCTblock, dest, stride); +} + +#if !MPEG2_COLOR +static void skip_mpeg1_intra_block (mpeg2_decoder_t * const decoder) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + int i = 0; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) + { + if (bit_buf >= 0x28000000) + { + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + bit_buf <<= tab->len + 1; + bits += tab->len + 1; + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + } + else if (bit_buf >= 0x04000000) + { + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + if (!(SBITS (bit_buf, 8) & 0x7f)) + DUMPBITS (bit_buf, bits, 8); + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; +} + +static void skip_intra_block_B14 (mpeg2_decoder_t * const decoder) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + int i = 0; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) + { + if (bit_buf >= 0x28000000) + { + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + bit_buf <<= tab->len + 1; + bits += tab->len + 1; + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + } + else if (bit_buf >= 0x04000000) + { + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + DUMPBITS (bit_buf, bits, 12); /* Can't dump more than 16 atm */ + NEEDBITS (bit_buf, bits, bit_ptr); + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; +} + +static void skip_intra_block_B15 (mpeg2_decoder_t * const decoder) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + int i = 0; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) + { + if (bit_buf >= 0x04000000) + { + tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + + if (i < 64) + { + normal_code: + bit_buf <<= tab->len + 1; + bits += tab->len + 1; + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + } + else + { + /* end of block. I commented out this code because if we */ + /* dont exit here we will still exit at the later test :) */ + + /* if (i >= 128) break; */ /* end of block */ + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check against buffer overflow */ + + DUMPBITS (bit_buf, bits, 12); /* Can't dump more than 16 atm */ + NEEDBITS (bit_buf, bits, bit_ptr); + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + } + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + DUMPBITS (bit_buf, bits, 4); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; +} + +static void skip_non_intra_block (mpeg2_decoder_t * const decoder) +{ + uint32_t bit_buf = decoder->bitstream_buf; + int bits = decoder->bitstream_bits; + const uint8_t * bit_ptr = decoder->bitstream_ptr; + int i = -1; + const DCTtab * tab; + + NEEDBITS (bit_buf, bits, bit_ptr); + + if (bit_buf >= 0x28000000) + { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } + else + { + goto entry_2; + } + + while (1) + { + if (bit_buf >= 0x28000000) + { + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + bit_buf <<= tab->len + 1; + bits += tab->len + 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + + entry_2: + if (bit_buf >= 0x04000000) + { + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + if (decoder->mpeg1) + { + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + if (!(SBITS (bit_buf, 8) & 0x7f)) + DUMPBITS (bit_buf, bits, 8); + + DUMPBITS (bit_buf, bits, 8); + } + else + { + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + DUMPBITS (bit_buf, bits, 12); + } + + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + } + else if (bit_buf >= 0x02000000) + { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00800000) + { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else if (bit_buf >= 0x00200000) + { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } + else + { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD (bit_buf, bits + 16, bit_ptr); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + decoder->bitstream_ptr = bit_ptr; +} + +static void skip_chroma_dc_dct_diff (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + + if (bit_buf < 0xf8000000) + { + tab = DC_chrom_5 + UBITS (bit_buf, 5); + size = tab->size; + + if (size) + { + bits += tab->len + size; + bit_buf <<= tab->len; + bit_buf <<= size; + } + else + { + DUMPBITS (bit_buf, bits, 2); + } + } + else + { + tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len + 1); + NEEDBITS (bit_buf, bits, bit_ptr); + DUMPBITS (bit_buf, bits, size); + } + +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void skip_chroma_non_intra (mpeg2_decoder_t * const decoder, + uint32_t coded_block_pattern) +{ + static const uint32_t cbp_mask[3] = + { + 0x00000030, + 0xc0000030, + 0xfc000030, + }; + + uint32_t cbp = coded_block_pattern & + cbp_mask[MIN((unsigned)decoder->chroma_format, 2u)]; + + while (cbp) + { + skip_non_intra_block (decoder); + cbp &= (cbp - 1); + } +} + +static void skip_chroma_intra (mpeg2_decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int i = 2 << decoder->chroma_format; + + if ((unsigned)i > 8) + i = 8; + + while (i-- > 0) + { + NEEDBITS (bit_buf, bits, bit_ptr); + + skip_chroma_dc_dct_diff (decoder); + + if (decoder->mpeg1) + { + if (decoder->coding_type != D_TYPE) + skip_mpeg1_intra_block (decoder); + } + else if (decoder->intra_vlc_format) + { + skip_intra_block_B15 (decoder); + } + else + { + skip_intra_block_B14 (decoder); + } + } + + if (decoder->chroma_format == 0 && decoder->coding_type == D_TYPE) + { + NEEDBITS (bit_buf, bits, bit_ptr); + DUMPBITS (bit_buf, bits, 1); + } + +#undef bit_buf +#undef bits +#undef bit_ptr +} +#endif /* !MPEG2_COLOR */ + +#define MOTION_420(table, ref, motion_x, motion_y, size, y) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y_ ## size)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \ + motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \ + ref[0] + (pos_x >> 1) + (pos_y >> 1) * decoder->stride, \ + decoder->stride, size); \ + \ + if (MPEG2_COLOR) \ + { \ + motion_x /= 2; \ + motion_y /= 2; \ + xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \ + offset = ((decoder->offset + motion_x) >> 1) + \ + ((((decoder->v_offset + motion_y) >> 1) + y/2) * \ + decoder->uv_stride); \ + \ + table[4+xy_half] (decoder->dest[1] + y/2 * decoder->uv_stride + \ + (decoder->offset >> 1), ref[1] + offset, \ + decoder->uv_stride, size/2); \ + table[4+xy_half] (decoder->dest[2] + y/2 * decoder->uv_stride + \ + (decoder->offset >> 1), ref[2] + offset, \ + decoder->uv_stride, size/2); \ + } + +#define MOTION_FIELD_420(table, ref, motion_x, motion_y, \ + dest_field, op, src_field) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = decoder->v_offset + motion_y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ + motion_y = pos_y - decoder->v_offset; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \ + decoder->offset, \ + (ref[0] + (pos_x >> 1) + \ + ((pos_y op) + src_field) * decoder->stride), \ + 2 * decoder->stride, 8); \ + \ + if (MPEG2_COLOR) \ + { \ + motion_x /= 2; \ + motion_y /= 2; \ + xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \ + offset = ((decoder->offset + motion_x) >> 1) + \ + (((decoder->v_offset >> 1) + (motion_y op) + src_field) * \ + decoder->uv_stride); \ + \ + table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride + \ + (decoder->offset >> 1), ref[1] + offset, \ + 2 * decoder->uv_stride, 4); \ + table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride + \ + (decoder->offset >> 1), ref[2] + offset, \ + 2 * decoder->uv_stride, 4); \ + } + +#define MOTION_DMV_420(table, ref, motion_x, motion_y) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = decoder->v_offset + motion_y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ + motion_y = pos_y - decoder->v_offset; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \ + table[xy_half] (decoder->dest[0] + decoder->offset, \ + ref[0] + offset, 2 * decoder->stride, 8); \ + table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \ + ref[0] + decoder->stride + offset, \ + 2 * decoder->stride, 8); \ + \ + if (MPEG2_COLOR) \ + { \ + motion_x /= 2; \ + motion_y /= 2; \ + xy_half = ((motion_y & 1) << 1) | (motion_x & 1); \ + offset = ((decoder->offset + motion_x) >> 1) + \ + (((decoder->v_offset >> 1) + (motion_y & ~1)) * \ + decoder->uv_stride); \ + \ + table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1), \ + ref[1] + offset, 2 * decoder->uv_stride, 4); \ + table[4+xy_half] (decoder->dest[1] + decoder->uv_stride + \ + (decoder->offset >> 1), \ + ref[1] + decoder->uv_stride + offset, \ + 2 * decoder->uv_stride, 4); \ + table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1), \ + ref[2] + offset, 2 * decoder->uv_stride, 4); \ + table[4+xy_half] (decoder->dest[2] + decoder->uv_stride + \ + (decoder->offset >> 1), \ + ref[2] + decoder->uv_stride + offset, \ + 2 * decoder->uv_stride, 4); \ + } + +#define MOTION_ZERO_420(table, ref) \ + table[0] (decoder->dest[0] + decoder->offset, \ + (ref[0] + decoder->offset + \ + decoder->v_offset * decoder->stride), decoder->stride, 16); \ + \ + if (MPEG2_COLOR) \ + { \ + offset = ((decoder->offset >> 1) + \ + (decoder->v_offset >> 1) * decoder->uv_stride); \ + \ + table[4] (decoder->dest[1] + (decoder->offset >> 1), \ + ref[1] + offset, decoder->uv_stride, 8); \ + table[4] (decoder->dest[2] + (decoder->offset >> 1), \ + ref[2] + offset, decoder->uv_stride, 8); \ + } + +#define MOTION_422(table, ref, motion_x, motion_y, size, y) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y_ ## size)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \ + motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride; \ + \ + table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \ + ref[0] + offset, decoder->stride, size); \ + \ + if (MPEG2_COLOR) \ + { \ + offset = (offset + (motion_x & (motion_x < 0))) >> 1; \ + motion_x /= 2; \ + xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \ + \ + table[4+xy_half] (decoder->dest[1] + y * decoder->uv_stride + \ + (decoder->offset >> 1), ref[1] + offset, \ + decoder->uv_stride, size); \ + table[4+xy_half] (decoder->dest[2] + y * decoder->uv_stride + \ + (decoder->offset >> 1), ref[2] + offset, \ + decoder->uv_stride, size); \ + } + +#define MOTION_FIELD_422(table, ref, motion_x, motion_y, \ + dest_field, op, src_field) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = decoder->v_offset + motion_y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ + motion_y = pos_y - decoder->v_offset; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride; \ + \ + table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \ + decoder->offset, ref[0] + offset, \ + 2 * decoder->stride, 8); \ + \ + if (MPEG2_COLOR) \ + { \ + offset = (offset + (motion_x & (motion_x < 0))) >> 1; \ + motion_x /= 2; \ + xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \ + \ + table[4+xy_half] (decoder->dest[1] + dest_field * decoder->uv_stride + \ + (decoder->offset >> 1), ref[1] + offset, \ + 2 * decoder->uv_stride, 8); \ + table[4+xy_half] (decoder->dest[2] + dest_field * decoder->uv_stride + \ + (decoder->offset >> 1), ref[2] + offset, \ + 2 * decoder->uv_stride, 8); \ + } + +#define MOTION_DMV_422(table, ref, motion_x, motion_y) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = decoder->v_offset + motion_y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ + motion_y = pos_y - decoder->v_offset; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \ + \ + table[xy_half] (decoder->dest[0] + decoder->offset, \ + ref[0] + offset, 2 * decoder->stride, 8); \ + table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \ + ref[0] + decoder->stride + offset, \ + 2 * decoder->stride, 8); \ + \ + if (MPEG2_COLOR) \ + { \ + offset = (offset + (motion_x & (motion_x < 0))) >> 1; \ + motion_x /= 2; \ + xy_half = ((pos_y & 1) << 1) | (motion_x & 1); \ + \ + table[4+xy_half] (decoder->dest[1] + (decoder->offset >> 1), \ + ref[1] + offset, 2 * decoder->uv_stride, 8); \ + table[4+xy_half] (decoder->dest[1] + decoder->uv_stride + \ + (decoder->offset >> 1), \ + ref[1] + decoder->uv_stride + offset, \ + 2 * decoder->uv_stride, 8); \ + table[4+xy_half] (decoder->dest[2] + (decoder->offset >> 1), \ + ref[2] + offset, 2 * decoder->uv_stride, 8); \ + table[4+xy_half] (decoder->dest[2] + decoder->uv_stride + \ + (decoder->offset >> 1), \ + ref[2] + decoder->uv_stride + offset, \ + 2 * decoder->uv_stride, 8); \ + } + +#define MOTION_ZERO_422(table, ref) \ + offset = decoder->offset + decoder->v_offset * decoder->stride; \ + table[0] (decoder->dest[0] + decoder->offset, \ + ref[0] + offset, decoder->stride, 16); \ + \ + if (MPEG2_COLOR) \ + { \ + offset >>= 1; \ + table[4] (decoder->dest[1] + (decoder->offset >> 1), \ + ref[1] + offset, decoder->uv_stride, 16); \ + table[4] (decoder->dest[2] + (decoder->offset >> 1), \ + ref[2] + offset, decoder->uv_stride, 16); \ + } + +#define MOTION_444(table, ref, motion_x, motion_y, size, y) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = 2 * decoder->v_offset + motion_y + 2 * y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y_ ## size)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y_ ## size; \ + motion_y = pos_y - 2 * decoder->v_offset - 2 * y; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + offset = (pos_x >> 1) + (pos_y >> 1) * decoder->stride; \ + \ + table[xy_half] (decoder->dest[0] + y * decoder->stride + decoder->offset, \ + ref[0] + offset, decoder->stride, size); \ + \ + if (MPEG2_COLOR) \ + { \ + table[xy_half] (decoder->dest[1] + y * decoder->stride + decoder->offset, \ + ref[1] + offset, decoder->stride, size); \ + table[xy_half] (decoder->dest[2] + y * decoder->stride + decoder->offset, \ + ref[2] + offset, decoder->stride, size); \ + } + +#define MOTION_FIELD_444(table, ref, motion_x, motion_y, \ + dest_field, op, src_field) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = decoder->v_offset + motion_y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ + motion_y = pos_y - decoder->v_offset; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + offset = (pos_x >> 1) + ((pos_y op) + src_field) * decoder->stride; \ + \ + table[xy_half] (decoder->dest[0] + dest_field * decoder->stride + \ + decoder->offset, ref[0] + offset, \ + 2 * decoder->stride, 8); \ + \ + if (MPEG2_COLOR) \ + { \ + table[xy_half] (decoder->dest[1] + dest_field * decoder->stride + \ + decoder->offset, ref[1] + offset, \ + 2 * decoder->stride, 8); \ + table[xy_half] (decoder->dest[2] + dest_field * decoder->stride + \ + decoder->offset, ref[2] + offset, \ + 2 * decoder->stride, 8); \ + } + +#define MOTION_DMV_444(table, ref, motion_x, motion_y) \ + pos_x = 2 * decoder->offset + motion_x; \ + pos_y = decoder->v_offset + motion_y; \ + \ + if (unlikely (pos_x > decoder->limit_x)) \ + { \ + pos_x = ((int)pos_x < 0) ? 0 : decoder->limit_x; \ + motion_x = pos_x - 2 * decoder->offset; \ + } \ + \ + if (unlikely (pos_y > decoder->limit_y)) \ + { \ + pos_y = ((int)pos_y < 0) ? 0 : decoder->limit_y; \ + motion_y = pos_y - decoder->v_offset; \ + } \ + \ + xy_half = ((pos_y & 1) << 1) | (pos_x & 1); \ + offset = (pos_x >> 1) + (pos_y & ~1) * decoder->stride; \ + \ + table[xy_half] (decoder->dest[0] + decoder->offset, \ + ref[0] + offset, 2 * decoder->stride, 8); \ + table[xy_half] (decoder->dest[0] + decoder->stride + decoder->offset, \ + ref[0] + decoder->stride + offset, \ + 2 * decoder->stride, 8); \ + \ + if (MPEG2_COLOR) \ + { \ + table[xy_half] (decoder->dest[1] + decoder->offset, \ + ref[1] + offset, 2 * decoder->stride, 8); \ + table[xy_half] (decoder->dest[1] + decoder->stride + decoder->offset, \ + ref[1] + decoder->stride + offset, \ + 2 * decoder->stride, 8); \ + table[xy_half] (decoder->dest[2] + decoder->offset, \ + ref[2] + offset, 2 * decoder->stride, 8); \ + table[xy_half] (decoder->dest[2] + decoder->stride + decoder->offset, \ + ref[2] + decoder->stride + offset, \ + 2 * decoder->stride, 8); \ + } + +#define MOTION_ZERO_444(table, ref) \ + offset = decoder->offset + decoder->v_offset * decoder->stride; \ + \ + table[0] (decoder->dest[0] + decoder->offset, \ + ref[0] + offset, decoder->stride, 16); \ + \ + if (MPEG2_COLOR) \ + { \ + table[4] (decoder->dest[1] + decoder->offset, \ + ref[1] + offset, decoder->stride, 16); \ + table[4] (decoder->dest[2] + decoder->offset, \ + ref[2] + offset, decoder->stride, 16); \ + } + +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + +static void motion_mp1 (mpeg2_decoder_t * const decoder, + motion_t * const motion, + mpeg2_mc_fct * const * const table) +{ + int motion_x, motion_y; + unsigned int pos_x, pos_y, xy_half, offset; + + NEEDBITS (bit_buf, bits, bit_ptr); + motion_x = motion->pmv[0][0] + + (get_motion_delta (decoder, + motion->f_code[0]) << motion->f_code[1]); + motion_x = bound_motion_vector (motion_x, + motion->f_code[0] + motion->f_code[1]); + motion->pmv[0][0] = motion_x; + + NEEDBITS (bit_buf, bits, bit_ptr); + motion_y = motion->pmv[0][1] + + (get_motion_delta (decoder, + motion->f_code[0]) << motion->f_code[1]); + motion_y = bound_motion_vector (motion_y, + motion->f_code[0] + motion->f_code[1]); + motion->pmv[0][1] = motion_y; + + MOTION_420 (table, motion->ref[0], motion_x, motion_y, 16, 0); +} + +#define MOTION_FUNCTIONS(FORMAT, MOTION, MOTION_FIELD, \ + MOTION_DMV, MOTION_ZERO) \ + \ +static void motion_fr_frame_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + int motion_x, motion_y; \ + unsigned int pos_x, pos_y, xy_half, offset; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ + motion->f_code[1]); \ + motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ + motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \ + \ + MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); \ +} \ + \ +static void motion_fr_field_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + int motion_x, motion_y, field; \ + unsigned int pos_x, pos_y, xy_half, offset; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + field = UBITS (bit_buf, 1); \ + DUMPBITS (bit_buf, bits, 1); \ + \ + motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[0][0] = motion_x; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_y = ((motion->pmv[0][1] >> 1) + \ + get_motion_delta (decoder, motion->f_code[1])); \ + /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \ + motion->pmv[0][1] = motion_y << 1; \ + \ + MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 0, & ~1, field); \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + field = UBITS (bit_buf, 1); \ + DUMPBITS (bit_buf, bits, 1); \ + \ + motion_x = motion->pmv[1][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[1][0] = motion_x; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_y = ((motion->pmv[1][1] >> 1) + \ + get_motion_delta (decoder, motion->f_code[1])); \ + /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \ + motion->pmv[1][1] = motion_y << 1; \ + \ + MOTION_FIELD (table, motion->ref[0], motion_x, motion_y, 1, & ~1, field); \ +} \ + \ +static void motion_fr_dmv_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + int motion_x, motion_y, dmv_x, dmv_y, m, other_x, other_y; \ + unsigned int pos_x, pos_y, xy_half, offset; \ + \ + (void)table; \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + dmv_x = get_dmv (decoder); \ + \ + motion_y = ((motion->pmv[0][1] >> 1) + \ + get_motion_delta (decoder, motion->f_code[1])); \ + /* motion_y = bound_motion_vector (motion_y, motion->f_code[1]); */ \ + motion->pmv[1][1] = motion->pmv[0][1] = motion_y << 1; \ + dmv_y = get_dmv (decoder); \ + \ + m = decoder->top_field_first ? 1 : 3; \ + other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; \ + other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y - 1; \ + MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 0, | 1, 0); \ + \ + m = decoder->top_field_first ? 3 : 1; \ + other_x = ((motion_x * m + (motion_x > 0)) >> 1) + dmv_x; \ + other_y = ((motion_y * m + (motion_y > 0)) >> 1) + dmv_y + 1; \ + MOTION_FIELD (mpeg2_mc.put, motion->ref[0], other_x, other_y, 1, & ~1, 0);\ + \ + MOTION_DMV (mpeg2_mc.avg, motion->ref[0], motion_x, motion_y); \ +} \ + \ +static void motion_reuse_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + int motion_x, motion_y; \ + unsigned int pos_x, pos_y, xy_half, offset; \ + \ + motion_x = motion->pmv[0][0]; \ + motion_y = motion->pmv[0][1]; \ + \ + MOTION (table, motion->ref[0], motion_x, motion_y, 16, 0); \ +} \ + \ +static void motion_zero_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + unsigned int offset; \ + \ + motion->pmv[0][0] = motion->pmv[0][1] = 0; \ + motion->pmv[1][0] = motion->pmv[1][1] = 0; \ + \ + MOTION_ZERO (table, motion->ref[0]); \ +} \ + \ +static void motion_fi_field_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + int motion_x, motion_y; \ + uint8_t ** ref_field; \ + unsigned int pos_x, pos_y, xy_half, offset; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + ref_field = motion->ref2[UBITS (bit_buf, 1)]; \ + DUMPBITS (bit_buf, bits, 1); \ + \ + motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ + motion->f_code[1]); \ + motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ + motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \ + \ + MOTION (table, ref_field, motion_x, motion_y, 16, 0); \ +} \ + \ +static void motion_fi_16x8_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + int motion_x, motion_y; \ + uint8_t ** ref_field; \ + unsigned int pos_x, pos_y, xy_half, offset; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + ref_field = motion->ref2[UBITS (bit_buf, 1)]; \ + DUMPBITS (bit_buf, bits, 1); \ + \ + motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[0][0] = motion_x; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ + motion->f_code[1]); \ + motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ + motion->pmv[0][1] = motion_y; \ + \ + MOTION (table, ref_field, motion_x, motion_y, 8, 0); \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + ref_field = motion->ref2[UBITS (bit_buf, 1)]; \ + DUMPBITS (bit_buf, bits, 1); \ + \ + motion_x = motion->pmv[1][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[1][0] = motion_x; \ + \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_y = motion->pmv[1][1] + get_motion_delta (decoder, \ + motion->f_code[1]); \ + motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ + motion->pmv[1][1] = motion_y; \ + \ + MOTION (table, ref_field, motion_x, motion_y, 8, 8); \ +} \ + \ +static void motion_fi_dmv_##FORMAT (mpeg2_decoder_t * const decoder, \ + motion_t * const motion, \ + mpeg2_mc_fct * const * const table) \ +{ \ + int motion_x, motion_y, other_x, other_y; \ + unsigned int pos_x, pos_y, xy_half, offset; \ + \ + (void)table; \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + motion_x = motion->pmv[0][0] + get_motion_delta (decoder, \ + motion->f_code[0]); \ + motion_x = bound_motion_vector (motion_x, motion->f_code[0]); \ + motion->pmv[1][0] = motion->pmv[0][0] = motion_x; \ + NEEDBITS (bit_buf, bits, bit_ptr); \ + other_x = ((motion_x + (motion_x > 0)) >> 1) + get_dmv (decoder); \ + \ + motion_y = motion->pmv[0][1] + get_motion_delta (decoder, \ + motion->f_code[1]); \ + motion_y = bound_motion_vector (motion_y, motion->f_code[1]); \ + motion->pmv[1][1] = motion->pmv[0][1] = motion_y; \ + other_y = (((motion_y + (motion_y > 0)) >> 1) + get_dmv (decoder) + \ + decoder->dmv_offset); \ + \ + MOTION (mpeg2_mc.put, motion->ref[0], motion_x, motion_y, 16, 0); \ + MOTION (mpeg2_mc.avg, motion->ref[1], other_x, other_y, 16, 0); \ +} \ + +MOTION_FUNCTIONS (420, MOTION_420, MOTION_FIELD_420, MOTION_DMV_420, + MOTION_ZERO_420) +MOTION_FUNCTIONS (422, MOTION_422, MOTION_FIELD_422, MOTION_DMV_422, + MOTION_ZERO_422) +MOTION_FUNCTIONS (444, MOTION_444, MOTION_FIELD_444, MOTION_DMV_444, + MOTION_ZERO_444) + +/* like motion_frame, but parsing without actual motion compensation */ +static void motion_fr_conceal (mpeg2_decoder_t * const decoder) +{ + int tmp; + + NEEDBITS (bit_buf, bits, bit_ptr); + tmp = (decoder->f_motion.pmv[0][0] + + get_motion_delta (decoder, decoder->f_motion.f_code[0])); + tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]); + decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[0][0] = tmp; + + NEEDBITS (bit_buf, bits, bit_ptr); + tmp = (decoder->f_motion.pmv[0][1] + + get_motion_delta (decoder, decoder->f_motion.f_code[1])); + tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]); + decoder->f_motion.pmv[1][1] = decoder->f_motion.pmv[0][1] = tmp; + + DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */ +} + +static void motion_fi_conceal (mpeg2_decoder_t * const decoder) +{ + int tmp; + + NEEDBITS (bit_buf, bits, bit_ptr); + DUMPBITS (bit_buf, bits, 1); /* remove field_select */ + + tmp = decoder->f_motion.pmv[0][0] + + get_motion_delta (decoder, decoder->f_motion.f_code[0]); + tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[0]); + + decoder->f_motion.pmv[1][0] = + decoder->f_motion.pmv[0][0] = tmp; + + NEEDBITS (bit_buf, bits, bit_ptr); + + tmp = (decoder->f_motion.pmv[0][1] + + get_motion_delta (decoder, decoder->f_motion.f_code[1])); + tmp = bound_motion_vector (tmp, decoder->f_motion.f_code[1]); + + decoder->f_motion.pmv[1][1] = + decoder->f_motion.pmv[0][1] = tmp; + + DUMPBITS (bit_buf, bits, 1); /* remove marker_bit */ +} + +#undef bit_buf +#undef bits +#undef bit_ptr + +#define MOTION_CALL(routine, direction) \ +do { \ + if ((direction) & MACROBLOCK_MOTION_FORWARD) \ + routine (decoder, &decoder->f_motion, mpeg2_mc.put); \ + \ + if ((direction) & MACROBLOCK_MOTION_BACKWARD) \ + { \ + routine (decoder, &decoder->b_motion, \ + ((direction) & MACROBLOCK_MOTION_FORWARD ? \ + mpeg2_mc.avg : mpeg2_mc.put)); \ + } \ +} while (0) + +#define NEXT_MACROBLOCK \ +do { \ + decoder->offset += 16; \ + \ + if (decoder->offset == decoder->width) \ + { \ + do { /* just so we can use the break statement */ \ + if (decoder->convert) \ + { \ + decoder->convert (decoder->convert_id, decoder->dest, \ + decoder->v_offset); \ + if (decoder->coding_type == B_TYPE) \ + break; \ + } \ + \ + decoder->dest[0] += decoder->slice_stride; \ + if (MPEG2_COLOR) \ + { \ + decoder->dest[1] += decoder->slice_uv_stride; \ + decoder->dest[2] += decoder->slice_uv_stride; \ + } \ + } while (0); \ + \ + decoder->v_offset += 16; \ + \ + if (decoder->v_offset > decoder->limit_y) \ + return; \ + \ + decoder->offset = 0; \ + } \ +} while (0) + +void mpeg2_init_fbuf (mpeg2_decoder_t * decoder, + uint8_t * current_fbuf[MPEG2_COMPONENTS], + uint8_t * forward_fbuf[MPEG2_COMPONENTS], + uint8_t * backward_fbuf[MPEG2_COMPONENTS]) +{ + int offset, stride, height, bottom_field; + + stride = decoder->stride_frame; + bottom_field = (decoder->picture_structure == BOTTOM_FIELD); + offset = bottom_field ? stride : 0; + height = decoder->height; + + decoder->picture_dest[0] = current_fbuf[0] + offset; +#if MPEG2_COLOR + decoder->picture_dest[1] = current_fbuf[1] + (offset >> 1); + decoder->picture_dest[2] = current_fbuf[2] + (offset >> 1); +#endif + + decoder->f_motion.ref[0][0] = forward_fbuf[0] + offset; +#if MPEG2_COLOR + decoder->f_motion.ref[0][1] = forward_fbuf[1] + (offset >> 1); + decoder->f_motion.ref[0][2] = forward_fbuf[2] + (offset >> 1); +#endif + + decoder->b_motion.ref[0][0] = backward_fbuf[0] + offset; +#if MPEG2_COLOR + decoder->b_motion.ref[0][1] = backward_fbuf[1] + (offset >> 1); + decoder->b_motion.ref[0][2] = backward_fbuf[2] + (offset >> 1); +#endif + + if (decoder->picture_structure != FRAME_PICTURE) + { + decoder->dmv_offset = bottom_field ? 1 : -1; + decoder->f_motion.ref2[0] = decoder->f_motion.ref[bottom_field]; + decoder->f_motion.ref2[1] = decoder->f_motion.ref[!bottom_field]; + decoder->b_motion.ref2[0] = decoder->b_motion.ref[bottom_field]; + decoder->b_motion.ref2[1] = decoder->b_motion.ref[!bottom_field]; + offset = stride - offset; + + if (decoder->second_field && (decoder->coding_type != B_TYPE)) + forward_fbuf = current_fbuf; + + decoder->f_motion.ref[1][0] = forward_fbuf[0] + offset; +#if MPEG2_COLOR + decoder->f_motion.ref[1][1] = forward_fbuf[1] + (offset >> 1); + decoder->f_motion.ref[1][2] = forward_fbuf[2] + (offset >> 1); +#endif + decoder->b_motion.ref[1][0] = backward_fbuf[0] + offset; +#if MPEG2_COLOR + decoder->b_motion.ref[1][1] = backward_fbuf[1] + (offset >> 1); + decoder->b_motion.ref[1][2] = backward_fbuf[2] + (offset >> 1); +#endif + stride <<= 1; + height >>= 1; + } + + decoder->stride = stride; + decoder->slice_stride = 16 * stride; +#if MPEG2_COLOR + decoder->uv_stride = stride >> 1; + decoder->slice_uv_stride = + decoder->slice_stride >> (2 - decoder->chroma_format); +#endif + decoder->limit_x = 2 * decoder->width - 32; + decoder->limit_y_16 = 2 * height - 32; + decoder->limit_y_8 = 2 * height - 16; + decoder->limit_y = height - 16; + + if (decoder->mpeg1) + { + decoder->motion_parser[0] = motion_zero_420; + decoder->motion_parser[MC_FRAME] = motion_mp1; + decoder->motion_parser[4] = motion_reuse_420; + } + else if (decoder->picture_structure == FRAME_PICTURE) + { + if (decoder->chroma_format == 0) + { + decoder->motion_parser[0] = motion_zero_420; + decoder->motion_parser[MC_FIELD] = motion_fr_field_420; + decoder->motion_parser[MC_FRAME] = motion_fr_frame_420; + decoder->motion_parser[MC_DMV] = motion_fr_dmv_420; + decoder->motion_parser[4] = motion_reuse_420; + } + else if (decoder->chroma_format == 1) + { + decoder->motion_parser[0] = motion_zero_422; + decoder->motion_parser[MC_FIELD] = motion_fr_field_422; + decoder->motion_parser[MC_FRAME] = motion_fr_frame_422; + decoder->motion_parser[MC_DMV] = motion_fr_dmv_422; + decoder->motion_parser[4] = motion_reuse_422; + } + else + { + decoder->motion_parser[0] = motion_zero_444; + decoder->motion_parser[MC_FIELD] = motion_fr_field_444; + decoder->motion_parser[MC_FRAME] = motion_fr_frame_444; + decoder->motion_parser[MC_DMV] = motion_fr_dmv_444; + decoder->motion_parser[4] = motion_reuse_444; + } + } + else + { + if (decoder->chroma_format == 0) + { + decoder->motion_parser[0] = motion_zero_420; + decoder->motion_parser[MC_FIELD] = motion_fi_field_420; + decoder->motion_parser[MC_16X8] = motion_fi_16x8_420; + decoder->motion_parser[MC_DMV] = motion_fi_dmv_420; + decoder->motion_parser[4] = motion_reuse_420; + } + else if (decoder->chroma_format == 1) + { + decoder->motion_parser[0] = motion_zero_422; + decoder->motion_parser[MC_FIELD] = motion_fi_field_422; + decoder->motion_parser[MC_16X8] = motion_fi_16x8_422; + decoder->motion_parser[MC_DMV] = motion_fi_dmv_422; + decoder->motion_parser[4] = motion_reuse_422; + } + else + { + decoder->motion_parser[0] = motion_zero_444; + decoder->motion_parser[MC_FIELD] = motion_fi_field_444; + decoder->motion_parser[MC_16X8] = motion_fi_16x8_444; + decoder->motion_parser[MC_DMV] = motion_fi_dmv_444; + decoder->motion_parser[4] = motion_reuse_444; + } + } +} + +static inline int slice_init (mpeg2_decoder_t * const decoder, int code) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int offset; + const MBAtab * mba; + +#if MPEG2_COLOR + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 16384; +#else + decoder->dc_dct_pred[0] = 16384; +#endif + + decoder->f_motion.pmv[0][0] = decoder->f_motion.pmv[0][1] = 0; + decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[1][1] = 0; + decoder->b_motion.pmv[0][0] = decoder->b_motion.pmv[0][1] = 0; + decoder->b_motion.pmv[1][0] = decoder->b_motion.pmv[1][1] = 0; + + if (decoder->vertical_position_extension) + { + code += UBITS (bit_buf, 3) << 7; + DUMPBITS (bit_buf, bits, 3); + } + + decoder->v_offset = (code - 1) * 16; + offset = 0; + + if (!(decoder->convert) || decoder->coding_type != B_TYPE) + { + offset = (code - 1) * decoder->slice_stride; + } + + decoder->dest[0] = decoder->picture_dest[0] + offset; +#if MPEG2_COLOR + offset >>= (2 - decoder->chroma_format); + decoder->dest[1] = decoder->picture_dest[1] + offset; + decoder->dest[2] = decoder->picture_dest[2] + offset; +#endif + + get_quantizer_scale (decoder); + + /* ignore intra_slice and all the extra data */ + while (bit_buf & 0x80000000) + { + DUMPBITS (bit_buf, bits, 9); + NEEDBITS (bit_buf, bits, bit_ptr); + } + + /* decode initial macroblock address increment */ + offset = 0; + while (1) + { + if (bit_buf >= 0x08000000) + { + mba = MBA_5 + (UBITS (bit_buf, 6) - 2); + break; + } + else if (bit_buf >= 0x01800000) + { + mba = MBA_11 + (UBITS (bit_buf, 12) - 24); + break; + } + else + { + switch (UBITS (bit_buf, 12)) + { + case 8: /* macroblock_escape */ + offset += 33; + DUMPBITS (bit_buf, bits, 11); + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + case 15: /* macroblock_stuffing (MPEG1 only) */ + bit_buf &= 0xfffff; + DUMPBITS (bit_buf, bits, 11); + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + default: /* error */ + return 1; + } + } + } + + DUMPBITS (bit_buf, bits, mba->len + 1); + decoder->offset = (offset + mba->mba) << 4; + + while (decoder->offset - decoder->width >= 0) + { + decoder->offset -= decoder->width; + + if (!(decoder->convert) || decoder->coding_type != B_TYPE) + { + decoder->dest[0] += decoder->slice_stride; +#if MPEG2_COLOR + decoder->dest[1] += decoder->slice_uv_stride; + decoder->dest[2] += decoder->slice_uv_stride; +#endif + } + + decoder->v_offset += 16; + } + + if (decoder->v_offset > decoder->limit_y) + return 1; + + return 0; + +#undef bit_buf +#undef bits +#undef bit_ptr +} + +void mpeg2_slice (mpeg2_decoder_t * const decoder, const int code, + const uint8_t * const buffer) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + bitstream_init (decoder, buffer); + + if (slice_init (decoder, code)) + return; + + while (1) + { + int macroblock_modes; + int mba_inc; + const MBAtab * mba; + + NEEDBITS (bit_buf, bits, bit_ptr); + + macroblock_modes = get_macroblock_modes (decoder); + + /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */ + if (macroblock_modes & MACROBLOCK_QUANT) + get_quantizer_scale (decoder); + + if (macroblock_modes & MACROBLOCK_INTRA) + { + int DCT_offset, DCT_stride; + int offset; + uint8_t * dest_y; + + if (decoder->concealment_motion_vectors) + { + if (decoder->picture_structure == FRAME_PICTURE) + motion_fr_conceal (decoder); + else + motion_fi_conceal (decoder); + } + else + { + decoder->f_motion.pmv[0][0] = decoder->f_motion.pmv[0][1] = 0; + decoder->f_motion.pmv[1][0] = decoder->f_motion.pmv[1][1] = 0; + decoder->b_motion.pmv[0][0] = decoder->b_motion.pmv[0][1] = 0; + decoder->b_motion.pmv[1][0] = decoder->b_motion.pmv[1][1] = 0; + } + + if (macroblock_modes & DCT_TYPE_INTERLACED) + { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } + else + { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + + offset = decoder->offset; + dest_y = decoder->dest[0] + offset; + slice_intra_DCT (decoder, 0, dest_y, DCT_stride); + slice_intra_DCT (decoder, 0, dest_y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, dest_y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, dest_y + DCT_offset + 8, DCT_stride); + +#if MPEG2_COLOR + if (likely (decoder->chroma_format == 0)) + { + slice_intra_DCT (decoder, 1, decoder->dest[1] + (offset >> 1), + decoder->uv_stride); + slice_intra_DCT (decoder, 2, decoder->dest[2] + (offset >> 1), + decoder->uv_stride); + + if (decoder->coding_type == D_TYPE) + { + NEEDBITS (bit_buf, bits, bit_ptr); + DUMPBITS (bit_buf, bits, 1); + } + } + else if (likely (decoder->chroma_format == 1)) + { + uint8_t * dest_u = decoder->dest[1] + (offset >> 1); + uint8_t * dest_v = decoder->dest[2] + (offset >> 1); + + DCT_stride >>= 1; + DCT_offset >>= 1; + + slice_intra_DCT (decoder, 1, dest_u, DCT_stride); + slice_intra_DCT (decoder, 2, dest_v, DCT_stride); + slice_intra_DCT (decoder, 1, dest_u + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 2, dest_v + DCT_offset, DCT_stride); + } + else + { + uint8_t * dest_u = decoder->dest[1] + offset; + uint8_t * dest_v = decoder->dest[2] + offset; + + slice_intra_DCT (decoder, 1, dest_u, DCT_stride); + slice_intra_DCT (decoder, 2, dest_v, DCT_stride); + slice_intra_DCT (decoder, 1, dest_u + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 2, dest_v + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 1, dest_u + 8, DCT_stride); + slice_intra_DCT (decoder, 2, dest_v + 8, DCT_stride); + slice_intra_DCT (decoder, 1, dest_u + DCT_offset + 8, + DCT_stride); + slice_intra_DCT (decoder, 2, dest_v + DCT_offset + 8, + DCT_stride); + } +#else + skip_chroma_intra(decoder); +#endif /* MPEG2_COLOR */ + } + else + { + motion_parser_t * parser; + + parser = + decoder->motion_parser[macroblock_modes >> MOTION_TYPE_SHIFT]; + MOTION_CALL (parser, macroblock_modes); + + if (macroblock_modes & MACROBLOCK_PATTERN) + { + int coded_block_pattern; + int DCT_offset, DCT_stride; + + if (macroblock_modes & DCT_TYPE_INTERLACED) + { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } + else + { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + + coded_block_pattern = get_coded_block_pattern (decoder); + + if (likely (decoder->chroma_format == 0)) + { + int offset = decoder->offset; + uint8_t * dest_y = decoder->dest[0] + offset; + + if (coded_block_pattern & 1) + slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride); + + if (coded_block_pattern & 2) + slice_non_intra_DCT (decoder, 0, dest_y + 8, + DCT_stride); + + if (coded_block_pattern & 4) + slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset, + DCT_stride); + + if (coded_block_pattern & 8) + slice_non_intra_DCT (decoder, 0, + dest_y + DCT_offset + 8, + DCT_stride); +#if MPEG2_COLOR + if (coded_block_pattern & 16) + slice_non_intra_DCT (decoder, 1, + decoder->dest[1] + (offset >> 1), + decoder->uv_stride); + + if (coded_block_pattern & 32) + slice_non_intra_DCT (decoder, 2, + decoder->dest[2] + (offset >> 1), + decoder->uv_stride); +#endif /* MPEG2_COLOR */ + } + else if (likely (decoder->chroma_format == 1)) + { + int offset; + uint8_t * dest_y; + + coded_block_pattern |= bit_buf & (3 << 30); + DUMPBITS (bit_buf, bits, 2); + + offset = decoder->offset; + dest_y = decoder->dest[0] + offset; + + if (coded_block_pattern & 1) + slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride); + + if (coded_block_pattern & 2) + slice_non_intra_DCT (decoder, 0, dest_y + 8, + DCT_stride); + + if (coded_block_pattern & 4) + slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset, + DCT_stride); + + if (coded_block_pattern & 8) + slice_non_intra_DCT (decoder, 0, + dest_y + DCT_offset + 8, + DCT_stride); +#if MPEG2_COLOR + DCT_stride >>= 1; + DCT_offset = (DCT_offset + offset) >> 1; + + if (coded_block_pattern & 16) + slice_non_intra_DCT (decoder, 1, + decoder->dest[1] + (offset >> 1), + DCT_stride); + + if (coded_block_pattern & 32) + slice_non_intra_DCT (decoder, 2, + decoder->dest[2] + (offset >> 1), + DCT_stride); + + if (coded_block_pattern & (2 << 30)) + slice_non_intra_DCT (decoder, 1, + decoder->dest[1] + DCT_offset, + DCT_stride); + + if (coded_block_pattern & (1 << 30)) + slice_non_intra_DCT (decoder, 2, + decoder->dest[2] + DCT_offset, + DCT_stride); +#endif /* MPEG2_COLOR */ + } + else + { + int offset = decoder->offset; + uint8_t * dest_y = decoder->dest[0] + offset; +#if MPEG2_COLOR + uint8_t * dest_u = decoder->dest[1] + offset; + uint8_t * dest_v = decoder->dest[2] + offset; +#endif + coded_block_pattern |= bit_buf & (63 << 26); + DUMPBITS (bit_buf, bits, 6); + + if (coded_block_pattern & 1) + slice_non_intra_DCT (decoder, 0, dest_y, DCT_stride); + + if (coded_block_pattern & 2) + slice_non_intra_DCT (decoder, 0, dest_y + 8, + DCT_stride); + + if (coded_block_pattern & 4) + slice_non_intra_DCT (decoder, 0, dest_y + DCT_offset, + DCT_stride); + + if (coded_block_pattern & 8) + slice_non_intra_DCT (decoder, 0, + dest_y + DCT_offset + 8, + DCT_stride); +#if MPEG2_COLOR + if (coded_block_pattern & 16) + slice_non_intra_DCT (decoder, 1, dest_u, DCT_stride); + + if (coded_block_pattern & 32) + slice_non_intra_DCT (decoder, 2, dest_v, DCT_stride); + + if (coded_block_pattern & (32 << 26)) + slice_non_intra_DCT (decoder, 1, dest_u + DCT_offset, + DCT_stride); + + if (coded_block_pattern & (16 << 26)) + slice_non_intra_DCT (decoder, 2, dest_v + DCT_offset, + DCT_stride); + + if (coded_block_pattern & (8 << 26)) + slice_non_intra_DCT (decoder, 1, dest_u + 8, + DCT_stride); + + if (coded_block_pattern & (4 << 26)) + slice_non_intra_DCT (decoder, 2, dest_v + 8, + DCT_stride); + + if (coded_block_pattern & (2 << 26)) + slice_non_intra_DCT (decoder, 1, + dest_u + DCT_offset + 8, + DCT_stride); + + if (coded_block_pattern & (1 << 26)) + slice_non_intra_DCT (decoder, 2, + dest_v + DCT_offset + 8, + DCT_stride); +#endif /* MPEG2_COLOR */ + } +#if !MPEG2_COLOR + skip_chroma_non_intra(decoder, coded_block_pattern); +#endif + } + +#if MPEG2_COLOR + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 16384; +#else + decoder->dc_dct_pred[0] = 16384; +#endif + } + + NEXT_MACROBLOCK; + + NEEDBITS (bit_buf, bits, bit_ptr); + mba_inc = 0; + + while (1) + { + if (bit_buf >= 0x10000000) + { + mba = MBA_5 + (UBITS (bit_buf, 5) - 2); + break; + } + else if (bit_buf >= 0x03000000) + { + mba = MBA_11 + (UBITS (bit_buf, 11) - 24); + break; + } + else + { + switch (UBITS (bit_buf, 11)) + { + case 8: /* macroblock_escape */ + mba_inc += 33; + /* pass through */ + case 15: /* macroblock_stuffing (MPEG1 only) */ + DUMPBITS (bit_buf, bits, 11); + NEEDBITS (bit_buf, bits, bit_ptr); + continue; + default: /* end of slice, or error */ + return; + } + } + } + + DUMPBITS (bit_buf, bits, mba->len); + mba_inc += mba->mba; + + if (mba_inc) + { +#if MPEG2_COLOR + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 16384; +#else + decoder->dc_dct_pred[0] = 16384; +#endif + if (decoder->coding_type == P_TYPE) + { + do + { + MOTION_CALL (decoder->motion_parser[0], + MACROBLOCK_MOTION_FORWARD); + NEXT_MACROBLOCK; + } + while (--mba_inc); + } + else + { + do + { + MOTION_CALL (decoder->motion_parser[4], macroblock_modes); + NEXT_MACROBLOCK; + } + while (--mba_inc); + } + } + } + +#undef bit_buf +#undef bits +#undef bit_ptr +} diff --git a/apps/plugins/mpegplayer/libmpeg2/vlc.h b/apps/plugins/mpegplayer/libmpeg2/vlc.h 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 + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + * libmpeg2 sync history: + * 2008-07-01 - CVS revision 1.12 + */ + +#define GETWORD(bit_buf, shift, bit_ptr) \ +do { \ + bit_buf |= ((bit_ptr[0] << 8) | bit_ptr[1]) << (shift); \ + bit_ptr += 2; \ +} while (0) + +static inline void bitstream_init (mpeg2_decoder_t * decoder, + const uint8_t * start) +{ + decoder->bitstream_buf = + (start[0] << 24) | (start[1] << 16) | (start[2] << 8) | start[3]; + decoder->bitstream_ptr = start + 4; + decoder->bitstream_bits = -16; +} + +/* make sure that there are at least 16 valid bits in bit_buf */ +#define NEEDBITS(bit_buf, bits, bit_ptr) \ +do { \ + if (unlikely (bits > 0)) { \ + GETWORD (bit_buf, bits, bit_ptr); \ + bits -= 16; \ + } \ +} while (0) + +/* remove num valid bits from bit_buf */ +#define DUMPBITS(bit_buf, bits, num) \ +do { \ + bit_buf <<= (num); \ + bits += (num); \ +} while (0) + +/* take num bits from the high part of bit_buf and zero extend them */ +#define UBITS(bit_buf,num) (((uint32_t)(bit_buf)) >> (32 - (num))) + +/* take num bits from the high part of bit_buf and sign extend them */ +#define SBITS(bit_buf,num) (((int32_t)(bit_buf)) >> (32 - (num))) + +typedef struct { + uint8_t modes; + uint8_t len; +} MBtab; + +typedef struct { + uint8_t delta; + uint8_t len; +} MVtab; + +typedef struct { + int8_t dmv; + uint8_t len; +} DMVtab; + +typedef struct { + uint8_t cbp; + uint8_t len; +} CBPtab; + +typedef struct { + uint8_t size; + uint8_t len; +} DCtab; + +typedef struct { + uint8_t run; + uint8_t level; + uint8_t len; +} DCTtab; + +typedef struct { + uint8_t mba; + uint8_t len; +} MBAtab; + + +#define INTRA MACROBLOCK_INTRA +#define QUANT MACROBLOCK_QUANT + +static const MBtab MB_I [] ICONST_ATTR = { + {INTRA|QUANT, 2}, {INTRA, 1} +}; + +#define MC MACROBLOCK_MOTION_FORWARD +#define CODED MACROBLOCK_PATTERN + +static const MBtab MB_P [] ICONST_ATTR = { + {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5}, + {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1} +}; + +#define FWD MACROBLOCK_MOTION_FORWARD +#define BWD MACROBLOCK_MOTION_BACKWARD +#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD + +static const MBtab MB_B [] ICONST_ATTR = { + {0, 6}, {INTRA|QUANT, 6}, + {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6}, + {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5}, + {INTRA, 5}, {INTRA, 5}, + {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4}, + {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2} +}; + +#undef INTRA +#undef QUANT +#undef MC +#undef CODED +#undef FWD +#undef BWD +#undef INTER + + +static const MVtab MV_4 [] ICONST_ATTR = { + { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} +}; + +static const MVtab MV_10 [] ICONST_ATTR = { + { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, + { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10}, + {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9}, + { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, + { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, + { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7} +}; + + +static const DMVtab DMV_2 [] ICONST_ATTR = { + { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2} +}; + + +static const CBPtab CBP_7 [] ICONST_ATTR = { + {0x11, 7}, {0x12, 7}, {0x14, 7}, {0x18, 7}, + {0x21, 7}, {0x22, 7}, {0x24, 7}, {0x28, 7}, + {0x3f, 6}, {0x3f, 6}, {0x30, 6}, {0x30, 6}, + {0x09, 6}, {0x09, 6}, {0x06, 6}, {0x06, 6}, + {0x1f, 5}, {0x1f, 5}, {0x1f, 5}, {0x1f, 5}, + {0x10, 5}, {0x10, 5}, {0x10, 5}, {0x10, 5}, + {0x2f, 5}, {0x2f, 5}, {0x2f, 5}, {0x2f, 5}, + {0x20, 5}, {0x20, 5}, {0x20, 5}, {0x20, 5}, + {0x07, 5}, {0x07, 5}, {0x07, 5}, {0x07, 5}, + {0x0b, 5}, {0x0b, 5}, {0x0b, 5}, {0x0b, 5}, + {0x0d, 5}, {0x0d, 5}, {0x0d, 5}, {0x0d, 5}, + {0x0e, 5}, {0x0e, 5}, {0x0e, 5}, {0x0e, 5}, + {0x05, 5}, {0x05, 5}, {0x05, 5}, {0x05, 5}, + {0x0a, 5}, {0x0a, 5}, {0x0a, 5}, {0x0a, 5}, + {0x03, 5}, {0x03, 5}, {0x03, 5}, {0x03, 5}, + {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, + {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4}, + {0x01, 4}, {0x01, 4}, {0x01, 4}, {0x01, 4}, + {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4}, + {0x02, 4}, {0x02, 4}, {0x02, 4}, {0x02, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, + {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, + {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, + {0x0f, 3}, {0x0f, 3}, {0x0f, 3}, {0x0f, 3} +}; + +static const CBPtab CBP_9 [] ICONST_ATTR = { + {0, 9}, {0x00, 9}, {0x39, 9}, {0x36, 9}, + {0x37, 9}, {0x3b, 9}, {0x3d, 9}, {0x3e, 9}, + {0x17, 8}, {0x17, 8}, {0x1b, 8}, {0x1b, 8}, + {0x1d, 8}, {0x1d, 8}, {0x1e, 8}, {0x1e, 8}, + {0x27, 8}, {0x27, 8}, {0x2b, 8}, {0x2b, 8}, + {0x2d, 8}, {0x2d, 8}, {0x2e, 8}, {0x2e, 8}, + {0x19, 8}, {0x19, 8}, {0x16, 8}, {0x16, 8}, + {0x29, 8}, {0x29, 8}, {0x26, 8}, {0x26, 8}, + {0x35, 8}, {0x35, 8}, {0x3a, 8}, {0x3a, 8}, + {0x33, 8}, {0x33, 8}, {0x3c, 8}, {0x3c, 8}, + {0x15, 8}, {0x15, 8}, {0x1a, 8}, {0x1a, 8}, + {0x13, 8}, {0x13, 8}, {0x1c, 8}, {0x1c, 8}, + {0x25, 8}, {0x25, 8}, {0x2a, 8}, {0x2a, 8}, + {0x23, 8}, {0x23, 8}, {0x2c, 8}, {0x2c, 8}, + {0x31, 8}, {0x31, 8}, {0x32, 8}, {0x32, 8}, + {0x34, 8}, {0x34, 8}, {0x38, 8}, {0x38, 8} +}; + + +static const DCtab DC_lum_5 [] ICONST_ATTR = { + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5} +}; + +static const DCtab DC_chrom_5 [] ICONST_ATTR = { + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5} +}; + +static const DCtab DC_long [] ICONST_ATTR = { + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6}, + {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9} +}; + + +static const DCTtab DCT_16 [] ICONST_ATTR = { + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0}, + { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0}, + { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0}, + { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0} +}; + +static const DCTtab DCT_15 [] ICONST_ATTR = { + { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15}, + { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15}, + { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15}, + { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15}, + { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14}, + { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14}, + { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14}, + { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14}, + { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14}, + { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14}, + { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14}, + { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14} +}; + +static const DCTtab DCT_13 [] ICONST_ATTR = { + { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13}, + { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13}, + { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13}, + { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13}, + { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12}, + { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12}, + { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12}, + { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12}, + { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12}, + { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12}, + { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12}, + { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12} +}; + +static const DCTtab DCT_B14_10 [] ICONST_ATTR = { + { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10}, + { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10} +}; + +static const DCTtab DCT_B14_8 [] ICONST_ATTR = { + { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, + { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7}, + { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, + { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, + { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8}, + { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8} +}; + +static const DCTtab DCT_B14AC_5 [] ICONST_ATTR = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2} +}; + +static const DCTtab DCT_B14DC_5 [] ICONST_ATTR = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1} +}; + +static const DCTtab DCT_B15_10 [] ICONST_ATTR = { + { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9}, + { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9} +}; + +static const DCTtab DCT_B15_8 [] ICONST_ATTR = { + { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, { 65, 0, 12}, + { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7}, + { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, + { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, + { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8}, + { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7}, + { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7}, + { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8}, + { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8} +}; + + +static const MBAtab MBA_5 [] ICONST_ATTR = { + {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} +}; + +static const MBAtab MBA_11 [] ICONST_ATTR = { + {32, 11}, {31, 11}, {30, 11}, {29, 11}, + {28, 11}, {27, 11}, {26, 11}, {25, 11}, + {24, 11}, {23, 11}, {22, 11}, {21, 11}, + {20, 10}, {20, 10}, {19, 10}, {19, 10}, + {18, 10}, {18, 10}, {17, 10}, {17, 10}, + {16, 10}, {16, 10}, {15, 10}, {15, 10}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} +}; -- cgit v1.2.3