summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2001-07-22 14:18:56 +0000
committerFabrice Bellard <fabrice@bellard.org>2001-07-22 14:18:56 +0000
commitde6d9b6404bfd1c589799142da5a95428f146edd (patch)
tree75ae0cbb74bdfafb6f1a40922db111a103db3bcf
parent1b58d58ddaf8a8c766a0353885ff504babed0453 (diff)
Initial revision
Originally committed as revision 5 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--Changelog139
-rw-r--r--INSTALL8
-rwxr-xr-xconfigure75
-rw-r--r--doc/README.dev20
-rw-r--r--doc/bench.txt52
-rw-r--r--doc/ffserver.txt79
-rw-r--r--libav/asf.c956
-rw-r--r--libav/audio.c179
-rw-r--r--libav/avformat.h192
-rw-r--r--libav/avi.h29
-rw-r--r--libav/avidec.c257
-rw-r--r--libav/avienc.c366
-rw-r--r--libav/avio.c146
-rw-r--r--libav/avio.h151
-rw-r--r--libav/aviobuf.c426
-rw-r--r--libav/ffm.c599
-rw-r--r--libav/file.c121
-rw-r--r--libav/grab.c321
-rw-r--r--libav/http.c318
-rw-r--r--libav/img.c578
-rw-r--r--libav/jpegenc.c102
-rw-r--r--libav/mpeg.c663
-rw-r--r--libav/raw.c288
-rw-r--r--libav/rm.c710
-rw-r--r--libav/swf.c552
-rw-r--r--libav/udp.c148
-rw-r--r--libav/utils.c533
-rw-r--r--libav/wav.c211
-rw-r--r--libavcodec/Makefile59
-rw-r--r--libavcodec/ac3dec.c189
-rw-r--r--libavcodec/ac3enc.c1460
-rw-r--r--libavcodec/ac3enc.h32
-rw-r--r--libavcodec/ac3tab.h180
-rw-r--r--libavcodec/apiexample.c407
-rw-r--r--libavcodec/avcodec.h177
-rw-r--r--libavcodec/common.c469
-rw-r--r--libavcodec/common.h170
-rw-r--r--libavcodec/dct-test.c105
-rw-r--r--libavcodec/dsputil.c383
-rw-r--r--libavcodec/dsputil.h91
-rw-r--r--libavcodec/fdctref.c120
-rw-r--r--libavcodec/h263.c1291
-rw-r--r--libavcodec/h263data.h115
-rw-r--r--libavcodec/h263dec.c205
-rw-r--r--libavcodec/i386/cputest.c102
-rw-r--r--libavcodec/i386/dsputil_mmx.c1061
-rw-r--r--libavcodec/i386/dsputil_mmx_avg.h352
-rw-r--r--libavcodec/i386/fdct_mmx.s507
-rw-r--r--libavcodec/i386/fdctdata.c143
-rw-r--r--libavcodec/i386/mmx.h536
-rw-r--r--libavcodec/i386/sad_mmx.s798
-rw-r--r--libavcodec/imgconvert.c214
-rw-r--r--libavcodec/imgresample.c614
-rw-r--r--libavcodec/jfdctfst.c224
-rw-r--r--libavcodec/jrevdct.c1167
-rw-r--r--libavcodec/libac3/ac3.h108
-rw-r--r--libavcodec/libac3/ac3_internal.h51
-rw-r--r--libavcodec/libac3/bit_allocate.c255
-rw-r--r--libavcodec/libac3/bitstream.c77
-rw-r--r--libavcodec/libac3/bitstream.h68
-rw-r--r--libavcodec/libac3/downmix.c533
-rw-r--r--libavcodec/libac3/imdct.c408
-rw-r--r--libavcodec/libac3/parse.c684
-rw-r--r--libavcodec/libac3/tables.h250
-rw-r--r--libavcodec/mjpegenc.c417
-rw-r--r--libavcodec/motion_est.c517
-rw-r--r--libavcodec/mpeg12.c1530
-rw-r--r--libavcodec/mpeg12data.h362
-rw-r--r--libavcodec/mpeg4data.h106
-rw-r--r--libavcodec/mpegaudio.c774
-rw-r--r--libavcodec/mpegaudio.h34
-rw-r--r--libavcodec/mpegaudiodec.c293
-rw-r--r--libavcodec/mpegaudiotab.h310
-rw-r--r--libavcodec/mpegvideo.c1281
-rw-r--r--libavcodec/mpegvideo.h273
-rw-r--r--libavcodec/msmpeg4.c931
-rw-r--r--libavcodec/msmpeg4data.h1767
-rw-r--r--libavcodec/resample.c301
-rw-r--r--libavcodec/rv10.c487
-rw-r--r--libavcodec/utils.c306
80 files changed, 31513 insertions, 0 deletions
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000000..3d1421639c
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,139 @@
+version 0.4.5:
+
+- some header fixes (Zdenek Kabelac <kabi@informatics.muni.cz>).
+- many MMX optimizations (Nick Kurshev <nickols_k@mail.ru>).
+- added configure system (actually a small shell script).
+- added mpeg audio layer 1/2/3 decoding using LGPL'ed mpglib by
+ Michael Hipp (temporary solution - waiting for integer only
+ decoder).
+- fixed VIDIOCSYNC interrupt.
+- added Intel H263 decoding support ('I263' avi fourCC)
+- added Real Video 1.0 decoding (needs further testing).
+- simplified image formats again. Added PGM format (=grey
+ pgm). Renamed old PGM to PGMYUV.
+- fixed msmpeg4 slice issues (tell me if you still find problems).
+- fixed opendivx bugs with newer versions (added VOL header decoding).
+- added support for mplayer interface.
+
+version 0.4.4:
+
+- fixed some std header definitions (Bjorn Lindgren
+ <bjorn.e.lindgren@telia.com>).
+- added mpeg demux (mpeg 1 and 2 compatible).
+- added ASF demux.
+- added prototype RM demux.
+- added AC3 decoding (done with libac3 by Aaron Holtzman).
+- added decoding codec parameter guessing (.e.g. for mpeg, because the
+ header does not include them).
+- fixed header generation in mpeg1, AVI and ASF mux : wmplayer can now
+ play them (only tested video).
+- fixed h263 white bug.
+- fixed phase rounding in img resample filter.
+- add mmx code for polyphase img resample filter.
+- added CPU autodetect.
+- added generic title/author/copyright/comment string handling (ASF and RM use them).
+- added SWF demux to extract MP3 track (not usable yet because no MP3
+ decoder).
+- added fractional frame rate support.
+- codecs are no longer searched by read_header() (should fix ffserver
+ segfault).
+
+version 0.4.3:
+
+- BGR24 patch (initial patch by Jeroen Vreeken <pe1rxq@amsat.org>).
+- fixed raw yuv output.
+- added motion rounding support in MPEG4.
+- fixed motion bug rounding in MSMPEG4.
+- added B frame handling in video core.
+- added full MPEG1 decoding support.
+- added partial (frame only) MPEG2 support.
+- changed the FOURCC code for H.263 to "U263" to be able to see the
++AVI/H.263 file with the UB Video H.263+ decoder. MPlayer works with
+this +codec ;) (JuanJo).
+- Halfpel motion estimation after mb type selection (JuanJo).
+- added pgm and .Y.U.V output format.
+- suppressed 'img:' protocol. Simply use: /tmp/test%d.[pgm|Y] as input or
+ output.
+- added pgmpipe I/O format (original patch from Martin Aumueller
+ <lists@reserv.at>, but changed completely since we use a format
+ instead of a protocol).
+
+version 0.4.2:
+
+- added H263/MPEG4/MSMPEG4 decoding support. MPEG4 decoding support
+ (for openDIVX) is almost complete: 8x8 MVs and rounding are
+ missing. MSMPEG4 support is complete.
+- added prototype MPEG1 decoder. Only I and P frames handled yet (it
+ can decode ffmpeg mpegs :-)).
+- added libavcodec API documentation (see apiexample.c).
+- fixed image polyphase bug (the bottom of some images could be
+ greenish).
+- added support for non clipped motion vectors (decoding only)
+ and image sizes non multiple of 16.
+- added support for AC prediction (decoding only).
+- added file overwrite confirmation (can be disabled with -y).
+- Added custom size picture to H.263 using H.263+ (Juanjo).
+
+version 0.4.1:
+
+- added MSMPEG4 (aka DIVX) compatible encoder. Changed default codec
+ of avi and asf to DIV3.
+- added -me option to set motion estimation method
+ (default=log). suppressed redundant -hq option.
+- added options -acodec and -vcodec to force a given codec (useful for
+ AVI for example).
+- fixed -an option.
+- improved dct_quantize speed.
+- factorized some motion estimation code.
+
+version 0.4.0:
+
+- removing grab code from ffserver and moved it to ffmpeg. Added multi
+ stream support to ffmpeg.
+- added timeshifting support for live feeds (option ?date=xxx in the
+ URL).
+- added high quality image resize code with polyphase filter (need
+ mmx/see optimisation). Enable multiple image size support in ffserver.
+- added multi live feed support in ffserver.
+- suppressed master feature from ffserver (it should be done with an
+ external program which opens the .ffm url and writes it to another
+ ffserver).
+- added preliminary support for video stream parsing (wav and avi half
+ done). Added proper support for audio/video file convertion in
+ ffmpeg.
+- added preliminary support for video file sending from ffserver.
+- redesigning I/O subsystem : now using URL based input and output
+ (see avio.h).
+- added wav format support.
+- added "tty user interface" to ffmpeg to stop grabbing gracefully.
+- added MMX/SSE optimizations to SAD (Sums of Absolutes Diferences)
+ (Juan J. Sierralta P. a.k.a. "Juanjo" <juanjo@atmlab.utfsm.cl>).
+- added MMX DCT from mpeg2_movie 1.5 (Juanjo).
+- added new motion estimation algorithms, log and phods (Juanjo).
+- changed directories : libav for format handling, libavcodec for
+ codecs.
+
+version 0.3.4:
+
+- added stereo in mpeg audio encoder.
+
+version 0.3.3:
+
+- added 'high quality' mode which use motion vectors. It can be used in
+ real time at low resolution.
+- fixed rounding problems which caused quality problems at high
+ bitrates and large gop size.
+
+version 0.3.2: small fixes
+
+- asf fixes
+- put_seek bug fix
+
+version 0.3.1: added avi/divx support
+
+- added avi support
+- added mpeg4 codec compatible with open divx. It is based on the h263
+ codec.
+- added sound for flash format (not tested)
+
+version 0.3: initial public release
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000000..aa2f6a3ef4
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,8 @@
+
+1) Type './configure' create the configuration (use './configure
+--help' to have the configure options).
+
+2) Then type 'make' to build ffmpeg.
+
+3) Type 'make install' to install ffmpeg and ffserver in
+/usr/local/bin.
diff --git a/configure b/configure
new file mode 100755
index 0000000000..f22c837398
--- /dev/null
+++ b/configure
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+# default parameters
+prefix="/usr/local"
+cc="gcc"
+ar="ar"
+cpu=`uname -m`
+case "$cpu" in
+ i386|i486|i586|i686)
+ cpu="x86"
+ mmx="yes"
+ ;;
+ *)
+ mmx="no"
+ ;;
+esac
+gprof="no"
+
+if [ "$1" = "-h" -o "$1" = "--help" ] ; then
+cat << EOF
+
+Usage: configure [options]
+Options: [defaults in brackets after descriptions]
+
+ --help print this message
+EOF
+echo " --prefix=PREFIX install in PREFIX [$prefix]"
+echo " --cc=CC use C compiler CC [$cc]"
+echo " --cpu=CPU force cpu to CPU [$cpu]"
+echo " --disable-mmx disable mmx usage"
+echo " --enable-gprof enable profiling with gprof [$gprof]"
+exit 1
+fi
+
+for opt do
+ case "$opt" in
+ --prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --cc=*) cc=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --disable-mmx) mmx="no"
+ ;;
+ --enable-gprof) gprof="yes"
+ ;;
+ esac
+done
+
+echo "Install prefix $prefix"
+echo "C compiler $cc"
+echo "CPU $cpu"
+echo "MMX enabled $mmx"
+echo "gprof enabled $gprof"
+
+echo "Creating config.mk and config.h"
+
+echo "# Automatically generated by configure - do not modify" > config.mk
+echo "/* Automatically generated by configure - do not modify */" > config.h
+
+echo "PREFIX=$prefix" >> config.mk
+echo "CC=$cc" >> config.mk
+echo "AR=$ar" >> config.mk
+if [ "$cpu" = "x86" ] ; then
+ echo "CONFIG_CPU_X86=y" >> config.mk
+ echo "#define CONFIG_CPU_X86 1" >> config.h
+fi
+if [ "$mmx" = "yes" ] ; then
+ echo "CONFIG_MMX=y" >> config.mk
+ echo "#define CONFIG_MMX 1" >> config.h
+fi
+if [ "$gprof" = "yes" ] ; then
+ echo "CONFIG_GPROF=y" >> config.mk
+ echo "#define CONFIG_GPROF 1" >> config.h
+fi
diff --git a/doc/README.dev b/doc/README.dev
new file mode 100644
index 0000000000..ae28bc03be
--- /dev/null
+++ b/doc/README.dev
@@ -0,0 +1,20 @@
+1) API
+------
+
+* libavcodec is the library containing the codecs (both encoding and
+ decoding). See libavcodec/apiexample.c to see how to use it.
+
+* libav is the library containing the file formats handling (mux and
+ demux code for several formats). (no example yet, the API is likely
+ to evolve).
+
+2) Coding Rules
+---------------
+
+ffmpeg is programmed in ANSI C language. GCC extension are
+tolerated. TAB size is 4. The identation is the one specified by
+'indent -i4 -kr'.
+
+Main priority in ffmpeg is simplicity and small code size (=less
+bugs).
+
diff --git a/doc/bench.txt b/doc/bench.txt
new file mode 100644
index 0000000000..a60572e54c
--- /dev/null
+++ b/doc/bench.txt
@@ -0,0 +1,52 @@
+
+source: MarsAttack, divx, 800 kbit/s
+
+q=10 constant:
+
+* full motion search, fcode=1, half pel:
+ Video: opendivx (hq), 640x352, 25 fps, 200 kb/s
+frame= 500 q=10 size= 1815kB time=20.0 bitrate= 743.6kbits/s
+
+* log motion search:
+ Video: opendivx (hq), 640x352, 25 fps, 200 kb/s
+frame= 500 q=10 size= 1995kB time=20.0 bitrate= 817.2kbits/s
+
+* no motion search:
+ Video: opendivx, 640x352, 25 fps, 200 kb/s
+frame= 500 size= 3197kB time=20.0 fps=25.0 bitrate=1309.6kbits/s q=10
+
+* log motion search:
+ Video: opendivx (hq), 640x352, 25 fps, 200 kb/s
+frame= 500 q=10 size= 1995kB time=20.0 bitrate= 817.2kbits/s
+
+./ffmpeg -me log -t 20 -g 100 -qscale 10 -i img:%d.pgm -an /tmp/b.avi
+ Stream #0.0: Video: msmpeg4, 640x352, 25 fps, 200 kb/s
+frame= 500 q=10 size= 1833kB time=20.0 bitrate= 750.9kbits/s
+
+./ffmpeg -me full -t 20 -g 100 -qscale 10 -i img:%d.pgm -an /tmp/b.avi
+ Stream #0.0: Video: msmpeg4, 640x352, 25 fps, 200 kb/s
+frame= 500 q=10 size= 1793kB time=20.0 bitrate= 734.8kbits/s
+
+-------------------------------------------
+
+* with -sameq, -me log
+
+./ffmpeg -g 100 -t 20 -sameq -i MarsAttacks_f800.avi -an /tmp/a.avi
+ Stream #0.0: Video: msmpeg4, 640x352, 25 fps, 200 kb/s
+frame= 500 q= 5 size= 2605kB time=20.0 bitrate=1067.1kbits/s
+
+./ffmpeg -g 100 -t 20 -sameq -i MarsAttacks_f800.avi -f mpeg1video -an /tmp/a.mpg
+ Stream #0.0: Video: mpeg1video, 640x352, 25 fps, 200 kb/s
+frame= 500 q= 5 size= 2655kB time=20.0 bitrate=1087.7kbits/s
+
+./ffmpeg -g 100 -t 20 -sameq -i MarsAttacks_f800.avi -vcodec opendivx -an /tmp/a.avi
+frame= 500 q= 5 size= 2774kB time=20.0 bitrate=1136.2kbits/s
+
+
+the matrix, complete, video only:
+
+source=14147kB
+
+ffmpeg:
+ mpeg1 17154kB (20%)
+ msmpeg4 17229kB
diff --git a/doc/ffserver.txt b/doc/ffserver.txt
new file mode 100644
index 0000000000..7019556043
--- /dev/null
+++ b/doc/ffserver.txt
@@ -0,0 +1,79 @@
+*************** FFserver live broadcast server *****************
+
+0) Introduction
+
+ffserver is a streaming server for both audio and video. It supports
+several live feeds, streaming from files and time shifting on live
+feeds (you can seek to positions in the past on each live feed,
+provided you specify a big enough feed storage in ffserver.conf).
+
+1) Quick help
+
+- First you must ensure that your grab system is OK. Verify with
+ 'xawtv' that your TV card is tuned on a correct video source.
+
+- Try with ffmpeg that you can record correctly. For example:
+
+ ffmpeg /tmp/a.mpg
+
+will record a ten seconds mpeg file from your TV card and audio
+card. Use for example the mpegtv player or MPlayer to view the created
+MPEG file.
+
+- Launch ffserver on your PC with the sample config file:
+
+ ffserver -f doc/ffserver.conf
+
+- Verify with your browser that ffserver is working correctly. For
+ that purpose, explore: http://localhost:8090/stat.html .
+
+- Now launch ffmpeg to do real time encoding :
+
+ ffmpeg http://localhost:8090/feed1.ffm
+
+- Then, use your favorite players to see each generated stream:
+
+ mtvp http://localhost:8090/test1.mpg
+
+ mpg123 http://localhost:8090/test.mp2
+
+ netscape http://localhost:8090/test.swf
+
+ realplayer http://localhost:8090/test.rm
+
+ etc...
+
+ Note that ffserver generate multiple streams in multiple formats AT
+ THE SAME TIME. It should be able to handle hundreds of users at the
+ same time if you internet connection is fast enough.
+
+- Now you can configure ffserver for your real needs. Edit the
+ ffserver.conf file to use only the formats you want. Read the ffmpeg
+ documentation (ffmpeg.txt) to learn more about the codec and format
+ stuff.
+
+- Report any bug you find (and the fix if you have it!).
+
+2) URL Format
+
+ ffserver supports that you seek in some formats. The syntax is to
+ add a '?' option to the URL. Only the 'date' option is supported.
+
+ The date format is [YYYY-MM-DDT][[HH:]MM:]SS[.m...] (clost to ISO
+ date format). For live streams, the date is absolute and give in
+ GMT. If the day is not specified, the current day is used.
+
+ example:
+
+ mpg123 http://localhost:8090/test.mp2?date=10:00
+
+ play the stream starting at 10:00 AM GMT today.
+
+ mpg123 http://localhost:8090/test.mp2?date=2001-06-23T23:00
+
+ is also a valid date.
+
+ For file streams, the date is relative to the start of the file. No
+ day can be specified.
+
+
diff --git a/libav/asf.c b/libav/asf.c
new file mode 100644
index 0000000000..0306ed37c9
--- /dev/null
+++ b/libav/asf.c
@@ -0,0 +1,956 @@
+/*
+ * ASF compatible encoder and decoder.
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "avformat.h"
+#include "avi.h"
+
+#define PACKET_SIZE 3200
+#define PACKET_HEADER_SIZE 12
+#define FRAME_HEADER_SIZE 17
+
+typedef struct {
+ int num;
+ int seq;
+ /* use for reading */
+ AVPacket pkt;
+ int frag_offset;
+} ASFStream;
+
+typedef struct {
+ int seqno;
+ int packet_size;
+
+ ASFStream streams[2];
+ /* non streamed additonnal info */
+ int data_offset;
+ INT64 nb_packets;
+ INT64 duration; /* in 100ns units */
+ /* packet filling */
+ int packet_size_left;
+ int packet_timestamp_start;
+ int packet_timestamp_end;
+ int packet_nb_frames;
+ UINT8 packet_buf[PACKET_SIZE];
+ ByteIOContext pb;
+ /* only for reading */
+ int packet_padsize;
+} ASFContext;
+
+typedef struct {
+ UINT32 v1;
+ UINT16 v2;
+ UINT16 v3;
+ UINT8 v4[8];
+} GUID;
+
+static const GUID asf_header = {
+ 0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C },
+};
+
+static const GUID file_header = {
+ 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
+};
+
+static const GUID stream_header = {
+ 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
+};
+
+static const GUID audio_stream = {
+ 0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
+};
+
+static const GUID audio_conceal_none = {
+ 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
+};
+
+static const GUID video_stream = {
+ 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
+};
+
+static const GUID video_conceal_none = {
+ 0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
+};
+
+
+static const GUID comment_header = {
+ 0x75b22633, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
+};
+
+static const GUID codec_comment_header = {
+ 0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },
+};
+static const GUID codec_comment1_header = {
+ 0x86d15241, 0x311d, 0x11d0, { 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
+};
+
+static const GUID data_header = {
+ 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
+};
+
+static const GUID index_guid = {
+ 0x33000890, 0xe5b1, 0x11cf, { 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb },
+};
+
+static const GUID head1_guid = {
+ 0x5fbf03b5, 0xa92e, 0x11cf, { 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
+};
+
+static const GUID head2_guid = {
+ 0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
+};
+
+/* I am not a number !!! This GUID is the one found on the PC used to
+ generate the stream */
+static const GUID my_guid = {
+ 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static void put_guid(ByteIOContext *s, const GUID *g)
+{
+ int i;
+
+ put_le32(s, g->v1);
+ put_le16(s, g->v2);
+ put_le16(s, g->v3);
+ for(i=0;i<8;i++)
+ put_byte(s, g->v4[i]);
+}
+
+static void put_str16(ByteIOContext *s, const char *tag)
+{
+ int c;
+
+ put_le16(s,strlen(tag) + 1);
+ for(;;) {
+ c = (UINT8)*tag++;
+ put_le16(s, c);
+ if (c == '\0')
+ break;
+ }
+}
+
+static void put_str16_nolen(ByteIOContext *s, const char *tag)
+{
+ int c;
+
+ for(;;) {
+ c = (UINT8)*tag++;
+ put_le16(s, c);
+ if (c == '\0')
+ break;
+ }
+}
+
+static INT64 put_header(ByteIOContext *pb, const GUID *g)
+{
+ INT64 pos;
+
+ pos = url_ftell(pb);
+ put_guid(pb, g);
+ put_le64(pb, 24);
+ return pos;
+}
+
+/* update header size */
+static void end_header(ByteIOContext *pb, INT64 pos)
+{
+ INT64 pos1;
+
+ pos1 = url_ftell(pb);
+ url_fseek(pb, pos + 16, SEEK_SET);
+ put_le64(pb, pos1 - pos);
+ url_fseek(pb, pos1, SEEK_SET);
+}
+
+/* write an asf chunk (only used in streaming case) */
+static void put_chunk(AVFormatContext *s, int type, int payload_length)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int length;
+
+ length = payload_length + 8;
+ put_le16(pb, type);
+ put_le16(pb, length);
+ put_le32(pb, asf->seqno);
+ put_le16(pb, 0); /* unknown bytes */
+ put_le16(pb, length);
+ asf->seqno++;
+}
+
+/* convert from unix to windows time */
+static INT64 unix_to_file_time(int ti)
+{
+ INT64 t;
+
+ t = ti * 10000000LL;
+ t += 116444736000000000LL;
+ return t;
+}
+
+/* write the header (used two times if non streamed) */
+static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chunk_size)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
+ int has_title;
+ AVCodecContext *enc;
+ INT64 header_offset, cur_pos, hpos;
+
+ has_title = (s->title[0] != '\0');
+
+ if (!url_is_streamed(&s->pb)) {
+ put_guid(pb, &asf_header);
+ put_le64(pb, 0); /* header length, will be patched after */
+ put_le32(pb, 3 + has_title + s->nb_streams); /* number of chunks in header */
+ put_byte(pb, 1); /* ??? */
+ put_byte(pb, 2); /* ??? */
+ } else {
+ put_chunk(s, 0x4824, 0); /* start of stream (length will be patched later) */
+ }
+
+ /* file header */
+ header_offset = url_ftell(pb);
+ hpos = put_header(pb, &file_header);
+ put_guid(pb, &my_guid);
+ put_le64(pb, file_size);
+ file_time = 0;
+ put_le64(pb, unix_to_file_time(file_time));
+ put_le64(pb, asf->nb_packets); /* number of packets */
+ put_le64(pb, asf->duration); /* end time stamp (in 100ns units) */
+ put_le64(pb, asf->duration); /* duration (in 100ns units) */
+ put_le32(pb, 0); /* start time stamp */
+ put_le32(pb, 0); /* ??? */
+ put_le32(pb, 0); /* ??? */
+ put_le32(pb, asf->packet_size); /* packet size */
+ put_le32(pb, asf->packet_size); /* packet size */
+ put_le32(pb, 80 * asf->packet_size); /* frame_size ??? */
+ end_header(pb, hpos);
+
+ /* unknown headers */
+ hpos = put_header(pb, &head1_guid);
+ put_guid(pb, &head2_guid);
+ put_le32(pb, 6);
+ put_le16(pb, 0);
+ end_header(pb, hpos);
+
+ /* title and other infos */
+ if (has_title) {
+ hpos = put_header(pb, &comment_header);
+ put_le16(pb, 2 * (strlen(s->title) + 1));
+ put_le16(pb, 2 * (strlen(s->author) + 1));
+ put_le16(pb, 2 * (strlen(s->copyright) + 1));
+ put_le16(pb, 2 * (strlen(s->comment) + 1));
+ put_le16(pb, 0);
+ put_str16_nolen(pb, s->title);
+ put_str16_nolen(pb, s->author);
+ put_str16_nolen(pb, s->copyright);
+ put_str16_nolen(pb, s->comment);
+ end_header(pb, hpos);
+ }
+
+ /* stream headers */
+ for(n=0;n<s->nb_streams;n++) {
+ enc = &s->streams[n]->codec;
+ asf->streams[n].num = n + 1;
+ asf->streams[n].seq = 0;
+
+ switch(enc->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ wav_extra_size = 0;
+ extra_size = 18 + wav_extra_size;
+ extra_size2 = 0;
+ break;
+ default:
+ case CODEC_TYPE_VIDEO:
+ wav_extra_size = 0;
+ extra_size = 0x33;
+ extra_size2 = 0;
+ break;
+ }
+
+ hpos = put_header(pb, &stream_header);
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ put_guid(pb, &audio_stream);
+ put_guid(pb, &audio_conceal_none);
+ } else {
+ put_guid(pb, &video_stream);
+ put_guid(pb, &video_conceal_none);
+ }
+ put_le64(pb, 0); /* ??? */
+ put_le32(pb, extra_size); /* wav header len */
+ put_le32(pb, extra_size2); /* additional data len */
+ put_le16(pb, n + 1); /* stream number */
+ put_le32(pb, 0); /* ??? */
+
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ /* WAVEFORMATEX header */
+ put_wav_header(pb, enc);
+ } else {
+ put_le32(pb, enc->width);
+ put_le32(pb, enc->height);
+ put_byte(pb, 2); /* ??? */
+ put_le16(pb, 40); /* size */
+
+ /* BITMAPINFOHEADER header */
+ put_bmp_header(pb, enc);
+ }
+ end_header(pb, hpos);
+ }
+
+ /* media comments */
+
+ hpos = put_header(pb, &codec_comment_header);
+ put_guid(pb, &codec_comment1_header);
+ put_le32(pb, s->nb_streams);
+ for(n=0;n<s->nb_streams;n++) {
+ enc = &s->streams[n]->codec;
+
+ put_le16(pb, asf->streams[n].num);
+ put_str16(pb, enc->codec_name);
+ put_le16(pb, 0); /* no parameters */
+ /* id */
+ if (enc->codec_type == CODEC_TYPE_AUDIO) {
+ put_le16(pb, 2);
+ put_le16(pb, codec_get_tag(codec_wav_tags, enc->codec_id));
+ } else {
+ put_le16(pb, 4);
+ put_le32(pb, codec_get_tag(codec_bmp_tags, enc->codec_id));
+ }
+ }
+ end_header(pb, hpos);
+
+ /* patch the header size fields */
+
+ cur_pos = url_ftell(pb);
+ header_size = cur_pos - header_offset;
+ if (!url_is_streamed(&s->pb)) {
+ header_size += 24 + 6;
+ url_fseek(pb, header_offset - 14, SEEK_SET);
+ put_le64(pb, header_size);
+ } else {
+ header_size += 8 + 50;
+ url_fseek(pb, header_offset - 10, SEEK_SET);
+ put_le16(pb, header_size);
+ url_fseek(pb, header_offset - 2, SEEK_SET);
+ put_le16(pb, header_size);
+ }
+ url_fseek(pb, cur_pos, SEEK_SET);
+
+ /* movie chunk, followed by packets of packet_size */
+ asf->data_offset = cur_pos;
+ put_guid(pb, &data_header);
+ put_le64(pb, data_chunk_size);
+ put_guid(pb, &my_guid);
+ put_le64(pb, asf->nb_packets); /* nb packets */
+ put_byte(pb, 1); /* ??? */
+ put_byte(pb, 1); /* ??? */
+ return 0;
+}
+
+static int asf_write_header(AVFormatContext *s)
+{
+ ASFContext *asf;
+
+ asf = av_mallocz(sizeof(ASFContext));
+ if (!asf)
+ return -1;
+ s->priv_data = asf;
+
+ asf->packet_size = PACKET_SIZE;
+ asf->nb_packets = 0;
+
+ asf_write_header1(s, 0, 24);
+
+ put_flush_packet(&s->pb);
+
+ asf->packet_nb_frames = 0;
+ asf->packet_timestamp_start = -1;
+ asf->packet_timestamp_end = -1;
+ asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
+ init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
+ NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+/* write a fixed size packet */
+static void put_packet(AVFormatContext *s,
+ unsigned int timestamp, unsigned int duration,
+ int nb_frames, int padsize)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int flags;
+
+ if (url_is_streamed(&s->pb)) {
+ put_chunk(s, 0x4424, asf->packet_size);
+ }
+
+ put_byte(pb, 0x82);
+ put_le16(pb, 0);
+
+ flags = 0x01; /* nb segments present */
+ if (padsize > 0) {
+ if (padsize < 256)
+ flags |= 0x08;
+ else
+ flags |= 0x10;
+ }
+ put_byte(pb, flags); /* flags */
+ put_byte(pb, 0x5d);
+ if (flags & 0x10)
+ put_le16(pb, padsize);
+ if (flags & 0x08)
+ put_byte(pb, padsize);
+ put_le32(pb, timestamp);
+ put_le16(pb, duration);
+ put_byte(pb, nb_frames | 0x80);
+}
+
+static void flush_packet(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ int hdr_size, ptr;
+
+ put_packet(s, asf->packet_timestamp_start,
+ asf->packet_timestamp_end - asf->packet_timestamp_start,
+ asf->packet_nb_frames, asf->packet_size_left);
+
+ /* compute padding */
+ hdr_size = PACKET_HEADER_SIZE;
+ if (asf->packet_size_left > 0) {
+ /* if padding needed, don't forget to count the
+ padding byte in the header size */
+ hdr_size++;
+ asf->packet_size_left--;
+ /* XXX: I do not test again exact limit to avoid boundary problems */
+ if (asf->packet_size_left > 200) {
+ hdr_size++;
+ asf->packet_size_left--;
+ }
+ }
+ ptr = asf->packet_size - PACKET_HEADER_SIZE - asf->packet_size_left;
+ memset(asf->packet_buf + ptr, 0, asf->packet_size_left);
+
+ put_buffer(&s->pb, asf->packet_buf, asf->packet_size - hdr_size);
+
+ put_flush_packet(&s->pb);
+ asf->nb_packets++;
+ asf->packet_nb_frames = 0;
+ asf->packet_timestamp_start = -1;
+ asf->packet_timestamp_end = -1;
+ asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
+ init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
+ NULL, NULL, NULL, NULL);
+}
+
+static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestamp,
+ int payload_size, int frag_offset, int frag_len)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &asf->pb;
+ int val;
+
+ val = stream->num;
+ if (s->streams[val - 1]->codec.key_frame)
+ val |= 0x80;
+ put_byte(pb, val);
+ put_byte(pb, stream->seq);
+ put_le32(pb, frag_offset); /* fragment offset */
+ put_byte(pb, 0x08); /* flags */
+ put_le32(pb, payload_size);
+ put_le32(pb, timestamp);
+ put_le16(pb, frag_len);
+}
+
+
+/* Output a frame. We suppose that payload_size <= PACKET_SIZE.
+
+ It is there that you understand that the ASF format is really
+ crap. They have misread the MPEG Systems spec !
+ */
+static void put_frame(AVFormatContext *s, ASFStream *stream, int timestamp,
+ UINT8 *buf, int payload_size)
+{
+ ASFContext *asf = s->priv_data;
+ int frag_pos, frag_len, frag_len1;
+
+ frag_pos = 0;
+ while (frag_pos < payload_size) {
+ frag_len = payload_size - frag_pos;
+ frag_len1 = asf->packet_size_left - FRAME_HEADER_SIZE;
+ if (frag_len1 > 0) {
+ if (frag_len > frag_len1)
+ frag_len = frag_len1;
+ put_frame_header(s, stream, timestamp, payload_size, frag_pos, frag_len);
+ put_buffer(&asf->pb, buf, frag_len);
+ asf->packet_size_left -= (frag_len + FRAME_HEADER_SIZE);
+ asf->packet_timestamp_end = timestamp;
+ if (asf->packet_timestamp_start == -1)
+ asf->packet_timestamp_start = timestamp;
+ asf->packet_nb_frames++;
+ } else {
+ frag_len = 0;
+ }
+ frag_pos += frag_len;
+ buf += frag_len;
+ /* output the frame if filled */
+ if (asf->packet_size_left <= FRAME_HEADER_SIZE)
+ flush_packet(s);
+ }
+ stream->seq++;
+}
+
+
+static int asf_write_packet(AVFormatContext *s, int stream_index,
+ UINT8 *buf, int size)
+{
+ ASFContext *asf = s->priv_data;
+ int timestamp;
+ INT64 duration;
+ AVCodecContext *codec;
+
+ codec = &s->streams[stream_index]->codec;
+ if (codec->codec_type == CODEC_TYPE_AUDIO) {
+ timestamp = (int)((float)codec->frame_number * codec->frame_size * 1000.0 /
+ codec->sample_rate);
+ duration = (codec->frame_number * codec->frame_size * 10000000LL) /
+ codec->sample_rate;
+ } else {
+ timestamp = (int)((float)codec->frame_number * 1000.0 * FRAME_RATE_BASE /
+ codec->frame_rate);
+ duration = codec->frame_number *
+ ((10000000LL * FRAME_RATE_BASE) / codec->frame_rate);
+ }
+ if (duration > asf->duration)
+ asf->duration = duration;
+
+ put_frame(s, &asf->streams[stream_index], (int)timestamp, buf, size);
+ return 0;
+}
+
+static int asf_write_trailer(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ long long file_size;
+
+ /* flush the current packet */
+ if (asf->pb.buf_ptr > asf->pb.buffer)
+ flush_packet(s);
+
+ if (url_is_streamed(&s->pb)) {
+ put_chunk(s, 0x4524, 0); /* end of stream */
+ } else {
+ /* rewrite an updated header */
+ file_size = url_ftell(&s->pb);
+ url_fseek(&s->pb, 0, SEEK_SET);
+ asf_write_header1(s, file_size, file_size - asf->data_offset);
+ }
+
+ put_flush_packet(&s->pb);
+
+ free(asf);
+ return 0;
+}
+
+/**********************************/
+/* decoding */
+
+//#define DEBUG
+
+#ifdef DEBUG
+static void print_guid(const GUID *g)
+{
+ int i;
+ printf("0x%08x, 0x%04x, 0x%04x, {", g->v1, g->v2, g->v3);
+ for(i=0;i<8;i++)
+ printf(" 0x%02x,", g->v4[i]);
+ printf("}\n");
+}
+#endif
+
+static void get_guid(ByteIOContext *s, GUID *g)
+{
+ int i;
+
+ g->v1 = get_le32(s);
+ g->v2 = get_le16(s);
+ g->v3 = get_le16(s);
+ for(i=0;i<8;i++)
+ g->v4[i] = get_byte(s);
+}
+
+#if 0
+static void get_str16(ByteIOContext *pb, char *buf, int buf_size)
+{
+ int len, c;
+ char *q;
+
+ len = get_le16(pb);
+ q = buf;
+ while (len > 0) {
+ c = get_le16(pb);
+ if ((q - buf) < buf_size - 1)
+ *q++ = c;
+ len--;
+ }
+ *q = '\0';
+}
+#endif
+
+static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
+{
+ int c;
+ char *q;
+
+ q = buf;
+ while (len > 0) {
+ c = get_le16(pb);
+ if ((q - buf) < buf_size - 1)
+ *q++ = c;
+ len-=2;
+ }
+ *q = '\0';
+}
+
+static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ ASFContext *asf;
+ GUID g;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ ASFStream *asf_st;
+ int size, i;
+ INT64 gsize;
+
+ asf = av_mallocz(sizeof(ASFContext));
+ if (!asf)
+ return -1;
+ s->priv_data = asf;
+
+ get_guid(pb, &g);
+ if (memcmp(&g, &asf_header, sizeof(GUID)))
+ goto fail;
+ get_le64(pb);
+ get_le32(pb);
+ get_byte(pb);
+ get_byte(pb);
+
+ for(;;) {
+ get_guid(pb, &g);
+ gsize = get_le64(pb);
+#ifdef DEBUG
+ printf("%08Lx: ", url_ftell(pb) - 24);
+ print_guid(&g);
+ printf(" size=0x%Lx\n", gsize);
+#endif
+ if (gsize < 24)
+ goto fail;
+ if (!memcmp(&g, &file_header, sizeof(GUID))) {
+ get_guid(pb, &g);
+ get_le64(pb); /* file size */
+ get_le64(pb); /* file time */
+ get_le64(pb); /* nb_packets */
+ get_le64(pb); /* length 0 in us */
+ get_le64(pb); /* length 1 in us */
+ get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ asf->packet_size = get_le32(pb);
+ get_le32(pb);
+ get_le32(pb);
+ } else if (!memcmp(&g, &stream_header, sizeof(GUID))) {
+ int type, id, total_size;
+ unsigned int tag1;
+ INT64 pos1, pos2;
+
+ pos1 = url_ftell(pb);
+
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ goto fail;
+ s->streams[s->nb_streams++] = st;
+ asf_st = av_mallocz(sizeof(ASFStream));
+ if (!asf_st)
+ goto fail;
+ st->priv_data = asf_st;
+
+ get_guid(pb, &g);
+ if (!memcmp(&g, &audio_stream, sizeof(GUID))) {
+ type = CODEC_TYPE_AUDIO;
+ } else if (!memcmp(&g, &video_stream, sizeof(GUID))) {
+ type = CODEC_TYPE_VIDEO;
+ } else {
+ goto fail;
+ }
+ get_guid(pb, &g);
+ total_size = get_le64(pb);
+ get_le32(pb);
+ get_le32(pb);
+ st->id = get_le16(pb); /* stream id */
+ get_le32(pb);
+ st->codec.codec_type = type;
+ if (type == CODEC_TYPE_AUDIO) {
+ id = get_le16(pb);
+ st->codec.codec_tag = id;
+ st->codec.codec_id = codec_get_id(codec_wav_tags, id);
+ st->codec.channels = get_le16(pb);
+ st->codec.sample_rate = get_le32(pb);
+ st->codec.bit_rate = get_le32(pb) * 8;
+ get_le16(pb); /* block align */
+ get_le16(pb); /* bits per sample */
+ size = get_le16(pb);
+ url_fskip(pb, size);
+ } else {
+ get_le32(pb);
+ get_le32(pb);
+ get_byte(pb);
+ size = get_le16(pb); /* size */
+ get_le32(pb); /* size */
+ st->codec.width = get_le32(pb);
+ st->codec.height = get_le32(pb);
+ st->codec.frame_rate = 25 * FRAME_RATE_BASE; /* XXX: find it */
+ get_le16(pb); /* panes */
+ get_le16(pb); /* depth */
+ tag1 = get_le32(pb);
+ st->codec.codec_tag = tag1;
+ st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1);
+ url_fskip(pb, size - 5 * 4);
+ }
+ pos2 = url_ftell(pb);
+ url_fskip(pb, gsize - (pos2 - pos1 + 24));
+ } else if (!memcmp(&g, &data_header, sizeof(GUID))) {
+ break;
+ } else if (!memcmp(&g, &comment_header, sizeof(GUID))) {
+ int len1, len2, len3, len4, len5;
+
+ len1 = get_le16(pb);
+ len2 = get_le16(pb);
+ len3 = get_le16(pb);
+ len4 = get_le16(pb);
+ len5 = get_le16(pb);
+ get_str16_nolen(pb, len1, s->title, sizeof(s->title));
+ get_str16_nolen(pb, len2, s->author, sizeof(s->author));
+ get_str16_nolen(pb, len3, s->copyright, sizeof(s->copyright));
+ get_str16_nolen(pb, len4, s->comment, sizeof(s->comment));
+ url_fskip(pb, len5);
+#if 0
+ } else if (!memcmp(&g, &head1_guid, sizeof(GUID))) {
+ int v1, v2;
+ get_guid(pb, &g);
+ v1 = get_le32(pb);
+ v2 = get_le16(pb);
+ } else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) {
+ int len, v1, n, num;
+ char str[256], *q;
+ char tag[16];
+
+ get_guid(pb, &g);
+ print_guid(&g);
+
+ n = get_le32(pb);
+ for(i=0;i<n;i++) {
+ num = get_le16(pb); /* stream number */
+ get_str16(pb, str, sizeof(str));
+ get_str16(pb, str, sizeof(str));
+ len = get_le16(pb);
+ q = tag;
+ while (len > 0) {
+ v1 = get_byte(pb);
+ if ((q - tag) < sizeof(tag) - 1)
+ *q++ = v1;
+ len--;
+ }
+ *q = '\0';
+ }
+#endif
+ } else if (url_feof(pb)) {
+ goto fail;
+ } else {
+ url_fseek(pb, gsize - 24, SEEK_CUR);
+ }
+ }
+ get_guid(pb, &g);
+ get_le64(pb);
+ get_byte(pb);
+ get_byte(pb);
+
+ asf->packet_size_left = 0;
+
+ return 0;
+
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ if (st)
+ free(st->priv_data);
+ free(st);
+ }
+ free(asf);
+ return -1;
+}
+
+static int asf_get_packet(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int c, flags, timestamp, hdr_size;
+
+ hdr_size = 12;
+ c = get_byte(pb);
+ if (c != 0x82)
+ return -EIO;
+ get_le16(pb);
+ flags = get_byte(pb);
+ get_byte(pb);
+ asf->packet_padsize = 0;
+ if (flags & 0x10) {
+ asf->packet_padsize = get_le16(pb);
+ hdr_size += 2;
+ } else if (flags & 0x08) {
+ asf->packet_padsize = get_byte(pb);
+ hdr_size++;
+ }
+ timestamp = get_le32(pb);
+ get_le16(pb); /* duration */
+ get_byte(pb); /* nb_frames */
+#ifdef DEBUG
+ printf("packet: size=%d padsize=%d\n", asf->packet_size, asf->packet_padsize);
+#endif
+ asf->packet_size_left = asf->packet_size - hdr_size;
+ return 0;
+}
+
+static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ASFContext *asf = s->priv_data;
+ AVStream *st;
+ ASFStream *asf_st;
+ ByteIOContext *pb = &s->pb;
+ int ret, num, seq, frag_offset, payload_size, frag_len;
+ int timestamp, i;
+
+ for(;;) {
+ if (asf->packet_size_left < FRAME_HEADER_SIZE ||
+ asf->packet_size_left <= asf->packet_padsize) {
+ /* fail safe */
+ if (asf->packet_size_left)
+ url_fskip(pb, asf->packet_size_left);
+ ret = asf_get_packet(s);
+ if (ret < 0)
+ return -EIO;
+ }
+ /* read frame header */
+ num = get_byte(pb) & 0x7f;
+ seq = get_byte(pb);
+ frag_offset = get_le32(pb);
+ get_byte(pb); /* flags */
+ payload_size = get_le32(pb);
+ timestamp = get_le32(pb);
+ frag_len = get_le16(pb);
+#ifdef DEBUG
+ printf("num=%d seq=%d totsize=%d frag_off=%d frag_size=%d\n",
+ num, seq, payload_size, frag_offset, frag_len);
+#endif
+ st = NULL;
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (st->id == num)
+ break;
+ }
+ asf->packet_size_left -= FRAME_HEADER_SIZE + frag_len;
+ if (i == s->nb_streams) {
+ /* unhandled packet (should not happen) */
+ url_fskip(pb, frag_len);
+ } else {
+ asf_st = st->priv_data;
+ if (asf_st->frag_offset == 0) {
+ /* new packet */
+ av_new_packet(&asf_st->pkt, payload_size);
+ asf_st->seq = seq;
+ } else {
+ if (seq == asf_st->seq &&
+ frag_offset == asf_st->frag_offset) {
+ /* continuing packet */
+ } else {
+ /* cannot continue current packet: free it */
+ av_free_packet(&asf_st->pkt);
+ asf_st->frag_offset = 0;
+ if (frag_offset != 0) {
+ /* cannot create new packet */
+ url_fskip(pb, frag_len);
+ goto next_frame;
+ } else {
+ /* create new packet */
+ av_new_packet(&asf_st->pkt, payload_size);
+ asf_st->seq = seq;
+ }
+ }
+ }
+ /* read data */
+ get_buffer(pb, asf_st->pkt.data + frag_offset, frag_len);
+ asf_st->frag_offset += frag_len;
+ /* test if whole packet read */
+ if (asf_st->frag_offset == asf_st->pkt.size) {
+ /* return packet */
+ asf_st->pkt.stream_index = i;
+ asf_st->frag_offset = 0;
+ memcpy(pkt, &asf_st->pkt, sizeof(AVPacket));
+ break;
+ }
+ }
+ next_frame:
+ }
+
+ return 0;
+}
+
+static int asf_read_close(AVFormatContext *s)
+{
+ ASFContext *asf = s->priv_data;
+ int i;
+
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ free(st->priv_data);
+ }
+ free(asf);
+ return 0;
+}
+
+AVFormat asf_format = {
+ "asf",
+ "asf format",
+ "application/octet-stream",
+ "asf",
+ CODEC_ID_MP2,
+ CODEC_ID_MSMPEG4,
+ asf_write_header,
+ asf_write_packet,
+ asf_write_trailer,
+
+ asf_read_header,
+ asf_read_packet,
+ asf_read_close,
+};
diff --git a/libav/audio.c b/libav/audio.c
new file mode 100644
index 0000000000..df5d88eaf6
--- /dev/null
+++ b/libav/audio.c
@@ -0,0 +1,179 @@
+/*
+ * Linux audio play and grab interface
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/soundcard.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include "avformat.h"
+
+const char *audio_device = "/dev/dsp";
+
+typedef struct {
+ int fd;
+ int rate;
+ int channels;
+} AudioData;
+
+#define AUDIO_BLOCK_SIZE 4096
+
+/* audio read support */
+
+static int audio_read(URLContext *h, UINT8 *buf, int size)
+{
+ AudioData *s = h->priv_data;
+ int ret;
+
+ ret = read(s->fd, buf, size);
+ if (ret < 0)
+ return -errno;
+ else
+ return ret;
+}
+
+static int audio_write(URLContext *h, UINT8 *buf, int size)
+{
+ AudioData *s = h->priv_data;
+ int ret;
+
+ ret = write(s->fd, buf, size);
+ if (ret < 0)
+ return -errno;
+ else
+ return ret;
+}
+
+static int audio_get_format(URLContext *h, URLFormat *f)
+{
+ AudioData *s = h->priv_data;
+
+ strcpy(f->format_name, "pcm");
+ f->sample_rate = s->rate;
+ f->channels = s->channels;
+ return 0;
+}
+
+/* URI syntax: 'audio:[rate[,channels]]'
+ default: rate=44100, channels=2
+ */
+static int audio_open(URLContext *h, const char *uri, int flags)
+{
+ AudioData *s;
+ const char *p;
+ int freq, channels, audio_fd;
+ int tmp, err;
+
+ h->is_streamed = 1;
+ h->packet_size = AUDIO_BLOCK_SIZE;
+
+ s = malloc(sizeof(AudioData));
+ if (!s)
+ return -ENOMEM;
+ h->priv_data = s;
+
+ /* extract parameters */
+ p = uri;
+ strstart(p, "audio:", &p);
+ freq = strtol(p, (char **)&p, 0);
+ if (freq <= 0)
+ freq = 44100;
+ if (*p == ',')
+ p++;
+ channels = strtol(p, (char **)&p, 0);
+ if (channels <= 0)
+ channels = 2;
+ s->rate = freq;
+ s->channels = channels;
+
+ /* open linux audio device */
+ if (flags & URL_WRONLY)
+ audio_fd = open(audio_device,O_WRONLY);
+ else
+ audio_fd = open(audio_device,O_RDONLY);
+ if (audio_fd < 0) {
+ perror(audio_device);
+ return -EIO;
+ }
+
+ /* non blocking mode */
+ fcntl(audio_fd, F_SETFL, O_NONBLOCK);
+
+#if 0
+ tmp=(NB_FRAGMENTS << 16) | FRAGMENT_BITS;
+ err=ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_SETFRAGMENT");
+ }
+#endif
+
+ tmp=AFMT_S16_LE;
+ err=ioctl(audio_fd,SNDCTL_DSP_SETFMT,&tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_SETFMT");
+ goto fail;
+ }
+
+ tmp= (channels == 2);
+ err=ioctl(audio_fd,SNDCTL_DSP_STEREO,&tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_STEREO");
+ goto fail;
+ }
+
+ tmp = freq;
+ err=ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
+ if (err < 0) {
+ perror("SNDCTL_DSP_SPEED");
+ goto fail;
+ }
+
+ s->rate = tmp;
+ s->fd = audio_fd;
+
+ return 0;
+ fail:
+ close(audio_fd);
+ free(s);
+ return -EIO;
+}
+
+static int audio_close(URLContext *h)
+{
+ AudioData *s = h->priv_data;
+
+ close(s->fd);
+ free(s);
+ return 0;
+}
+
+URLProtocol audio_protocol = {
+ "audio",
+ audio_open,
+ audio_read,
+ audio_write,
+ NULL, /* seek */
+ audio_close,
+ audio_get_format,
+};
diff --git a/libav/avformat.h b/libav/avformat.h
new file mode 100644
index 0000000000..44e9da2a55
--- /dev/null
+++ b/libav/avformat.h
@@ -0,0 +1,192 @@
+
+#include "avcodec.h"
+
+#define FFMPEG_VERSION "0.4.5"
+
+#include "avio.h"
+
+/* packet functions */
+
+typedef struct AVPacket {
+ INT64 pts;
+ UINT8 *data;
+ int size;
+ int stream_index;
+ int flags;
+#define PKT_FLAG_KEY 0x0001
+} AVPacket;
+
+int av_new_packet(AVPacket *pkt, int size);
+void av_free_packet(AVPacket *pkt);
+
+/*************************************************/
+/* output formats */
+
+struct AVFormatContext;
+struct AVFormatInputContext;
+
+typedef struct AVFormatParameters {
+ int frame_rate;
+ int sample_rate;
+ int channels;
+ int width;
+ int height;
+ int pix_fmt;
+} AVFormatParameters;
+
+typedef struct AVFormat {
+ const char *name;
+ const char *long_name;
+ const char *mime_type;
+ const char *extensions; /* comma separated extensions */
+
+ /* output support */
+ enum CodecID audio_codec; /* default audio codec */
+ enum CodecID video_codec; /* default video codec */
+ int (*write_header)(struct AVFormatContext *);
+ int (*write_packet)(struct AVFormatContext *,
+ int stream_index,
+ unsigned char *buf, int size);
+ int (*write_trailer)(struct AVFormatContext *);
+
+ /* optional input support */
+ /* read the format header and initialize the AVFormatInputContext
+ structure. Return 0 if OK. 'ap' if non NULL contains
+ additionnal paramters. Only used in raw format right now */
+ int (*read_header)(struct AVFormatContext *,
+ AVFormatParameters *ap);
+ /* read one packet and put it in 'pkt'. pts and flags are also set */
+ int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
+ /* close the stream. The AVFormatContext and AVStreams are not
+ freed by this function */
+ int (*read_close)(struct AVFormatContext *);
+ /* seek at or before a given pts (given in microsecond). The pts
+ origin is defined by the stream */
+ int (*read_seek)(struct AVFormatContext *, INT64 pts);
+ int flags;
+#define AVFMT_NOFILE 0x0001 /* no file should be opened */
+ struct AVFormat *next;
+} AVFormat;
+
+typedef struct AVStream {
+ int id; /* internal stream id */
+ AVCodecContext codec; /* codec context */
+ void *priv_data;
+} AVStream;
+
+#define MAX_STREAMS 20
+
+/* format I/O context */
+typedef struct AVFormatContext {
+ struct AVFormat *format;
+ void *priv_data;
+ ByteIOContext pb;
+ int nb_streams;
+ AVStream *streams[MAX_STREAMS];
+ char filename[1024]; /* input or output filename */
+ /* stream info */
+ char title[512];
+ char author[512];
+ char copyright[512];
+ char comment[512];
+ /* This buffer is only needed when packets were already buffered but
+ not decoded, for example to get the codec parameters in mpeg
+ streams */
+ struct AVPacketList *packet_buffer;
+} AVFormatContext;
+
+typedef struct AVPacketList {
+ AVPacket pkt;
+ struct AVPacketList *next;
+} AVPacketList;
+
+extern AVFormat *first_format;
+
+/* rv10enc.c */
+extern AVFormat rm_format;
+
+/* mpegmux.c */
+extern AVFormat mpeg_mux_format;
+
+/* asfenc.c */
+extern AVFormat asf_format;
+
+/* avienc.c */
+extern AVFormat avi_format;
+
+/* jpegenc.c */
+extern AVFormat mpjpeg_format;
+extern AVFormat jpeg_format;
+
+/* swfenc.c */
+extern AVFormat swf_format;
+
+/* wav.c */
+extern AVFormat wav_format;
+
+/* img.c */
+extern AVFormat pgm_format;
+extern AVFormat pgmyuv_format;
+extern AVFormat imgyuv_format;
+extern AVFormat pgmpipe_format;
+
+/* raw.c */
+extern AVFormat mp2_format;
+extern AVFormat ac3_format;
+extern AVFormat h263_format;
+extern AVFormat mpeg1video_format;
+extern AVFormat pcm_format;
+extern AVFormat rawvideo_format;
+
+/* ffm.c */
+extern AVFormat ffm_format;
+
+/* formats.c */
+
+#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
+#define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
+
+void register_avformat(AVFormat *format);
+AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type);
+
+int strstart(const char *str, const char *val, const char **ptr);
+void nstrcpy(char *buf, int buf_size, const char *str);
+int match_ext(const char *filename, const char *extensions);
+
+void register_all(void);
+
+INT64 gettime(void);
+
+typedef struct FifoBuffer {
+ UINT8 *buffer;
+ UINT8 *rptr, *wptr, *end;
+} FifoBuffer;
+
+int fifo_init(FifoBuffer *f, int size);
+void fifo_free(FifoBuffer *f);
+int fifo_size(FifoBuffer *f, UINT8 *rptr);
+int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr);
+void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr);
+
+AVFormatContext *av_open_input_file(const char *filename, int buf_size);
+int av_read_packet(AVFormatContext *s, AVPacket *pkt);
+void av_close_input_file(AVFormatContext *s);
+
+int av_write_packet(AVFormatContext *s, AVPacket *pkt);
+
+void dump_format(AVFormatContext *ic,
+ int index,
+ const char *url,
+ int is_output);
+int parse_image_size(int *width_ptr, int *height_ptr, const char *str);
+INT64 gettime(void);
+INT64 parse_date(const char *datestr, int duration);
+
+/* ffm specific for ffserver */
+#define FFM_PACKET_SIZE 4096
+offset_t ffm_read_write_index(int fd);
+void ffm_write_write_index(int fd, offset_t pos);
+void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size);
+
+int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info);
+
diff --git a/libav/avi.h b/libav/avi.h
new file mode 100644
index 0000000000..06834cfcbf
--- /dev/null
+++ b/libav/avi.h
@@ -0,0 +1,29 @@
+
+#define AVIF_HASINDEX 0x00000010 // Index at end of file?
+#define AVIF_MUSTUSEINDEX 0x00000020
+#define AVIF_ISINTERLEAVED 0x00000100
+#define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
+#define AVIF_WASCAPTUREFILE 0x00010000
+#define AVIF_COPYRIGHTED 0x00020000
+
+offset_t start_tag(ByteIOContext *pb, char *tag);
+void end_tag(ByteIOContext *pb, offset_t start);
+
+void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc);
+void put_wav_header(ByteIOContext *pb, AVCodecContext *enc);
+
+typedef struct CodecTag {
+ int id;
+ unsigned int tag;
+} CodecTag;
+
+extern CodecTag codec_bmp_tags[];
+extern CodecTag codec_wav_tags[];
+
+unsigned int codec_get_tag(CodecTag *tags, int id);
+int codec_get_id(CodecTag *tags, unsigned int tag);
+
+/* avidec.c */
+int avi_read_header(AVFormatContext *s, AVFormatParameters *ap);
+int avi_read_packet(AVFormatContext *s, AVPacket *pkt);
+int avi_read_close(AVFormatContext *s);
diff --git a/libav/avidec.c b/libav/avidec.c
new file mode 100644
index 0000000000..ec90565feb
--- /dev/null
+++ b/libav/avidec.c
@@ -0,0 +1,257 @@
+/*
+ * AVI decoder.
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+
+#include "avformat.h"
+#include "avi.h"
+
+//#define DEBUG
+
+typedef struct AVIIndex {
+ unsigned char tag[4];
+ unsigned int flags, pos, len;
+ struct AVIIndex *next;
+} AVIIndex;
+
+typedef struct {
+ INT64 movi_end;
+ offset_t movi_list;
+ AVIIndex *first, *last;
+} AVIContext;
+
+#ifdef DEBUG
+void print_tag(const char *str, unsigned int tag, int size)
+{
+ printf("%s: tag=%c%c%c%c size=0x%x\n",
+ str, tag & 0xff,
+ (tag >> 8) & 0xff,
+ (tag >> 16) & 0xff,
+ (tag >> 24) & 0xff,
+ size);
+}
+#endif
+
+int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ AVIContext *avi;
+ ByteIOContext *pb = &s->pb;
+ UINT32 tag, tag1;
+ int codec_type, stream_index, size, frame_period, bit_rate;
+ int i;
+ AVStream *st;
+
+ avi = malloc(sizeof(AVIContext));
+ if (!avi)
+ return -1;
+ memset(avi, 0, sizeof(AVIContext));
+ s->priv_data = avi;
+
+ /* check RIFF header */
+ tag = get_le32(pb);
+
+ if (tag != MKTAG('R', 'I', 'F', 'F'))
+ return -1;
+ get_le32(pb); /* file size */
+ tag = get_le32(pb);
+ if (tag != MKTAG('A', 'V', 'I', ' '))
+ return -1;
+
+ /* first list tag */
+ stream_index = -1;
+ codec_type = -1;
+ frame_period = 0;
+ for(;;) {
+ if (url_feof(pb))
+ goto fail;
+ tag = get_le32(pb);
+ size = get_le32(pb);
+#ifdef DEBUG
+ print_tag("tag", tag, size);
+#endif
+
+ switch(tag) {
+ case MKTAG('L', 'I', 'S', 'T'):
+ /* ignored, except when start of video packets */
+ tag1 = get_le32(pb);
+#ifdef DEBUG
+ print_tag("list", tag1, 0);
+#endif
+ if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
+ avi->movi_end = url_ftell(pb) + size - 4;
+#ifdef DEBUG
+ printf("movi end=%Lx\n", avi->movi_end);
+#endif
+ goto end_of_header;
+ }
+ break;
+ case MKTAG('a', 'v', 'i', 'h'):
+ /* avi header */
+ frame_period = get_le32(pb);
+ bit_rate = get_le32(pb) * 8;
+ url_fskip(pb, 4 * 4);
+ s->nb_streams = get_le32(pb);
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st;
+ st = malloc(sizeof(AVStream));
+ if (!st)
+ goto fail;
+ memset(st, 0, sizeof(AVStream));
+ s->streams[i] = st;
+ }
+ url_fskip(pb, size - 7 * 4);
+ break;
+ case MKTAG('s', 't', 'r', 'h'):
+ /* stream header */
+ stream_index++;
+ tag1 = get_le32(pb);
+ switch(tag1) {
+ case MKTAG('v', 'i', 'd', 's'):
+ codec_type = CODEC_TYPE_VIDEO;
+ get_le32(pb); /* codec tag */
+ get_le32(pb); /* flags */
+ get_le16(pb); /* priority */
+ get_le16(pb); /* language */
+ get_le32(pb); /* XXX: initial frame ? */
+ get_le32(pb); /* scale */
+ get_le32(pb); /* rate */
+ url_fskip(pb, size - 7 * 4);
+ break;
+ case MKTAG('a', 'u', 'd', 's'):
+ codec_type = CODEC_TYPE_AUDIO;
+ /* nothing really useful */
+ url_fskip(pb, size - 4);
+ break;
+ default:
+ goto fail;
+ }
+ break;
+ case MKTAG('s', 't', 'r', 'f'):
+ /* stream header */
+ if (stream_index >= s->nb_streams) {
+ url_fskip(pb, size);
+ } else {
+ st = s->streams[stream_index];
+ switch(codec_type) {
+ case CODEC_TYPE_VIDEO:
+ get_le32(pb); /* size */
+ st->codec.width = get_le32(pb);
+ st->codec.height = get_le32(pb);
+ if (frame_period)
+ st->codec.frame_rate = (1000000LL * FRAME_RATE_BASE) / frame_period;
+ else
+ st->codec.frame_rate = 25 * FRAME_RATE_BASE;
+ get_le16(pb); /* panes */
+ get_le16(pb); /* depth */
+ tag1 = get_le32(pb);
+#ifdef DEBUG
+ print_tag("video", tag1, 0);
+#endif
+ st->codec.codec_type = CODEC_TYPE_VIDEO;
+ st->codec.codec_tag = tag1;
+ st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1);
+ url_fskip(pb, size - 5 * 4);
+ break;
+ case CODEC_TYPE_AUDIO:
+ tag1 = get_le16(pb);
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ st->codec.codec_tag = tag1;
+ st->codec.codec_id = codec_get_id(codec_wav_tags, tag1);
+#ifdef DEBUG
+ printf("audio: 0x%x\n", tag1);
+#endif
+ st->codec.channels = get_le16(pb);
+ st->codec.sample_rate = get_le32(pb);
+ st->codec.bit_rate = get_le32(pb) * 8;
+ url_fskip(pb, size - 3 * 4);
+ break;
+ default:
+ url_fskip(pb, size);
+ break;
+ }
+ }
+ break;
+ default:
+ /* skip tag */
+ size += (size & 1);
+ url_fskip(pb, size);
+ break;
+ }
+ }
+ end_of_header:
+ /* check stream number */
+ if (stream_index != s->nb_streams - 1) {
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ if (s->streams[i])
+ free(s->streams[i]);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int n, d1, d2, size;
+
+ find_next:
+ if (url_feof(pb) || url_ftell(pb) >= avi->movi_end)
+ return -1;
+ d1 = get_byte(pb);
+ if (d1 < '0' || d1 > '9')
+ goto find_next;
+ d2 = get_byte(pb);
+ if (d2 < '0' || d2 > '9')
+ goto find_next;
+ n = (d1 - '0') * 10 + (d2 - '0');
+
+ if (n < 0 || n >= s->nb_streams)
+ goto find_next;
+
+ d1 = get_byte(pb);
+ d2 = get_byte(pb);
+ if ((d1 != 'd' && d2 != 'c') &&
+ (d1 != 'w' && d2 != 'b'))
+ goto find_next;
+
+ size = get_le32(pb);
+ av_new_packet(pkt, size);
+ pkt->stream_index = n;
+
+ get_buffer(pb, pkt->data, pkt->size);
+
+ if (size & 1)
+ get_byte(pb);
+
+ return 0;
+}
+
+int avi_read_close(AVFormatContext *s)
+{
+ AVIContext *avi = s->priv_data;
+ free(avi);
+ return 0;
+}
diff --git a/libav/avienc.c b/libav/avienc.c
new file mode 100644
index 0000000000..cef541d7ba
--- /dev/null
+++ b/libav/avienc.c
@@ -0,0 +1,366 @@
+/*
+ * AVI encoder.
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#include "avformat.h"
+#include "avi.h"
+
+/*
+ * TODO:
+ * - fill all fields if non streamed (nb_frames for example)
+ */
+
+typedef struct AVIIndex {
+ unsigned char tag[4];
+ unsigned int flags, pos, len;
+ struct AVIIndex *next;
+} AVIIndex;
+
+typedef struct {
+ offset_t movi_list;
+ AVIIndex *first, *last;
+} AVIContext;
+
+offset_t start_tag(ByteIOContext *pb, char *tag)
+{
+ put_tag(pb, tag);
+ put_le32(pb, 0);
+ return url_ftell(pb);
+}
+
+void end_tag(ByteIOContext *pb, offset_t start)
+{
+ offset_t pos;
+
+ pos = url_ftell(pb);
+ url_fseek(pb, start - 4, SEEK_SET);
+ put_le32(pb, pos - start);
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+/* Note: when encoding, the first matching tag is used, so order is
+ important if multiple tags possible for a given codec. */
+CodecTag codec_bmp_tags[] = {
+ { CODEC_ID_H263, MKTAG('U', '2', '6', '3') },
+ { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
+ { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
+ { CODEC_ID_OPENDIVX, MKTAG('D', 'I', 'V', 'X') },
+ { CODEC_ID_OPENDIVX, MKTAG('d', 'i', 'v', 'x') },
+ { CODEC_ID_OPENDIVX, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
+ { CODEC_ID_MSMPEG4, MKTAG('D', 'I', 'V', '3') }, /* default signature when using MSMPEG4 */
+ { CODEC_ID_MSMPEG4, MKTAG('M', 'P', '4', '3') },
+ { 0, 0 },
+};
+
+CodecTag codec_wav_tags[] = {
+ { CODEC_ID_MP2, 0x55 },
+ { CODEC_ID_MP2, 0x50 },
+ { CODEC_ID_AC3, 0x2000 },
+ { CODEC_ID_PCM, 0x01 },
+ { 0, 0 },
+};
+
+
+unsigned int codec_get_tag(CodecTag *tags, int id)
+{
+ while (tags->id != 0) {
+ if (tags->id == id)
+ return tags->tag;
+ tags++;
+ }
+ return 0;
+}
+
+int codec_get_id(CodecTag *tags, unsigned int tag)
+{
+ while (tags->id != 0) {
+ if (tags->tag == tag)
+ return tags->id;
+ tags++;
+ }
+ return 0;
+}
+
+unsigned int codec_get_bmp_tag(int id)
+{
+ return codec_get_tag(codec_bmp_tags, id);
+}
+
+/* BITMAPINFOHEADER header */
+void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc)
+{
+ put_le32(pb, 40); /* size */
+ put_le32(pb, enc->width);
+ put_le32(pb, enc->height);
+ put_le16(pb, 1); /* planes */
+ put_le16(pb, 24); /* depth */
+ /* compression type */
+ put_le32(pb, codec_get_bmp_tag(enc->codec_id));
+ put_le32(pb, enc->width * enc->height * 3);
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+}
+
+/* WAVEFORMATEX header */
+void put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
+{
+ int tag;
+
+ tag = codec_get_tag(codec_wav_tags, enc->codec_id);
+
+ put_le16(pb, tag);
+ put_le16(pb, enc->channels);
+ put_le32(pb, enc->sample_rate);
+ put_le32(pb, enc->bit_rate / 8);
+ put_le16(pb, 1); /* block align */
+ put_le16(pb, 16); /* bits per sample */
+ put_le16(pb, 0); /* wav_extra_size */
+}
+
+static int avi_write_header(AVFormatContext *s)
+{
+ AVIContext *avi;
+ ByteIOContext *pb = &s->pb;
+ int bitrate, n, i, nb_frames;
+ AVCodecContext *stream, *video_enc;
+ offset_t list1, list2, strh, strf;
+
+ avi = malloc(sizeof(AVIContext));
+ if (!avi)
+ return -1;
+ memset(avi, 0, sizeof(AVIContext));
+ s->priv_data = avi;
+
+ put_tag(pb, "RIFF");
+ put_le32(pb, 0); /* file length */
+ put_tag(pb, "AVI ");
+
+ /* header list */
+ list1 = start_tag(pb, "LIST");
+ put_tag(pb, "hdrl");
+
+ /* avi header */
+ put_tag(pb, "avih");
+ put_le32(pb, 14 * 4);
+ bitrate = 0;
+
+ video_enc = NULL;
+ for(n=0;n<s->nb_streams;n++) {
+ stream = &s->streams[n]->codec;
+ bitrate += stream->bit_rate;
+ if (stream->codec_type == CODEC_TYPE_VIDEO)
+ video_enc = stream;
+ }
+
+ if (!video_enc) {
+ free(avi);
+ return -1;
+ }
+ nb_frames = 0;
+
+ put_le32(pb, 1000000LL * FRAME_RATE_BASE / video_enc->frame_rate);
+ put_le32(pb, bitrate / 8); /* XXX: not quite exact */
+ put_le32(pb, 0); /* padding */
+ put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
+ put_le32(pb, nb_frames); /* nb frames, filled later */
+ put_le32(pb, 0); /* initial frame */
+ put_le32(pb, s->nb_streams); /* nb streams */
+ put_le32(pb, 1024 * 1024); /* suggested buffer size */
+ put_le32(pb, video_enc->width);
+ put_le32(pb, video_enc->height);
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+ put_le32(pb, 0); /* reserved */
+
+ /* stream list */
+ for(i=0;i<n;i++) {
+ list2 = start_tag(pb, "LIST");
+ put_tag(pb, "strl");
+
+ stream = &s->streams[i]->codec;
+
+ /* stream generic header */
+ strh = start_tag(pb, "strh");
+ switch(stream->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ put_tag(pb, "vids");
+ put_le32(pb, codec_get_bmp_tag(stream->codec_id));
+ put_le32(pb, 0); /* flags */
+ put_le16(pb, 0); /* priority */
+ put_le16(pb, 0); /* language */
+ put_le32(pb, 0); /* initial frame */
+ put_le32(pb, 1000); /* scale */
+ put_le32(pb, (1000 * stream->frame_rate) / FRAME_RATE_BASE); /* rate */
+ put_le32(pb, 0); /* start */
+ put_le32(pb, nb_frames); /* length, XXX: fill later */
+ put_le32(pb, 1024 * 1024); /* suggested buffer size */
+ put_le32(pb, 10000); /* quality */
+ put_le32(pb, stream->width * stream->height * 3); /* sample size */
+ put_le16(pb, 0);
+ put_le16(pb, 0);
+ put_le16(pb, stream->width);
+ put_le16(pb, stream->height);
+ break;
+ case CODEC_TYPE_AUDIO:
+ put_tag(pb, "auds");
+ put_le32(pb, 0);
+ put_le32(pb, 0); /* flags */
+ put_le16(pb, 0); /* priority */
+ put_le16(pb, 0); /* language */
+ put_le32(pb, 0); /* initial frame */
+ put_le32(pb, 1); /* scale */
+ put_le32(pb, stream->bit_rate / 8); /* rate */
+ put_le32(pb, 0); /* start */
+ put_le32(pb, 0); /* length, XXX: filled later */
+ put_le32(pb, 12 * 1024); /* suggested buffer size */
+ put_le32(pb, -1); /* quality */
+ put_le32(pb, 1); /* sample size */
+ put_le32(pb, 0);
+ put_le32(pb, 0);
+ break;
+ }
+ end_tag(pb, strh);
+
+ strf = start_tag(pb, "strf");
+ switch(stream->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ put_bmp_header(pb, stream);
+ break;
+ case CODEC_TYPE_AUDIO:
+ put_wav_header(pb, stream);
+ break;
+ }
+ end_tag(pb, strf);
+ end_tag(pb, list2);
+ }
+
+ end_tag(pb, list1);
+
+ avi->movi_list = start_tag(pb, "LIST");
+ avi->first = NULL;
+ avi->last = NULL;
+ put_tag(pb, "movi");
+
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int avi_write_packet(AVFormatContext *s, int stream_index,
+ UINT8 *buf, int size)
+{
+ AVIContext *avi = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVIIndex *idx;
+ unsigned char tag[5];
+ unsigned int flags;
+ AVCodecContext *enc;
+
+ enc = &s->streams[stream_index]->codec;
+
+ tag[0] = '0';
+ tag[1] = '0' + stream_index;
+ if (enc->codec_type == CODEC_TYPE_VIDEO) {
+ tag[2] = 'd';
+ tag[3] = 'c';
+ flags = enc->key_frame ? 0x10 : 0x00;
+ } else {
+ tag[2] = 'w';
+ tag[3] = 'b';
+ flags = 0x10;
+ }
+
+ if (!url_is_streamed(&s->pb)) {
+ idx = malloc(sizeof(AVIIndex));
+ memcpy(idx->tag, tag, 4);
+ idx->flags = flags;
+ idx->pos = url_ftell(pb) - avi->movi_list;
+ idx->len = size;
+ idx->next = NULL;
+ if (!avi->last)
+ avi->first = idx;
+ else
+ avi->last->next = idx;
+ avi->last = idx;
+ }
+
+ put_buffer(pb, tag, 4);
+ put_le32(pb, size);
+ put_buffer(pb, buf, size);
+ if (size & 1)
+ put_byte(pb, 0);
+
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int avi_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ AVIContext *avi = s->priv_data;
+ offset_t file_size, idx_chunk;
+ AVIIndex *idx;
+
+ if (!url_is_streamed(&s->pb)) {
+ end_tag(pb, avi->movi_list);
+
+ idx_chunk = start_tag(pb, "idx1");
+ idx = avi->first;
+ while (idx != NULL) {
+ put_buffer(pb, idx->tag, 4);
+ put_le32(pb, idx->flags);
+ put_le32(pb, idx->pos);
+ put_le32(pb, idx->len);
+ idx = idx->next;
+ }
+ end_tag(pb, idx_chunk);
+
+ /* update file size */
+ file_size = url_ftell(pb);
+ url_fseek(pb, 4, SEEK_SET);
+ put_le32(pb, file_size);
+ url_fseek(pb, file_size, SEEK_SET);
+ }
+ put_flush_packet(pb);
+
+ free(avi);
+ return 0;
+}
+
+AVFormat avi_format = {
+ "avi",
+ "avi format",
+ "video/x-msvideo",
+ "avi",
+ CODEC_ID_MP2,
+ CODEC_ID_MSMPEG4,
+ avi_write_header,
+ avi_write_packet,
+ avi_write_trailer,
+
+ avi_read_header,
+ avi_read_packet,
+ avi_read_close,
+};
diff --git a/libav/avio.c b/libav/avio.c
new file mode 100644
index 0000000000..243f76f379
--- /dev/null
+++ b/libav/avio.c
@@ -0,0 +1,146 @@
+/*
+ * Unbuffered io for ffmpeg system
+ * Copyright (c) 2001 Gerard Lantau
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "avformat.h"
+
+URLProtocol *first_protocol = NULL;
+
+int register_protocol(URLProtocol *protocol)
+{
+ URLProtocol **p;
+ p = &first_protocol;
+ while (*p != NULL) p = &(*p)->next;
+ *p = protocol;
+ protocol->next = NULL;
+ return 0;
+}
+
+int url_open(URLContext **puc, const char *filename, int flags)
+{
+ URLContext *uc;
+ URLProtocol *up;
+ const char *p;
+ char proto_str[128], *q;
+ int err;
+
+ p = filename;
+ q = proto_str;
+ while (*p != '\0' && *p != ':') {
+ if ((q - proto_str) < sizeof(proto_str) - 1)
+ *q++ = *p;
+ p++;
+ }
+ if (*p == '\0') {
+ strcpy(proto_str, "file");
+ } else {
+ *q = '\0';
+ }
+
+ up = first_protocol;
+ while (up != NULL) {
+ if (!strcmp(proto_str, up->name))
+ goto found;
+ up = up->next;
+ }
+ return -ENOENT;
+ found:
+ uc = malloc(sizeof(URLContext));
+ if (!uc)
+ return -ENOMEM;
+ uc->prot = up;
+ uc->flags = flags;
+ uc->is_streamed = 0; /* default = not streamed */
+ uc->packet_size = 1; /* default packet size */
+ err = up->url_open(uc, filename, flags);
+ if (err < 0) {
+ free(uc);
+ *puc = NULL;
+ return err;
+ }
+ *puc = uc;
+ return 0;
+}
+
+int url_read(URLContext *h, unsigned char *buf, int size)
+{
+ int ret;
+ if (h->flags & URL_WRONLY)
+ return -EIO;
+ ret = h->prot->url_read(h, buf, size);
+ return ret;
+}
+
+int url_write(URLContext *h, unsigned char *buf, int size)
+{
+ int ret;
+ if (!(h->flags & URL_WRONLY))
+ return -EIO;
+ ret = h->prot->url_write(h, buf, size);
+ return ret;
+}
+
+offset_t url_seek(URLContext *h, offset_t pos, int whence)
+{
+ offset_t ret;
+
+ if (!h->prot->url_seek)
+ return -EPIPE;
+ ret = h->prot->url_seek(h, pos, whence);
+ return ret;
+}
+
+int url_getformat(URLContext *h, URLFormat *f)
+{
+ memset(f, 0, sizeof(*f));
+ if (!h->prot->url_getformat)
+ return -ENODATA;
+ return h->prot->url_getformat(h, f);
+}
+
+int url_close(URLContext *h)
+{
+ int ret;
+
+ ret = h->prot->url_close(h);
+ free(h);
+ return ret;
+}
+
+int url_exist(const char *filename)
+{
+ URLContext *h;
+ if (url_open(&h, filename, URL_RDONLY) < 0)
+ return 0;
+ url_close(h);
+ return 1;
+}
+
+offset_t url_filesize(URLContext *h)
+{
+ offset_t pos, size;
+
+ pos = url_seek(h, 0, SEEK_CUR);
+ size = url_seek(h, 0, SEEK_END);
+ url_seek(h, pos, SEEK_SET);
+ return size;
+}
diff --git a/libav/avio.h b/libav/avio.h
new file mode 100644
index 0000000000..a3e11b61aa
--- /dev/null
+++ b/libav/avio.h
@@ -0,0 +1,151 @@
+/* output byte stream handling */
+
+typedef long long offset_t;
+
+/* unbuffered I/O */
+
+struct URLContext {
+ struct URLProtocol *prot;
+ int flags;
+ int is_streamed; /* true if streamed (no seek possible), default = false */
+ int packet_size;
+ void *priv_data;
+};
+
+typedef struct URLFormat {
+ char format_name[32];
+ int sample_rate;
+ int frame_rate;
+ int channels;
+ int height;
+ int width;
+ int pix_fmt;
+} URLFormat;
+
+typedef struct URLContext URLContext;
+
+typedef struct URLPollEntry {
+ URLContext *handle;
+ int events;
+ int revents;
+} URLPollEntry;
+
+#define URL_RDONLY 0
+#define URL_WRONLY 1
+int url_open(URLContext **h, const char *filename, int flags);
+int url_read(URLContext *h, unsigned char *buf, int size);
+int url_write(URLContext *h, unsigned char *buf, int size);
+offset_t url_seek(URLContext *h, offset_t pos, int whence);
+int url_getformat(URLContext *h, URLFormat *f);
+int url_close(URLContext *h);
+int url_exist(const char *filename);
+offset_t url_filesize(URLContext *h);
+/* not implemented */
+int url_poll(URLPollEntry *poll_table, int n, int timeout);
+
+typedef struct URLProtocol {
+ const char *name;
+ int (*url_open)(URLContext *h, const char *filename, int flags);
+ int (*url_read)(URLContext *h, unsigned char *buf, int size);
+ int (*url_write)(URLContext *h, unsigned char *buf, int size);
+ offset_t (*url_seek)(URLContext *h, offset_t pos, int whence);
+ int (*url_close)(URLContext *h);
+ /* get precise information about the format, if available. return
+ -ENODATA if not available */
+ int (*url_getformat)(URLContext *h, URLFormat *f);
+ struct URLProtocol *next;
+} URLProtocol;
+
+extern URLProtocol *first_protocol;
+
+int register_protocol(URLProtocol *protocol);
+
+typedef struct {
+ unsigned char *buffer;
+ int buffer_size;
+ unsigned char *buf_ptr, *buf_end;
+ void *opaque;
+ int (*read_packet)(void *opaque, UINT8 *buf, int buf_size);
+ void (*write_packet)(void *opaque, UINT8 *buf, int buf_size);
+ int (*seek)(void *opaque, offset_t offset, int whence);
+ offset_t pos; /* position in the file of the current buffer */
+ int must_flush; /* true if the next seek should flush */
+ int eof_reached; /* true if eof reached */
+ int write_flag; /* true if open for writing */
+ int is_streamed;
+ int packet_size;
+} ByteIOContext;
+
+int init_put_byte(ByteIOContext *s,
+ unsigned char *buffer,
+ int buffer_size,
+ int write_flag,
+ void *opaque,
+ int (*read_packet)(void *opaque, UINT8 *buf, int buf_size),
+ void (*write_packet)(void *opaque, UINT8 *buf, int buf_size),
+ int (*seek)(void *opaque, offset_t offset, int whence));
+
+void put_byte(ByteIOContext *s, int b);
+void put_buffer(ByteIOContext *s, unsigned char *buf, int size);
+void put_le64(ByteIOContext *s, unsigned long long val);
+void put_be64(ByteIOContext *s, unsigned long long val);
+void put_le32(ByteIOContext *s, unsigned int val);
+void put_be32(ByteIOContext *s, unsigned int val);
+void put_le16(ByteIOContext *s, unsigned int val);
+void put_be16(ByteIOContext *s, unsigned int val);
+void put_tag(ByteIOContext *s, char *tag);
+
+offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence);
+void url_fskip(ByteIOContext *s, offset_t offset);
+offset_t url_ftell(ByteIOContext *s);
+int url_feof(ByteIOContext *s);
+
+void put_flush_packet(ByteIOContext *s);
+
+int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
+int get_byte(ByteIOContext *s);
+unsigned int get_le32(ByteIOContext *s);
+unsigned long long get_le64(ByteIOContext *s);
+unsigned int get_le16(ByteIOContext *s);
+
+unsigned int get_be16(ByteIOContext *s);
+unsigned int get_be32(ByteIOContext *s);
+unsigned long long get_be64(ByteIOContext *s);
+
+extern inline int url_is_streamed(ByteIOContext *s)
+{
+ return s->is_streamed;
+}
+/* get the prefered packet size of the device. All I/Os should be done
+ by multiple of this size */
+extern inline int url_get_packet_size(ByteIOContext *s)
+{
+ return s->packet_size;
+}
+
+int url_fdopen(ByteIOContext *s, URLContext *h);
+int url_setbufsize(ByteIOContext *s, int buf_size);
+int url_fopen(ByteIOContext *s, const char *filename, int flags);
+int url_fclose(ByteIOContext *s);
+URLContext *url_fileno(ByteIOContext *s);
+
+int url_open_buf(ByteIOContext *s, UINT8 *buf, int buf_size, int flags);
+int url_close_buf(ByteIOContext *s);
+
+/* file.c */
+extern URLProtocol file_protocol;
+extern URLProtocol pipe_protocol;
+
+/* udp.c */
+extern URLProtocol udp_protocol;
+
+/* http.c */
+extern URLProtocol http_protocol;
+
+/* audio.c */
+extern const char *audio_device;
+extern URLProtocol audio_protocol;
+
+/* grab.c */
+extern const char *v4l_device;
+extern URLProtocol video_protocol;
diff --git a/libav/aviobuf.c b/libav/aviobuf.c
new file mode 100644
index 0000000000..c50629e067
--- /dev/null
+++ b/libav/aviobuf.c
@@ -0,0 +1,426 @@
+/*
+ * Buffered I/O for ffmpeg system
+ * Copyright (c) 2000,2001 Gerard Lantau
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <getopt.h>
+#include <string.h>
+
+#include "avformat.h"
+
+#define IO_BUFFER_SIZE 32768
+
+int init_put_byte(ByteIOContext *s,
+ unsigned char *buffer,
+ int buffer_size,
+ int write_flag,
+ void *opaque,
+ int (*read_packet)(void *opaque, UINT8 *buf, int buf_size),
+ void (*write_packet)(void *opaque, UINT8 *buf, int buf_size),
+ int (*seek)(void *opaque, offset_t offset, int whence))
+{
+ s->buffer = buffer;
+ s->buffer_size = buffer_size;
+ s->buf_ptr = buffer;
+ s->write_flag = write_flag;
+ if (!s->write_flag)
+ s->buf_end = buffer;
+ else
+ s->buf_end = buffer + buffer_size;
+ s->opaque = opaque;
+ s->write_packet = write_packet;
+ s->read_packet = read_packet;
+ s->seek = seek;
+ s->pos = 0;
+ s->must_flush = 0;
+ s->eof_reached = 0;
+ s->is_streamed = 0;
+ s->packet_size = 1;
+ return 0;
+}
+
+
+static void flush_buffer(ByteIOContext *s)
+{
+ if (s->buf_ptr > s->buffer) {
+ if (s->write_packet)
+ s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
+ s->pos += s->buf_ptr - s->buffer;
+ }
+ s->buf_ptr = s->buffer;
+}
+
+void put_byte(ByteIOContext *s, int b)
+{
+ *(s->buf_ptr)++ = b;
+ if (s->buf_ptr >= s->buf_end)
+ flush_buffer(s);
+}
+
+void put_buffer(ByteIOContext *s, unsigned char *buf, int size)
+{
+ int len;
+
+ while (size > 0) {
+ len = (s->buf_end - s->buf_ptr);
+ if (len > size)
+ len = size;
+ memcpy(s->buf_ptr, buf, len);
+ s->buf_ptr += len;
+
+ if (s->buf_ptr >= s->buf_end)
+ flush_buffer(s);
+
+ buf += len;
+ size -= len;
+ }
+}
+
+void put_flush_packet(ByteIOContext *s)
+{
+ flush_buffer(s);
+ s->must_flush = 0;
+}
+
+offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)
+{
+ offset_t offset1;
+
+ if (whence != SEEK_CUR && whence != SEEK_SET)
+ return -EINVAL;
+
+ if (s->write_flag) {
+ if (whence == SEEK_CUR) {
+ offset1 = s->pos + s->buf_ptr - s->buffer;
+ if (offset == 0)
+ return offset1;
+ offset += offset1;
+ }
+ offset1 = offset - s->pos;
+ if (!s->must_flush &&
+ offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
+ /* can do the seek inside the buffer */
+ s->buf_ptr = s->buffer + offset1;
+ } else {
+ if (!s->seek)
+ return -EPIPE;
+ flush_buffer(s);
+ s->must_flush = 1;
+ s->buf_ptr = s->buffer;
+ s->seek(s->opaque, offset, SEEK_SET);
+ s->pos = offset;
+ }
+ } else {
+ if (whence == SEEK_CUR) {
+ offset1 = s->pos - (s->buf_end - s->buffer) + (s->buf_ptr - s->buffer);
+ if (offset == 0)
+ return offset1;
+ offset += offset1;
+ }
+ offset1 = offset - (s->pos - (s->buf_end - s->buffer));
+ if (offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
+ /* can do the seek inside the buffer */
+ s->buf_ptr = s->buffer + offset1;
+ } else {
+ if (!s->seek)
+ return -EPIPE;
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer;
+ s->eof_reached = 0;
+ s->seek(s->opaque, offset, SEEK_SET);
+ s->pos = offset;
+ }
+ }
+ return offset;
+}
+
+void url_fskip(ByteIOContext *s, offset_t offset)
+{
+ url_fseek(s, offset, SEEK_CUR);
+}
+
+offset_t url_ftell(ByteIOContext *s)
+{
+ return url_fseek(s, 0, SEEK_CUR);
+}
+
+int url_feof(ByteIOContext *s)
+{
+ return s->eof_reached;
+}
+
+void put_le32(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val);
+ put_byte(s, val >> 8);
+ put_byte(s, val >> 16);
+ put_byte(s, val >> 24);
+}
+
+void put_be32(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val >> 24);
+ put_byte(s, val >> 16);
+ put_byte(s, val >> 8);
+ put_byte(s, val);
+}
+
+void put_le64(ByteIOContext *s, unsigned long long val)
+{
+ put_le32(s, val & 0xffffffff);
+ put_le32(s, val >> 32);
+}
+
+void put_be64(ByteIOContext *s, unsigned long long val)
+{
+ put_be32(s, val >> 32);
+ put_be32(s, val & 0xffffffff);
+}
+
+void put_le16(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val);
+ put_byte(s, val >> 8);
+}
+
+void put_be16(ByteIOContext *s, unsigned int val)
+{
+ put_byte(s, val >> 8);
+ put_byte(s, val);
+}
+
+void put_tag(ByteIOContext *s, char *tag)
+{
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+
+/* Input stream */
+
+static void fill_buffer(ByteIOContext *s)
+{
+ int len;
+
+ len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
+ s->pos += len;
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer + len;
+ if (len == 0) {
+ s->eof_reached = 1;
+ }
+}
+
+int get_byte(ByteIOContext *s)
+{
+ if (s->buf_ptr < s->buf_end) {
+ return *s->buf_ptr++;
+ } else {
+ fill_buffer(s);
+ if (s->buf_ptr < s->buf_end)
+ return *s->buf_ptr++;
+ else
+ return 0;
+ }
+}
+
+int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
+{
+ int len, size1;
+
+ size1 = size;
+ while (size > 0) {
+ len = s->buf_end - s->buf_ptr;
+ if (len > size)
+ len = size;
+ if (len == 0) {
+ fill_buffer(s);
+ len = s->buf_end - s->buf_ptr;
+ if (len == 0)
+ break;
+ } else {
+ memcpy(buf, s->buf_ptr, len);
+ buf += len;
+ s->buf_ptr += len;
+ size -= len;
+ }
+ }
+ return size1 - size;
+}
+
+unsigned int get_le16(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_byte(s);
+ val |= get_byte(s) << 8;
+ return val;
+}
+
+unsigned int get_le32(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_byte(s);
+ val |= get_byte(s) << 8;
+ val |= get_byte(s) << 16;
+ val |= get_byte(s) << 24;
+ return val;
+}
+
+unsigned long long get_le64(ByteIOContext *s)
+{
+ UINT64 val;
+ val = (UINT64)get_le32(s);
+ val |= (UINT64)get_le32(s) << 32;
+ return val;
+}
+
+unsigned int get_be16(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_byte(s) << 8;
+ val |= get_byte(s);
+ return val;
+}
+
+unsigned int get_be32(ByteIOContext *s)
+{
+ unsigned int val;
+ val = get_byte(s) << 24;
+ val |= get_byte(s) << 16;
+ val |= get_byte(s) << 8;
+ val |= get_byte(s);
+ return val;
+}
+
+unsigned long long get_be64(ByteIOContext *s)
+{
+ UINT64 val;
+ val = (UINT64)get_be32(s) << 32;
+ val |= (UINT64)get_be32(s);
+ return val;
+}
+
+/* link with avio functions */
+
+void url_write_packet(void *opaque, UINT8 *buf, int buf_size)
+{
+ URLContext *h = opaque;
+ url_write(h, buf, buf_size);
+}
+
+int url_read_packet(void *opaque, UINT8 *buf, int buf_size)
+{
+ URLContext *h = opaque;
+ return url_read(h, buf, buf_size);
+}
+
+int url_seek_packet(void *opaque, long long offset, int whence)
+{
+ URLContext *h = opaque;
+ url_seek(h, offset, whence);
+ return 0;
+}
+
+int url_fdopen(ByteIOContext *s, URLContext *h)
+{
+ UINT8 *buffer;
+ int buffer_size;
+
+ buffer_size = (IO_BUFFER_SIZE / h->packet_size) * h->packet_size;
+ buffer = malloc(buffer_size);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (init_put_byte(s, buffer, buffer_size,
+ (h->flags & URL_WRONLY) != 0, h,
+ url_read_packet, url_write_packet, url_seek_packet) < 0) {
+ free(buffer);
+ return -EIO;
+ }
+ s->is_streamed = h->is_streamed;
+ s->packet_size = h->packet_size;
+ return 0;
+}
+
+/* XXX: must be called before any I/O */
+int url_setbufsize(ByteIOContext *s, int buf_size)
+{
+ UINT8 *buffer;
+ buffer = malloc(buf_size);
+ if (!buffer)
+ return -ENOMEM;
+
+ free(s->buffer);
+ s->buffer = buffer;
+ s->buffer_size = buf_size;
+ s->buf_ptr = buffer;
+ if (!s->write_flag)
+ s->buf_end = buffer;
+ else
+ s->buf_end = buffer + buf_size;
+ return 0;
+}
+
+int url_fopen(ByteIOContext *s, const char *filename, int flags)
+{
+ URLContext *h;
+ int err;
+
+ err = url_open(&h, filename, flags);
+ if (err < 0)
+ return err;
+ err = url_fdopen(s, h);
+ if (err < 0) {
+ url_close(h);
+ return err;
+ }
+ return 0;
+}
+
+int url_fclose(ByteIOContext *s)
+{
+ URLContext *h = s->opaque;
+
+ free(s->buffer);
+ memset(s, 0, sizeof(ByteIOContext));
+ return url_close(h);
+}
+
+URLContext *url_fileno(ByteIOContext *s)
+{
+ return s->opaque;
+}
+
+/* buffer handling */
+int url_open_buf(ByteIOContext *s, UINT8 *buf, int buf_size, int flags)
+{
+ return init_put_byte(s, buf, buf_size,
+ (flags & URL_WRONLY) != 0, NULL, NULL, NULL, NULL);
+}
+
+/* return the written or read size */
+int url_close_buf(ByteIOContext *s)
+{
+ return s->buf_ptr - s->buffer;
+}
diff --git a/libav/ffm.c b/libav/ffm.c
new file mode 100644
index 0000000000..76e7613286
--- /dev/null
+++ b/libav/ffm.c
@@ -0,0 +1,599 @@
+/*
+ * FFM (ffserver live feed) encoder and decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "avformat.h"
+
+/* The FFM file is made of blocks of fixed size */
+#define FFM_HEADER_SIZE 14
+#define PACKET_ID 0x666d
+
+/* each packet contains frames (which can span several packets */
+#define FRAME_HEADER_SIZE 5
+#define FLAG_KEY_FRAME 0x01
+
+typedef struct FFMStream {
+ INT64 pts;
+} FFMStream;
+
+enum {
+ READ_HEADER,
+ READ_DATA,
+};
+
+typedef struct FFMContext {
+ /* only reading mode */
+ offset_t write_index, file_size;
+ int read_state;
+ UINT8 header[FRAME_HEADER_SIZE];
+
+ /* read and write */
+ int first_packet; /* true if first packet, needed to set the discontinuity tag */
+ int packet_size;
+ int frame_offset;
+ INT64 pts;
+ UINT8 *packet_ptr, *packet_end;
+ UINT8 packet[1]; /* must be last */
+} FFMContext;
+
+static void flush_packet(AVFormatContext *s)
+{
+ FFMContext *ffm = s->priv_data;
+ int fill_size, h;
+ ByteIOContext *pb = &s->pb;
+
+ fill_size = ffm->packet_end - ffm->packet_ptr;
+ memset(ffm->packet_ptr, 0, fill_size);
+
+ /* put header */
+ put_be16(pb, PACKET_ID);
+ put_be16(pb, fill_size);
+ put_be64(pb, ffm->pts);
+ h = ffm->frame_offset;
+ if (ffm->first_packet)
+ h |= 0x8000;
+ put_be16(pb, h);
+ put_buffer(pb, ffm->packet, ffm->packet_end - ffm->packet);
+
+ /* prepare next packet */
+ ffm->frame_offset = 0; /* no key frame */
+ ffm->pts = 0; /* no pts */
+ ffm->packet_ptr = ffm->packet;
+ ffm->first_packet = 0;
+}
+
+/* 'first' is true if first data of a frame */
+static void ffm_write_data(AVFormatContext *s,
+ UINT8 *buf, int size,
+ INT64 pts, int first)
+{
+ FFMContext *ffm = s->priv_data;
+ int len;
+
+ if (first && ffm->frame_offset == 0)
+ ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE;
+ if (first && ffm->pts == 0)
+ ffm->pts = pts;
+
+ /* write as many packets as needed */
+ while (size > 0) {
+ len = ffm->packet_end - ffm->packet_ptr;
+ if (len > size)
+ len = size;
+ memcpy(ffm->packet_ptr, buf, len);
+
+ ffm->packet_ptr += len;
+ buf += len;
+ size -= len;
+ if (ffm->packet_ptr >= ffm->packet_end) {
+ /* special case : no pts in packet : we leave the current one */
+ if (ffm->pts == 0)
+ ffm->pts = pts;
+
+ flush_packet(s);
+ }
+ }
+}
+
+static int ffm_write_header(AVFormatContext *s)
+{
+ AVStream *st;
+ FFMStream *fst;
+ FFMContext *ffm;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *codec;
+ int bit_rate, i;
+
+ ffm = av_mallocz(sizeof(FFMContext) + FFM_PACKET_SIZE);
+ if (!ffm)
+ return -1;
+
+ s->priv_data = ffm;
+ ffm->packet_size = FFM_PACKET_SIZE;
+
+ /* header */
+ put_tag(pb, "FFM1");
+ put_be32(pb, ffm->packet_size);
+ /* XXX: store write position in other file ? */
+ put_be64(pb, ffm->packet_size); /* current write position */
+
+ put_be32(pb, s->nb_streams);
+ bit_rate = 0;
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ bit_rate += st->codec.bit_rate;
+ }
+ put_be32(pb, bit_rate);
+
+ /* list of streams */
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ fst = av_mallocz(sizeof(FFMStream) + ffm->packet_size);
+ if (!fst)
+ goto fail;
+ st->priv_data = fst;
+
+ codec = &st->codec;
+ /* generic info */
+ put_be32(pb, codec->codec_id);
+ put_byte(pb, codec->codec_type);
+ put_be32(pb, codec->bit_rate);
+ /* specific info */
+ switch(codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ put_be32(pb, (codec->frame_rate * 1000) / FRAME_RATE_BASE);
+ put_be16(pb, codec->width);
+ put_be16(pb, codec->height);
+ break;
+ case CODEC_TYPE_AUDIO:
+ put_be32(pb, codec->sample_rate);
+ put_le16(pb, codec->channels);
+ break;
+ }
+ /* hack to have real time */
+ fst->pts = gettime();
+ }
+
+ /* flush until end of block reached */
+ while ((url_ftell(pb) % ffm->packet_size) != 0)
+ put_byte(pb, 0);
+
+ put_flush_packet(pb);
+
+ /* init packet mux */
+ ffm->packet_ptr = ffm->packet;
+ ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
+ ffm->frame_offset = 0;
+ ffm->pts = 0;
+ ffm->first_packet = 1;
+
+ return 0;
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ fst = st->priv_data;
+ if (fst)
+ free(fst);
+ }
+ free(ffm);
+ return -1;
+}
+
+static int ffm_write_packet(AVFormatContext *s, int stream_index,
+ UINT8 *buf, int size)
+{
+ AVStream *st = s->streams[stream_index];
+ FFMStream *fst = st->priv_data;
+ INT64 pts;
+ UINT8 header[FRAME_HEADER_SIZE];
+
+ pts = fst->pts;
+ /* packet size & key_frame */
+ header[0] = stream_index;
+ header[1] = 0;
+ if (st->codec.key_frame)
+ header[1] |= FLAG_KEY_FRAME;
+ header[2] = (size >> 16) & 0xff;
+ header[3] = (size >> 8) & 0xff;
+ header[4] = size & 0xff;
+ ffm_write_data(s, header, FRAME_HEADER_SIZE, pts, 1);
+ ffm_write_data(s, buf, size, pts, 0);
+
+ if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
+ fst->pts += (INT64)((float)st->codec.frame_size / st->codec.sample_rate * 1000000.0);
+ } else {
+ fst->pts += (INT64)(1000000.0 * FRAME_RATE_BASE / (float)st->codec.frame_rate);
+ }
+ return 0;
+}
+
+static int ffm_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ FFMContext *ffm = s->priv_data;
+ int i;
+
+ /* flush packets */
+ if (ffm->packet_ptr > ffm->packet)
+ flush_packet(s);
+
+ put_flush_packet(pb);
+
+ for(i=0;i<s->nb_streams;i++)
+ free(s->streams[i]->priv_data);
+ free(ffm);
+ return 0;
+}
+
+/* ffm demux */
+
+static int ffm_is_avail_data(AVFormatContext *s, int size)
+{
+ FFMContext *ffm = s->priv_data;
+ offset_t pos, avail_size;
+ int len;
+
+ len = ffm->packet_end - ffm->packet_ptr;
+ if (size <= len)
+ return 1;
+ pos = url_ftell(&s->pb);
+ if (pos == ffm->write_index) {
+ /* exactly at the end of stream */
+ return 0;
+ } else if (pos < ffm->write_index) {
+ avail_size = ffm->write_index - pos;
+ } else {
+ avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
+ }
+ avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
+ if (size <= avail_size)
+ return 1;
+ else
+ return 0;
+}
+
+/* first is true if we read the frame header */
+static int ffm_read_data(AVFormatContext *s,
+ UINT8 *buf, int size, int first)
+{
+ FFMContext *ffm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ int len, fill_size, size1, frame_offset;
+
+ size1 = size;
+ while (size > 0) {
+ redo:
+ len = ffm->packet_end - ffm->packet_ptr;
+ if (len > size)
+ len = size;
+ if (len == 0) {
+ if (url_ftell(pb) == ffm->file_size)
+ url_fseek(pb, ffm->packet_size, SEEK_SET);
+ get_be16(pb); /* PACKET_ID */
+ fill_size = get_be16(pb);
+ ffm->pts = get_be64(pb);
+ frame_offset = get_be16(pb);
+ get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
+ ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
+ /* if first packet or resynchronization packet, we must
+ handle it specifically */
+ if (ffm->first_packet || (frame_offset & 0x8000)) {
+ ffm->first_packet = 0;
+ ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
+ if (!first)
+ break;
+ } else {
+ ffm->packet_ptr = ffm->packet;
+ }
+ goto redo;
+ }
+ memcpy(buf, ffm->packet_ptr, len);
+ buf += len;
+ ffm->packet_ptr += len;
+ size -= len;
+ first = 0;
+ }
+ return size1 - size;
+}
+
+
+static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ AVStream *st;
+ FFMStream *fst;
+ FFMContext *ffm;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *codec;
+ int i;
+ UINT32 tag;
+
+ ffm = av_mallocz(sizeof(FFMContext) + FFM_PACKET_SIZE);
+ if (!ffm)
+ return -1;
+
+ s->priv_data = ffm;
+
+ /* header */
+ tag = get_le32(pb);
+ if (tag != MKTAG('F', 'F', 'M', '1'))
+ goto fail;
+ ffm->packet_size = get_be32(pb);
+ if (ffm->packet_size != FFM_PACKET_SIZE)
+ goto fail;
+ ffm->write_index = get_be64(pb);
+ /* get also filesize */
+ if (!url_is_streamed(pb)) {
+ ffm->file_size = url_filesize(url_fileno(pb));
+ } else {
+ ffm->file_size = (1ULL << 63) - 1;
+ }
+
+ s->nb_streams = get_be32(pb);
+ get_be32(pb); /* total bitrate */
+ /* read each stream */
+ for(i=0;i<s->nb_streams;i++) {
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ goto fail;
+ s->streams[i] = st;
+ fst = av_mallocz(sizeof(FFMStream) + ffm->packet_size);
+ if (!fst)
+ goto fail;
+ st->priv_data = fst;
+
+ codec = &st->codec;
+ /* generic info */
+ st->codec.codec_id = get_be32(pb);
+ st->codec.codec_type = get_byte(pb); /* codec_type */
+ codec->bit_rate = get_be32(pb);
+ /* specific info */
+ switch(codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ codec->frame_rate = ((INT64)get_be32(pb) * FRAME_RATE_BASE) / 1000;
+ codec->width = get_be16(pb);
+ codec->height = get_be16(pb);
+ break;
+ case CODEC_TYPE_AUDIO:
+ codec->sample_rate = get_be32(pb);
+ codec->channels = get_le16(pb);
+ break;
+ }
+
+ }
+
+ /* get until end of block reached */
+ while ((url_ftell(pb) % ffm->packet_size) != 0)
+ get_byte(pb);
+
+ /* init packet demux */
+ ffm->packet_ptr = ffm->packet;
+ ffm->packet_end = ffm->packet;
+ ffm->frame_offset = 0;
+ ffm->pts = 0;
+ ffm->read_state = READ_HEADER;
+ ffm->first_packet = 1;
+ return 0;
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (st) {
+ fst = st->priv_data;
+ if (fst)
+ free(fst);
+ free(st);
+ }
+ }
+ if (ffm)
+ free(ffm);
+ return -1;
+}
+
+/* return < 0 if eof */
+static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int size;
+ FFMContext *ffm = s->priv_data;
+
+ switch(ffm->read_state) {
+ case READ_HEADER:
+ if (!ffm_is_avail_data(s, FRAME_HEADER_SIZE))
+ return -EAGAIN;
+#if 0
+ printf("pos=%08Lx spos=%Lx, write_index=%Lx size=%Lx\n",
+ url_ftell(&s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
+#endif
+ if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) != FRAME_HEADER_SIZE)
+ return -EAGAIN;
+
+#if 0
+ {
+ int i;
+ for(i=0;i<FRAME_HEADER_SIZE;i++)
+ printf("%02x ", ffm->header[i]);
+ printf("\n");
+ }
+#endif
+ ffm->read_state = READ_DATA;
+ /* fall thru */
+ case READ_DATA:
+ size = (ffm->header[2] << 16) | (ffm->header[3] << 8) | ffm->header[4];
+ if (!ffm_is_avail_data(s, size)) {
+ return -EAGAIN;
+ }
+
+ av_new_packet(pkt, size);
+ pkt->stream_index = ffm->header[0];
+ if (ffm->header[1] & FLAG_KEY_FRAME)
+ pkt->flags |= PKT_FLAG_KEY;
+
+ ffm->read_state = READ_HEADER;
+ if (ffm_read_data(s, pkt->data, size, 0) != size) {
+ /* bad case: desynchronized packet. we cancel all the packet loading */
+ av_free_packet(pkt);
+ return -EAGAIN;
+ }
+ break;
+ }
+ return 0;
+}
+
+//#define DEBUG_SEEK
+
+/* pos is between 0 and file_size - FFM_PACKET_SIZE. It is translated
+ by the write position inside this function */
+static void ffm_seek1(AVFormatContext *s, offset_t pos1)
+{
+ FFMContext *ffm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ offset_t pos;
+
+ pos = pos1 + ffm->write_index;
+ if (pos >= ffm->file_size)
+ pos -= (ffm->file_size - FFM_PACKET_SIZE);
+#ifdef DEBUG_SEEK
+ printf("seek to %Lx -> %Lx\n", pos1, pos);
+#endif
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+static INT64 get_pts(AVFormatContext *s, offset_t pos)
+{
+ ByteIOContext *pb = &s->pb;
+ INT64 pts;
+
+ ffm_seek1(s, pos);
+ url_fskip(pb, 4);
+ pts = get_be64(pb);
+#ifdef DEBUG_SEEK
+ printf("pts=%0.6f\n", pts / 1000000.0);
+#endif
+ return pts;
+}
+
+/* seek to a given time in the file. The file read pointer is
+ positionned at or before pts. XXX: the following code is quite
+ approximative */
+static int ffm_seek(AVFormatContext *s, INT64 wanted_pts)
+{
+ FFMContext *ffm = s->priv_data;
+ offset_t pos_min, pos_max, pos;
+ INT64 pts_min, pts_max, pts;
+ double pos1;
+
+#ifdef DEBUG_SEEK
+ printf("wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
+#endif
+ /* find the position using linear interpolation (better than
+ dichotomy in typical cases) */
+ pos_min = 0;
+ pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
+ while (pos_min <= pos_max) {
+ pts_min = get_pts(s, pos_min);
+ pts_max = get_pts(s, pos_max);
+ /* linear interpolation */
+ pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
+ (double)(pts_max - pts_min);
+ pos = (((INT64)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
+ if (pos <= pos_min)
+ pos = pos_min;
+ else if (pos >= pos_max)
+ pos = pos_max;
+ pts = get_pts(s, pos);
+ /* check if we are lucky */
+ if (pts == wanted_pts) {
+ goto found;
+ } else if (pts > wanted_pts) {
+ pos_max = pos - FFM_PACKET_SIZE;
+ } else {
+ pos_min = pos + FFM_PACKET_SIZE;
+ }
+ }
+ pos = pos_min;
+ if (pos > 0)
+ pos -= FFM_PACKET_SIZE;
+ found:
+ ffm_seek1(s, pos);
+ return 0;
+}
+
+offset_t ffm_read_write_index(int fd)
+{
+ UINT8 buf[8];
+ offset_t pos;
+ int i;
+
+ lseek(fd, 8, SEEK_SET);
+ read(fd, buf, 8);
+ pos = 0;
+ for(i=0;i<8;i++)
+ pos |= buf[i] << (56 - i * 8);
+ return pos;
+}
+
+void ffm_write_write_index(int fd, offset_t pos)
+{
+ UINT8 buf[8];
+ int i;
+
+ for(i=0;i<8;i++)
+ buf[i] = (pos >> (56 - i * 8)) & 0xff;
+ lseek(fd, 8, SEEK_SET);
+ write(fd, buf, 8);
+}
+
+void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size)
+{
+ FFMContext *ffm = s->priv_data;
+ ffm->write_index = pos;
+ ffm->file_size = file_size;
+}
+
+static int ffm_read_close(AVFormatContext *s)
+{
+ AVStream *st;
+ int i;
+
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ free(st->priv_data);
+ }
+ free(s->priv_data);
+ return 0;
+}
+
+AVFormat ffm_format = {
+ "ffm",
+ "ffm format",
+ "",
+ "ffm",
+ /* not really used */
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG1VIDEO,
+ ffm_write_header,
+ ffm_write_packet,
+ ffm_write_trailer,
+ ffm_read_header,
+ ffm_read_packet,
+ ffm_read_close,
+ ffm_seek,
+};
diff --git a/libav/file.c b/libav/file.c
new file mode 100644
index 0000000000..0b255341c8
--- /dev/null
+++ b/libav/file.c
@@ -0,0 +1,121 @@
+/*
+ * Buffered file io for ffmpeg system
+ * Copyright (c) 2001 Gerard Lantau
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include "avformat.h"
+
+/* standard file protocol */
+
+static int file_open(URLContext *h, const char *filename, int flags)
+{
+ int access;
+ int fd;
+
+ if (flags & URL_WRONLY) {
+ access = O_CREAT | O_TRUNC | O_WRONLY;
+ } else {
+ access = O_RDONLY;
+ }
+ fd = open(filename, access, 0666);
+ if (fd < 0)
+ return -ENOENT;
+ h->priv_data = (void *)fd;
+ return 0;
+}
+
+static int file_read(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (int)h->priv_data;
+ return read(fd, buf, size);
+}
+
+static int file_write(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (int)h->priv_data;
+ return write(fd, buf, size);
+}
+
+/* XXX: use llseek */
+static offset_t file_seek(URLContext *h, offset_t pos, int whence)
+{
+ int fd = (int)h->priv_data;
+ return lseek(fd, pos, whence);
+}
+
+static int file_close(URLContext *h)
+{
+ int fd = (int)h->priv_data;
+ return close(fd);
+}
+
+URLProtocol file_protocol = {
+ "file",
+ file_open,
+ file_read,
+ file_write,
+ file_seek,
+ file_close,
+};
+
+/* pipe protocol */
+
+static int pipe_open(URLContext *h, const char *filename, int flags)
+{
+ int fd;
+
+ if (flags & URL_WRONLY) {
+ fd = 1;
+ } else {
+ fd = 0;
+ }
+ h->priv_data = (void *)fd;
+ return 0;
+}
+
+static int pipe_read(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (int)h->priv_data;
+ return read(fd, buf, size);
+}
+
+static int pipe_write(URLContext *h, unsigned char *buf, int size)
+{
+ int fd = (int)h->priv_data;
+ return write(fd, buf, size);
+}
+
+static int pipe_close(URLContext *h)
+{
+ return 0;
+}
+
+URLProtocol pipe_protocol = {
+ "pipe",
+ pipe_open,
+ pipe_read,
+ pipe_write,
+ NULL,
+ pipe_close,
+};
diff --git a/libav/grab.c b/libav/grab.c
new file mode 100644
index 0000000000..f92cc397e6
--- /dev/null
+++ b/libav/grab.c
@@ -0,0 +1,321 @@
+/*
+ * Linux video grab interface
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/videodev.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include "avformat.h"
+
+typedef struct {
+ int fd;
+ int frame_format; /* see VIDEO_PALETTE_xxx */
+ int use_mmap;
+ int width, height;
+ float rate;
+ INT64 time_frame;
+} VideoData;
+
+const char *v4l_device = "/dev/video";
+
+/* XXX: move all that to the context */
+
+static struct video_capability video_cap;
+static UINT8 *video_buf;
+static struct video_mbuf gb_buffers;
+static struct video_mmap gb_buf;
+static struct video_audio audio;
+static int gb_frame = 0;
+
+static int v4l_init(URLContext *h)
+{
+ VideoData *s = h->priv_data;
+ int width, height;
+ int ret;
+ int video_fd, frame_size;
+
+ width = s->width;
+ height = s->height;
+
+ video_fd = open(v4l_device, O_RDWR);
+ if (video_fd < 0) {
+ perror(v4l_device);
+ return -EIO;
+ }
+
+ if (ioctl(video_fd,VIDIOCGCAP,&video_cap) < 0) {
+ perror("VIDIOCGCAP");
+ goto fail;
+ }
+
+ if (!(video_cap.type & VID_TYPE_CAPTURE)) {
+ fprintf(stderr, "Fatal: grab device does not handle capture\n");
+ goto fail;
+ }
+
+ /* unmute audio */
+ ioctl(video_fd, VIDIOCGAUDIO, &audio);
+ audio.flags &= ~VIDEO_AUDIO_MUTE;
+ ioctl(video_fd, VIDIOCSAUDIO, &audio);
+
+ ret = ioctl(video_fd,VIDIOCGMBUF,&gb_buffers);
+ if (ret < 0) {
+ /* try to use read based access */
+ struct video_window win;
+ struct video_picture pict;
+ int val;
+
+ win.x = 0;
+ win.y = 0;
+ win.width = width;
+ win.height = height;
+ win.chromakey = -1;
+ win.flags = 0;
+
+ ioctl(video_fd, VIDIOCSWIN, &win);
+
+ ioctl(video_fd, VIDIOCGPICT, &pict);
+#if 0
+ printf("v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n",
+ pict.colour,
+ pict.hue,
+ pict.brightness,
+ pict.contrast,
+ pict.whiteness);
+#endif
+ /* try to choose a suitable video format */
+ pict.palette=VIDEO_PALETTE_YUV420P;
+ ret = ioctl(video_fd, VIDIOCSPICT, &pict);
+ if (ret < 0) {
+ pict.palette=VIDEO_PALETTE_YUV422;
+ ret = ioctl(video_fd, VIDIOCSPICT, &pict);
+ if (ret < 0) {
+ pict.palette=VIDEO_PALETTE_RGB24;
+ ret = ioctl(video_fd, VIDIOCSPICT, &pict);
+ if (ret < 0)
+ goto fail1;
+ }
+ }
+
+ s->frame_format = pict.palette;
+
+ val = 1;
+ ioctl(video_fd, VIDIOCCAPTURE, &val);
+
+ s->time_frame = gettime();
+ s->use_mmap = 0;
+ } else {
+ video_buf = mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0);
+ if ((unsigned char*)-1 == video_buf) {
+ perror("mmap");
+ goto fail;
+ }
+ gb_frame = 0;
+ s->time_frame = gettime();
+
+ /* start to grab the first frame */
+ gb_buf.frame = 1 - gb_frame;
+ gb_buf.height = height;
+ gb_buf.width = width;
+ gb_buf.format = VIDEO_PALETTE_YUV420P;
+
+ ret = ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf);
+ if (ret < 0 && errno != EAGAIN) {
+ /* try YUV422 */
+ gb_buf.format = VIDEO_PALETTE_YUV422;
+
+ ret = ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf);
+ if (ret < 0 && errno != EAGAIN) {
+ /* try RGB24 */
+ gb_buf.format = VIDEO_PALETTE_RGB24;
+ ret = ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf);
+ }
+ }
+ if (ret < 0) {
+ if (errno != EAGAIN) {
+ fail1:
+ fprintf(stderr, "Fatal: grab device does not support suitable format\n");
+ } else {
+ fprintf(stderr,"Fatal: grab device does not receive any video signal\n");
+ }
+ goto fail;
+ }
+ s->frame_format = gb_buf.format;
+ s->use_mmap = 1;
+ }
+
+ switch(s->frame_format) {
+ case VIDEO_PALETTE_YUV420P:
+ frame_size = (width * height * 3) / 2;
+ break;
+ case VIDEO_PALETTE_YUV422:
+ frame_size = width * height * 2;
+ break;
+ case VIDEO_PALETTE_RGB24:
+ frame_size = width * height * 3;
+ break;
+ default:
+ goto fail;
+ }
+ s->fd = video_fd;
+ h->packet_size = frame_size;
+ return 0;
+ fail:
+ close(video_fd);
+ return -EIO;
+}
+
+static int v4l_mm_read_picture(URLContext *h, UINT8 *buf)
+{
+ VideoData *s = h->priv_data;
+ UINT8 *ptr;
+
+ gb_buf.frame = gb_frame;
+ if (ioctl(s->fd, VIDIOCMCAPTURE, &gb_buf) < 0) {
+ if (errno == EAGAIN)
+ fprintf(stderr,"Cannot Sync\n");
+ else
+ perror("VIDIOCMCAPTURE");
+ return -EIO;
+ }
+ gb_frame = 1 - gb_frame;
+
+ while (ioctl(s->fd, VIDIOCSYNC, &gb_frame) < 0 &&
+ (errno == EAGAIN || errno == EINTR));
+
+ ptr = video_buf + gb_buffers.offsets[gb_frame];
+ memcpy(buf, ptr, h->packet_size);
+ return h->packet_size;
+}
+
+/* note: we support only one picture read at a time */
+static int video_read(URLContext *h, UINT8 *buf, int size)
+{
+ VideoData *s = h->priv_data;
+ INT64 curtime;
+
+ if (size != h->packet_size)
+ return -EINVAL;
+
+ /* wait based on the frame rate */
+ s->time_frame += (int)(1000000 / s->rate);
+ do {
+ curtime = gettime();
+ } while (curtime < s->time_frame);
+
+ /* read one frame */
+ if (s->use_mmap) {
+ return v4l_mm_read_picture(h, buf);
+ } else {
+ if (read(s->fd, buf, size) != size)
+ return -EIO;
+ return h->packet_size;
+ }
+}
+
+static int video_get_format(URLContext *h, URLFormat *f)
+{
+ VideoData *s = h->priv_data;
+
+ f->width = s->width;
+ f->height = s->height;
+ f->frame_rate = (int)(s->rate * FRAME_RATE_BASE);
+ strcpy(f->format_name, "rawvideo");
+
+ switch(s->frame_format) {
+ case VIDEO_PALETTE_YUV420P:
+ f->pix_fmt = PIX_FMT_YUV420P;
+ break;
+ case VIDEO_PALETTE_YUV422:
+ f->pix_fmt = PIX_FMT_YUV422;
+ break;
+ case VIDEO_PALETTE_RGB24:
+ f->pix_fmt = PIX_FMT_BGR24; /* NOTE: v4l uses BGR24, not RGB24 ! */
+ break;
+ default:
+ abort();
+ }
+ return 0;
+}
+
+/* URI syntax: 'video:width,height,rate'
+ */
+static int video_open(URLContext *h, const char *uri, int flags)
+{
+ VideoData *s;
+ const char *p;
+ int width, height;
+ int ret;
+ float rate;
+
+ /* extract parameters */
+ p = uri;
+ strstart(p, "video:", &p);
+ width = strtol(p, (char **)&p, 0);
+ if (width <= 0)
+ return -EINVAL;
+ if (*p == ',')
+ p++;
+ height = strtol(p, (char **)&p, 0);
+ if (height <= 0)
+ return -EINVAL;
+ if (*p == ',')
+ p++;
+ rate = strtod(p, (char **)&p);
+ if (rate <= 0)
+ return -EINVAL;
+
+ s = malloc(sizeof(VideoData));
+ if (!s)
+ return -ENOMEM;
+ h->priv_data = s;
+ h->is_streamed = 1;
+ s->width = width;
+ s->height = height;
+ s->rate = rate;
+ ret = v4l_init(h);
+ if (ret)
+ free(s);
+ return ret;
+}
+
+static int video_close(URLContext *h)
+{
+ VideoData *s = h->priv_data;
+
+ close(s->fd);
+ free(s);
+ return 0;
+}
+
+URLProtocol video_protocol = {
+ "video",
+ video_open,
+ video_read,
+ NULL,
+ NULL, /* seek */
+ video_close,
+ video_get_format,
+};
diff --git a/libav/http.c b/libav/http.c
new file mode 100644
index 0000000000..824f98b9e3
--- /dev/null
+++ b/libav/http.c
@@ -0,0 +1,318 @@
+/*
+ * HTTP protocol for ffmpeg client
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "avformat.h"
+
+/* XXX: POST protocol is not completly implemented because ffmpeg use
+ only a subset of it */
+
+//#define DEBUG
+
+/* used for protocol handling */
+#define BUFFER_SIZE 1024
+#define URL_SIZE 4096
+
+typedef struct {
+ int fd;
+ unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end;
+ int line_count;
+ int http_code;
+ char location[URL_SIZE];
+} HTTPContext;
+
+static int http_connect(URLContext *h, const char *path);
+static int http_write(URLContext *h, UINT8 *buf, int size);
+
+/* return non zero if error */
+static int http_open(URLContext *h, const char *uri, int flags)
+{
+ struct sockaddr_in dest_addr;
+ const char *p, *path, *proxy_path;
+ char hostname[1024], *q;
+ int port, fd = -1, use_proxy;
+ struct hostent *hp;
+ HTTPContext *s;
+
+ h->is_streamed = 1;
+
+ s = malloc(sizeof(HTTPContext));
+ if (!s) {
+ return -ENOMEM;
+ }
+ h->priv_data = s;
+
+ proxy_path = getenv("http_proxy");
+ use_proxy = (proxy_path != NULL) && !getenv("no_proxy");
+
+ /* fill the dest addr */
+ redo:
+ if (use_proxy) {
+ p = proxy_path;
+ } else {
+ p = uri;
+ }
+ if (!strstart(p, "http://", &p))
+ goto fail;
+ q = hostname;
+ while (*p != ':' && *p != '/' && *p != '\0') {
+ if ((q - hostname) < sizeof(hostname) - 1)
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ port = 80;
+ if (*p == ':') {
+ p++;
+ port = strtoul(p, (char **)&p, 10);
+ }
+ if (port <= 0)
+ goto fail;
+ if (use_proxy) {
+ path = uri;
+ } else {
+ if (*p == '\0')
+ path = "/";
+ else
+ path = p;
+ }
+
+ dest_addr.sin_family = AF_INET;
+ dest_addr.sin_port = htons(port);
+ if ((inet_aton(hostname, &dest_addr.sin_addr)) == 0) {
+ hp = gethostbyname(hostname);
+ if (!hp)
+ goto fail;
+ memcpy (&dest_addr.sin_addr, hp->h_addr, sizeof(dest_addr.sin_addr));
+ }
+
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0)
+ goto fail;
+
+ if (connect(fd, (struct sockaddr *)&dest_addr,
+ sizeof(dest_addr)) < 0)
+ goto fail;
+
+ s->fd = fd;
+ if (http_connect(h, path) < 0)
+ goto fail;
+ if (s->http_code == 303 && s->location[0] != '\0') {
+ /* url moved, get next */
+ uri = s->location;
+ goto redo;
+ }
+
+ return 0;
+ fail:
+ if (fd >= 0)
+ close(fd);
+ free(s);
+ return -EIO;
+}
+
+static int http_getc(HTTPContext *s)
+{
+ int len;
+ if (s->buf_ptr >= s->buf_end) {
+ redo:
+ len = read(s->fd, s->buffer, BUFFER_SIZE);
+ if (len < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto redo;
+ return -EIO;
+ } else if (len == 0) {
+ return -1;
+ } else {
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer + len;
+ }
+ }
+ return *s->buf_ptr++;
+}
+
+static int process_line(HTTPContext *s, char *line, int line_count)
+{
+ char *tag, *p;
+
+ /* end of header */
+ if (line[0] == '\0')
+ return 0;
+
+ p = line;
+ if (line_count == 0) {
+ while (!isspace(*p) && *p != '\0')
+ p++;
+ while (isspace(*p))
+ p++;
+ s->http_code = strtol(p, NULL, 10);
+#ifdef DEBUG
+ printf("http_code=%d\n", s->http_code);
+#endif
+ } else {
+ while (*p != '\0' && *p != ':')
+ p++;
+ if (*p != ':')
+ return 1;
+
+ *p = '\0';
+ tag = line;
+ p++;
+ while (isspace(*p))
+ p++;
+ if (!strcmp(tag, "Location")) {
+ strcpy(s->location, p);
+ }
+ }
+ return 1;
+}
+
+static int http_connect(URLContext *h, const char *path)
+{
+ HTTPContext *s = h->priv_data;
+ int post, err, ch;
+ char line[1024], *q;
+
+
+ /* send http header */
+ post = h->flags & URL_WRONLY;
+
+ snprintf(s->buffer, sizeof(s->buffer),
+ "%s %s HTTP/1.0\n"
+ "User-Agent: FFmpeg %s\n"
+ "Accept: */*\n"
+ "\n",
+ post ? "POST" : "GET",
+ path,
+ FFMPEG_VERSION
+ );
+
+ if (http_write(h, s->buffer, strlen(s->buffer)) < 0)
+ return -EIO;
+
+ /* init input buffer */
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer;
+ s->line_count = 0;
+ s->location[0] = '\0';
+ if (post)
+ return 0;
+
+ /* wait for header */
+ q = line;
+ for(;;) {
+ ch = http_getc(s);
+ if (ch < 0)
+ return -EIO;
+ if (ch == '\n') {
+ /* process line */
+ if (q > line && q[-1] == '\r')
+ q--;
+ *q = '\0';
+#ifdef DEBUG
+ printf("header='%s'\n", line);
+#endif
+ err = process_line(s, line, s->line_count);
+ if (err < 0)
+ return err;
+ if (err == 0)
+ return 0;
+ s->line_count++;
+ q = line;
+ } else {
+ if ((q - line) < sizeof(line) - 1)
+ *q++ = ch;
+ }
+ }
+}
+
+
+static int http_read(URLContext *h, UINT8 *buf, int size)
+{
+ HTTPContext *s = h->priv_data;
+ int size1, len;
+
+ size1 = size;
+ while (size > 0) {
+ /* read bytes from input buffer first */
+ len = s->buf_end - s->buf_ptr;
+ if (len > 0) {
+ if (len > size)
+ len = size;
+ memcpy(buf, s->buf_ptr, len);
+ s->buf_ptr += len;
+ } else {
+ len = read (s->fd, buf, size);
+ if (len < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ return -errno;
+ else
+ continue;
+ } else if (len == 0) {
+ break;
+ }
+ }
+ size -= len;
+ buf += len;
+ }
+ return size1 - size;
+}
+
+/* used only when posting data */
+static int http_write(URLContext *h, UINT8 *buf, int size)
+{
+ HTTPContext *s = h->priv_data;
+ int ret, size1;
+
+ size1 = size;
+ while (size > 0) {
+ ret = write (s->fd, buf, size);
+ if (ret < 0 && errno != EINTR && errno != EAGAIN)
+ return -errno;
+ size -= ret;
+ buf += ret;
+ }
+ return size1 - size;
+}
+
+static int http_close(URLContext *h)
+{
+ HTTPContext *s = h->priv_data;
+ close(s->fd);
+ return 0;
+}
+
+URLProtocol http_protocol = {
+ "http",
+ http_open,
+ http_read,
+ http_write,
+ NULL, /* seek */
+ http_close,
+};
diff --git a/libav/img.c b/libav/img.c
new file mode 100644
index 0000000000..db2d933ac0
--- /dev/null
+++ b/libav/img.c
@@ -0,0 +1,578 @@
+/*
+ * Image format
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+
+#include "avformat.h"
+
+#define IMGFMT_YUV 1
+#define IMGFMT_PGMYUV 2
+#define IMGFMT_PGM 3
+
+typedef struct {
+ int width;
+ int height;
+ int img_number;
+ int img_size;
+ int img_fmt;
+ int is_pipe;
+ char path[1024];
+} VideoData;
+
+static inline int pnm_space(int c)
+{
+ return (c==' ' || c=='\n' || c=='\r' || c=='\t');
+}
+
+static void pnm_get(ByteIOContext *f, char *str, int buf_size)
+{
+ char *s;
+ int c;
+
+ do {
+ c=get_byte(f);
+ if (c=='#') {
+ do {
+ c=get_byte(f);
+ } while (c!='\n');
+ c=get_byte(f);
+ }
+ } while (pnm_space(c));
+
+ s=str;
+ do {
+ if (url_feof(f))
+ break;
+ if ((s - str) < buf_size - 1)
+ *s++=c;
+ c=get_byte(f);
+ } while (!pnm_space(c));
+ *s = '\0';
+}
+
+static int pgm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size, int is_yuv)
+{
+ int width, height, i;
+ char buf1[32];
+ UINT8 *picture[3];
+
+ width = s->width;
+ height = s->height;
+
+ pnm_get(f, buf1, sizeof(buf1));
+ if (strcmp(buf1, "P5")) {
+ return -EIO;
+ }
+ pnm_get(f, buf1, sizeof(buf1));
+ pnm_get(f, buf1, sizeof(buf1));
+ pnm_get(f, buf1, sizeof(buf1));
+
+ picture[0] = buf;
+ picture[1] = buf + width * height;
+ picture[2] = buf + width * height + (width * height / 4);
+ get_buffer(f, picture[0], width * height);
+
+ height>>=1;
+ width>>=1;
+ if (is_yuv) {
+ for(i=0;i<height;i++) {
+ get_buffer(f, picture[1] + i * width, width);
+ get_buffer(f, picture[2] + i * width, width);
+ }
+ } else {
+ for(i=0;i<height;i++) {
+ memset(picture[1] + i * width, 128, width);
+ memset(picture[2] + i * width, 128, width);
+ }
+ }
+ return 0;
+}
+
+static int yuv_read(VideoData *s, const char *filename, UINT8 *buf, int size1)
+{
+ ByteIOContext pb1, *pb = &pb1;
+ char fname[1024], *p;
+ int size;
+
+ size = s->width * s->height;
+
+ strcpy(fname, filename);
+ p = strrchr(fname, '.');
+ if (!p || p[1] != 'Y')
+ return -EIO;
+
+ if (url_fopen(pb, fname, URL_RDONLY) < 0)
+ return -EIO;
+
+ get_buffer(pb, buf, size);
+ url_fclose(pb);
+
+ p[1] = 'U';
+ if (url_fopen(pb, fname, URL_RDONLY) < 0)
+ return -EIO;
+
+ get_buffer(pb, buf + size, size / 4);
+ url_fclose(pb);
+
+ p[1] = 'V';
+ if (url_fopen(pb, fname, URL_RDONLY) < 0)
+ return -EIO;
+
+ get_buffer(pb, buf + size + (size / 4), size / 4);
+ url_fclose(pb);
+ return 0;
+}
+
+int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+ VideoData *s = s1->priv_data;
+ char filename[1024];
+ int ret;
+ ByteIOContext f1, *f;
+
+ snprintf(filename, sizeof(filename), s->path, s->img_number);
+
+ if (!s->is_pipe) {
+ f = &f1;
+ if (url_fopen(f, filename, URL_RDONLY) < 0)
+ return -EIO;
+ } else {
+ f = &s1->pb;
+ if (url_feof(f))
+ return -EIO;
+ }
+
+ av_new_packet(pkt, s->img_size);
+ pkt->stream_index = 0;
+
+ switch(s->img_fmt) {
+ case IMGFMT_PGMYUV:
+ ret = pgm_read(s, f, pkt->data, pkt->size, 1);
+ break;
+ case IMGFMT_PGM:
+ ret = pgm_read(s, f, pkt->data, pkt->size, 0);
+ break;
+ case IMGFMT_YUV:
+ ret = yuv_read(s, filename, pkt->data, pkt->size);
+ break;
+ default:
+ return -EIO;
+ }
+
+ if (!s->is_pipe) {
+ url_fclose(f);
+ }
+
+ if (ret < 0) {
+ av_free_packet(pkt);
+ return -EIO; /* signal EOF */
+ } else {
+ s->img_number++;
+ return 0;
+ }
+}
+
+static int sizes[][2] = {
+ { 640, 480 },
+ { 720, 480 },
+ { 720, 576 },
+ { 352, 288 },
+ { 352, 240 },
+ { 160, 128 },
+ { 512, 384 },
+ { 640, 352 },
+};
+
+static int infer_size(int *width_ptr, int *height_ptr, int size)
+{
+ int i;
+
+ for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
+ if ((sizes[i][0] * sizes[i][1]) == size) {
+ *width_ptr = sizes[i][0];
+ *height_ptr = sizes[i][1];
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
+{
+ VideoData *s;
+ int i, h;
+ char buf[1024];
+ char buf1[32];
+ ByteIOContext pb1, *f = &pb1;
+ AVStream *st;
+
+ s = malloc(sizeof(VideoData));
+ if (!s)
+ return -ENOMEM;
+
+ s1->priv_data = s;
+
+ s1->nb_streams = 1;
+ st = av_mallocz(sizeof(AVStream));
+ if (!st) {
+ free(s);
+ return -ENOMEM;
+ }
+ s1->streams[0] = st;
+
+ strcpy(s->path, s1->filename);
+ s->img_number = 0;
+
+ /* find format */
+ if (s1->format->flags & AVFMT_NOFILE)
+ s->is_pipe = 0;
+ else
+ s->is_pipe = 1;
+
+ if (s1->format == &pgmpipe_format ||
+ s1->format == &pgmyuv_format)
+ s->img_fmt = IMGFMT_PGMYUV;
+ else if (s1->format == &pgm_format)
+ s->img_fmt = IMGFMT_PGM;
+ else if (s1->format == &imgyuv_format)
+ s->img_fmt = IMGFMT_YUV;
+ else
+ goto fail;
+
+ if (!s->is_pipe) {
+ /* try to find the first image */
+ for(i=0;i<5;i++) {
+ snprintf(buf, sizeof(buf), s->path, s->img_number);
+ if (url_fopen(f, buf, URL_RDONLY) >= 0)
+ break;
+ s->img_number++;
+ }
+ if (i == 5)
+ goto fail;
+ } else {
+ f = &s1->pb;
+ }
+
+ /* find the image size */
+ /* XXX: use generic file format guessing, as mpeg */
+ switch(s->img_fmt) {
+ case IMGFMT_PGM:
+ case IMGFMT_PGMYUV:
+ pnm_get(f, buf1, sizeof(buf1));
+ pnm_get(f, buf1, sizeof(buf1));
+ s->width = atoi(buf1);
+ pnm_get(f, buf1, sizeof(buf1));
+ h = atoi(buf1);
+ if (s->img_fmt == IMGFMT_PGMYUV)
+ h = (h * 2) / 3;
+ s->height = h;
+ if (s->width <= 0 ||
+ s->height <= 0 ||
+ (s->width % 2) != 0 ||
+ (s->height % 2) != 0) {
+ goto fail1;
+ }
+ break;
+ case IMGFMT_YUV:
+ /* infer size by using the file size. */
+ {
+ int img_size;
+ URLContext *h;
+
+ /* XXX: hack hack */
+ h = url_fileno(f);
+ img_size = lseek((int)h->priv_data, 0, SEEK_END);
+ if (infer_size(&s->width, &s->height, img_size) < 0) {
+ goto fail1;
+ }
+ }
+ break;
+ }
+
+ if (!s->is_pipe) {
+ url_fclose(f);
+ } else {
+ url_fseek(f, 0, SEEK_SET);
+ }
+
+ s->img_size = (s->width * s->height * 3) / 2;
+
+ st->codec.codec_type = CODEC_TYPE_VIDEO;
+ st->codec.codec_id = CODEC_ID_RAWVIDEO;
+ st->codec.width = s->width;
+ st->codec.height = s->height;
+ st->codec.pix_fmt = PIX_FMT_YUV420P;
+ if (!ap || !ap->frame_rate)
+ st->codec.frame_rate = 25 * FRAME_RATE_BASE;
+ else
+ st->codec.frame_rate = ap->frame_rate;
+
+ return 0;
+ fail1:
+ if (!s->is_pipe)
+ url_fclose(f);
+ fail:
+ free(s);
+ return -EIO;
+}
+
+static int img_read_close(AVFormatContext *s1)
+{
+ VideoData *s = s1->priv_data;
+ free(s);
+ return 0;
+}
+
+/******************************************************/
+/* image output */
+
+int pgm_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int is_yuv)
+{
+ int i, h;
+ char buf[100];
+ UINT8 *ptr, *ptr1, *ptr2;
+
+ h = height;
+ if (is_yuv)
+ h = (height * 3) / 2;
+ snprintf(buf, sizeof(buf),
+ "P5\n%d %d\n%d\n",
+ width, h, 255);
+ put_buffer(pb, buf, strlen(buf));
+
+ ptr = picture->data[0];
+ for(i=0;i<height;i++) {
+ put_buffer(pb, ptr, width);
+ ptr += picture->linesize[0];
+ }
+
+ if (is_yuv) {
+ height >>= 1;
+ width >>= 1;
+ ptr1 = picture->data[1];
+ ptr2 = picture->data[2];
+ for(i=0;i<height;i++) {
+ put_buffer(pb, ptr1, width);
+ put_buffer(pb, ptr2, width);
+ ptr1 += picture->linesize[1];
+ ptr2 += picture->linesize[2];
+ }
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int yuv_save(AVPicture *picture, int width, int height, const char *filename)
+{
+ ByteIOContext pb1, *pb = &pb1;
+ char fname[1024], *p;
+ int i, j;
+ UINT8 *ptr;
+ static char *ext = "YUV";
+
+ strcpy(fname, filename);
+ p = strrchr(fname, '.');
+ if (!p || p[1] != 'Y')
+ return -EIO;
+
+ for(i=0;i<3;i++) {
+ if (i == 1) {
+ width >>= 1;
+ height >>= 1;
+ }
+
+ p[1] = ext[i];
+ if (url_fopen(pb, fname, URL_WRONLY) < 0)
+ return -EIO;
+
+ ptr = picture->data[i];
+ for(j=0;j<height;j++) {
+ put_buffer(pb, ptr, width);
+ ptr += picture->linesize[i];
+ }
+ put_flush_packet(pb);
+ url_fclose(pb);
+ }
+ return 0;
+}
+
+static int img_write_header(AVFormatContext *s)
+{
+ VideoData *img;
+
+ img = av_mallocz(sizeof(VideoData));
+ if (!img)
+ return -1;
+ s->priv_data = img;
+ img->img_number = 1;
+ strcpy(img->path, s->filename);
+
+ /* find format */
+ if (s->format->flags & AVFMT_NOFILE)
+ img->is_pipe = 0;
+ else
+ img->is_pipe = 1;
+
+ if (s->format == &pgmpipe_format ||
+ s->format == &pgmyuv_format)
+ img->img_fmt = IMGFMT_PGMYUV;
+ else if (s->format == &pgm_format)
+ img->img_fmt = IMGFMT_PGM;
+ else if (s->format == &imgyuv_format)
+ img->img_fmt = IMGFMT_YUV;
+ else
+ goto fail;
+ return 0;
+ fail:
+ free(img);
+ return -EIO;
+}
+
+static int img_write_packet(AVFormatContext *s, int stream_index,
+ UINT8 *buf, int size)
+{
+ VideoData *img = s->priv_data;
+ AVStream *st = s->streams[stream_index];
+ ByteIOContext pb1, *pb;
+ AVPicture picture;
+ int width, height, ret, size1;
+ char filename[1024];
+
+ width = st->codec.width;
+ height = st->codec.height;
+ size1 = (width * height * 3) / 2;
+ if (size != size1)
+ return -EIO;
+
+ picture.data[0] = buf;
+ picture.data[1] = picture.data[0] + width * height;
+ picture.data[2] = picture.data[1] + (width * height) / 4;
+ picture.linesize[0] = width;
+ picture.linesize[1] = width >> 1;
+ picture.linesize[2] = width >> 1;
+ snprintf(filename, sizeof(filename), img->path, img->img_number);
+
+ if (!img->is_pipe) {
+ pb = &pb1;
+ if (url_fopen(pb, filename, URL_WRONLY) < 0)
+ return -EIO;
+ } else {
+ pb = &s->pb;
+ }
+ switch(img->img_fmt) {
+ case IMGFMT_PGMYUV:
+ ret = pgm_save(&picture, width, height, pb, 1);
+ break;
+ case IMGFMT_PGM:
+ ret = pgm_save(&picture, width, height, pb, 0);
+ break;
+ case IMGFMT_YUV:
+ ret = yuv_save(&picture, width, height, filename);
+ break;
+ }
+ if (!img->is_pipe) {
+ url_fclose(pb);
+ }
+
+ img->img_number++;
+ return 0;
+}
+
+static int img_write_trailer(AVFormatContext *s)
+{
+ VideoData *img = s->priv_data;
+ free(img);
+ return 0;
+}
+
+AVFormat pgm_format = {
+ "pgm",
+ "pgm image format",
+ "",
+ "pgm",
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+ AVFMT_NOFILE,
+};
+
+AVFormat pgmyuv_format = {
+ "pgmyuv",
+ "pgm with YUV content image format",
+ "",
+ "pgm",
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+ AVFMT_NOFILE,
+};
+
+AVFormat imgyuv_format = {
+ ".Y.U.V",
+ ".Y.U.V format",
+ "",
+ "Y",
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+ AVFMT_NOFILE,
+};
+
+AVFormat pgmpipe_format = {
+ "pgmpipe",
+ "PGM pipe format",
+ "",
+ "pgm",
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ img_write_header,
+ img_write_packet,
+ img_write_trailer,
+
+ img_read_header,
+ img_read_packet,
+ img_read_close,
+ NULL,
+};
diff --git a/libav/jpegenc.c b/libav/jpegenc.c
new file mode 100644
index 0000000000..d02332cd79
--- /dev/null
+++ b/libav/jpegenc.c
@@ -0,0 +1,102 @@
+/*
+ * Miscellaneous MJPEG based formats
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <string.h>
+#include "avformat.h"
+
+/* Multipart JPEG */
+
+#define BOUNDARY_TAG "ffserver"
+
+static int mpjpeg_write_header(AVFormatContext *s)
+{
+ UINT8 buf1[256];
+
+ snprintf(buf1, sizeof(buf1), "--%s\n", BOUNDARY_TAG);
+ put_buffer(&s->pb, buf1, strlen(buf1));
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int mpjpeg_write_packet(AVFormatContext *s,
+ int stream_index, UINT8 *buf, int size)
+{
+ UINT8 buf1[256];
+
+ snprintf(buf1, sizeof(buf1), "Content-type: image/jpeg\n\n");
+ put_buffer(&s->pb, buf1, strlen(buf1));
+ put_buffer(&s->pb, buf, size);
+
+ snprintf(buf1, sizeof(buf1), "\n--%s\n", BOUNDARY_TAG);
+ put_buffer(&s->pb, buf1, strlen(buf1));
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int mpjpeg_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVFormat mpjpeg_format = {
+ "mpjpeg",
+ "Mime multipart JPEG format",
+ "multipart/x-mixed-replace;boundary=" BOUNDARY_TAG,
+ "mjpg",
+ CODEC_ID_NONE,
+ CODEC_ID_MJPEG,
+ mpjpeg_write_header,
+ mpjpeg_write_packet,
+ mpjpeg_write_trailer,
+};
+
+
+/* single frame JPEG */
+
+static int jpeg_write_header(AVFormatContext *s)
+{
+ return 0;
+}
+
+static int jpeg_write_packet(AVFormatContext *s, int stream_index,
+ UINT8 *buf, int size)
+{
+ put_buffer(&s->pb, buf, size);
+ put_flush_packet(&s->pb);
+ return 1; /* no more data can be sent */
+}
+
+static int jpeg_write_trailer(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVFormat jpeg_format = {
+ "jpeg",
+ "JPEG image",
+ "image/jpeg",
+ "jpg,jpeg",
+ CODEC_ID_NONE,
+ CODEC_ID_MJPEG,
+ jpeg_write_header,
+ jpeg_write_packet,
+ jpeg_write_trailer,
+};
diff --git a/libav/mpeg.c b/libav/mpeg.c
new file mode 100644
index 0000000000..86e3af6184
--- /dev/null
+++ b/libav/mpeg.c
@@ -0,0 +1,663 @@
+/*
+ * Output a MPEG1 multiplexed video/audio stream
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include "avformat.h"
+
+#define MAX_PAYLOAD_SIZE 4096
+#define NB_STREAMS 2
+
+typedef struct {
+ UINT8 buffer[MAX_PAYLOAD_SIZE];
+ int buffer_ptr;
+ UINT8 id;
+ int max_buffer_size; /* in bytes */
+ int packet_number;
+ float pts;
+ INT64 start_pts;
+} StreamInfo;
+
+typedef struct {
+ int packet_size; /* required packet size */
+ int packet_data_max_size; /* maximum data size inside a packet */
+ int packet_number;
+ int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */
+ int system_header_freq;
+ int mux_rate; /* bitrate in units of 50 bytes/s */
+ /* stream info */
+ int audio_bound;
+ int video_bound;
+} MpegMuxContext;
+
+#define PACK_START_CODE ((unsigned int)0x000001ba)
+#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)
+#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)
+#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)
+#define ISO_11172_END_CODE ((unsigned int)0x000001b9)
+
+/* mpeg2 */
+#define PROGRAM_STREAM_MAP 0x1bc
+#define PRIVATE_STREAM_1 0x1bd
+#define PADDING_STREAM 0x1be
+#define PRIVATE_STREAM_2 0x1bf
+
+
+#define AUDIO_ID 0xc0
+#define VIDEO_ID 0xe0
+
+static int put_pack_header(AVFormatContext *ctx,
+ UINT8 *buf, long long timestamp)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ PutBitContext pb;
+
+ init_put_bits(&pb, buf, 128, NULL, NULL);
+
+ put_bits(&pb, 32, PACK_START_CODE);
+ put_bits(&pb, 4, 0x2);
+ put_bits(&pb, 3, (timestamp >> 30) & 0x07);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 15, (timestamp >> 15) & 0x7fff);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 15, (timestamp) & 0x7fff);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 22, s->mux_rate);
+ put_bits(&pb, 1, 1);
+
+ flush_put_bits(&pb);
+ return pb.buf_ptr - pb.buf;
+}
+
+static int put_system_header(AVFormatContext *ctx, UINT8 *buf)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ int size, rate_bound, i, private_stream_coded, id;
+ PutBitContext pb;
+
+ init_put_bits(&pb, buf, 128, NULL, NULL);
+
+ put_bits(&pb, 32, SYSTEM_HEADER_START_CODE);
+ put_bits(&pb, 16, 0);
+ put_bits(&pb, 1, 1);
+
+ rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */
+ put_bits(&pb, 22, rate_bound);
+ put_bits(&pb, 1, 1); /* marker */
+ put_bits(&pb, 6, s->audio_bound);
+
+ put_bits(&pb, 1, 1); /* variable bitrate */
+ put_bits(&pb, 1, 1); /* non constrainted bit stream */
+
+ put_bits(&pb, 1, 0); /* audio locked */
+ put_bits(&pb, 1, 0); /* video locked */
+ put_bits(&pb, 1, 1); /* marker */
+
+ put_bits(&pb, 5, s->video_bound);
+ put_bits(&pb, 8, 0xff); /* reserved byte */
+
+ /* audio stream info */
+ private_stream_coded = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = ctx->streams[i]->priv_data;
+ id = stream->id;
+ if (id < 0xc0) {
+ /* special case for private streams (AC3 use that) */
+ if (private_stream_coded)
+ continue;
+ private_stream_coded = 1;
+ id = 0xbd;
+ }
+ put_bits(&pb, 8, id); /* stream ID */
+ put_bits(&pb, 2, 3);
+ if (id < 0xe0) {
+ /* audio */
+ put_bits(&pb, 1, 0);
+ put_bits(&pb, 13, stream->max_buffer_size / 128);
+ } else {
+ /* video */
+ put_bits(&pb, 1, 1);
+ put_bits(&pb, 13, stream->max_buffer_size / 1024);
+ }
+ }
+ flush_put_bits(&pb);
+ size = pb.buf_ptr - pb.buf;
+ /* patch packet size */
+ buf[4] = (size - 6) >> 8;
+ buf[5] = (size - 6) & 0xff;
+
+ return size;
+}
+
+static int mpeg_mux_init(AVFormatContext *ctx)
+{
+ MpegMuxContext *s;
+ int bitrate, i, mpa_id, mpv_id, ac3_id;
+ AVStream *st;
+ StreamInfo *stream;
+
+ s = malloc(sizeof(MpegMuxContext));
+ if (!s)
+ return -1;
+ memset(s, 0, sizeof(MpegMuxContext));
+ ctx->priv_data = s;
+ s->packet_number = 0;
+
+ /* XXX: hardcoded */
+ s->packet_size = 2048;
+ /* startcode(4) + length(2) + flags(1) */
+ s->packet_data_max_size = s->packet_size - 7;
+ s->audio_bound = 0;
+ s->video_bound = 0;
+ mpa_id = AUDIO_ID;
+ ac3_id = 0x80;
+ mpv_id = VIDEO_ID;
+ for(i=0;i<ctx->nb_streams;i++) {
+ st = ctx->streams[i];
+ stream = av_mallocz(sizeof(StreamInfo));
+ if (!stream)
+ goto fail;
+ st->priv_data = stream;
+
+ switch(st->codec.codec_type) {
+ case CODEC_TYPE_AUDIO:
+ if (st->codec.codec_id == CODEC_ID_AC3)
+ stream->id = ac3_id++;
+ else
+ stream->id = mpa_id++;
+ stream->max_buffer_size = 4 * 1024;
+ s->audio_bound++;
+ break;
+ case CODEC_TYPE_VIDEO:
+ stream->id = mpv_id++;
+ stream->max_buffer_size = 46 * 1024;
+ s->video_bound++;
+ break;
+ }
+ }
+
+ /* we increase slightly the bitrate to take into account the
+ headers. XXX: compute it exactly */
+ bitrate = 2000;
+ for(i=0;i<ctx->nb_streams;i++) {
+ st = ctx->streams[i];
+ bitrate += st->codec.bit_rate;
+ }
+ s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
+ /* every 2 seconds */
+ s->pack_header_freq = 2 * bitrate / s->packet_size / 8;
+ /* every 10 seconds */
+ s->system_header_freq = s->pack_header_freq * 5;
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+ stream->buffer_ptr = 0;
+ stream->packet_number = 0;
+ stream->pts = 0;
+ stream->start_pts = -1;
+ }
+ return 0;
+ fail:
+ for(i=0;i<ctx->nb_streams;i++) {
+ free(ctx->streams[i]->priv_data);
+ }
+ free(s);
+ return -ENOMEM;
+}
+
+/* flush the packet on stream stream_index */
+static void flush_packet(AVFormatContext *ctx, int stream_index)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ StreamInfo *stream = ctx->streams[stream_index]->priv_data;
+ UINT8 *buf_ptr;
+ int size, payload_size, startcode, id, len, stuffing_size, i;
+ INT64 timestamp;
+ UINT8 buffer[128];
+
+ id = stream->id;
+ timestamp = stream->start_pts;
+
+#if 0
+ printf("packet ID=%2x PTS=%0.3f\n",
+ id, timestamp / 90000.0);
+#endif
+
+ buf_ptr = buffer;
+ if ((s->packet_number % s->pack_header_freq) == 0) {
+ /* output pack and systems header if needed */
+ size = put_pack_header(ctx, buf_ptr, timestamp);
+ buf_ptr += size;
+ if ((s->packet_number % s->system_header_freq) == 0) {
+ size = put_system_header(ctx, buf_ptr);
+ buf_ptr += size;
+ }
+ }
+ size = buf_ptr - buffer;
+ put_buffer(&ctx->pb, buffer, size);
+
+ /* packet header */
+ payload_size = s->packet_size - (size + 6 + 5);
+ if (id < 0xc0) {
+ startcode = PRIVATE_STREAM_1;
+ payload_size -= 4;
+ } else {
+ startcode = 0x100 + id;
+ }
+ stuffing_size = payload_size - stream->buffer_ptr;
+ if (stuffing_size < 0)
+ stuffing_size = 0;
+
+ put_be32(&ctx->pb, startcode);
+
+ put_be16(&ctx->pb, payload_size + 5);
+ /* stuffing */
+ for(i=0;i<stuffing_size;i++)
+ put_byte(&ctx->pb, 0xff);
+
+ /* presentation time stamp */
+ put_byte(&ctx->pb,
+ (0x02 << 4) |
+ (((timestamp >> 30) & 0x07) << 1) |
+ 1);
+ put_be16(&ctx->pb, (((timestamp >> 15) & 0x7fff) << 1) | 1);
+ put_be16(&ctx->pb, (((timestamp) & 0x7fff) << 1) | 1);
+
+ if (startcode == PRIVATE_STREAM_1) {
+ put_byte(&ctx->pb, id);
+ if (id >= 0x80 && id <= 0xbf) {
+ /* XXX: need to check AC3 spec */
+ put_byte(&ctx->pb, 1);
+ put_byte(&ctx->pb, 0);
+ put_byte(&ctx->pb, 2);
+ }
+ }
+
+ /* output data */
+ put_buffer(&ctx->pb, stream->buffer, payload_size - stuffing_size);
+ put_flush_packet(&ctx->pb);
+
+ /* preserve remaining data */
+ len = stream->buffer_ptr - payload_size;
+ if (len < 0)
+ len = 0;
+ memmove(stream->buffer, stream->buffer + stream->buffer_ptr - len, len);
+ stream->buffer_ptr = len;
+
+ s->packet_number++;
+ stream->packet_number++;
+ stream->start_pts = -1;
+}
+
+static int mpeg_mux_write_packet(AVFormatContext *ctx,
+ int stream_index, UINT8 *buf, int size)
+{
+ MpegMuxContext *s = ctx->priv_data;
+ AVStream *st = ctx->streams[stream_index];
+ StreamInfo *stream = st->priv_data;
+ int len;
+
+ while (size > 0) {
+ /* set pts */
+ if (stream->start_pts == -1)
+ stream->start_pts = stream->pts * 90000.0;
+ len = s->packet_data_max_size - stream->buffer_ptr;
+ if (len > size)
+ len = size;
+ memcpy(stream->buffer + stream->buffer_ptr, buf, len);
+ stream->buffer_ptr += len;
+ buf += len;
+ size -= len;
+ while (stream->buffer_ptr >= s->packet_data_max_size) {
+ /* output the packet */
+ if (stream->start_pts == -1)
+ stream->start_pts = stream->pts * 90000.0;
+ flush_packet(ctx, stream_index);
+ }
+ }
+
+ if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
+ stream->pts += (float)st->codec.frame_size / st->codec.sample_rate;
+ } else {
+ stream->pts += FRAME_RATE_BASE / (float)st->codec.frame_rate;
+ }
+ return 0;
+}
+
+static int mpeg_mux_end(AVFormatContext *ctx)
+{
+ StreamInfo *stream;
+ int i;
+
+ /* flush each packet */
+ for(i=0;i<ctx->nb_streams;i++) {
+ stream = ctx->streams[i]->priv_data;
+ if (stream->buffer_ptr > 0)
+ flush_packet(ctx, i);
+ }
+
+ /* write the end header */
+ put_be32(&ctx->pb, ISO_11172_END_CODE);
+ put_flush_packet(&ctx->pb);
+ return 0;
+}
+
+/*********************************************/
+/* demux code */
+
+#define MAX_SYNC_SIZE 100000
+
+typedef struct MpegDemuxContext {
+ int header_state;
+ int mux_rate; /* 50 byte/s unit */
+} MpegDemuxContext;
+
+static int find_start_code(ByteIOContext *pb, int *size_ptr,
+ UINT32 *header_state)
+{
+ unsigned int state, v;
+ int val, n;
+
+ state = *header_state;
+ n = *size_ptr;
+ while (n > 0) {
+ if (url_feof(pb))
+ break;
+ v = get_byte(pb);
+ n--;
+ if (state == 0x000001) {
+ state = ((state << 8) | v) & 0xffffff;
+ val = state;
+ goto found;
+ }
+ state = ((state << 8) | v) & 0xffffff;
+ }
+ val = -1;
+ found:
+ *header_state = state;
+ *size_ptr = n;
+ return val;
+}
+
+static int mpeg_mux_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ MpegDemuxContext *m;
+ int size, startcode, c, rate_bound, audio_bound, video_bound, mux_rate, val;
+ int codec_id, n, i, type;
+ AVStream *st;
+
+ m = av_mallocz(sizeof(MpegDemuxContext));
+ if (!m)
+ return -ENOMEM;
+ s->priv_data = m;
+
+ /* search first pack header */
+ m->header_state = 0xff;
+ size = MAX_SYNC_SIZE;
+ for(;;) {
+ while (size > 0) {
+ startcode = find_start_code(&s->pb, &size, &m->header_state);
+ if (startcode == PACK_START_CODE)
+ goto found;
+ }
+ return -ENODATA;
+ found:
+ /* search system header just after pack header */
+ /* parse pack header */
+ get_byte(&s->pb); /* ts1 */
+ get_be16(&s->pb); /* ts2 */
+ get_be16(&s->pb); /* ts3 */
+
+ mux_rate = get_byte(&s->pb) << 16;
+ mux_rate |= get_byte(&s->pb) << 8;
+ mux_rate |= get_byte(&s->pb);
+ mux_rate &= (1 << 22) - 1;
+ m->mux_rate = mux_rate;
+
+ startcode = find_start_code(&s->pb, &size, &m->header_state);
+ if (startcode == SYSTEM_HEADER_START_CODE)
+ break;
+ }
+ size = get_be16(&s->pb);
+ rate_bound = get_byte(&s->pb) << 16;
+ rate_bound |= get_byte(&s->pb) << 8;
+ rate_bound |= get_byte(&s->pb);
+ rate_bound = (rate_bound >> 1) & ((1 << 22) - 1);
+ audio_bound = get_byte(&s->pb) >> 2;
+ video_bound = get_byte(&s->pb) & 0x1f;
+ get_byte(&s->pb); /* reserved byte */
+#if 0
+ printf("mux_rate=%d kbit/s\n", (m->mux_rate * 50 * 8) / 1000);
+ printf("rate_bound=%d\n", rate_bound);
+ printf("audio_bound=%d\n", audio_bound);
+ printf("video_bound=%d\n", video_bound);
+#endif
+ size -= 6;
+ s->nb_streams = 0;
+ while (size > 0) {
+ c = get_byte(&s->pb);
+ size--;
+ if ((c & 0x80) == 0)
+ break;
+ val = get_be16(&s->pb);
+ size -= 2;
+ if (c >= 0xc0 && c <= 0xdf) {
+ /* mpeg audio stream */
+ type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_MP2;
+ n = 1;
+ c = c | 0x100;
+ } else if (c >= 0xe0 && c <= 0xef) {
+ type = CODEC_TYPE_VIDEO;
+ codec_id = CODEC_ID_MPEG1VIDEO;
+ n = 1;
+ c = c | 0x100;
+ } else if (c == 0xb8) {
+ /* all audio streams */
+ /* XXX: hack for DVD: we force AC3, although we do not
+ know that this codec will be used */
+ type = CODEC_TYPE_AUDIO;
+ codec_id = CODEC_ID_AC3;
+ n = audio_bound;
+ c = 0x80;
+ /* c = 0x1c0; */
+ } else if (c == 0xb9) {
+ /* all video streams */
+ type = CODEC_TYPE_VIDEO;
+ codec_id = CODEC_ID_MPEG1VIDEO;
+ n = video_bound;
+ c = 0x1e0;
+ } else {
+ type = 0;
+ codec_id = 0;
+ n = 0;
+ }
+
+ for(i=0;i<n;i++) {
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ return -ENOMEM;
+ s->streams[s->nb_streams++] = st;
+ st->id = c + i;
+ st->codec.codec_type = type;
+ st->codec.codec_id = codec_id;
+ }
+ }
+
+ return 0;
+}
+
+static INT64 get_pts(ByteIOContext *pb, int c)
+{
+ INT64 pts;
+ int val;
+
+ if (c < 0)
+ c = get_byte(pb);
+ pts = (INT64)((c >> 1) & 0x07) << 30;
+ val = get_be16(pb);
+ pts |= (INT64)(val >> 1) << 15;
+ val = get_be16(pb);
+ pts |= (INT64)(val >> 1);
+ return pts;
+}
+
+static int mpeg_mux_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ MpegDemuxContext *m = s->priv_data;
+ AVStream *st;
+ int len, size, startcode, i, c, flags, header_len;
+ INT64 pts, dts;
+
+ /* next start code (should be immediately after */
+ redo:
+ m->header_state = 0xff;
+ size = MAX_SYNC_SIZE;
+ startcode = find_start_code(&s->pb, &size, &m->header_state);
+ // printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb));
+ if (startcode < 0)
+ return -EIO;
+ if (startcode == PACK_START_CODE)
+ goto redo;
+ if (startcode == SYSTEM_HEADER_START_CODE)
+ goto redo;
+ if (startcode == PADDING_STREAM ||
+ startcode == PRIVATE_STREAM_2) {
+ /* skip them */
+ len = get_be16(&s->pb);
+ url_fskip(&s->pb, len);
+ goto redo;
+ }
+ /* find matching stream */
+ if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||
+ (startcode >= 0x1e0 && startcode <= 0x1ef) ||
+ (startcode == 0x1bd)))
+ goto redo;
+
+ len = get_be16(&s->pb);
+ pts = 0;
+ dts = 0;
+ /* stuffing */
+ for(;;) {
+ c = get_byte(&s->pb);
+ len--;
+ /* XXX: for mpeg1, should test only bit 7 */
+ if (c != 0xff)
+ break;
+ }
+ if ((c & 0xc0) == 0x40) {
+ /* buffer scale & size */
+ get_byte(&s->pb);
+ c = get_byte(&s->pb);
+ len -= 2;
+ }
+ if ((c & 0xf0) == 0x20) {
+ pts = get_pts(&s->pb, c);
+ len -= 4;
+ dts = pts;
+ } else if ((c & 0xf0) == 0x30) {
+ pts = get_pts(&s->pb, c);
+ dts = get_pts(&s->pb, -1);
+ len -= 9;
+ } else if ((c & 0xc0) == 0x80) {
+ /* mpeg 2 PES */
+ if ((c & 0x30) != 0) {
+ fprintf(stderr, "Encrypted multiplex not handled\n");
+ return -EIO;
+ }
+ flags = get_byte(&s->pb);
+ header_len = get_byte(&s->pb);
+ len -= 2;
+ if (header_len > len)
+ goto redo;
+ if ((flags & 0xc0) == 0x40) {
+ pts = get_pts(&s->pb, -1);
+ dts = pts;
+ header_len -= 5;
+ len -= 5;
+ } if ((flags & 0xc0) == 0xc0) {
+ pts = get_pts(&s->pb, -1);
+ dts = get_pts(&s->pb, -1);
+ header_len -= 10;
+ len -= 10;
+ }
+ len -= header_len;
+ while (header_len > 0) {
+ get_byte(&s->pb);
+ header_len--;
+ }
+ }
+ if (startcode == 0x1bd) {
+ startcode = get_byte(&s->pb);
+ len--;
+ if (startcode >= 0x80 && startcode <= 0xbf) {
+ /* audio: skip header */
+ get_byte(&s->pb);
+ get_byte(&s->pb);
+ get_byte(&s->pb);
+ len -= 3;
+ }
+ }
+
+ /* now find stream */
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (st->id == startcode)
+ goto found;
+ }
+ /* skip packet */
+ url_fskip(&s->pb, len);
+ goto redo;
+ found:
+ av_new_packet(pkt, len);
+ get_buffer(&s->pb, pkt->data, pkt->size);
+ pkt->pts = pts;
+ pkt->stream_index = i;
+ return 0;
+}
+
+static int mpeg_mux_read_close(AVFormatContext *s)
+{
+ MpegDemuxContext *m = s->priv_data;
+ free(m);
+ return 0;
+}
+
+AVFormat mpeg_mux_format = {
+ "mpeg",
+ "MPEG multiplex format",
+ "video/x-mpeg",
+ "mpg,mpeg,vob",
+ CODEC_ID_MP2,
+ CODEC_ID_MPEG1VIDEO,
+ mpeg_mux_init,
+ mpeg_mux_write_packet,
+ mpeg_mux_end,
+
+ mpeg_mux_read_header,
+ mpeg_mux_read_packet,
+ mpeg_mux_read_close,
+};
diff --git a/libav/raw.c b/libav/raw.c
new file mode 100644
index 0000000000..47dfa3b0fe
--- /dev/null
+++ b/libav/raw.c
@@ -0,0 +1,288 @@
+/*
+ * RAW encoder and decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include "avformat.h"
+
+/* simple formats */
+int raw_write_header(struct AVFormatContext *s)
+{
+ return 0;
+}
+
+int raw_write_packet(struct AVFormatContext *s,
+ int stream_index,
+ unsigned char *buf, int size)
+{
+ put_buffer(&s->pb, buf, size);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+int raw_write_trailer(struct AVFormatContext *s)
+{
+ return 0;
+}
+
+/* raw input */
+static int raw_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = malloc(sizeof(AVStream));
+ if (!st)
+ return -1;
+ s->nb_streams = 1;
+ s->streams[0] = st;
+
+ st->id = 0;
+
+ if (ap) {
+ if (s->format->audio_codec != CODEC_ID_NONE) {
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ st->codec.codec_id = s->format->audio_codec;
+ } else if (s->format->video_codec != CODEC_ID_NONE) {
+ st->codec.codec_type = CODEC_TYPE_VIDEO;
+ st->codec.codec_id = s->format->video_codec;
+ } else {
+ free(st);
+ return -1;
+ }
+
+ switch(st->codec.codec_type) {
+ case CODEC_TYPE_AUDIO:
+ st->codec.sample_rate = ap->sample_rate;
+ st->codec.channels = ap->channels;
+ /* XXX: endianness */
+ break;
+ case CODEC_TYPE_VIDEO:
+ st->codec.frame_rate = ap->frame_rate;
+ st->codec.width = ap->width;
+ st->codec.height = ap->height;
+ break;
+ default:
+ abort();
+ break;
+ }
+ } else {
+ abort();
+ }
+ return 0;
+}
+
+#define MIN_SIZE 1024
+
+int raw_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ int packet_size, n, ret;
+
+ if (url_feof(&s->pb))
+ return -EIO;
+
+ packet_size = url_get_packet_size(&s->pb);
+ n = MIN_SIZE / packet_size;
+ if (n <= 0)
+ n = 1;
+ if (av_new_packet(pkt, n * packet_size) < 0)
+ return -EIO;
+
+ pkt->stream_index = 0;
+ ret = get_buffer(&s->pb, pkt->data, pkt->size);
+ if (ret < 0)
+ av_free_packet(pkt);
+ return ret;
+}
+
+int raw_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+/* mp3 read */
+static int mp3_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = malloc(sizeof(AVStream));
+ if (!st)
+ return -1;
+ s->nb_streams = 1;
+ s->streams[0] = st;
+
+ st->id = 0;
+
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ st->codec.codec_id = CODEC_ID_MP2;
+ /* XXX: read the first frame and extract rate and channels */
+ st->codec.sample_rate = 44100;
+ st->codec.channels = 2;
+ return 0;
+}
+
+/* mpeg1/h263 input */
+static int video_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ AVStream *st;
+
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ return -1;
+ s->nb_streams = 1;
+ s->streams[0] = st;
+
+ st->codec.codec_type = CODEC_TYPE_VIDEO;
+ st->codec.codec_id = s->format->video_codec;
+ return 0;
+}
+
+AVFormat mp2_format = {
+ "mp2",
+ "MPEG audio",
+ "audio/x-mpeg",
+ "mp2,mp3",
+ CODEC_ID_MP2,
+ 0,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+
+ mp3_read_header,
+ raw_read_packet,
+ raw_read_close,
+};
+
+AVFormat ac3_format = {
+ "ac3",
+ "raw ac3",
+ "audio/x-ac3",
+ "ac3",
+ CODEC_ID_AC3,
+ 0,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+};
+
+AVFormat h263_format = {
+ "h263",
+ "raw h263",
+ "video/x-h263",
+ "h263",
+ 0,
+ CODEC_ID_H263,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ video_read_header,
+ raw_read_packet,
+ raw_read_close,
+};
+
+AVFormat mpeg1video_format = {
+ "mpegvideo",
+ "MPEG video",
+ "video/x-mpeg",
+ "mpg,mpeg",
+ 0,
+ CODEC_ID_MPEG1VIDEO,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+ video_read_header,
+ raw_read_packet,
+ raw_read_close,
+};
+
+AVFormat pcm_format = {
+ "pcm",
+ "pcm raw format",
+ NULL,
+ "sw",
+ CODEC_ID_PCM,
+ 0,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+
+ raw_read_header,
+ raw_read_packet,
+ raw_read_close,
+};
+
+int rawvideo_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ int packet_size, ret, width, height;
+ AVStream *st = s->streams[0];
+
+ width = st->codec.width;
+ height = st->codec.height;
+
+ switch(st->codec.pix_fmt) {
+ case PIX_FMT_YUV420P:
+ packet_size = (width * height * 3) / 2;
+ break;
+ case PIX_FMT_YUV422:
+ packet_size = (width * height * 2);
+ break;
+ case PIX_FMT_BGR24:
+ case PIX_FMT_RGB24:
+ packet_size = (width * height * 3);
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ if (av_new_packet(pkt, packet_size) < 0)
+ return -EIO;
+
+ pkt->stream_index = 0;
+ /* bypass buffered I/O */
+ ret = url_read(url_fileno(&s->pb), pkt->data, pkt->size);
+ if (ret != pkt->size) {
+ av_free_packet(pkt);
+ return -EIO;
+ } else {
+ return 0;
+ }
+}
+
+AVFormat rawvideo_format = {
+ "rawvideo",
+ "raw video format",
+ NULL,
+ "yuv",
+ CODEC_ID_NONE,
+ CODEC_ID_RAWVIDEO,
+ raw_write_header,
+ raw_write_packet,
+ raw_write_trailer,
+
+ raw_read_header,
+ rawvideo_read_packet,
+ raw_read_close,
+};
diff --git a/libav/rm.c b/libav/rm.c
new file mode 100644
index 0000000000..8c850400e4
--- /dev/null
+++ b/libav/rm.c
@@ -0,0 +1,710 @@
+/*
+ * "Real" compatible mux and demux.
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "avformat.h"
+
+/* in ms */
+#define BUFFER_DURATION 0
+
+typedef struct {
+ int nb_packets;
+ int packet_total_size;
+ int packet_max_size;
+ /* codec related output */
+ int bit_rate;
+ float frame_rate;
+ int nb_frames; /* current frame number */
+ int total_frames; /* total number of frames */
+ int num;
+ AVCodecContext *enc;
+} StreamInfo;
+
+typedef struct {
+ StreamInfo streams[2];
+ StreamInfo *audio_stream, *video_stream;
+ int data_pos; /* position of the data after the header */
+ int nb_packets;
+} RMContext;
+
+static void put_str(ByteIOContext *s, const char *tag)
+{
+ put_be16(s,strlen(tag));
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+
+static void put_str8(ByteIOContext *s, const char *tag)
+{
+ put_byte(s, strlen(tag));
+ while (*tag) {
+ put_byte(s, *tag++);
+ }
+}
+
+static void rv10_write_header(AVFormatContext *ctx,
+ int data_size, int index_pos)
+{
+ RMContext *rm = ctx->priv_data;
+ ByteIOContext *s = &ctx->pb;
+ StreamInfo *stream;
+ unsigned char *data_offset_ptr, *start_ptr;
+ const char *desc, *mimetype;
+ int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
+ int bit_rate, v, duration, flags, data_pos;
+
+ start_ptr = s->buf_ptr;
+
+ put_tag(s, ".RMF");
+ put_be32(s,18); /* header size */
+ put_be16(s,0);
+ put_be32(s,0);
+ put_be32(s,4 + ctx->nb_streams); /* num headers */
+
+ put_tag(s,"PROP");
+ put_be32(s, 50);
+ put_be16(s, 0);
+ packet_max_size = 0;
+ packet_total_size = 0;
+ nb_packets = 0;
+ bit_rate = 0;
+ duration = 0;
+ for(i=0;i<ctx->nb_streams;i++) {
+ StreamInfo *stream = &rm->streams[i];
+ bit_rate += stream->bit_rate;
+ if (stream->packet_max_size > packet_max_size)
+ packet_max_size = stream->packet_max_size;
+ nb_packets += stream->nb_packets;
+ packet_total_size += stream->packet_total_size;
+ /* select maximum duration */
+ v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate);
+ if (v > duration)
+ duration = v;
+ }
+ put_be32(s, bit_rate); /* max bit rate */
+ put_be32(s, bit_rate); /* avg bit rate */
+ put_be32(s, packet_max_size); /* max packet size */
+ if (nb_packets > 0)
+ packet_avg_size = packet_total_size / nb_packets;
+ else
+ packet_avg_size = 0;
+ put_be32(s, packet_avg_size); /* avg packet size */
+ put_be32(s, nb_packets); /* num packets */
+ put_be32(s, duration); /* duration */
+ put_be32(s, BUFFER_DURATION); /* preroll */
+ put_be32(s, index_pos); /* index offset */
+ /* computation of data the data offset */
+ data_offset_ptr = s->buf_ptr;
+ put_be32(s, 0); /* data offset : will be patched after */
+ put_be16(s, ctx->nb_streams); /* num streams */
+ flags = 1 | 2; /* save allowed & perfect play */
+ if (url_is_streamed(s))
+ flags |= 4; /* live broadcast */
+ put_be16(s, flags);
+
+ /* comments */
+
+ put_tag(s,"CONT");
+ size = strlen(ctx->title) + strlen(ctx->author) + strlen(ctx->copyright) +
+ strlen(ctx->comment) + 4 * 2 + 10;
+ put_be32(s,size);
+ put_be16(s,0);
+ put_str(s, ctx->title);
+ put_str(s, ctx->author);
+ put_str(s, ctx->copyright);
+ put_str(s, ctx->comment);
+
+ for(i=0;i<ctx->nb_streams;i++) {
+ int codec_data_size;
+
+ stream = &rm->streams[i];
+
+ if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+ desc = "The Audio Stream";
+ mimetype = "audio/x-pn-realaudio";
+ codec_data_size = 73;
+ } else {
+ desc = "The Video Stream";
+ mimetype = "video/x-pn-realvideo";
+ codec_data_size = 34;
+ }
+
+ put_tag(s,"MDPR");
+ size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size;
+ put_be32(s, size);
+ put_be16(s, 0);
+
+ put_be16(s, i); /* stream number */
+ put_be32(s, stream->bit_rate); /* max bit rate */
+ put_be32(s, stream->bit_rate); /* avg bit rate */
+ put_be32(s, stream->packet_max_size); /* max packet size */
+ if (stream->nb_packets > 0)
+ packet_avg_size = stream->packet_total_size /
+ stream->nb_packets;
+ else
+ packet_avg_size = 0;
+ put_be32(s, packet_avg_size); /* avg packet size */
+ put_be32(s, 0); /* start time */
+ put_be32(s, BUFFER_DURATION); /* preroll */
+ /* duration */
+ put_be32(s, (int)(stream->total_frames * 1000 / stream->frame_rate));
+ put_str8(s, desc);
+ put_str8(s, mimetype);
+ put_be32(s, codec_data_size);
+
+ if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+ int coded_frame_size, fscode, sample_rate;
+ sample_rate = stream->enc->sample_rate;
+ coded_frame_size = (stream->enc->bit_rate *
+ stream->enc->frame_size) / (8 * sample_rate);
+ /* audio codec info */
+ put_tag(s, ".ra");
+ put_byte(s, 0xfd);
+ put_be32(s, 0x00040000); /* version */
+ put_tag(s, ".ra4");
+ put_be32(s, 0x01b53530); /* stream length */
+ put_be16(s, 4); /* unknown */
+ put_be32(s, 0x39); /* header size */
+
+ switch(sample_rate) {
+ case 48000:
+ case 24000:
+ case 12000:
+ fscode = 1;
+ break;
+ default:
+ case 44100:
+ case 22050:
+ case 11025:
+ fscode = 2;
+ break;
+ case 32000:
+ case 16000:
+ case 8000:
+ fscode = 3;
+ }
+ put_be16(s, fscode); /* codec additional info, for AC3, seems
+ to be a frequency code */
+ /* special hack to compensate rounding errors... */
+ if (coded_frame_size == 557)
+ coded_frame_size--;
+ put_be32(s, coded_frame_size); /* frame length */
+ put_be32(s, 0x51540); /* unknown */
+ put_be32(s, 0x249f0); /* unknown */
+ put_be32(s, 0x249f0); /* unknown */
+ put_be16(s, 0x01);
+ /* frame length : seems to be very important */
+ put_be16(s, coded_frame_size);
+ put_be32(s, 0); /* unknown */
+ put_be16(s, stream->enc->sample_rate); /* sample rate */
+ put_be32(s, 0x10); /* unknown */
+ put_be16(s, stream->enc->channels);
+ put_str8(s, "Int0"); /* codec name */
+ put_str8(s, "dnet"); /* codec name */
+ put_be16(s, 0); /* title length */
+ put_be16(s, 0); /* author length */
+ put_be16(s, 0); /* copyright length */
+ put_byte(s, 0); /* end of header */
+ } else {
+ /* video codec info */
+ put_be32(s,34); /* size */
+ put_tag(s,"VIDORV10");
+ put_be16(s, stream->enc->width);
+ put_be16(s, stream->enc->height);
+ put_be16(s, 24); /* frames per seconds ? */
+ put_be32(s,0); /* unknown meaning */
+ put_be16(s, 12); /* unknown meaning */
+ put_be32(s,0); /* unknown meaning */
+ put_be16(s, 8); /* unknown meaning */
+ /* Seems to be the codec version: only use basic H263. The next
+ versions seems to add a diffential DC coding as in
+ MPEG... nothing new under the sun */
+ put_be32(s,0x10000000);
+ //put_be32(s,0x10003000);
+ }
+ }
+
+ /* patch data offset field */
+ data_pos = s->buf_ptr - start_ptr;
+ rm->data_pos = data_pos;
+ data_offset_ptr[0] = data_pos >> 24;
+ data_offset_ptr[1] = data_pos >> 16;
+ data_offset_ptr[2] = data_pos >> 8;
+ data_offset_ptr[3] = data_pos;
+
+ /* data stream */
+ put_tag(s,"DATA");
+ put_be32(s,data_size + 10 + 8);
+ put_be16(s,0);
+
+ put_be32(s, nb_packets); /* number of packets */
+ put_be32(s,0); /* next data header */
+}
+
+static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
+ int length, int key_frame)
+{
+ int timestamp;
+ ByteIOContext *s = &ctx->pb;
+
+ stream->nb_packets++;
+ stream->packet_total_size += length;
+ if (length > stream->packet_max_size)
+ stream->packet_max_size = length;
+
+ put_be16(s,0); /* version */
+ put_be16(s,length + 12);
+ put_be16(s, stream->num); /* stream number */
+ timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate;
+ put_be32(s, timestamp); /* timestamp */
+ put_byte(s, 0); /* reserved */
+ put_byte(s, key_frame ? 2 : 0); /* flags */
+}
+
+static int rm_write_header(AVFormatContext *s)
+{
+ StreamInfo *stream;
+ RMContext *rm;
+ int n;
+ AVCodecContext *codec;
+
+ rm = malloc(sizeof(RMContext));
+ if (!rm)
+ return -1;
+ memset(rm, 0, sizeof(RMContext));
+ s->priv_data = rm;
+
+ for(n=0;n<s->nb_streams;n++) {
+ s->streams[n]->id = n;
+ codec = &s->streams[n]->codec;
+ stream = &rm->streams[n];
+ memset(stream, 0, sizeof(StreamInfo));
+ stream->num = n;
+ stream->bit_rate = codec->bit_rate;
+ stream->enc = codec;
+
+ switch(codec->codec_type) {
+ case CODEC_TYPE_AUDIO:
+ rm->audio_stream = stream;
+ stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size;
+ /* XXX: dummy values */
+ stream->packet_max_size = 1024;
+ stream->nb_packets = 0;
+ stream->total_frames = stream->nb_packets;
+ break;
+ case CODEC_TYPE_VIDEO:
+ rm->video_stream = stream;
+ stream->frame_rate = (float)codec->frame_rate / (float)FRAME_RATE_BASE;
+ /* XXX: dummy values */
+ stream->packet_max_size = 4096;
+ stream->nb_packets = 0;
+ stream->total_frames = stream->nb_packets;
+ break;
+ }
+ }
+
+ rv10_write_header(s, 0, 0);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int rm_write_audio(AVFormatContext *s, UINT8 *buf, int size)
+{
+ UINT8 buf1[size];
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ StreamInfo *stream = rm->audio_stream;
+ int i;
+
+ write_packet_header(s, stream, size, stream->enc->key_frame);
+
+ /* for AC3, the words seems to be reversed */
+ for(i=0;i<size;i+=2) {
+ buf1[i] = buf[i+1];
+ buf1[i+1] = buf[i];
+ }
+ put_buffer(pb, buf1, size);
+ put_flush_packet(pb);
+ stream->nb_frames++;
+ return 0;
+}
+
+static int rm_write_video(AVFormatContext *s, UINT8 *buf, int size)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ StreamInfo *stream = rm->video_stream;
+ int key_frame = stream->enc->key_frame;
+
+ /* XXX: this is incorrect: should be a parameter */
+
+ /* Well, I spent some time finding the meaning of these bits. I am
+ not sure I understood everything, but it works !! */
+#if 1
+ write_packet_header(s, stream, size + 7, key_frame);
+ /* bit 7: '1' if final packet of a frame converted in several packets */
+ put_byte(pb, 0x81);
+ /* bit 7: '1' if I frame. bits 6..0 : sequence number in current
+ frame starting from 1 */
+ if (key_frame) {
+ put_byte(pb, 0x81);
+ } else {
+ put_byte(pb, 0x01);
+ }
+ put_be16(pb, 0x4000 | (size)); /* total frame size */
+ put_be16(pb, 0x4000 | (size)); /* offset from the start or the end */
+#else
+ /* full frame */
+ write_packet_header(s, size + 6);
+ put_byte(pb, 0xc0);
+ put_be16(pb, 0x4000 | size); /* total frame size */
+ put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */
+#endif
+ put_byte(pb, stream->nb_frames & 0xff);
+
+ put_buffer(pb, buf, size);
+ put_flush_packet(pb);
+
+ stream->nb_frames++;
+ return 0;
+}
+
+static int rm_write_packet(AVFormatContext *s, int stream_index,
+ UINT8 *buf, int size)
+{
+ if (s->streams[stream_index]->codec.codec_type ==
+ CODEC_TYPE_AUDIO)
+ return rm_write_audio(s, buf, size);
+ else
+ return rm_write_video(s, buf, size);
+}
+
+static int rm_write_trailer(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+ int data_size, index_pos, i;
+ ByteIOContext *pb = &s->pb;
+
+ if (!url_is_streamed(&s->pb)) {
+ /* end of file: finish to write header */
+ index_pos = url_fseek(pb, 0, SEEK_CUR);
+ data_size = index_pos - rm->data_pos;
+
+ /* index */
+ put_tag(pb, "INDX");
+ put_be32(pb, 10 + 10 * s->nb_streams);
+ put_be16(pb, 0);
+
+ for(i=0;i<s->nb_streams;i++) {
+ put_be32(pb, 0); /* zero indices */
+ put_be16(pb, i); /* stream number */
+ put_be32(pb, 0); /* next index */
+ }
+ /* undocumented end header */
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+
+ url_fseek(pb, 0, SEEK_SET);
+ for(i=0;i<s->nb_streams;i++)
+ rm->streams[i].total_frames = rm->streams[i].nb_frames;
+ rv10_write_header(s, data_size, index_pos);
+ } else {
+ /* undocumented end header */
+ put_be32(pb, 0);
+ put_be32(pb, 0);
+ }
+ put_flush_packet(pb);
+
+ free(rm);
+ return 0;
+}
+
+/***************************************************/
+
+static void get_str(ByteIOContext *pb, char *buf, int buf_size)
+{
+ int len, i;
+ char *q;
+
+ len = get_be16(pb);
+ q = buf;
+ for(i=0;i<len;i++) {
+ if (i < buf_size - 1)
+ *q++ = get_byte(pb);
+ }
+ *q = '\0';
+}
+
+static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
+{
+ int len, i;
+ char *q;
+
+ len = get_byte(pb);
+ q = buf;
+ for(i=0;i<len;i++) {
+ if (i < buf_size - 1)
+ *q++ = get_byte(pb);
+ }
+ *q = '\0';
+}
+
+static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ RMContext *rm;
+ AVStream *st;
+ ByteIOContext *pb = &s->pb;
+ unsigned int tag, v;
+ int tag_size, size, codec_data_size, i;
+ INT64 codec_pos;
+ unsigned int h263_hack_version;
+ char buf[128];
+
+ if (get_le32(pb) != MKTAG('.', 'R', 'M', 'F'))
+ return -EIO;
+ rm = av_mallocz(sizeof(RMContext));
+ if (!rm)
+ return -ENOMEM;
+ s->priv_data = rm;
+
+ get_be32(pb); /* header size */
+ get_be16(pb);
+ get_be32(pb);
+ get_be32(pb); /* number of headers */
+
+ for(;;) {
+ if (url_feof(pb))
+ goto fail;
+ tag = get_le32(pb);
+ tag_size = get_be32(pb);
+ get_be16(pb);
+#if 0
+ printf("tag=%c%c%c%c (%08x) size=%d\n",
+ (tag) & 0xff,
+ (tag >> 8) & 0xff,
+ (tag >> 16) & 0xff,
+ (tag >> 24) & 0xff,
+ tag,
+ tag_size);
+#endif
+ if (tag_size < 10)
+ goto fail;
+ switch(tag) {
+ case MKTAG('P', 'R', 'O', 'P'):
+ /* file header */
+ get_be32(pb); /* max bit rate */
+ get_be32(pb); /* avg bit rate */
+ get_be32(pb); /* max packet size */
+ get_be32(pb); /* avg packet size */
+ get_be32(pb); /* nb packets */
+ get_be32(pb); /* duration */
+ get_be32(pb); /* preroll */
+ get_be32(pb); /* index offset */
+ get_be32(pb); /* data offset */
+ get_be16(pb); /* nb streams */
+ get_be16(pb); /* flags */
+ break;
+ case MKTAG('C', 'O', 'N', 'T'):
+ get_str(pb, s->title, sizeof(s->title));
+ get_str(pb, s->author, sizeof(s->author));
+ get_str(pb, s->copyright, sizeof(s->copyright));
+ get_str(pb, s->comment, sizeof(s->comment));
+ break;
+ case MKTAG('M', 'D', 'P', 'R'):
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ goto fail;
+ s->streams[s->nb_streams++] = st;
+ st->id = get_be16(pb);
+ get_be32(pb); /* max bit rate */
+ st->codec.bit_rate = get_be32(pb); /* bit rate */
+ get_be32(pb); /* max packet size */
+ get_be32(pb); /* avg packet size */
+ get_be32(pb); /* start time */
+ get_be32(pb); /* preroll */
+ get_be32(pb); /* duration */
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ get_str8(pb, buf, sizeof(buf)); /* mimetype */
+ codec_data_size = get_be32(pb);
+ codec_pos = url_ftell(pb);
+
+ v = get_be32(pb);
+ if (v == MKTAG(0xfd, 'a', 'r', '.')) {
+ /* ra type header */
+ get_be32(pb); /* version */
+ get_be32(pb); /* .ra4 */
+ get_be32(pb);
+ get_be16(pb);
+ get_be32(pb); /* header size */
+ get_be16(pb); /* add codec info */
+ get_be32(pb); /* coded frame size */
+ get_be32(pb); /* ??? */
+ get_be32(pb); /* ??? */
+ get_be32(pb); /* ??? */
+ get_be16(pb); /* 1 */
+ get_be16(pb); /* coded frame size */
+ get_be32(pb);
+ st->codec.sample_rate = get_be16(pb);
+ get_be32(pb);
+ st->codec.channels = get_be16(pb);
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ get_str8(pb, buf, sizeof(buf)); /* desc */
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ if (!strcmp(buf, "dnet")) {
+ st->codec.codec_id = CODEC_ID_AC3;
+ } else {
+ st->codec.codec_id = CODEC_ID_NONE;
+ nstrcpy(st->codec.codec_name, sizeof(st->codec.codec_name),
+ buf);
+ }
+ } else {
+ if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) {
+ fail1:
+ fprintf(stderr, "Unsupported video codec\n");
+ goto fail;
+ }
+ st->codec.codec_tag = get_le32(pb);
+ if (st->codec.codec_tag != MKTAG('R', 'V', '1', '0'))
+ goto fail1;
+ st->codec.width = get_be16(pb);
+ st->codec.height = get_be16(pb);
+ st->codec.frame_rate = get_be16(pb) * FRAME_RATE_BASE;
+ st->codec.codec_type = CODEC_TYPE_VIDEO;
+ get_be32(pb);
+ get_be16(pb);
+ get_be32(pb);
+ get_be16(pb);
+ /* modification of h263 codec version (!) */
+ h263_hack_version = get_be32(pb);
+ switch(h263_hack_version) {
+ case 0x10000000:
+ st->codec.sub_id = 0;
+ st->codec.codec_id = CODEC_ID_RV10;
+ break;
+ case 0x10003000:
+ case 0x10003001:
+ st->codec.sub_id = 3;
+ st->codec.codec_id = CODEC_ID_RV10;
+ break;
+ default:
+ /* not handled */
+ st->codec.codec_id = CODEC_ID_NONE;
+ break;
+ }
+ }
+ /* skip codec info */
+ size = url_ftell(pb) - codec_pos;
+ url_fskip(pb, codec_data_size - size);
+ break;
+ case MKTAG('D', 'A', 'T', 'A'):
+ goto header_end;
+ default:
+ /* unknown tag: skip it */
+ url_fskip(pb, tag_size - 10);
+ break;
+ }
+ }
+ header_end:
+ rm->nb_packets = get_be32(pb); /* number of packets */
+ get_be32(pb); /* next data header */
+ return 0;
+
+ fail:
+ for(i=0;i<s->nb_streams;i++) {
+ free(s->streams[i]);
+ }
+ return -EIO;
+}
+
+static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ RMContext *rm = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVStream *st;
+ int len, num, timestamp, i, tmp, j;
+ UINT8 *ptr;
+
+ redo:
+ if (rm->nb_packets == 0)
+ return -EIO;
+ get_be16(pb);
+ len = get_be16(pb);
+ if (len < 12)
+ return -EIO;
+ num = get_be16(pb);
+ timestamp = get_be32(pb);
+ get_byte(pb); /* reserved */
+ get_byte(pb); /* flags */
+ rm->nb_packets--;
+ len -= 12;
+
+ st = NULL;
+ for(i=0;i<s->nb_streams;i++) {
+ st = s->streams[i];
+ if (num == st->id)
+ break;
+ }
+ if (i == s->nb_streams) {
+ /* skip packet if unknown number */
+ url_fskip(pb, len);
+ goto redo;
+ }
+
+ av_new_packet(pkt, len);
+ pkt->stream_index = i;
+ get_buffer(pb, pkt->data, len);
+ /* for AC3, needs to swap bytes */
+ if (st->codec.codec_id == CODEC_ID_AC3) {
+ ptr = pkt->data;
+ for(j=0;j<len;j+=2) {
+ tmp = ptr[0];
+ ptr[0] = ptr[1];
+ ptr[1] = tmp;
+ ptr += 2;
+ }
+ }
+ return 0;
+}
+
+static int rm_read_close(AVFormatContext *s)
+{
+ RMContext *rm = s->priv_data;
+ free(rm);
+ return 0;
+}
+
+AVFormat rm_format = {
+ "rm",
+ "rm format",
+ "audio/x-pn-realaudio",
+ "rm,ra",
+ CODEC_ID_AC3,
+ CODEC_ID_RV10,
+ rm_write_header,
+ rm_write_packet,
+ rm_write_trailer,
+
+ rm_read_header,
+ rm_read_packet,
+ rm_read_close,
+};
diff --git a/libav/swf.c b/libav/swf.c
new file mode 100644
index 0000000000..a93c4f7097
--- /dev/null
+++ b/libav/swf.c
@@ -0,0 +1,552 @@
+/*
+ * Flash Compatible Streaming Format
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "avformat.h"
+
+#include <assert.h>
+
+/* should have a generic way to indicate probable size */
+#define DUMMY_FILE_SIZE (100 * 1024 * 1024)
+#define DUMMY_DURATION 600 /* in seconds */
+
+#define TAG_END 0
+#define TAG_SHOWFRAME 1
+#define TAG_DEFINESHAPE 2
+#define TAG_FREECHARACTER 3
+#define TAG_PLACEOBJECT 4
+#define TAG_REMOVEOBJECT 5
+#define TAG_STREAMHEAD 18
+#define TAG_STREAMBLOCK 19
+#define TAG_JPEG2 21
+
+#define TAG_LONG 0x100
+
+/* flags for shape definition */
+#define FLAG_MOVETO 0x01
+#define FLAG_SETFILL0 0x02
+#define FLAG_SETFILL1 0x04
+
+/* character id used */
+#define BITMAP_ID 0
+#define SHAPE_ID 1
+
+typedef struct {
+ long long duration_pos;
+ long long tag_pos;
+ int tag;
+} SWFContext;
+
+static void put_swf_tag(AVFormatContext *s, int tag)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+
+ swf->tag_pos = url_ftell(pb);
+ swf->tag = tag;
+ /* reserve some room for the tag */
+ if (tag & TAG_LONG) {
+ put_le16(pb, 0);
+ put_le32(pb, 0);
+ } else {
+ put_le16(pb, 0);
+ }
+}
+
+static void put_swf_end_tag(AVFormatContext *s)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ long long pos;
+ int tag_len, tag;
+
+ pos = url_ftell(pb);
+ tag_len = pos - swf->tag_pos - 2;
+ tag = swf->tag;
+ url_fseek(pb, swf->tag_pos, SEEK_SET);
+ if (tag & TAG_LONG) {
+ tag &= ~TAG_LONG;
+ put_le16(pb, (tag << 6) | 0x3f);
+ put_le32(pb, tag_len - 4);
+ } else {
+ assert(tag_len < 0x3f);
+ put_le16(pb, (tag << 6) | tag_len);
+ }
+ url_fseek(pb, pos, SEEK_SET);
+}
+
+static inline void max_nbits(int *nbits_ptr, int val)
+{
+ int n;
+
+ if (val == 0)
+ return;
+ val = abs(val);
+ n = 1;
+ while (val != 0) {
+ n++;
+ val >>= 1;
+ }
+ if (n > *nbits_ptr)
+ *nbits_ptr = n;
+}
+
+static void put_swf_rect(ByteIOContext *pb,
+ int xmin, int xmax, int ymin, int ymax)
+{
+ PutBitContext p;
+ UINT8 buf[256];
+ int nbits, mask;
+
+ init_put_bits(&p, buf, sizeof(buf), NULL, NULL);
+
+ nbits = 0;
+ max_nbits(&nbits, xmin);
+ max_nbits(&nbits, xmax);
+ max_nbits(&nbits, ymin);
+ max_nbits(&nbits, ymax);
+ mask = (1 << nbits) - 1;
+
+ /* rectangle info */
+ put_bits(&p, 5, nbits);
+ put_bits(&p, nbits, xmin & mask);
+ put_bits(&p, nbits, xmax & mask);
+ put_bits(&p, nbits, ymin & mask);
+ put_bits(&p, nbits, ymax & mask);
+
+ flush_put_bits(&p);
+ put_buffer(pb, buf, p.buf_ptr - p.buf);
+}
+
+static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
+{
+ int nbits, mask;
+
+ put_bits(pb, 1, 1); /* edge */
+ put_bits(pb, 1, 1); /* line select */
+ nbits = 2;
+ max_nbits(&nbits, dx);
+ max_nbits(&nbits, dy);
+
+ mask = (1 << nbits) - 1;
+ put_bits(pb, 4, nbits - 2); /* 16 bits precision */
+ if (dx == 0) {
+ put_bits(pb, 1, 0);
+ put_bits(pb, 1, 1);
+ put_bits(pb, nbits, dy & mask);
+ } else if (dy == 0) {
+ put_bits(pb, 1, 0);
+ put_bits(pb, 1, 0);
+ put_bits(pb, nbits, dx & mask);
+ } else {
+ put_bits(pb, 1, 1);
+ put_bits(pb, nbits, dx & mask);
+ put_bits(pb, nbits, dy & mask);
+ }
+}
+
+#define FRAC_BITS 16
+
+/* put matrix (not size optimized */
+static void put_swf_matrix(ByteIOContext *pb,
+ int a, int b, int c, int d, int tx, int ty)
+{
+ PutBitContext p;
+ UINT8 buf[256];
+
+ init_put_bits(&p, buf, sizeof(buf), NULL, NULL);
+
+ put_bits(&p, 1, 1); /* a, d present */
+ put_bits(&p, 5, 20); /* nb bits */
+ put_bits(&p, 20, a);
+ put_bits(&p, 20, d);
+
+ put_bits(&p, 1, 1); /* b, c present */
+ put_bits(&p, 5, 20); /* nb bits */
+ put_bits(&p, 20, c);
+ put_bits(&p, 20, b);
+
+ put_bits(&p, 5, 20); /* nb bits */
+ put_bits(&p, 20, tx);
+ put_bits(&p, 20, ty);
+
+ flush_put_bits(&p);
+ put_buffer(pb, buf, p.buf_ptr - p.buf);
+}
+
+/* XXX: handle audio only */
+static int swf_write_header(AVFormatContext *s)
+{
+ SWFContext *swf;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc, *audio_enc, *video_enc;
+ PutBitContext p;
+ UINT8 buf1[256];
+ int i, width, height, rate;
+
+ swf = malloc(sizeof(SWFContext));
+ if (!swf)
+ return -1;
+ s->priv_data = swf;
+
+ video_enc = NULL;
+ audio_enc = NULL;
+ for(i=0;i<s->nb_streams;i++) {
+ enc = &s->streams[i]->codec;
+ if (enc->codec_type == CODEC_TYPE_AUDIO)
+ audio_enc = enc;
+ else
+ video_enc = enc;
+ }
+
+ if (!video_enc) {
+ /* currenty, cannot work correctly if audio only */
+ width = 320;
+ height = 200;
+ rate = 10 * FRAME_RATE_BASE;
+ } else {
+ width = video_enc->width;
+ height = video_enc->height;
+ rate = video_enc->frame_rate;
+ }
+
+ put_tag(pb, "FWS");
+ put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
+ put_le32(pb, DUMMY_FILE_SIZE); /* dummy size
+ (will be patched if not streamed) */
+
+ put_swf_rect(pb, 0, width, 0, height);
+ put_le16(pb, (rate * 256) / FRAME_RATE_BASE); /* frame rate */
+ swf->duration_pos = url_ftell(pb);
+ put_le16(pb, DUMMY_DURATION * (INT64)rate / FRAME_RATE_BASE); /* frame count */
+
+ /* define a shape with the jpeg inside */
+
+ put_swf_tag(s, TAG_DEFINESHAPE);
+
+ put_le16(pb, SHAPE_ID); /* ID of shape */
+ /* bounding rectangle */
+ put_swf_rect(pb, 0, width, 0, height);
+ /* style info */
+ put_byte(pb, 1); /* one fill style */
+ put_byte(pb, 0x41); /* clipped bitmap fill */
+ put_le16(pb, BITMAP_ID); /* bitmap ID */
+ /* position of the bitmap */
+ put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,
+ 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
+ put_byte(pb, 0); /* no line style */
+
+ /* shape drawing */
+ init_put_bits(&p, buf1, sizeof(buf1), NULL, NULL);
+ put_bits(&p, 4, 1); /* one fill bit */
+ put_bits(&p, 4, 0); /* zero line bit */
+
+ put_bits(&p, 1, 0); /* not an edge */
+ put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
+ put_bits(&p, 5, 1); /* nbits */
+ put_bits(&p, 1, 0); /* X */
+ put_bits(&p, 1, 0); /* Y */
+ put_bits(&p, 1, 1); /* set fill style 1 */
+
+ /* draw the rectangle ! */
+ put_swf_line_edge(&p, width, 0);
+ put_swf_line_edge(&p, 0, height);
+ put_swf_line_edge(&p, -width, 0);
+ put_swf_line_edge(&p, 0, -height);
+
+ /* end of shape */
+ put_bits(&p, 1, 0); /* not an edge */
+ put_bits(&p, 5, 0);
+
+ flush_put_bits(&p);
+ put_buffer(pb, buf1, p.buf_ptr - p.buf);
+
+ put_swf_end_tag(s);
+
+
+ if (audio_enc) {
+ int v;
+
+ /* start sound */
+
+ v = 0;
+ switch(audio_enc->sample_rate) {
+ case 11025:
+ v |= 1 << 2;
+ break;
+ case 22050:
+ v |= 2 << 2;
+ break;
+ case 44100:
+ v |= 3 << 2;
+ break;
+ default:
+ /* not supported */
+ free(swf);
+ return -1;
+ }
+ if (audio_enc->channels == 2)
+ v |= 1;
+ v |= 0x20; /* mp3 compressed */
+ v |= 0x02; /* 16 bits */
+
+ put_swf_tag(s, TAG_STREAMHEAD);
+ put_byte(&s->pb, 0);
+ put_byte(&s->pb, v);
+ put_le16(&s->pb, (audio_enc->sample_rate * FRAME_RATE_BASE) / rate); /* avg samples per frame */
+
+
+ put_swf_end_tag(s);
+ }
+
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int swf_write_video(AVFormatContext *s,
+ AVCodecContext *enc, UINT8 *buf, int size)
+{
+ ByteIOContext *pb = &s->pb;
+ static int tag_id = 0;
+
+ if (enc->frame_number > 1) {
+ /* remove the shape */
+ put_swf_tag(s, TAG_REMOVEOBJECT);
+ put_le16(pb, SHAPE_ID); /* shape ID */
+ put_le16(pb, 1); /* depth */
+ put_swf_end_tag(s);
+
+ /* free the bitmap */
+ put_swf_tag(s, TAG_FREECHARACTER);
+ put_le16(pb, BITMAP_ID);
+ put_swf_end_tag(s);
+ }
+
+ put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
+
+ put_le16(pb, tag_id); /* ID of the image */
+
+ /* a dummy jpeg header seems to be required */
+ put_byte(pb, 0xff);
+ put_byte(pb, 0xd8);
+ put_byte(pb, 0xff);
+ put_byte(pb, 0xd9);
+ /* write the jpeg image */
+ put_buffer(pb, buf, size);
+
+ put_swf_end_tag(s);
+
+ /* draw the shape */
+
+ put_swf_tag(s, TAG_PLACEOBJECT);
+ put_le16(pb, SHAPE_ID); /* shape ID */
+ put_le16(pb, 1); /* depth */
+ put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
+ put_swf_end_tag(s);
+
+ /* output the frame */
+ put_swf_tag(s, TAG_SHOWFRAME);
+ put_swf_end_tag(s);
+
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int swf_write_audio(AVFormatContext *s, UINT8 *buf, int size)
+{
+ ByteIOContext *pb = &s->pb;
+
+ put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
+
+ put_buffer(pb, buf, size);
+
+ put_swf_end_tag(s);
+ put_flush_packet(&s->pb);
+ return 0;
+}
+
+static int swf_write_packet(AVFormatContext *s, int stream_index,
+ UINT8 *buf, int size)
+{
+ AVCodecContext *codec = &s->streams[stream_index]->codec;
+ if (codec->codec_type == CODEC_TYPE_AUDIO)
+ return swf_write_audio(s, buf, size);
+ else
+ return swf_write_video(s, codec, buf, size);
+}
+
+static int swf_write_trailer(AVFormatContext *s)
+{
+ SWFContext *swf = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ AVCodecContext *enc, *video_enc;
+ int file_size, i;
+
+ video_enc = NULL;
+ for(i=0;i<s->nb_streams;i++) {
+ enc = &s->streams[i]->codec;
+ if (enc->codec_type == CODEC_TYPE_VIDEO)
+ video_enc = enc;
+ }
+
+ put_swf_tag(s, TAG_END);
+ put_swf_end_tag(s);
+
+ put_flush_packet(&s->pb);
+
+ /* patch file size and number of frames if not streamed */
+ if (!url_is_streamed(&s->pb) && video_enc) {
+ file_size = url_ftell(pb);
+ url_fseek(pb, 4, SEEK_SET);
+ put_le32(pb, file_size);
+ url_fseek(pb, swf->duration_pos, SEEK_SET);
+ put_le16(pb, video_enc->frame_number);
+ }
+ free(swf);
+ return 0;
+}
+
+/***********************************/
+/* just to extract MP3 from swf */
+
+static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
+{
+ int tag, len;
+
+ if (url_feof(pb))
+ return -1;
+
+ tag = get_le16(pb);
+ len = tag & 0x3f;
+ tag = tag >> 6;
+ if (len == 0x3f) {
+ len = get_le32(pb);
+ }
+ *len_ptr = len;
+ return tag;
+}
+
+static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ ByteIOContext *pb = &s->pb;
+ int nbits, len, frame_rate, tag, v;
+ AVStream *st;
+
+ if ((get_be32(pb) & 0xffffff00) != MKBETAG('F', 'W', 'S', 0))
+ return -EIO;
+ get_le32(pb);
+ /* skip rectangle size */
+ nbits = get_byte(pb) >> 3;
+ len = (4 * nbits - 3 + 7) / 8;
+ url_fskip(pb, len);
+ frame_rate = get_le16(pb);
+ get_le16(pb); /* frame count */
+
+ for(;;) {
+ tag = get_swf_tag(pb, &len);
+ if (tag < 0) {
+ fprintf(stderr, "No streaming found in SWF\n");
+ return -EIO;
+ }
+ if (tag == TAG_STREAMHEAD) {
+ /* streaming found */
+ get_byte(pb);
+ v = get_byte(pb);
+ get_le16(pb);
+ /* if mp3 streaming found, OK */
+ if ((v & 0x20) != 0) {
+ st = av_mallocz(sizeof(AVStream));
+ if (!st)
+ return -ENOMEM;
+ if (v & 0x01)
+ st->codec.channels = 2;
+ else
+ st->codec.channels = 1;
+ s->nb_streams = 1;
+ s->streams[0] = st;
+
+ switch((v>> 2) & 0x03) {
+ case 1:
+ st->codec.sample_rate = 11025;
+ break;
+ case 2:
+ st->codec.sample_rate = 22050;
+ break;
+ case 3:
+ st->codec.sample_rate = 44100;
+ break;
+ default:
+ free(st);
+ return -EIO;
+ }
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ st->codec.codec_id = CODEC_ID_MP2;
+ break;
+ }
+ } else {
+ url_fskip(pb, len);
+ }
+ }
+
+ return 0;
+}
+
+static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ ByteIOContext *pb = &s->pb;
+ int tag, len;
+
+ for(;;) {
+ tag = get_swf_tag(pb, &len);
+ if (tag < 0)
+ return -EIO;
+ if (tag == TAG_STREAMBLOCK) {
+ av_new_packet(pkt, len);
+ get_buffer(pb, pkt->data, pkt->size);
+ break;
+ } else {
+ url_fskip(pb, len);
+ }
+ }
+ return 0;
+}
+
+static int swf_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVFormat swf_format = {
+ "swf",
+ "Flash format",
+ "application/x-shockwave-flash",
+ "swf",
+ CODEC_ID_MP2,
+ CODEC_ID_MJPEG,
+ swf_write_header,
+ swf_write_packet,
+ swf_write_trailer,
+
+ swf_read_header,
+ swf_read_packet,
+ swf_read_close,
+};
diff --git a/libav/udp.c b/libav/udp.c
new file mode 100644
index 0000000000..329653bf18
--- /dev/null
+++ b/libav/udp.c
@@ -0,0 +1,148 @@
+/*
+ * UDP prototype streaming system
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "avformat.h"
+
+typedef struct {
+ int udp_socket;
+ int max_payload_size; /* in bytes */
+} UDPContext;
+
+#define UDP_TX_BUF_SIZE 32768
+
+/* put it in UDP context */
+static struct sockaddr_in dest_addr;
+
+/* return non zero if error */
+static int udp_open(URLContext *h, const char *uri, int flags)
+{
+ int local_port = 0;
+ struct sockaddr_in my_addr;
+ const char *p, *q;
+ char hostname[1024];
+ int port, udp_socket, tmp;
+ struct hostent *hp;
+ UDPContext *s;
+
+ h->is_streamed = 1;
+
+ if (!(flags & URL_WRONLY))
+ return -EIO;
+
+ /* fill the dest addr */
+ p = uri;
+ if (!strstart(p, "udp:", &p))
+ return -1;
+ q = strchr(p, ':');
+ if (!q)
+ return -1;
+ memcpy(hostname, p, q - p);
+ hostname[q - p] = '\0';
+ port = strtol(q+1, NULL, 10);
+ if (port <= 0)
+ return -1;
+
+ dest_addr.sin_family = AF_INET;
+ dest_addr.sin_port = htons(port);
+ if ((inet_aton(hostname, &dest_addr.sin_addr)) == 0) {
+ hp = gethostbyname(hostname);
+ if (!hp)
+ return -1;
+ memcpy ((char *) &dest_addr.sin_addr, hp->h_addr, hp->h_length);
+ }
+
+ udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
+ if (udp_socket < 0)
+ return -1;
+
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(local_port);
+ my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ /* the bind is needed to give a port to the socket now */
+ if (bind(udp_socket,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+ goto fail;
+
+ /* limit the tx buf size to limit latency */
+
+ tmp = UDP_TX_BUF_SIZE;
+ if (setsockopt(udp_socket, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
+ perror("setsockopt sndbuf");
+ goto fail;
+ }
+
+ s = malloc(sizeof(UDPContext));
+ if (!s)
+ return -ENOMEM;
+ h->priv_data = s;
+ s->udp_socket = udp_socket;
+ h->packet_size = 1500;
+ return 0;
+ fail:
+ return -EIO;
+}
+
+int udp_close(URLContext *h)
+{
+ UDPContext *s = h->priv_data;
+ close(s->udp_socket);
+ return 0;
+}
+
+int udp_write(URLContext *h, UINT8 *buf, int size)
+{
+ UDPContext *s = h->priv_data;
+ int ret, len, size1;
+
+ /* primitive way to avoid big packets */
+ size1 = size;
+ while (size > 0) {
+ len = size;
+ if (len > h->packet_size)
+ len = h->packet_size;
+
+ ret = sendto (s->udp_socket, buf, len, 0,
+ (struct sockaddr *) &dest_addr,
+ sizeof (dest_addr));
+ if (ret < 0)
+ perror("sendto");
+ buf += len;
+ size -= len;
+ }
+ return size1 - size;
+}
+
+URLProtocol udp_protocol = {
+ "udp",
+ udp_open,
+ NULL, /* read */
+ udp_write,
+ NULL, /* seek */
+ udp_close,
+};
diff --git a/libav/utils.c b/libav/utils.c
new file mode 100644
index 0000000000..9018d0fb8d
--- /dev/null
+++ b/libav/utils.c
@@ -0,0 +1,533 @@
+/*
+ * Various utilities for ffmpeg system
+ * Copyright (c) 2000,2001 Gerard Lantau
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "avformat.h"
+
+AVFormat *first_format;
+
+void register_avformat(AVFormat *format)
+{
+ AVFormat **p;
+ p = &first_format;
+ while (*p != NULL) p = &(*p)->next;
+ *p = format;
+ format->next = NULL;
+}
+
+int match_ext(const char *filename, const char *extensions)
+{
+ const char *ext, *p;
+ char ext1[32], *q;
+
+ ext = strrchr(filename, '.');
+ if (ext) {
+ ext++;
+ p = extensions;
+ for(;;) {
+ q = ext1;
+ while (*p != '\0' && *p != ',')
+ *q++ = *p++;
+ *q = '\0';
+ if (!strcasecmp(ext1, ext))
+ return 1;
+ if (*p == '\0')
+ break;
+ p++;
+ }
+ }
+ return 0;
+}
+
+AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type)
+{
+ AVFormat *fmt, *fmt_found;
+ int score_max, score;
+
+ /* find the proper file type */
+ fmt_found = NULL;
+ score_max = 0;
+ fmt = first_format;
+ while (fmt != NULL) {
+ score = 0;
+ if (fmt->name && short_name && !strcmp(fmt->name, short_name))
+ score += 100;
+ if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
+ score += 10;
+ if (filename && fmt->extensions &&
+ match_ext(filename, fmt->extensions)) {
+ score += 5;
+ }
+ if (score > score_max) {
+ score_max = score;
+ fmt_found = fmt;
+ }
+ fmt = fmt->next;
+ }
+ return fmt_found;
+}
+
+/* return TRUE if val is a prefix of str. If it returns TRUE, ptr is
+ set to the next character in 'str' after the prefix */
+int strstart(const char *str, const char *val, const char **ptr)
+{
+ const char *p, *q;
+ p = str;
+ q = val;
+ while (*q != '\0') {
+ if (*p != *q)
+ return 0;
+ p++;
+ q++;
+ }
+ if (ptr)
+ *ptr = p;
+ return 1;
+}
+
+void nstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+void register_all(void)
+{
+ avcodec_init();
+ avcodec_register_all();
+ avcodec_register_more();
+
+ register_avformat(&mp2_format);
+ register_avformat(&ac3_format);
+ register_avformat(&mpeg_mux_format);
+ register_avformat(&mpeg1video_format);
+ register_avformat(&h263_format);
+ register_avformat(&rm_format);
+ register_avformat(&asf_format);
+ register_avformat(&avi_format);
+ register_avformat(&mpjpeg_format);
+ register_avformat(&jpeg_format);
+ register_avformat(&swf_format);
+ register_avformat(&wav_format);
+ register_avformat(&pcm_format);
+ register_avformat(&rawvideo_format);
+ register_avformat(&ffm_format);
+ register_avformat(&pgm_format);
+ register_avformat(&pgmyuv_format);
+ register_avformat(&imgyuv_format);
+ register_avformat(&pgmpipe_format);
+
+ register_protocol(&file_protocol);
+ register_protocol(&pipe_protocol);
+ register_protocol(&audio_protocol);
+ register_protocol(&video_protocol);
+ register_protocol(&udp_protocol);
+ register_protocol(&http_protocol);
+}
+
+/* memory handling */
+
+int av_new_packet(AVPacket *pkt, int size)
+{
+ pkt->data = malloc(size);
+ if (!pkt->data)
+ return -ENOMEM;
+ pkt->size = size;
+ /* sane state */
+ pkt->pts = 0;
+ pkt->stream_index = 0;
+ pkt->flags = 0;
+ return 0;
+}
+
+void av_free_packet(AVPacket *pkt)
+{
+ free(pkt->data);
+ /* fail safe */
+ pkt->data = NULL;
+ pkt->size = 0;
+}
+
+/* fifo handling */
+
+int fifo_init(FifoBuffer *f, int size)
+{
+ f->buffer = malloc(size);
+ if (!f->buffer)
+ return -1;
+ f->end = f->buffer + size;
+ f->wptr = f->rptr = f->buffer;
+ return 0;
+}
+
+void fifo_free(FifoBuffer *f)
+{
+ free(f->buffer);
+}
+
+int fifo_size(FifoBuffer *f, UINT8 *rptr)
+{
+ int size;
+
+ if (f->wptr >= rptr) {
+ size = f->wptr - rptr;
+ } else {
+ size = (f->end - rptr) + (f->wptr - f->buffer);
+ }
+ return size;
+}
+
+/* get data from the fifo (return -1 if not enough data) */
+int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
+{
+ UINT8 *rptr = *rptr_ptr;
+ int size, len;
+
+ if (f->wptr >= rptr) {
+ size = f->wptr - rptr;
+ } else {
+ size = (f->end - rptr) + (f->wptr - f->buffer);
+ }
+
+ if (size < buf_size)
+ return -1;
+ while (buf_size > 0) {
+ len = f->end - rptr;
+ if (len > buf_size)
+ len = buf_size;
+ memcpy(buf, rptr, len);
+ buf += len;
+ rptr += len;
+ if (rptr >= f->end)
+ rptr = f->buffer;
+ buf_size -= len;
+ }
+ *rptr_ptr = rptr;
+ return 0;
+}
+
+void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
+{
+ int len;
+ UINT8 *wptr;
+ wptr = *wptr_ptr;
+ while (size > 0) {
+ len = f->end - wptr;
+ if (len > size)
+ len = size;
+ memcpy(wptr, buf, len);
+ wptr += len;
+ if (wptr >= f->end)
+ wptr = f->buffer;
+ buf += len;
+ size -= len;
+ }
+ *wptr_ptr = wptr;
+}
+
+/* media file handling */
+
+AVFormatContext *av_open_input_file(const char *filename, int buf_size)
+{
+ AVFormatParameters params, *ap;
+ AVFormat *fmt;
+ AVFormatContext *ic = NULL;
+ URLFormat url_format;
+ int err;
+
+ ic = av_mallocz(sizeof(AVFormatContext));
+ if (!ic)
+ goto fail;
+ if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0)
+ goto fail;
+
+ if (buf_size > 0) {
+ url_setbufsize(&ic->pb, buf_size);
+ }
+
+ /* find format */
+ err = url_getformat(url_fileno(&ic->pb), &url_format);
+ if (err >= 0) {
+ fmt = guess_format(url_format.format_name, NULL, NULL);
+ ap = &params;
+ ap->sample_rate = url_format.sample_rate;
+ ap->frame_rate = url_format.frame_rate;
+ ap->channels = url_format.channels;
+ ap->width = url_format.width;
+ ap->height = url_format.height;
+ ap->pix_fmt = url_format.pix_fmt;
+ } else {
+ fmt = guess_format(NULL, filename, NULL);
+ ap = NULL;
+ }
+ if (!fmt || !fmt->read_header) {
+ return NULL;
+ }
+ ic->format = fmt;
+
+ err = ic->format->read_header(ic, ap);
+ if (err < 0) {
+ url_fclose(&ic->pb);
+ goto fail;
+ }
+
+ return ic;
+
+ fail:
+ if (ic)
+ free(ic);
+ return NULL;
+}
+
+int av_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVPacketList *pktl;
+
+ pktl = s->packet_buffer;
+ if (pktl) {
+ /* read packet from packet buffer, if there is data */
+ *pkt = pktl->pkt;
+ s->packet_buffer = pktl->next;
+ free(pktl);
+ return 0;
+ } else {
+ return s->format->read_packet(s, pkt);
+ }
+}
+
+void av_close_input_file(AVFormatContext *s)
+{
+ int i;
+
+ if (s->format->read_close)
+ s->format->read_close(s);
+ for(i=0;i<s->nb_streams;i++) {
+ free(s->streams[i]);
+ }
+ if (s->packet_buffer) {
+ AVPacketList *p, *p1;
+ p = s->packet_buffer;
+ while (p != NULL) {
+ p1 = p->next;
+ av_free_packet(&p->pkt);
+ free(p);
+ p = p1;
+ }
+ s->packet_buffer = NULL;
+ }
+ url_fclose(&s->pb);
+ free(s);
+}
+
+
+int av_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ /* XXX: currently, an emulation because internal API must change */
+ return s->format->write_packet(s, pkt->stream_index, pkt->data, pkt->size);
+}
+
+/* "user interface" functions */
+
+void dump_format(AVFormatContext *ic,
+ int index,
+ const char *url,
+ int is_output)
+{
+ int i;
+ char buf[256];
+
+ fprintf(stderr, "%s #%d, %s, %s '%s':\n",
+ is_output ? "Output" : "Input",
+ index, ic->format->name,
+ is_output ? "to" : "from", url);
+ for(i=0;i<ic->nb_streams;i++) {
+ AVStream *st = ic->streams[i];
+ avcodec_string(buf, sizeof(buf), &st->codec, is_output);
+ fprintf(stderr, " Stream #%d.%d: %s\n", index, i, buf);
+ }
+}
+
+typedef struct {
+ const char *str;
+ int width, height;
+} SizeEntry;
+
+static SizeEntry sizes[] = {
+ { "sqcif", 128, 96 },
+ { "qcif", 176, 144 },
+ { "cif", 352, 288 },
+ { "4cif", 704, 576 },
+};
+
+int parse_image_size(int *width_ptr, int *height_ptr, const char *str)
+{
+ int i;
+ int n = sizeof(sizes) / sizeof(SizeEntry);
+ const char *p;
+ int frame_width = 0, frame_height = 0;
+
+ for(i=0;i<n;i++) {
+ if (!strcmp(sizes[i].str, str)) {
+ frame_width = sizes[i].width;
+ frame_height = sizes[i].height;
+ break;
+ }
+ }
+ if (i == n) {
+ p = str;
+ frame_width = strtol(p, (char **)&p, 10);
+ if (*p)
+ p++;
+ frame_height = strtol(p, (char **)&p, 10);
+ }
+ if (frame_width <= 0 || frame_height <= 0)
+ return -1;
+ *width_ptr = frame_width;
+ *height_ptr = frame_height;
+ return 0;
+}
+
+INT64 gettime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+/* syntax: [YYYY-MM-DD ][[HH:]MM:]SS[.m...] . Return the date in micro seconds since 1970 */
+INT64 parse_date(const char *datestr, int duration)
+{
+ const char *p;
+ INT64 t;
+ int sec;
+
+ p = datestr;
+ if (!duration) {
+ static const UINT8 months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int year, month, day, i;
+
+ if (strlen(p) >= 5 && p[4] == '-') {
+
+ year = strtol(p, (char **)&p, 10);
+ if (*p)
+ p++;
+ month = strtol(p, (char **)&p, 10) - 1;
+ if (*p)
+ p++;
+ day = strtol(p, (char **)&p, 10) - 1;
+ if (*p)
+ p++;
+ day += (year - 1970) * 365;
+ /* if >= March, take February of current year into account too */
+ if (month >= 2)
+ year++;
+ for(i=1970;i<year;i++) {
+ if ((i % 100) == 0) {
+ if ((i % 400) == 0) day++;
+ } else if ((i % 4) == 0) {
+ day++;
+ }
+ }
+ for(i=0;i<month;i++)
+ day += months[i];
+ } else {
+ day = (time(NULL) / (3600 * 24));
+ }
+ t = day * (3600 * 24);
+ } else {
+ t = 0;
+ }
+
+ sec = 0;
+ for(;;) {
+ int val;
+ val = strtol(p, (char **)&p, 10);
+ sec = sec * 60 + val;
+ if (*p != ':')
+ break;
+ p++;
+ }
+ t = (t + sec) * 1000000;
+ if (*p == '.') {
+ int val, n;
+ p++;
+ n = strlen(p);
+ if (n > 6)
+ n = 6;
+ val = strtol(p, NULL, 10);
+ while (n < 6) {
+ val = val * 10;
+ n++;
+ }
+ t += val;
+ }
+ return t;
+}
+
+/* syntax: '?tag1=val1&tag2=val2...'. No URL decoding is done. Return
+ 1 if found */
+int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
+{
+ const char *p;
+ char tag[128], *q;
+
+ p = info;
+ if (*p == '?')
+ p++;
+ for(;;) {
+ q = tag;
+ while (*p != '\0' && *p != '=' && *p != '&') {
+ if ((q - tag) < sizeof(tag) - 1)
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ q = arg;
+ if (*p == '=') {
+ p++;
+ while (*p != '&' && *p != '\0') {
+ if ((q - arg) < arg_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ }
+ if (!strcmp(tag, tag1))
+ return 1;
+ if (*p != '&')
+ break;
+ }
+ return 0;
+}
+
diff --git a/libav/wav.c b/libav/wav.c
new file mode 100644
index 0000000000..9f430bb2f6
--- /dev/null
+++ b/libav/wav.c
@@ -0,0 +1,211 @@
+/*
+ * WAV encoder and decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include "avformat.h"
+#include "avi.h"
+
+typedef struct {
+ offset_t data;
+} WAVContext;
+
+static int wav_write_header(AVFormatContext *s)
+{
+ WAVContext *wav;
+ ByteIOContext *pb = &s->pb;
+ offset_t fmt;
+
+ wav = malloc(sizeof(WAVContext));
+ if (!wav)
+ return -1;
+ memset(wav, 0, sizeof(WAVContext));
+ s->priv_data = wav;
+
+ put_tag(pb, "RIFF");
+ put_le32(pb, 0); /* file length */
+ put_tag(pb, "WAVE");
+
+ /* format header */
+ fmt = start_tag(pb, "fmt ");
+ put_wav_header(pb, &s->streams[0]->codec);
+ end_tag(pb, fmt);
+
+ /* data header */
+ wav->data = start_tag(pb, "data");
+
+ put_flush_packet(pb);
+
+ return 0;
+}
+
+static int wav_write_packet(AVFormatContext *s, int stream_index_ptr,
+ UINT8 *buf, int size)
+{
+ ByteIOContext *pb = &s->pb;
+ put_buffer(pb, buf, size);
+ return 0;
+}
+
+static int wav_write_trailer(AVFormatContext *s)
+{
+ ByteIOContext *pb = &s->pb;
+ WAVContext *wav = s->priv_data;
+ offset_t file_size;
+
+ if (!url_is_streamed(&s->pb)) {
+ end_tag(pb, wav->data);
+
+ /* update file size */
+ file_size = url_ftell(pb);
+ url_fseek(pb, 4, SEEK_SET);
+ put_le32(pb, file_size);
+ url_fseek(pb, file_size, SEEK_SET);
+
+ put_flush_packet(pb);
+ }
+
+ free(wav);
+ return 0;
+}
+
+/* return the size of the found tag */
+/* XXX: > 2GB ? */
+static int find_tag(ByteIOContext *pb, int tag1)
+{
+ unsigned int tag;
+ int size;
+
+ for(;;) {
+ if (url_feof(pb))
+ return -1;
+ tag = get_le32(pb);
+ size = get_le32(pb);
+ if (tag == tag1)
+ break;
+ url_fseek(pb, size, SEEK_CUR);
+ }
+ if (size < 0)
+ size = 0x7fffffff;
+ return size;
+}
+
+/* wav input */
+static int wav_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ int size;
+ unsigned int tag;
+ ByteIOContext *pb = &s->pb;
+ unsigned int id, channels, rate, bit_rate, extra_size;
+ AVStream *st;
+
+ /* check RIFF header */
+ tag = get_le32(pb);
+
+ if (tag != MKTAG('R', 'I', 'F', 'F'))
+ return -1;
+ get_le32(pb); /* file size */
+ tag = get_le32(pb);
+ if (tag != MKTAG('W', 'A', 'V', 'E'))
+ return -1;
+
+ /* parse fmt header */
+ size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
+ if (size < 0)
+ return -1;
+ id = get_le16(pb);
+ channels = get_le16(pb);
+ rate = get_le32(pb);
+ bit_rate = get_le32(pb) * 8;
+ get_le16(pb); /* block align */
+ get_le16(pb); /* bits per sample */
+ if (size >= 18) {
+ /* wav_extra_size */
+ extra_size = get_le16(pb);
+ /* skip unused data */
+ url_fseek(pb, size - 18, SEEK_CUR);
+ }
+
+ size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
+ if (size < 0)
+ return -1;
+
+ /* now we are ready: build format streams */
+ st = malloc(sizeof(AVStream));
+ if (!st)
+ return -1;
+ s->nb_streams = 1;
+ s->streams[0] = st;
+
+ st->id = 0;
+
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ st->codec.codec_tag = id;
+ st->codec.codec_id = codec_get_id(codec_wav_tags, id);
+ st->codec.channels = channels;
+ st->codec.sample_rate = rate;
+ return 0;
+}
+
+#define MAX_SIZE 4096
+
+static int wav_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ int packet_size, n, ret;
+
+ if (url_feof(&s->pb))
+ return -EIO;
+ packet_size = url_get_packet_size(&s->pb);
+ n = MAX_SIZE / packet_size;
+ if (n <= 0)
+ return n = 1;
+ if (av_new_packet(pkt, n * packet_size))
+ return -EIO;
+ pkt->stream_index = 0;
+
+ ret = get_buffer(&s->pb, pkt->data, pkt->size);
+ if (ret < 0)
+ av_free_packet(pkt);
+ return ret;
+}
+
+static int wav_read_close(AVFormatContext *s)
+{
+ return 0;
+}
+
+AVFormat wav_format = {
+ "wav",
+ "wav format",
+ "audio/x-wav",
+ "wav",
+ CODEC_ID_PCM,
+ CODEC_ID_NONE,
+ wav_write_header,
+ wav_write_packet,
+ wav_write_trailer,
+
+ wav_read_header,
+ wav_read_packet,
+ wav_read_close,
+};
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
new file mode 100644
index 0000000000..a418516b16
--- /dev/null
+++ b/libavcodec/Makefile
@@ -0,0 +1,59 @@
+include ../config.mk
+CFLAGS= -O2 -Wall -g
+LDFLAGS= -g
+
+OBJS= common.o utils.o mpegvideo.o h263.o jrevdct.o jfdctfst.o \
+ mpegaudio.o ac3enc.o mjpegenc.o resample.o dsputil.o \
+ motion_est.o imgconvert.o imgresample.o msmpeg4.o \
+ mpeg12.o h263dec.o rv10.o
+
+# currently using libac3 for ac3 decoding
+OBJS+= ac3dec.o \
+ libac3/bit_allocate.o libac3/bitstream.o libac3/downmix.o \
+ libac3/imdct.o libac3/parse.o
+
+# currently using mpglib for mpeg audio decoding
+OBJS+= mpegaudiodec.o \
+ mpglib/layer1.o mpglib/layer2.o mpglib/layer3.o \
+ mpglib/dct64_i386.o mpglib/decode_i386.o mpglib/tabinit.o
+
+# i386 mmx specific stuff
+ifdef CONFIG_MMX
+OBJS += i386/fdct_mmx.o i386/fdctdata.o i386/sad_mmx.o i386/cputest.o \
+ i386/dsputil_mmx.o
+endif
+
+LIB= libavcodec.a
+TESTS= imgresample-test dct-test
+
+all: $(LIB) apiexample
+
+$(LIB): $(OBJS)
+ rm -f $@
+ $(AR) rcs $@ $(OBJS)
+
+dsputil.o: dsputil.c dsputil.h
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.o: %.s
+ nasm -f elf -o $@ $<
+
+clean:
+ rm -f *.o *~ *.a i386/*.o i386/*~ \
+ libac3/*.o libac3/*~ \
+ mpglib/*.o mpglib/*~ \
+ apiexample $(TESTS)
+
+# api example program
+apiexample: apiexample.c $(LIB)
+ $(CC) $(CFLAGS) -o $@ $< $(LIB) -lm
+
+# testing progs
+
+imgresample-test: imgresample.c
+ $(CC) $(CFLAGS) -DTEST -o $@ $^
+
+dct-test: dct-test.o jfdctfst.o i386/fdct_mmx.o i386/fdctdata.o fdctref.o
+ $(CC) -o $@ $^
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
new file mode 100644
index 0000000000..7332a11d8e
--- /dev/null
+++ b/libavcodec/ac3dec.c
@@ -0,0 +1,189 @@
+/*
+ * AC3 decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "avcodec.h"
+
+#include <inttypes.h>
+#include "libac3/ac3.h"
+
+/* currently, I use libac3 which is Copyright (C) Aaron Holtzman and
+ released under the GPL license. I may reimplement it someday... */
+typedef struct AC3DecodeState {
+ UINT8 inbuf[4096]; /* input buffer */
+ UINT8 *inbuf_ptr;
+ int frame_size;
+ int flags;
+ ac3_state_t state;
+} AC3DecodeState;
+
+static int ac3_decode_init(AVCodecContext *avctx)
+{
+ AC3DecodeState *s = avctx->priv_data;
+
+ ac3_init ();
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ return 0;
+}
+
+stream_samples_t samples;
+
+/**** the following two functions comes from ac3dec */
+static inline int blah (int32_t i)
+{
+ if (i > 0x43c07fff)
+ return 32767;
+ else if (i < 0x43bf8000)
+ return -32768;
+ else
+ return i - 0x43c00000;
+}
+
+static inline void float_to_int (float * _f, INT16 * s16)
+{
+ int i;
+ int32_t * f = (int32_t *) _f; // XXX assumes IEEE float format
+
+ for (i = 0; i < 256; i++) {
+ s16[2*i] = blah (f[i]);
+ s16[2*i+1] = blah (f[i+256]);
+ }
+}
+
+static inline void float_to_int_mono (float * _f, INT16 * s16)
+{
+ int i;
+ int32_t * f = (int32_t *) _f; // XXX assumes IEEE float format
+
+ for (i = 0; i < 256; i++) {
+ s16[i] = blah (f[i]);
+ }
+}
+
+/**** end */
+
+#define HEADER_SIZE 7
+
+static int ac3_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ UINT8 *buf, int buf_size)
+{
+ AC3DecodeState *s = avctx->priv_data;
+ UINT8 *buf_ptr;
+ int flags, i, len;
+ int sample_rate, bit_rate;
+ short *out_samples = data;
+ float level;
+
+ *data_size = 0;
+ buf_ptr = buf;
+ while (buf_size > 0) {
+ len = s->inbuf_ptr - s->inbuf;
+ if (s->frame_size == 0) {
+ /* no header seen : find one. We need at least 7 bytes to parse it */
+ len = HEADER_SIZE - len;
+ if (len > buf_size)
+ len = buf_size;
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ if ((s->inbuf_ptr - s->inbuf) == HEADER_SIZE) {
+ len = ac3_syncinfo (s->inbuf, &s->flags, &sample_rate, &bit_rate);
+ if (len == 0) {
+ /* no sync found : move by one byte (inefficient, but simple!) */
+ memcpy(s->inbuf, s->inbuf + 1, HEADER_SIZE - 1);
+ s->inbuf_ptr--;
+ } else {
+ s->frame_size = len;
+ /* update codec info */
+ avctx->sample_rate = sample_rate;
+ if ((s->flags & AC3_CHANNEL_MASK) == AC3_MONO)
+ avctx->channels = 1;
+ else
+ avctx->channels = 2;
+ avctx->bit_rate = bit_rate;
+ }
+ }
+ } else if (len < s->frame_size) {
+ len = s->frame_size - len;
+ if (len > buf_size)
+ len = buf_size;
+
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ } else {
+ if (avctx->channels == 1)
+ flags = AC3_MONO;
+ else
+ flags = AC3_STEREO;
+
+ flags |= AC3_ADJUST_LEVEL;
+ level = 1;
+ if (ac3_frame (&s->state, s->inbuf, &flags, &level, 384)) {
+ fail:
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ continue;
+ }
+ for (i = 0; i < 6; i++) {
+ if (ac3_block (&s->state))
+ goto fail;
+ if (avctx->channels == 1)
+ float_to_int_mono (*samples, out_samples + i * 256);
+ else
+ float_to_int (*samples, out_samples + i * 512);
+ }
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ *data_size = 6 * avctx->channels * 256 * sizeof(INT16);
+ break;
+ }
+ }
+ return buf_ptr - buf;
+}
+
+static int ac3_decode_end(AVCodecContext *s)
+{
+ return 0;
+}
+
+AVCodec ac3_decoder = {
+ "ac3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AC3,
+ sizeof(AC3DecodeState),
+ ac3_decode_init,
+ NULL,
+ ac3_decode_end,
+ ac3_decode_frame,
+};
+
+/* register codecs which could clash with mplayer symbols */
+/* XXX: rename all symbols to avoid clashed */
+void avcodec_register_more(void)
+{
+ register_avcodec(&mp3_decoder);
+ register_avcodec(&ac3_decoder);
+}
+
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
new file mode 100644
index 0000000000..2bd4179aab
--- /dev/null
+++ b/libavcodec/ac3enc.c
@@ -0,0 +1,1460 @@
+/*
+ * The simplest AC3 encoder
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "avcodec.h"
+
+#include "ac3enc.h"
+#include "ac3tab.h"
+
+//#define DEBUG
+//#define DEBUG_BITALLOC
+#define NDEBUG
+#include <assert.h>
+
+#define MDCT_NBITS 9
+#define N (1 << MDCT_NBITS)
+#define NB_BLOCKS 6 /* number of PCM blocks inside an AC3 frame */
+
+/* new exponents are sent if their Norm 1 exceed this number */
+#define EXP_DIFF_THRESHOLD 1000
+
+/* exponent encoding strategy */
+#define EXP_REUSE 0
+#define EXP_NEW 1
+
+#define EXP_D15 1
+#define EXP_D25 2
+#define EXP_D45 3
+
+static void fft_init(int ln);
+static void ac3_crc_init(void);
+
+static inline INT16 fix15(float a)
+{
+ int v;
+ v = (int)(a * (float)(1 << 15));
+ if (v < -32767)
+ v = -32767;
+ else if (v > 32767)
+ v = 32767;
+ return v;
+}
+
+static inline int calc_lowcomp1(int a, int b0, int b1)
+{
+ if ((b0 + 256) == b1) {
+ a = 384 ;
+ } else if (b0 > b1) {
+ a = a - 64;
+ if (a < 0) a=0;
+ }
+ return a;
+}
+
+static inline int calc_lowcomp(int a, int b0, int b1, int bin)
+{
+ if (bin < 7) {
+ if ((b0 + 256) == b1) {
+ a = 384 ;
+ } else if (b0 > b1) {
+ a = a - 64;
+ if (a < 0) a=0;
+ }
+ } else if (bin < 20) {
+ if ((b0 + 256) == b1) {
+ a = 320 ;
+ } else if (b0 > b1) {
+ a= a - 64;
+ if (a < 0) a=0;
+ }
+ } else {
+ a = a - 128;
+ if (a < 0) a=0;
+ }
+ return a;
+}
+
+/* AC3 bit allocation. The algorithm is the one described in the AC3
+ spec with some optimizations because of our simplified encoding
+ assumptions. */
+void parametric_bit_allocation(AC3EncodeContext *s, UINT8 *bap,
+ INT8 *exp, int start, int end,
+ int snroffset, int fgain)
+{
+ int bin,i,j,k,end1,v,v1,bndstrt,bndend,lowcomp,begin;
+ int fastleak,slowleak,address,tmp;
+ INT16 psd[256]; /* scaled exponents */
+ INT16 bndpsd[50]; /* interpolated exponents */
+ INT16 excite[50]; /* excitation */
+ INT16 mask[50]; /* masking value */
+
+ /* exponent mapping to PSD */
+ for(bin=start;bin<end;bin++) {
+ psd[bin]=(3072 - (exp[bin] << 7));
+ }
+
+ /* PSD integration */
+ j=start;
+ k=masktab[start];
+ do {
+ v=psd[j];
+ j++;
+ end1=bndtab[k+1];
+ if (end1 > end) end1=end;
+ for(i=j;i<end1;i++) {
+ int c,adr;
+ /* logadd */
+ v1=psd[j];
+ c=v-v1;
+ if (c >= 0) {
+ adr=c >> 1;
+ if (adr > 255) adr=255;
+ v=v + latab[adr];
+ } else {
+ adr=(-c) >> 1;
+ if (adr > 255) adr=255;
+ v=v1 + latab[adr];
+ }
+ j++;
+ }
+ bndpsd[k]=v;
+ k++;
+ } while (end > bndtab[k]);
+
+ /* excitation function */
+ bndstrt = masktab[start];
+ bndend = masktab[end-1] + 1;
+
+ lowcomp = 0;
+ lowcomp = calc_lowcomp1(lowcomp, bndpsd[0], bndpsd[1]) ;
+ excite[0] = bndpsd[0] - fgain - lowcomp ;
+ lowcomp = calc_lowcomp1(lowcomp, bndpsd[1], bndpsd[2]) ;
+ excite[1] = bndpsd[1] - fgain - lowcomp ;
+ begin = 7 ;
+ for (bin = 2; bin < 7; bin++) {
+ lowcomp = calc_lowcomp1(lowcomp, bndpsd[bin], bndpsd[bin+1]) ;
+ fastleak = bndpsd[bin] - fgain ;
+ slowleak = bndpsd[bin] - s->sgain ;
+ excite[bin] = fastleak - lowcomp ;
+ if (bndpsd[bin] <= bndpsd[bin+1]) {
+ begin = bin + 1 ;
+ break ;
+ }
+ }
+
+ end1=bndend;
+ if (end1 > 22) end1=22;
+
+ for (bin = begin; bin < end1; bin++) {
+ lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin) ;
+
+ fastleak -= s->fdecay ;
+ v = bndpsd[bin] - fgain;
+ if (fastleak < v) fastleak = v;
+
+ slowleak -= s->sdecay ;
+ v = bndpsd[bin] - s->sgain;
+ if (slowleak < v) slowleak = v;
+
+ v=fastleak - lowcomp;
+ if (slowleak > v) v=slowleak;
+
+ excite[bin] = v;
+ }
+
+ for (bin = 22; bin < bndend; bin++) {
+ fastleak -= s->fdecay ;
+ v = bndpsd[bin] - fgain;
+ if (fastleak < v) fastleak = v;
+ slowleak -= s->sdecay ;
+ v = bndpsd[bin] - s->sgain;
+ if (slowleak < v) slowleak = v;
+
+ v=fastleak;
+ if (slowleak > v) v = slowleak;
+ excite[bin] = v;
+ }
+
+ /* compute masking curve */
+
+ for (bin = bndstrt; bin < bndend; bin++) {
+ v1 = excite[bin];
+ tmp = s->dbknee - bndpsd[bin];
+ if (tmp > 0) {
+ v1 += tmp >> 2;
+ }
+ v=hth[bin >> s->halfratecod][s->fscod];
+ if (v1 > v) v=v1;
+ mask[bin] = v;
+ }
+
+ /* compute bit allocation */
+
+ i = start ;
+ j = masktab[start] ;
+ do {
+ v=mask[j];
+ v -= snroffset ;
+ v -= s->floor ;
+ if (v < 0) v = 0;
+ v &= 0x1fe0 ;
+ v += s->floor ;
+
+ end1=bndtab[j] + bndsz[j];
+ if (end1 > end) end1=end;
+
+ for (k = i; k < end1; k++) {
+ address = (psd[i] - v) >> 5 ;
+ if (address < 0) address=0;
+ else if (address > 63) address=63;
+ bap[i] = baptab[address];
+ i++;
+ }
+ } while (end > bndtab[j++]) ;
+}
+
+typedef struct IComplex {
+ short re,im;
+} IComplex;
+
+static void fft_init(int ln)
+{
+ int i, j, m, n;
+ float alpha;
+
+ n = 1 << ln;
+
+ for(i=0;i<(n/2);i++) {
+ alpha = 2 * M_PI * (float)i / (float)n;
+ costab[i] = fix15(cos(alpha));
+ sintab[i] = fix15(sin(alpha));
+ }
+
+ for(i=0;i<n;i++) {
+ m=0;
+ for(j=0;j<ln;j++) {
+ m |= ((i >> j) & 1) << (ln-j-1);
+ }
+ fft_rev[i]=m;
+ }
+}
+
+/* butter fly op */
+#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \
+{\
+ int ax, ay, bx, by;\
+ bx=pre1;\
+ by=pim1;\
+ ax=qre1;\
+ ay=qim1;\
+ pre = (bx + ax) >> 1;\
+ pim = (by + ay) >> 1;\
+ qre = (bx - ax) >> 1;\
+ qim = (by - ay) >> 1;\
+}
+
+#define MUL16(a,b) ((a) * (b))
+
+#define CMUL(pre, pim, are, aim, bre, bim) \
+{\
+ pre = (MUL16(are, bre) - MUL16(aim, bim)) >> 15;\
+ pim = (MUL16(are, bim) + MUL16(bre, aim)) >> 15;\
+}
+
+
+/* do a 2^n point complex fft on 2^ln points. */
+static void fft(IComplex *z, int ln)
+{
+ int j, l, np, np2;
+ int nblocks, nloops;
+ register IComplex *p,*q;
+ int tmp_re, tmp_im;
+
+ np = 1 << ln;
+
+ /* reverse */
+ for(j=0;j<np;j++) {
+ int k;
+ IComplex tmp;
+ k = fft_rev[j];
+ if (k < j) {
+ tmp = z[k];
+ z[k] = z[j];
+ z[j] = tmp;
+ }
+ }
+
+ /* pass 0 */
+
+ p=&z[0];
+ j=(np >> 1);
+ do {
+ BF(p[0].re, p[0].im, p[1].re, p[1].im,
+ p[0].re, p[0].im, p[1].re, p[1].im);
+ p+=2;
+ } while (--j != 0);
+
+ /* pass 1 */
+
+ p=&z[0];
+ j=np >> 2;
+ do {
+ BF(p[0].re, p[0].im, p[2].re, p[2].im,
+ p[0].re, p[0].im, p[2].re, p[2].im);
+ BF(p[1].re, p[1].im, p[3].re, p[3].im,
+ p[1].re, p[1].im, p[3].im, -p[3].re);
+ p+=4;
+ } while (--j != 0);
+
+ /* pass 2 .. ln-1 */
+
+ nblocks = np >> 3;
+ nloops = 1 << 2;
+ np2 = np >> 1;
+ do {
+ p = z;
+ q = z + nloops;
+ for (j = 0; j < nblocks; ++j) {
+
+ BF(p->re, p->im, q->re, q->im,
+ p->re, p->im, q->re, q->im);
+
+ p++;
+ q++;
+ for(l = nblocks; l < np2; l += nblocks) {
+ CMUL(tmp_re, tmp_im, costab[l], -sintab[l], q->re, q->im);
+ BF(p->re, p->im, q->re, q->im,
+ p->re, p->im, tmp_re, tmp_im);
+ p++;
+ q++;
+ }
+ p += nloops;
+ q += nloops;
+ }
+ nblocks = nblocks >> 1;
+ nloops = nloops << 1;
+ } while (nblocks != 0);
+}
+
+/* do a 512 point mdct */
+static void mdct512(INT32 *out, INT16 *in)
+{
+ int i, re, im, re1, im1;
+ INT16 rot[N];
+ IComplex x[N/4];
+
+ /* shift to simplify computations */
+ for(i=0;i<N/4;i++)
+ rot[i] = -in[i + 3*N/4];
+ for(i=N/4;i<N;i++)
+ rot[i] = in[i - N/4];
+
+ /* pre rotation */
+ for(i=0;i<N/4;i++) {
+ re = ((int)rot[2*i] - (int)rot[N-1-2*i]) >> 1;
+ im = -((int)rot[N/2+2*i] - (int)rot[N/2-1-2*i]) >> 1;
+ CMUL(x[i].re, x[i].im, re, im, -xcos1[i], xsin1[i]);
+ }
+
+ fft(x, MDCT_NBITS - 2);
+
+ /* post rotation */
+ for(i=0;i<N/4;i++) {
+ re = x[i].re;
+ im = x[i].im;
+ CMUL(re1, im1, re, im, xsin1[i], xcos1[i]);
+ out[2*i] = im1;
+ out[N/2-1-2*i] = re1;
+ }
+}
+
+/* XXX: use another norm ? */
+static int calc_exp_diff(UINT8 *exp1, UINT8 *exp2, int n)
+{
+ int sum, i;
+ sum = 0;
+ for(i=0;i<n;i++) {
+ sum += abs(exp1[i] - exp2[i]);
+ }
+ return sum;
+}
+
+static void compute_exp_strategy(UINT8 exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS],
+ UINT8 exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ int ch)
+{
+ int i, j;
+ int exp_diff;
+
+ /* estimate if the exponent variation & decide if they should be
+ reused in the next frame */
+ exp_strategy[0][ch] = EXP_NEW;
+ for(i=1;i<NB_BLOCKS;i++) {
+ exp_diff = calc_exp_diff(exp[i][ch], exp[i-1][ch], N/2);
+#ifdef DEBUG
+ printf("exp_diff=%d\n", exp_diff);
+#endif
+ if (exp_diff > EXP_DIFF_THRESHOLD)
+ exp_strategy[i][ch] = EXP_NEW;
+ else
+ exp_strategy[i][ch] = EXP_REUSE;
+ }
+ /* now select the encoding strategy type : if exponents are often
+ recoded, we use a coarse encoding */
+ i = 0;
+ while (i < NB_BLOCKS) {
+ j = i + 1;
+ while (j < NB_BLOCKS && exp_strategy[j][ch] == EXP_REUSE)
+ j++;
+ switch(j - i) {
+ case 1:
+ exp_strategy[i][ch] = EXP_D45;
+ break;
+ case 2:
+ case 3:
+ exp_strategy[i][ch] = EXP_D25;
+ break;
+ default:
+ exp_strategy[i][ch] = EXP_D15;
+ break;
+ }
+ i = j;
+ }
+}
+
+/* set exp[i] to min(exp[i], exp1[i]) */
+static void exponent_min(UINT8 exp[N/2], UINT8 exp1[N/2], int n)
+{
+ int i;
+
+ for(i=0;i<n;i++) {
+ if (exp1[i] < exp[i])
+ exp[i] = exp1[i];
+ }
+}
+
+/* update the exponents so that they are the ones the decoder will
+ decode. Return the number of bits used to code the exponents */
+static int encode_exp(UINT8 encoded_exp[N/2],
+ UINT8 exp[N/2],
+ int nb_exps,
+ int exp_strategy)
+{
+ int group_size, nb_groups, i, j, k, recurse, exp_min, delta;
+ UINT8 exp1[N/2];
+
+ switch(exp_strategy) {
+ case EXP_D15:
+ group_size = 1;
+ break;
+ case EXP_D25:
+ group_size = 2;
+ break;
+ default:
+ case EXP_D45:
+ group_size = 4;
+ break;
+ }
+ nb_groups = ((nb_exps + (group_size * 3) - 4) / (3 * group_size)) * 3;
+
+ /* for each group, compute the minimum exponent */
+ exp1[0] = exp[0]; /* DC exponent is handled separately */
+ k = 1;
+ for(i=1;i<=nb_groups;i++) {
+ exp_min = exp[k];
+ assert(exp_min >= 0 && exp_min <= 24);
+ for(j=1;j<group_size;j++) {
+ if (exp[k+j] < exp_min)
+ exp_min = exp[k+j];
+ }
+ exp1[i] = exp_min;
+ k += group_size;
+ }
+
+ /* constraint for DC exponent */
+ if (exp1[0] > 15)
+ exp1[0] = 15;
+
+ /* Iterate until the delta constraints between each groups are
+ satisfyed. I'm sure it is possible to find a better algorithm,
+ but I am lazy */
+ do {
+ recurse = 0;
+ for(i=1;i<=nb_groups;i++) {
+ delta = exp1[i] - exp1[i-1];
+ if (delta > 2) {
+ /* if delta too big, we encode a smaller exponent */
+ exp1[i] = exp1[i-1] + 2;
+ } else if (delta < -2) {
+ /* if delta is too small, we must decrease the previous
+ exponent, which means we must recurse */
+ recurse = 1;
+ exp1[i-1] = exp1[i] + 2;
+ }
+ }
+ } while (recurse);
+
+ /* now we have the exponent values the decoder will see */
+ encoded_exp[0] = exp1[0];
+ k = 1;
+ for(i=1;i<=nb_groups;i++) {
+ for(j=0;j<group_size;j++) {
+ encoded_exp[k+j] = exp1[i];
+ }
+ k += group_size;
+ }
+
+#if defined(DEBUG)
+ printf("exponents: strategy=%d\n", exp_strategy);
+ for(i=0;i<=nb_groups * group_size;i++) {
+ printf("%d ", encoded_exp[i]);
+ }
+ printf("\n");
+#endif
+
+ return 4 + (nb_groups / 3) * 7;
+}
+
+/* return the size in bits taken by the mantissa */
+int compute_mantissa_size(AC3EncodeContext *s, UINT8 *m, int nb_coefs)
+{
+ int bits, mant, i;
+
+ bits = 0;
+ for(i=0;i<nb_coefs;i++) {
+ mant = m[i];
+ switch(mant) {
+ case 0:
+ /* nothing */
+ break;
+ case 1:
+ /* 3 mantissa in 5 bits */
+ if (s->mant1_cnt == 0)
+ bits += 5;
+ if (++s->mant1_cnt == 3)
+ s->mant1_cnt = 0;
+ break;
+ case 2:
+ /* 3 mantissa in 7 bits */
+ if (s->mant2_cnt == 0)
+ bits += 7;
+ if (++s->mant2_cnt == 3)
+ s->mant2_cnt = 0;
+ break;
+ case 3:
+ bits += 3;
+ break;
+ case 4:
+ /* 2 mantissa in 7 bits */
+ if (s->mant4_cnt == 0)
+ bits += 7;
+ if (++s->mant4_cnt == 2)
+ s->mant4_cnt = 0;
+ break;
+ case 14:
+ bits += 14;
+ break;
+ case 15:
+ bits += 16;
+ break;
+ default:
+ bits += mant - 1;
+ break;
+ }
+ }
+ return bits;
+}
+
+
+static int bit_alloc(AC3EncodeContext *s,
+ UINT8 bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ UINT8 encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ UINT8 exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS],
+ int frame_bits, int csnroffst, int fsnroffst)
+{
+ int i, ch;
+
+ /* compute size */
+ for(i=0;i<NB_BLOCKS;i++) {
+ s->mant1_cnt = 0;
+ s->mant2_cnt = 0;
+ s->mant4_cnt = 0;
+ for(ch=0;ch<s->nb_channels;ch++) {
+ parametric_bit_allocation(s, bap[i][ch], encoded_exp[i][ch],
+ 0, s->nb_coefs[ch],
+ (((csnroffst-15) << 4) +
+ fsnroffst) << 2,
+ fgaintab[s->fgaincod[ch]]);
+ frame_bits += compute_mantissa_size(s, bap[i][ch],
+ s->nb_coefs[ch]);
+ }
+ }
+#if 0
+ printf("csnr=%d fsnr=%d frame_bits=%d diff=%d\n",
+ csnroffst, fsnroffst, frame_bits,
+ 16 * s->frame_size - ((frame_bits + 7) & ~7));
+#endif
+ return 16 * s->frame_size - frame_bits;
+}
+
+#define SNR_INC1 4
+
+static int compute_bit_allocation(AC3EncodeContext *s,
+ UINT8 bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ UINT8 encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
+ UINT8 exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS],
+ int frame_bits)
+{
+ int i, ch;
+ int csnroffst, fsnroffst;
+ UINT8 bap1[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+
+ /* init default parameters */
+ s->sdecaycod = 2;
+ s->fdecaycod = 1;
+ s->sgaincod = 1;
+ s->dbkneecod = 2;
+ s->floorcod = 4;
+ for(ch=0;ch<s->nb_channels;ch++)
+ s->fgaincod[ch] = 4;
+
+ /* compute real values */
+ s->sdecay = sdecaytab[s->sdecaycod] >> s->halfratecod;
+ s->fdecay = fdecaytab[s->fdecaycod] >> s->halfratecod;
+ s->sgain = sgaintab[s->sgaincod];
+ s->dbknee = dbkneetab[s->dbkneecod];
+ s->floor = floortab[s->floorcod];
+
+ /* header size */
+ frame_bits += 65;
+ if (s->acmod == 2)
+ frame_bits += 2;
+
+ /* audio blocks */
+ for(i=0;i<NB_BLOCKS;i++) {
+ frame_bits += s->nb_channels * 2 + 2;
+ if (s->acmod == 2)
+ frame_bits++;
+ frame_bits += 2 * s->nb_channels;
+ for(ch=0;ch<s->nb_channels;ch++) {
+ if (exp_strategy[i][ch] != EXP_REUSE)
+ frame_bits += 6 + 2;
+ }
+ frame_bits++; /* baie */
+ frame_bits++; /* snr */
+ frame_bits += 2; /* delta / skip */
+ }
+ frame_bits++; /* cplinu for block 0 */
+ /* bit alloc info */
+ frame_bits += 2*4 + 3 + 6 + s->nb_channels * (4 + 3);
+
+ /* CRC */
+ frame_bits += 16;
+
+ /* now the big work begins : do the bit allocation. Modify the snr
+ offset until we can pack everything in the requested frame size */
+
+ csnroffst = s->csnroffst;
+ while (csnroffst >= 0 &&
+ bit_alloc(s, bap, encoded_exp, exp_strategy, frame_bits, csnroffst, 0) < 0)
+ csnroffst -= SNR_INC1;
+ if (csnroffst < 0) {
+ fprintf(stderr, "Error !!!\n");
+ return -1;
+ }
+ while ((csnroffst + SNR_INC1) <= 63 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits,
+ csnroffst + SNR_INC1, 0) >= 0) {
+ csnroffst += SNR_INC1;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+ while ((csnroffst + 1) <= 63 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits, csnroffst + 1, 0) >= 0) {
+ csnroffst++;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+
+ fsnroffst = 0;
+ while ((fsnroffst + SNR_INC1) <= 15 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits,
+ csnroffst, fsnroffst + SNR_INC1) >= 0) {
+ fsnroffst += SNR_INC1;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+ while ((fsnroffst + 1) <= 15 &&
+ bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits,
+ csnroffst, fsnroffst + 1) >= 0) {
+ fsnroffst++;
+ memcpy(bap, bap1, sizeof(bap1));
+ }
+
+ s->csnroffst = csnroffst;
+ for(ch=0;ch<s->nb_channels;ch++)
+ s->fsnroffst[ch] = fsnroffst;
+#if defined(DEBUG_BITALLOC)
+ {
+ int j;
+
+ for(i=0;i<6;i++) {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ printf("Block #%d Ch%d:\n", i, ch);
+ printf("bap=");
+ for(j=0;j<s->nb_coefs[ch];j++) {
+ printf("%d ",bap[i][ch][j]);
+ }
+ printf("\n");
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+static int AC3_encode_init(AVCodecContext *avctx)
+{
+ int freq = avctx->sample_rate;
+ int bitrate = avctx->bit_rate;
+ int channels = avctx->channels;
+ AC3EncodeContext *s = avctx->priv_data;
+ int i, j, k, l, ch, v;
+ float alpha;
+ static unsigned short freqs[3] = { 48000, 44100, 32000 };
+
+ avctx->frame_size = AC3_FRAME_SIZE;
+ avctx->key_frame = 1; /* always key frame */
+
+ /* number of channels */
+ if (channels == 1)
+ s->acmod = 1;
+ else if (channels == 2)
+ s->acmod = 2;
+ else
+ return -1;
+ s->nb_channels = channels;
+
+ /* frequency */
+ for(i=0;i<3;i++) {
+ for(j=0;j<3;j++)
+ if ((freqs[j] >> i) == freq)
+ goto found;
+ }
+ return -1;
+ found:
+ s->sample_rate = freq;
+ s->halfratecod = i;
+ s->fscod = j;
+ s->bsid = 8 + s->halfratecod;
+ s->bsmod = 0; /* complete main audio service */
+
+ /* bitrate & frame size */
+ bitrate /= 1000;
+ for(i=0;i<19;i++) {
+ if ((bitratetab[i] >> s->halfratecod) == bitrate)
+ break;
+ }
+ if (i == 19)
+ return -1;
+ s->bit_rate = bitrate;
+ s->frmsizecod = i << 1;
+ s->frame_size_min = (bitrate * 1000 * AC3_FRAME_SIZE) / (freq * 16);
+ /* for now we do not handle fractional sizes */
+ s->frame_size = s->frame_size_min;
+
+ /* bit allocation init */
+ for(ch=0;ch<s->nb_channels;ch++) {
+ /* bandwidth for each channel */
+ /* XXX: should compute the bandwidth according to the frame
+ size, so that we avoid anoying high freq artefacts */
+ s->chbwcod[ch] = 50; /* sample bandwidth as mpeg audio layer 2 table 0 */
+ s->nb_coefs[ch] = ((s->chbwcod[ch] + 12) * 3) + 37;
+ }
+ /* initial snr offset */
+ s->csnroffst = 40;
+
+ /* compute bndtab and masktab from bandsz */
+ k = 0;
+ l = 0;
+ for(i=0;i<50;i++) {
+ bndtab[i] = l;
+ v = bndsz[i];
+ for(j=0;j<v;j++) masktab[k++]=i;
+ l += v;
+ }
+ bndtab[50] = 0;
+
+ /* mdct init */
+ fft_init(MDCT_NBITS - 2);
+ for(i=0;i<N/4;i++) {
+ alpha = 2 * M_PI * (i + 1.0 / 8.0) / (float)N;
+ xcos1[i] = fix15(-cos(alpha));
+ xsin1[i] = fix15(-sin(alpha));
+ }
+
+ ac3_crc_init();
+
+ return 0;
+}
+
+/* output the AC3 frame header */
+static void output_frame_header(AC3EncodeContext *s, unsigned char *frame)
+{
+ init_put_bits(&s->pb, frame, AC3_MAX_CODED_FRAME_SIZE, NULL, NULL);
+
+ put_bits(&s->pb, 16, 0x0b77); /* frame header */
+ put_bits(&s->pb, 16, 0); /* crc1: will be filled later */
+ put_bits(&s->pb, 2, s->fscod);
+ put_bits(&s->pb, 6, s->frmsizecod + (s->frame_size - s->frame_size_min));
+ put_bits(&s->pb, 5, s->bsid);
+ put_bits(&s->pb, 3, s->bsmod);
+ put_bits(&s->pb, 3, s->acmod);
+ if (s->acmod == 2) {
+ put_bits(&s->pb, 2, 0); /* surround not indicated */
+ }
+ put_bits(&s->pb, 1, 0); /* no LFE */
+ put_bits(&s->pb, 5, 31); /* dialog norm: -31 db */
+ put_bits(&s->pb, 1, 0); /* no compression control word */
+ put_bits(&s->pb, 1, 0); /* no lang code */
+ put_bits(&s->pb, 1, 0); /* no audio production info */
+ put_bits(&s->pb, 1, 0); /* no copyright */
+ put_bits(&s->pb, 1, 1); /* original bitstream */
+ put_bits(&s->pb, 1, 0); /* no time code 1 */
+ put_bits(&s->pb, 1, 0); /* no time code 2 */
+ put_bits(&s->pb, 1, 0); /* no addtional bit stream info */
+}
+
+/* symetric quantization on 'levels' levels */
+static inline int sym_quant(int c, int e, int levels)
+{
+ int v;
+
+ if (c >= 0) {
+ v = (levels * (c << e)) >> 25;
+ v = (levels >> 1) + v;
+ } else {
+ v = (levels * ((-c) << e)) >> 25;
+ v = (levels >> 1) - v;
+ }
+ assert (v >= 0 && v < levels);
+ return v;
+}
+
+/* asymetric quantization on 2^qbits levels */
+static inline int asym_quant(int c, int e, int qbits)
+{
+ int lshift, m, v;
+
+ lshift = e + qbits - 24;
+ if (lshift >= 0)
+ v = c << lshift;
+ else
+ v = c >> (-lshift);
+ /* rounding */
+ v = (v + 1) >> 1;
+ m = (1 << (qbits-1));
+ if (v >= m)
+ v = m - 1;
+ assert(v >= -m);
+ return v & ((1 << qbits)-1);
+}
+
+/* Output one audio block. There are NB_BLOCKS audio blocks in one AC3
+ frame */
+static void output_audio_block(AC3EncodeContext *s,
+ UINT8 exp_strategy[AC3_MAX_CHANNELS],
+ UINT8 encoded_exp[AC3_MAX_CHANNELS][N/2],
+ UINT8 bap[AC3_MAX_CHANNELS][N/2],
+ INT32 mdct_coefs[AC3_MAX_CHANNELS][N/2],
+ INT8 global_exp[AC3_MAX_CHANNELS],
+ int block_num)
+{
+ int ch, nb_groups, group_size, i, baie;
+ UINT8 *p;
+ UINT16 qmant[AC3_MAX_CHANNELS][N/2];
+ int exp0, exp1;
+ int mant1_cnt, mant2_cnt, mant4_cnt;
+ UINT16 *qmant1_ptr, *qmant2_ptr, *qmant4_ptr;
+ int delta0, delta1, delta2;
+
+ for(ch=0;ch<s->nb_channels;ch++)
+ put_bits(&s->pb, 1, 0); /* 512 point MDCT */
+ for(ch=0;ch<s->nb_channels;ch++)
+ put_bits(&s->pb, 1, 1); /* no dither */
+ put_bits(&s->pb, 1, 0); /* no dynamic range */
+ if (block_num == 0) {
+ /* for block 0, even if no coupling, we must say it. This is a
+ waste of bit :-) */
+ put_bits(&s->pb, 1, 1); /* coupling strategy present */
+ put_bits(&s->pb, 1, 0); /* no coupling strategy */
+ } else {
+ put_bits(&s->pb, 1, 0); /* no new coupling strategy */
+ }
+
+ if (s->acmod == 2) {
+ put_bits(&s->pb, 1, 0); /* no matrixing (but should be used in the future) */
+ }
+
+#if defined(DEBUG)
+ {
+ static int count = 0;
+ printf("Block #%d (%d)\n", block_num, count++);
+ }
+#endif
+ /* exponent strategy */
+ for(ch=0;ch<s->nb_channels;ch++) {
+ put_bits(&s->pb, 2, exp_strategy[ch]);
+ }
+
+ for(ch=0;ch<s->nb_channels;ch++) {
+ if (exp_strategy[ch] != EXP_REUSE)
+ put_bits(&s->pb, 6, s->chbwcod[ch]);
+ }
+
+ /* exponents */
+ for (ch = 0; ch < s->nb_channels; ch++) {
+ switch(exp_strategy[ch]) {
+ case EXP_REUSE:
+ continue;
+ case EXP_D15:
+ group_size = 1;
+ break;
+ case EXP_D25:
+ group_size = 2;
+ break;
+ default:
+ case EXP_D45:
+ group_size = 4;
+ break;
+ }
+ nb_groups = (s->nb_coefs[ch] + (group_size * 3) - 4) / (3 * group_size);
+ p = encoded_exp[ch];
+
+ /* first exponent */
+ exp1 = *p++;
+ put_bits(&s->pb, 4, exp1);
+
+ /* next ones are delta encoded */
+ for(i=0;i<nb_groups;i++) {
+ /* merge three delta in one code */
+ exp0 = exp1;
+ exp1 = p[0];
+ p += group_size;
+ delta0 = exp1 - exp0 + 2;
+
+ exp0 = exp1;
+ exp1 = p[0];
+ p += group_size;
+ delta1 = exp1 - exp0 + 2;
+
+ exp0 = exp1;
+ exp1 = p[0];
+ p += group_size;
+ delta2 = exp1 - exp0 + 2;
+
+ put_bits(&s->pb, 7, ((delta0 * 5 + delta1) * 5) + delta2);
+ }
+
+ put_bits(&s->pb, 2, 0); /* no gain range info */
+ }
+
+ /* bit allocation info */
+ baie = (block_num == 0);
+ put_bits(&s->pb, 1, baie);
+ if (baie) {
+ put_bits(&s->pb, 2, s->sdecaycod);
+ put_bits(&s->pb, 2, s->fdecaycod);
+ put_bits(&s->pb, 2, s->sgaincod);
+ put_bits(&s->pb, 2, s->dbkneecod);
+ put_bits(&s->pb, 3, s->floorcod);
+ }
+
+ /* snr offset */
+ put_bits(&s->pb, 1, baie); /* always present with bai */
+ if (baie) {
+ put_bits(&s->pb, 6, s->csnroffst);
+ for(ch=0;ch<s->nb_channels;ch++) {
+ put_bits(&s->pb, 4, s->fsnroffst[ch]);
+ put_bits(&s->pb, 3, s->fgaincod[ch]);
+ }
+ }
+
+ put_bits(&s->pb, 1, 0); /* no delta bit allocation */
+ put_bits(&s->pb, 1, 0); /* no data to skip */
+
+ /* mantissa encoding : we use two passes to handle the grouping. A
+ one pass method may be faster, but it would necessitate to
+ modify the output stream. */
+
+ /* first pass: quantize */
+ mant1_cnt = mant2_cnt = mant4_cnt = 0;
+ qmant1_ptr = qmant2_ptr = qmant4_ptr = NULL;
+
+ for (ch = 0; ch < s->nb_channels; ch++) {
+ int b, c, e, v;
+
+ for(i=0;i<s->nb_coefs[ch];i++) {
+ c = mdct_coefs[ch][i];
+ e = encoded_exp[ch][i] - global_exp[ch];
+ b = bap[ch][i];
+ switch(b) {
+ case 0:
+ v = 0;
+ break;
+ case 1:
+ v = sym_quant(c, e, 3);
+ switch(mant1_cnt) {
+ case 0:
+ qmant1_ptr = &qmant[ch][i];
+ v = 9 * v;
+ mant1_cnt = 1;
+ break;
+ case 1:
+ *qmant1_ptr += 3 * v;
+ mant1_cnt = 2;
+ v = 128;
+ break;
+ default:
+ *qmant1_ptr += v;
+ mant1_cnt = 0;
+ v = 128;
+ break;
+ }
+ break;
+ case 2:
+ v = sym_quant(c, e, 5);
+ switch(mant2_cnt) {
+ case 0:
+ qmant2_ptr = &qmant[ch][i];
+ v = 25 * v;
+ mant2_cnt = 1;
+ break;
+ case 1:
+ *qmant2_ptr += 5 * v;
+ mant2_cnt = 2;
+ v = 128;
+ break;
+ default:
+ *qmant2_ptr += v;
+ mant2_cnt = 0;
+ v = 128;
+ break;
+ }
+ break;
+ case 3:
+ v = sym_quant(c, e, 7);
+ break;
+ case 4:
+ v = sym_quant(c, e, 11);
+ switch(mant4_cnt) {
+ case 0:
+ qmant4_ptr = &qmant[ch][i];
+ v = 11 * v;
+ mant4_cnt = 1;
+ break;
+ default:
+ *qmant4_ptr += v;
+ mant4_cnt = 0;
+ v = 128;
+ break;
+ }
+ break;
+ case 5:
+ v = sym_quant(c, e, 15);
+ break;
+ case 14:
+ v = asym_quant(c, e, 14);
+ break;
+ case 15:
+ v = asym_quant(c, e, 16);
+ break;
+ default:
+ v = asym_quant(c, e, b - 1);
+ break;
+ }
+ qmant[ch][i] = v;
+ }
+ }
+
+ /* second pass : output the values */
+ for (ch = 0; ch < s->nb_channels; ch++) {
+ int b, q;
+
+ for(i=0;i<s->nb_coefs[ch];i++) {
+ q = qmant[ch][i];
+ b = bap[ch][i];
+ switch(b) {
+ case 0:
+ break;
+ case 1:
+ if (q != 128)
+ put_bits(&s->pb, 5, q);
+ break;
+ case 2:
+ if (q != 128)
+ put_bits(&s->pb, 7, q);
+ break;
+ case 3:
+ put_bits(&s->pb, 3, q);
+ break;
+ case 4:
+ if (q != 128)
+ put_bits(&s->pb, 7, q);
+ break;
+ case 14:
+ put_bits(&s->pb, 14, q);
+ break;
+ case 15:
+ put_bits(&s->pb, 16, q);
+ break;
+ default:
+ put_bits(&s->pb, b - 1, q);
+ break;
+ }
+ }
+ }
+}
+
+/* compute the ac3 crc */
+
+#define CRC16_POLY ((1 << 0) | (1 << 2) | (1 << 15) | (1 << 16))
+
+static void ac3_crc_init(void)
+{
+ unsigned int c, n, k;
+
+ for(n=0;n<256;n++) {
+ c = n << 8;
+ for (k = 0; k < 8; k++) {
+ if (c & (1 << 15))
+ c = ((c << 1) & 0xffff) ^ (CRC16_POLY & 0xffff);
+ else
+ c = c << 1;
+ }
+ crc_table[n] = c;
+ }
+}
+
+static unsigned int ac3_crc(UINT8 *data, int n, unsigned int crc)
+{
+ int i;
+ for(i=0;i<n;i++) {
+ crc = (crc_table[data[i] ^ (crc >> 8)] ^ (crc << 8)) & 0xffff;
+ }
+ return crc;
+}
+
+static unsigned int mul_poly(unsigned int a, unsigned int b, unsigned int poly)
+{
+ unsigned int c;
+
+ c = 0;
+ while (a) {
+ if (a & 1)
+ c ^= b;
+ a = a >> 1;
+ b = b << 1;
+ if (b & (1 << 16))
+ b ^= poly;
+ }
+ return c;
+}
+
+static unsigned int pow_poly(unsigned int a, unsigned int n, unsigned int poly)
+{
+ unsigned int r;
+ r = 1;
+ while (n) {
+ if (n & 1)
+ r = mul_poly(r, a, poly);
+ a = mul_poly(a, a, poly);
+ n >>= 1;
+ }
+ return r;
+}
+
+
+/* compute log2(max(abs(tab[]))) */
+static int log2_tab(INT16 *tab, int n)
+{
+ int i, v;
+
+ v = 0;
+ for(i=0;i<n;i++) {
+ v |= abs(tab[i]);
+ }
+ return log2(v);
+}
+
+static void lshift_tab(INT16 *tab, int n, int lshift)
+{
+ int i;
+
+ if (lshift > 0) {
+ for(i=0;i<n;i++) {
+ tab[i] <<= lshift;
+ }
+ } else if (lshift < 0) {
+ lshift = -lshift;
+ for(i=0;i<n;i++) {
+ tab[i] >>= lshift;
+ }
+ }
+}
+
+/* fill the end of the frame and compute the two crcs */
+static int output_frame_end(AC3EncodeContext *s)
+{
+ int frame_size, frame_size_58, n, crc1, crc2, crc_inv;
+ UINT8 *frame;
+
+ frame_size = s->frame_size; /* frame size in words */
+ /* align to 8 bits */
+ flush_put_bits(&s->pb);
+ /* add zero bytes to reach the frame size */
+ frame = s->pb.buf;
+ n = 2 * s->frame_size - (s->pb.buf_ptr - frame) - 2;
+ assert(n >= 0);
+ memset(s->pb.buf_ptr, 0, n);
+
+ /* Now we must compute both crcs : this is not so easy for crc1
+ because it is at the beginning of the data... */
+ frame_size_58 = (frame_size >> 1) + (frame_size >> 3);
+ crc1 = ac3_crc(frame + 4, (2 * frame_size_58) - 4, 0);
+ /* XXX: could precompute crc_inv */
+ crc_inv = pow_poly((CRC16_POLY >> 1), (16 * frame_size_58) - 16, CRC16_POLY);
+ crc1 = mul_poly(crc_inv, crc1, CRC16_POLY);
+ frame[2] = crc1 >> 8;
+ frame[3] = crc1;
+
+ crc2 = ac3_crc(frame + 2 * frame_size_58, (frame_size - frame_size_58) * 2 - 2, 0);
+ frame[2*frame_size - 2] = crc2 >> 8;
+ frame[2*frame_size - 1] = crc2;
+
+ // printf("n=%d frame_size=%d\n", n, frame_size);
+ return frame_size * 2;
+}
+
+int AC3_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ AC3EncodeContext *s = avctx->priv_data;
+ short *samples = data;
+ int i, j, k, v, ch;
+ INT16 input_samples[N];
+ INT32 mdct_coef[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ UINT8 exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ UINT8 exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS];
+ UINT8 encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ UINT8 bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
+ INT8 exp_samples[NB_BLOCKS][AC3_MAX_CHANNELS];
+ int frame_bits;
+
+ frame_bits = 0;
+ for(ch=0;ch<s->nb_channels;ch++) {
+ /* fixed mdct to the six sub blocks & exponent computation */
+ for(i=0;i<NB_BLOCKS;i++) {
+ INT16 *sptr;
+ int sinc;
+
+ /* compute input samples */
+ memcpy(input_samples, s->last_samples[ch], N/2 * sizeof(INT16));
+ sinc = s->nb_channels;
+ sptr = samples + (sinc * (N/2) * i) + ch;
+ for(j=0;j<N/2;j++) {
+ v = *sptr;
+ input_samples[j + N/2] = v;
+ s->last_samples[ch][j] = v;
+ sptr += sinc;
+ }
+
+ /* apply the MDCT window */
+ for(j=0;j<N/2;j++) {
+ input_samples[j] = MUL16(input_samples[j],
+ ac3_window[j]) >> 15;
+ input_samples[N-j-1] = MUL16(input_samples[N-j-1],
+ ac3_window[j]) >> 15;
+ }
+
+ /* Normalize the samples to use the maximum available
+ precision */
+ v = 14 - log2_tab(input_samples, N);
+ if (v < 0)
+ v = 0;
+ exp_samples[i][ch] = v - 8;
+ lshift_tab(input_samples, N, v);
+
+ /* do the MDCT */
+ mdct512(mdct_coef[i][ch], input_samples);
+
+ /* compute "exponents". We take into account the
+ normalization there */
+ for(j=0;j<N/2;j++) {
+ int e;
+ v = abs(mdct_coef[i][ch][j]);
+ if (v == 0)
+ e = 24;
+ else {
+ e = 23 - log2(v) + exp_samples[i][ch];
+ if (e >= 24) {
+ e = 24;
+ mdct_coef[i][ch][j] = 0;
+ }
+ }
+ exp[i][ch][j] = e;
+ }
+ }
+
+ compute_exp_strategy(exp_strategy, exp, ch);
+
+ /* compute the exponents as the decoder will see them. The
+ EXP_REUSE case must be handled carefully : we select the
+ min of the exponents */
+ i = 0;
+ while (i < NB_BLOCKS) {
+ j = i + 1;
+ while (j < NB_BLOCKS && exp_strategy[j][ch] == EXP_REUSE) {
+ exponent_min(exp[i][ch], exp[j][ch], s->nb_coefs[ch]);
+ j++;
+ }
+ frame_bits += encode_exp(encoded_exp[i][ch],
+ exp[i][ch], s->nb_coefs[ch],
+ exp_strategy[i][ch]);
+ /* copy encoded exponents for reuse case */
+ for(k=i+1;k<j;k++) {
+ memcpy(encoded_exp[k][ch], encoded_exp[i][ch],
+ s->nb_coefs[ch] * sizeof(UINT8));
+ }
+ i = j;
+ }
+ }
+
+ compute_bit_allocation(s, bap, encoded_exp, exp_strategy, frame_bits);
+ /* everything is known... let's output the frame */
+ output_frame_header(s, frame);
+
+ for(i=0;i<NB_BLOCKS;i++) {
+ output_audio_block(s, exp_strategy[i], encoded_exp[i],
+ bap[i], mdct_coef[i], exp_samples[i], i);
+ }
+ return output_frame_end(s);
+}
+
+#if 0
+/*************************************************************************/
+/* TEST */
+
+#define FN (N/4)
+
+void fft_test(void)
+{
+ IComplex in[FN], in1[FN];
+ int k, n, i;
+ float sum_re, sum_im, a;
+
+ /* FFT test */
+
+ for(i=0;i<FN;i++) {
+ in[i].re = random() % 65535 - 32767;
+ in[i].im = random() % 65535 - 32767;
+ in1[i] = in[i];
+ }
+ fft(in, 7);
+
+ /* do it by hand */
+ for(k=0;k<FN;k++) {
+ sum_re = 0;
+ sum_im = 0;
+ for(n=0;n<FN;n++) {
+ a = -2 * M_PI * (n * k) / FN;
+ sum_re += in1[n].re * cos(a) - in1[n].im * sin(a);
+ sum_im += in1[n].re * sin(a) + in1[n].im * cos(a);
+ }
+ printf("%3d: %6d,%6d %6.0f,%6.0f\n",
+ k, in[k].re, in[k].im, sum_re / FN, sum_im / FN);
+ }
+}
+
+void mdct_test(void)
+{
+ INT16 input[N];
+ INT32 output[N/2];
+ float input1[N];
+ float output1[N/2];
+ float s, a, err, e, emax;
+ int i, k, n;
+
+ for(i=0;i<N;i++) {
+ input[i] = (random() % 65535 - 32767) * 9 / 10;
+ input1[i] = input[i];
+ }
+
+ mdct512(output, input);
+
+ /* do it by hand */
+ for(k=0;k<N/2;k++) {
+ s = 0;
+ for(n=0;n<N;n++) {
+ a = (2*M_PI*(2*n+1+N/2)*(2*k+1) / (4 * N));
+ s += input1[n] * cos(a);
+ }
+ output1[k] = -2 * s / N;
+ }
+
+ err = 0;
+ emax = 0;
+ for(i=0;i<N/2;i++) {
+ printf("%3d: %7d %7.0f\n", i, output[i], output1[i]);
+ e = output[i] - output1[i];
+ if (e > emax)
+ emax = e;
+ err += e * e;
+ }
+ printf("err2=%f emax=%f\n", err / (N/2), emax);
+}
+
+void test_ac3(void)
+{
+ AC3EncodeContext ctx;
+ unsigned char frame[AC3_MAX_CODED_FRAME_SIZE];
+ short samples[AC3_FRAME_SIZE];
+ int ret, i;
+
+ AC3_encode_init(&ctx, 44100, 64000, 1);
+
+ fft_test();
+ mdct_test();
+
+ for(i=0;i<AC3_FRAME_SIZE;i++)
+ samples[i] = (int)(sin(2*M_PI*i*1000.0/44100) * 10000);
+ ret = AC3_encode_frame(&ctx, frame, samples);
+ printf("ret=%d\n", ret);
+}
+#endif
+
+AVCodec ac3_encoder = {
+ "ac3",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_AC3,
+ sizeof(AC3EncodeContext),
+ AC3_encode_init,
+ AC3_encode_frame,
+ NULL,
+};
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
new file mode 100644
index 0000000000..40cc53aced
--- /dev/null
+++ b/libavcodec/ac3enc.h
@@ -0,0 +1,32 @@
+
+#define AC3_FRAME_SIZE (6*256)
+#define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */
+#define AC3_MAX_CHANNELS 2 /* we handle at most two channels, although
+ AC3 allows 6 channels */
+
+typedef struct AC3EncodeContext {
+ PutBitContext pb;
+ int nb_channels;
+ int bit_rate;
+ int sample_rate;
+ int bsid;
+ int frame_size_min; /* minimum frame size in case rounding is necessary */
+ int frame_size; /* current frame size in words */
+ int halfratecod;
+ int frmsizecod;
+ int fscod; /* frequency */
+ int acmod;
+ int bsmod;
+ short last_samples[AC3_MAX_CHANNELS][256];
+ int chbwcod[AC3_MAX_CHANNELS];
+ int nb_coefs[AC3_MAX_CHANNELS];
+
+ /* bitrate allocation control */
+ int sgaincod, sdecaycod, fdecaycod, dbkneecod, floorcod;
+ int sgain, sdecay, fdecay, dbknee, floor;
+ int csnroffst;
+ int fgaincod[AC3_MAX_CHANNELS];
+ int fsnroffst[AC3_MAX_CHANNELS];
+ /* mantissa encoding */
+ int mant1_cnt, mant2_cnt, mant4_cnt;
+} AC3EncodeContext;
diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h
new file mode 100644
index 0000000000..2d379f0404
--- /dev/null
+++ b/libavcodec/ac3tab.h
@@ -0,0 +1,180 @@
+/* tables taken directly from AC3 spec */
+
+/* possible bitrates */
+static const UINT16 bitratetab[19] = {
+ 32, 40, 48, 56, 64, 80, 96, 112, 128,
+ 160, 192, 224, 256, 320, 384, 448, 512, 576, 640
+};
+
+/* AC3 MDCT window */
+
+/* MDCT window */
+static const INT16 ac3_window[256]= {
+ 4, 7, 12, 16, 21, 28, 34, 42,
+ 51, 61, 72, 84, 97, 111, 127, 145,
+ 164, 184, 207, 231, 257, 285, 315, 347,
+ 382, 419, 458, 500, 544, 591, 641, 694,
+ 750, 810, 872, 937, 1007, 1079, 1155, 1235,
+ 1318, 1406, 1497, 1593, 1692, 1796, 1903, 2016,
+ 2132, 2253, 2379, 2509, 2644, 2783, 2927, 3076,
+ 3230, 3389, 3552, 3721, 3894, 4072, 4255, 4444,
+ 4637, 4835, 5038, 5246, 5459, 5677, 5899, 6127,
+ 6359, 6596, 6837, 7083, 7334, 7589, 7848, 8112,
+ 8380, 8652, 8927, 9207, 9491, 9778,10069,10363,
+10660,10960,11264,11570,11879,12190,12504,12820,
+13138,13458,13780,14103,14427,14753,15079,15407,
+15735,16063,16392,16720,17049,17377,17705,18032,
+18358,18683,19007,19330,19651,19970,20287,20602,
+20914,21225,21532,21837,22139,22438,22733,23025,
+23314,23599,23880,24157,24430,24699,24964,25225,
+25481,25732,25979,26221,26459,26691,26919,27142,
+27359,27572,27780,27983,28180,28373,28560,28742,
+28919,29091,29258,29420,29577,29729,29876,30018,
+30155,30288,30415,30538,30657,30771,30880,30985,
+31086,31182,31274,31363,31447,31528,31605,31678,
+31747,31814,31877,31936,31993,32046,32097,32145,
+32190,32232,32272,32310,32345,32378,32409,32438,
+32465,32490,32513,32535,32556,32574,32592,32608,
+32623,32636,32649,32661,32671,32681,32690,32698,
+32705,32712,32718,32724,32729,32733,32737,32741,
+32744,32747,32750,32752,32754,32756,32757,32759,
+32760,32761,32762,32763,32764,32764,32765,32765,
+32766,32766,32766,32766,32767,32767,32767,32767,
+32767,32767,32767,32767,32767,32767,32767,32767,
+32767,32767,32767,32767,32767,32767,32767,32767,
+};
+
+static UINT8 masktab[253];
+
+static const UINT8 latab[260]= {
+0x0040,0x003f,0x003e,0x003d,0x003c,0x003b,0x003a,0x0039,0x0038,0x0037,
+0x0036,0x0035,0x0034,0x0034,0x0033,0x0032,0x0031,0x0030,0x002f,0x002f,
+0x002e,0x002d,0x002c,0x002c,0x002b,0x002a,0x0029,0x0029,0x0028,0x0027,
+0x0026,0x0026,0x0025,0x0024,0x0024,0x0023,0x0023,0x0022,0x0021,0x0021,
+0x0020,0x0020,0x001f,0x001e,0x001e,0x001d,0x001d,0x001c,0x001c,0x001b,
+0x001b,0x001a,0x001a,0x0019,0x0019,0x0018,0x0018,0x0017,0x0017,0x0016,
+0x0016,0x0015,0x0015,0x0015,0x0014,0x0014,0x0013,0x0013,0x0013,0x0012,
+0x0012,0x0012,0x0011,0x0011,0x0011,0x0010,0x0010,0x0010,0x000f,0x000f,
+0x000f,0x000e,0x000e,0x000e,0x000d,0x000d,0x000d,0x000d,0x000c,0x000c,
+0x000c,0x000c,0x000b,0x000b,0x000b,0x000b,0x000a,0x000a,0x000a,0x000a,
+0x000a,0x0009,0x0009,0x0009,0x0009,0x0009,0x0008,0x0008,0x0008,0x0008,
+0x0008,0x0008,0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,0x0006,0x0006,
+0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0005,0x0005,0x0005,0x0005,
+0x0005,0x0005,0x0005,0x0005,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,
+0x0004,0x0004,0x0004,0x0004,0x0004,0x0003,0x0003,0x0003,0x0003,0x0003,
+0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0002,
+0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0001,0x0001,
+0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
+0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
+0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+};
+
+static const UINT16 hth[50][3]= {
+{ 0x04d0,0x04f0,0x0580 },
+{ 0x04d0,0x04f0,0x0580 },
+{ 0x0440,0x0460,0x04b0 },
+{ 0x0400,0x0410,0x0450 },
+{ 0x03e0,0x03e0,0x0420 },
+{ 0x03c0,0x03d0,0x03f0 },
+{ 0x03b0,0x03c0,0x03e0 },
+{ 0x03b0,0x03b0,0x03d0 },
+{ 0x03a0,0x03b0,0x03c0 },
+{ 0x03a0,0x03a0,0x03b0 },
+{ 0x03a0,0x03a0,0x03b0 },
+{ 0x03a0,0x03a0,0x03b0 },
+{ 0x03a0,0x03a0,0x03a0 },
+{ 0x0390,0x03a0,0x03a0 },
+{ 0x0390,0x0390,0x03a0 },
+{ 0x0390,0x0390,0x03a0 },
+{ 0x0380,0x0390,0x03a0 },
+{ 0x0380,0x0380,0x03a0 },
+{ 0x0370,0x0380,0x03a0 },
+{ 0x0370,0x0380,0x03a0 },
+{ 0x0360,0x0370,0x0390 },
+{ 0x0360,0x0370,0x0390 },
+{ 0x0350,0x0360,0x0390 },
+{ 0x0350,0x0360,0x0390 },
+{ 0x0340,0x0350,0x0380 },
+{ 0x0340,0x0350,0x0380 },
+{ 0x0330,0x0340,0x0380 },
+{ 0x0320,0x0340,0x0370 },
+{ 0x0310,0x0320,0x0360 },
+{ 0x0300,0x0310,0x0350 },
+{ 0x02f0,0x0300,0x0340 },
+{ 0x02f0,0x02f0,0x0330 },
+{ 0x02f0,0x02f0,0x0320 },
+{ 0x02f0,0x02f0,0x0310 },
+{ 0x0300,0x02f0,0x0300 },
+{ 0x0310,0x0300,0x02f0 },
+{ 0x0340,0x0320,0x02f0 },
+{ 0x0390,0x0350,0x02f0 },
+{ 0x03e0,0x0390,0x0300 },
+{ 0x0420,0x03e0,0x0310 },
+{ 0x0460,0x0420,0x0330 },
+{ 0x0490,0x0450,0x0350 },
+{ 0x04a0,0x04a0,0x03c0 },
+{ 0x0460,0x0490,0x0410 },
+{ 0x0440,0x0460,0x0470 },
+{ 0x0440,0x0440,0x04a0 },
+{ 0x0520,0x0480,0x0460 },
+{ 0x0800,0x0630,0x0440 },
+{ 0x0840,0x0840,0x0450 },
+{ 0x0840,0x0840,0x04e0 },
+};
+
+static const UINT8 baptab[64]= {
+ 0, 1, 1, 1, 1, 1, 2, 2, 3, 3,
+ 3, 4, 4, 5, 5, 6, 6, 6, 6, 7,
+ 7, 7, 7, 8, 8, 8, 8, 9, 9, 9,
+ 9, 10, 10, 10, 10, 11, 11, 11, 11, 12,
+ 12, 12, 12, 13, 13, 13, 13, 14, 14, 14,
+ 14, 14, 14, 14, 14, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15,
+};
+
+static const UINT8 sdecaytab[4]={
+ 0x0f, 0x11, 0x13, 0x15,
+};
+
+static const UINT8 fdecaytab[4]={
+ 0x3f, 0x53, 0x67, 0x7b,
+};
+
+static const UINT16 sgaintab[4]= {
+ 0x540, 0x4d8, 0x478, 0x410,
+};
+
+static const UINT16 dbkneetab[4]= {
+ 0x000, 0x700, 0x900, 0xb00,
+};
+
+static const UINT16 floortab[8]= {
+ 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800,
+};
+
+static const UINT16 fgaintab[8]= {
+ 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400,
+};
+
+static const UINT8 bndsz[50]={
+ 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, 3, 3, 3, 3, 3, 3,
+ 3, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 24, 24, 24, 24, 24
+};
+
+static UINT8 bndtab[51];
+
+/* fft & mdct sin cos tables */
+static INT16 costab[64];
+static INT16 sintab[64];
+static INT16 fft_rev[512];
+static INT16 xcos1[128];
+static INT16 xsin1[128];
+
+static UINT16 crc_table[256];
diff --git a/libavcodec/apiexample.c b/libavcodec/apiexample.c
new file mode 100644
index 0000000000..e7ae6e80be
--- /dev/null
+++ b/libavcodec/apiexample.c
@@ -0,0 +1,407 @@
+/* avcodec API use example.
+ *
+ * Note that this library only handles codecs (mpeg, mpeg4, etc...),
+ * not file formats (avi, vob, etc...). See library 'libav' for the
+ * format handling
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "avcodec.h"
+
+#define INBUF_SIZE 4096
+
+/*
+ * Audio encoding example
+ */
+void audio_encode_example(const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext codec_context, *c = &codec_context;
+ int frame_size, i, j, out_size, outbuf_size;
+ FILE *f;
+ short *samples;
+ float t, tincr;
+ UINT8 *outbuf;
+
+ printf("Audio encoding\n");
+
+ /* find the MP2 encoder */
+ codec = avcodec_find_encoder(CODEC_ID_MP2);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ /* put default values */
+ memset(c, 0, sizeof(*c));
+
+ /* put sample parameters */
+ c->bit_rate = 64000;
+ c->sample_rate = 44100;
+ c->channels = 2;
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ /* the codec gives us the frame size, in samples */
+ frame_size = c->frame_size;
+ samples = malloc(frame_size * 2 * c->channels);
+ outbuf_size = 10000;
+ outbuf = malloc(outbuf_size);
+
+ f = fopen(filename, "w");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+
+ /* encode a single tone sound */
+ t = 0;
+ tincr = 2 * M_PI * 440.0 / c->sample_rate;
+ for(i=0;i<200;i++) {
+ for(j=0;j<frame_size;j++) {
+ samples[2*j] = (int)(sin(t) * 10000);
+ samples[2*j+1] = samples[2*j];
+ t += tincr;
+ }
+ /* encode the samples */
+ out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples);
+ fwrite(outbuf, 1, out_size, f);
+ }
+ fclose(f);
+ free(outbuf);
+ free(samples);
+
+ avcodec_close(c);
+}
+
+/*
+ * Audio decoding.
+ */
+void audio_decode_example(const char *outfilename, const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext codec_context, *c = &codec_context;
+ int out_size, size, len;
+ FILE *f, *outfile;
+ UINT8 *outbuf;
+ UINT8 inbuf[INBUF_SIZE], *inbuf_ptr;
+
+ printf("Audio decoding\n");
+
+ /* find the mpeg audio decoder */
+ codec = avcodec_find_decoder(CODEC_ID_MP2);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ /* put default values */
+ memset(c, 0, sizeof(*c));
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
+
+ f = fopen(filename, "r");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+ outfile = fopen(outfilename, "w");
+ if (!outfile) {
+ fprintf(stderr, "could not open %s\n", outfilename);
+ exit(1);
+ }
+
+ /* decode until eof */
+ inbuf_ptr = inbuf;
+ for(;;) {
+ size = fread(inbuf, 1, INBUF_SIZE, f);
+ if (size == 0)
+ break;
+
+ inbuf_ptr = inbuf;
+ while (size > 0) {
+ len = avcodec_decode_audio(c, (short *)outbuf, &out_size,
+ inbuf_ptr, size);
+ if (len < 0) {
+ fprintf(stderr, "Error while decoding\n");
+ exit(1);
+ }
+ if (out_size > 0) {
+ /* if a frame has been decoded, output it */
+ fwrite(outbuf, 1, out_size, outfile);
+ }
+ size -= len;
+ inbuf_ptr += len;
+ }
+ }
+
+ fclose(outfile);
+ fclose(f);
+ free(outbuf);
+
+ avcodec_close(c);
+}
+
+/*
+ * Video encoding example
+ */
+void video_encode_example(const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext codec_context, *c = &codec_context;
+ int i, out_size, size, x, y, outbuf_size;
+ FILE *f;
+ AVPicture picture;
+ UINT8 *outbuf, *picture_buf;
+
+ printf("Video encoding\n");
+
+ /* find the mpeg1 video encoder */
+ codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ /* put default values */
+ memset(c, 0, sizeof(*c));
+
+ /* put sample parameters */
+ c->bit_rate = 400000;
+ /* resolution must be a multiple of two */
+ c->width = 352;
+ c->height = 288;
+ /* frames per second */
+ c->frame_rate = 25 * FRAME_RATE_BASE;
+ c->gop_size = 10; /* emit one intra frame every ten frames */
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ /* the codec gives us the frame size, in samples */
+
+ f = fopen(filename, "w");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+
+ /* alloc image and output buffer */
+ outbuf_size = 100000;
+ outbuf = malloc(outbuf_size);
+ size = c->width * c->height;
+ picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */
+
+ picture.data[0] = picture_buf;
+ picture.data[1] = picture.data[0] + size;
+ picture.data[2] = picture.data[1] + size / 4;
+ picture.linesize[0] = c->width;
+ picture.linesize[1] = c->width / 2;
+ picture.linesize[2] = c->width / 2;
+
+ /* encode 1 second of video */
+ for(i=0;i<25;i++) {
+ printf("encoding frame %3d\r", i);
+ fflush(stdout);
+ /* prepare a dummy image */
+ /* Y */
+ for(y=0;y<c->height;y++) {
+ for(x=0;x<c->width;x++) {
+ picture.data[0][y * picture.linesize[0] + x] = x + y + i * 3;
+ }
+ }
+
+ /* Cb and Cr */
+ for(y=0;y<c->height/2;y++) {
+ for(x=0;x<c->width/2;x++) {
+ picture.data[1][y * picture.linesize[1] + x] = 128 + y + i * 2;
+ picture.data[2][y * picture.linesize[2] + x] = 64 + x + i * 5;
+ }
+ }
+
+ /* encode the image */
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, &picture);
+ fwrite(outbuf, 1, out_size, f);
+ }
+
+ /* add sequence end code to have a real mpeg file */
+ outbuf[0] = 0x00;
+ outbuf[1] = 0x00;
+ outbuf[2] = 0x01;
+ outbuf[3] = 0xb7;
+ fwrite(outbuf, 1, 4, f);
+ fclose(f);
+ free(picture_buf);
+ free(outbuf);
+
+ avcodec_close(c);
+ printf("\n");
+}
+
+/*
+ * Video decoding example
+ */
+
+void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
+{
+ FILE *f;
+ int i;
+
+ f=fopen(filename,"w");
+ fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
+ for(i=0;i<ysize;i++)
+ fwrite(buf + i * wrap,1,xsize,f);
+ fclose(f);
+}
+
+void video_decode_example(const char *outfilename, const char *filename)
+{
+ AVCodec *codec;
+ AVCodecContext codec_context, *c = &codec_context;
+ int frame, size, got_picture, len;
+ FILE *f;
+ AVPicture picture;
+ UINT8 inbuf[INBUF_SIZE], *inbuf_ptr;
+ char buf[1024];
+
+ printf("Video decoding\n");
+
+ /* find the mpeg1 video decoder */
+ codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO);
+ if (!codec) {
+ fprintf(stderr, "codec not found\n");
+ exit(1);
+ }
+
+ /* put default values */
+ memset(c, 0, sizeof(*c));
+
+ /* for some codecs, such as msmpeg4 and opendivx, width and height
+ MUST be initialized there because these info are not available
+ in the bitstream */
+
+ /* open it */
+ if (avcodec_open(c, codec) < 0) {
+ fprintf(stderr, "could not open codec\n");
+ exit(1);
+ }
+
+ /* the codec gives us the frame size, in samples */
+
+ f = fopen(filename, "r");
+ if (!f) {
+ fprintf(stderr, "could not open %s\n", filename);
+ exit(1);
+ }
+
+ frame = 0;
+ for(;;) {
+ size = fread(inbuf, 1, INBUF_SIZE, f);
+ if (size == 0)
+ break;
+
+ /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
+ and this is the only method to use them because you cannot
+ know the compressed data size before analysing it.
+
+ BUT some other codecs (msmpeg4, opendivx) are inherently
+ frame based, so you must call them with all the data for
+ one frame exactly. You must also initialize 'width' and
+ 'height' before initializing them. */
+
+ /* NOTE2: some codecs allow the raw parameters (frame size,
+ sample rate) to be changed at any frame. We handle this, so
+ you should also take care of it */
+
+ /* here, we use a stream based decoder (mpeg1video), so we
+ feed decoder and see if it could decode a frame */
+ inbuf_ptr = inbuf;
+ while (size > 0) {
+ len = avcodec_decode_video(c, &picture, &got_picture,
+ inbuf_ptr, size);
+ if (len < 0) {
+ fprintf(stderr, "Error while decoding frame %d\n", frame);
+ exit(1);
+ }
+ if (got_picture) {
+ printf("saving frame %3d\r", frame);
+ fflush(stdout);
+
+ /* the picture is allocated by the decoder. no need to
+ free it */
+ snprintf(buf, sizeof(buf), outfilename, frame);
+ pgm_save(picture.data[0], picture.linesize[0],
+ c->width, c->height, buf);
+ frame++;
+ }
+ size -= len;
+ inbuf_ptr += len;
+ }
+ }
+
+ /* some codecs, such as MPEG, transmit the I and P frame with a
+ latency of one frame. You must do the following to have a
+ chance to get the last frame of the video */
+ len = avcodec_decode_video(c, &picture, &got_picture,
+ NULL, 0);
+ if (got_picture) {
+ printf("saving frame %3d\r", frame);
+ fflush(stdout);
+
+ /* the picture is allocated by the decoder. no need to
+ free it */
+ snprintf(buf, sizeof(buf), outfilename, frame);
+ pgm_save(picture.data[0], picture.linesize[0],
+ c->width, c->height, buf);
+ frame++;
+ }
+
+ fclose(f);
+
+ avcodec_close(c);
+ printf("\n");
+}
+
+
+int main(int argc, char **argv)
+{
+ const char *filename;
+
+ /* must be called before using avcodec lib */
+ avcodec_init();
+
+ /* register all the codecs (you can also register only the codec
+ you wish to have smaller code */
+ avcodec_register_all();
+
+ if (argc <= 1) {
+ audio_encode_example("/tmp/test.mp2");
+ audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
+
+ video_encode_example("/tmp/test.mpg");
+ filename = "/tmp/test.mpg";
+ } else {
+ filename = argv[1];
+ }
+
+ // audio_decode_example("/tmp/test.sw", filename);
+ video_decode_example("/tmp/test%d.pgm", filename);
+
+ return 0;
+}
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
new file mode 100644
index 0000000000..8516d2a176
--- /dev/null
+++ b/libavcodec/avcodec.h
@@ -0,0 +1,177 @@
+#include "common.h"
+
+enum CodecID {
+ CODEC_ID_NONE,
+ CODEC_ID_MPEG1VIDEO,
+ CODEC_ID_H263,
+ CODEC_ID_RV10,
+ CODEC_ID_MP2,
+ CODEC_ID_AC3,
+ CODEC_ID_MJPEG,
+ CODEC_ID_OPENDIVX,
+ CODEC_ID_PCM,
+ CODEC_ID_RAWVIDEO,
+ CODEC_ID_MSMPEG4,
+ CODEC_ID_H263P,
+ CODEC_ID_H263I,
+};
+
+enum CodecType {
+ CODEC_TYPE_VIDEO,
+ CODEC_TYPE_AUDIO,
+};
+
+enum PixelFormat {
+ PIX_FMT_YUV420P,
+ PIX_FMT_YUV422,
+ PIX_FMT_RGB24,
+ PIX_FMT_BGR24,
+};
+
+/* in bytes */
+#define AVCODEC_MAX_AUDIO_FRAME_SIZE 18432
+
+/* motion estimation type */
+extern int motion_estimation_method;
+#define ME_ZERO 0
+#define ME_FULL 1
+#define ME_LOG 2
+#define ME_PHODS 3
+
+/* encoding support */
+
+#define CODEC_FLAG_HQ 0x0001 /* high quality (non real time) encoding */
+#define CODEC_FLAG_QSCALE 0x0002 /* use fixed qscale */
+
+#define FRAME_RATE_BASE 10000
+
+typedef struct AVCodecContext {
+ int bit_rate;
+ int flags;
+ int sub_id; /* some codecs needs additionnal format info. It is
+ stored there */
+ /* video only */
+ int frame_rate; /* frames per sec multiplied by FRAME_RATE_BASE */
+ int width, height;
+ int gop_size; /* 0 = intra only */
+ int pix_fmt; /* pixel format, see PIX_FMT_xxx */
+ /* audio only */
+ int sample_rate; /* samples per sec */
+ int channels;
+
+ /* the following data should not be initialized */
+ int frame_size; /* in samples, initialized when calling 'init' */
+ int frame_number; /* audio or video frame number */
+ int key_frame; /* true if the previous compressed frame was
+ a key frame (intra, or seekable) */
+ int quality; /* quality of the previous encoded frame
+ (between 1 (good) and 31 (bad)) */
+ struct AVCodec *codec;
+ void *priv_data;
+
+ /* the following fields are ignored */
+ char codec_name[32];
+ int codec_type; /* see CODEC_TYPE_xxx */
+ int codec_id; /* see CODEC_ID_xxx */
+ unsigned int codec_tag; /* codec tag, only used if unknown codec */
+} AVCodecContext;
+
+typedef struct AVCodec {
+ char *name;
+ int type;
+ int id;
+ int priv_data_size;
+ int (*init)(AVCodecContext *);
+ int (*encode)(AVCodecContext *, UINT8 *buf, int buf_size, void *data);
+ int (*close)(AVCodecContext *);
+ int (*decode)(AVCodecContext *, void *outdata, int *outdata_size,
+ UINT8 *buf, int buf_size);
+ struct AVCodec *next;
+} AVCodec;
+
+/* three components are given, that's all */
+typedef struct AVPicture {
+ UINT8 *data[3];
+ int linesize[3];
+} AVPicture;
+
+extern AVCodec ac3_encoder;
+extern AVCodec mp2_encoder;
+extern AVCodec mpeg1video_encoder;
+extern AVCodec h263_encoder;
+extern AVCodec h263p_encoder;
+extern AVCodec rv10_encoder;
+extern AVCodec mjpeg_encoder;
+extern AVCodec opendivx_encoder;
+extern AVCodec msmpeg4_encoder;
+
+extern AVCodec h263_decoder;
+extern AVCodec opendivx_decoder;
+extern AVCodec msmpeg4_decoder;
+extern AVCodec mpeg_decoder;
+extern AVCodec h263i_decoder;
+extern AVCodec rv10_decoder;
+
+/* dummy raw codecs */
+extern AVCodec pcm_codec;
+extern AVCodec rawvideo_codec;
+
+/* the following codecs use external GPL libs */
+extern AVCodec mp3_decoder;
+extern AVCodec ac3_decoder;
+
+/* resample.c */
+
+struct ReSampleContext;
+
+typedef struct ReSampleContext ReSampleContext;
+
+ReSampleContext *audio_resample_init(int output_channels, int input_channels,
+ int output_rate, int input_rate);
+int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples);
+void audio_resample_close(ReSampleContext *s);
+
+/* YUV420 format is assumed ! */
+
+struct ImgReSampleContext;
+
+typedef struct ImgReSampleContext ImgReSampleContext;
+
+ImgReSampleContext *img_resample_init(int output_width, int output_height,
+ int input_width, int input_height);
+void img_resample(ImgReSampleContext *s,
+ AVPicture *output, AVPicture *input);
+
+void img_resample_close(ImgReSampleContext *s);
+
+int img_convert_to_yuv420(UINT8 *img_out, UINT8 *img,
+ int pix_fmt, int width, int height);
+
+/* external high level API */
+
+extern AVCodec *first_avcodec;
+
+void avcodec_init(void);
+
+void register_avcodec(AVCodec *format);
+AVCodec *avcodec_find_encoder(enum CodecID id);
+AVCodec *avcodec_find_decoder(enum CodecID id);
+AVCodec *avcodec_find_decoder_by_name(const char *name);
+void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);
+
+int avcodec_open(AVCodecContext *avctx, AVCodec *codec);
+int avcodec_decode_audio(AVCodecContext *avctx, INT16 *samples,
+ int *frame_size_ptr,
+ UINT8 *buf, int buf_size);
+int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture,
+ int *got_picture_ptr,
+ UINT8 *buf, int buf_size);
+int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size,
+ const short *samples);
+int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size,
+ const AVPicture *pict);
+
+int avcodec_close(AVCodecContext *avctx);
+
+void avcodec_register_all(void);
+void avcodec_register_more(void);
diff --git a/libavcodec/common.c b/libavcodec/common.c
new file mode 100644
index 0000000000..b9365c9d8d
--- /dev/null
+++ b/libavcodec/common.c
@@ -0,0 +1,469 @@
+/*
+ * Common bit i/o utils
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#endif
+#include <netinet/in.h>
+#include <math.h>
+#include "common.h"
+
+#define NDEBUG
+#include <assert.h>
+
+void init_put_bits(PutBitContext *s,
+ UINT8 *buffer, int buffer_size,
+ void *opaque,
+ void (*write_data)(void *, UINT8 *, int))
+{
+ s->buf = buffer;
+ s->buf_ptr = s->buf;
+ s->buf_end = s->buf + buffer_size;
+ s->bit_cnt=0;
+ s->bit_buf=0;
+ s->data_out_size = 0;
+ s->write_data = write_data;
+ s->opaque = opaque;
+}
+
+static void flush_buffer(PutBitContext *s)
+{
+ int size;
+ if (s->write_data) {
+ size = s->buf_ptr - s->buf;
+ if (size > 0)
+ s->write_data(s->opaque, s->buf, size);
+ s->buf_ptr = s->buf;
+ s->data_out_size += size;
+ }
+}
+
+void put_bits(PutBitContext *s, int n, unsigned int value)
+{
+ unsigned int bit_buf;
+ int bit_cnt;
+
+#ifdef STATS
+ st_out_bit_counts[st_current_index] += n;
+#endif
+ // printf("put_bits=%d %x\n", n, value);
+ assert(n == 32 || value < (1U << n));
+
+ bit_buf = s->bit_buf;
+ bit_cnt = s->bit_cnt;
+
+ // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
+ /* XXX: optimize */
+ if (n < (32-bit_cnt)) {
+ bit_buf |= value << (32 - n - bit_cnt);
+ bit_cnt+=n;
+ } else {
+ bit_buf |= value >> (n + bit_cnt - 32);
+ *(UINT32 *)s->buf_ptr = htonl(bit_buf);
+ //printf("bitbuf = %08x\n", bit_buf);
+ s->buf_ptr+=4;
+ if (s->buf_ptr >= s->buf_end)
+ flush_buffer(s);
+ bit_cnt=bit_cnt + n - 32;
+ if (bit_cnt == 0) {
+ bit_buf = 0;
+ } else {
+ bit_buf = value << (32 - bit_cnt);
+ }
+ }
+
+ s->bit_buf = bit_buf;
+ s->bit_cnt = bit_cnt;
+}
+
+/* return the number of bits output */
+long long get_bit_count(PutBitContext *s)
+{
+ return (s->buf_ptr - s->buf + s->data_out_size) * 8 + (long long)s->bit_cnt;
+}
+
+void align_put_bits(PutBitContext *s)
+{
+ put_bits(s,(8 - s->bit_cnt) & 7,0);
+}
+
+/* pad the end of the output stream with zeros */
+void flush_put_bits(PutBitContext *s)
+{
+ while (s->bit_cnt > 0) {
+ /* XXX: should test end of buffer */
+ *s->buf_ptr++=s->bit_buf >> 24;
+ s->bit_buf<<=8;
+ s->bit_cnt-=8;
+ }
+ flush_buffer(s);
+ s->bit_cnt=0;
+ s->bit_buf=0;
+}
+
+/* for jpeg : espace 0xff with 0x00 after it */
+void jput_bits(PutBitContext *s, int n, unsigned int value)
+{
+ unsigned int bit_buf, b;
+ int bit_cnt, i;
+
+ assert(n == 32 || value < (1U << n));
+
+ bit_buf = s->bit_buf;
+ bit_cnt = s->bit_cnt;
+
+ //printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
+ /* XXX: optimize */
+ if (n < (32-bit_cnt)) {
+ bit_buf |= value << (32 - n - bit_cnt);
+ bit_cnt+=n;
+ } else {
+ bit_buf |= value >> (n + bit_cnt - 32);
+ /* handle escape */
+ for(i=0;i<4;i++) {
+ b = (bit_buf >> 24);
+ *(s->buf_ptr++) = b;
+ if (b == 0xff)
+ *(s->buf_ptr++) = 0;
+ bit_buf <<= 8;
+ }
+ /* we flush the buffer sooner to handle worst case */
+ if (s->buf_ptr >= (s->buf_end - 8))
+ flush_buffer(s);
+
+ bit_cnt=bit_cnt + n - 32;
+ if (bit_cnt == 0) {
+ bit_buf = 0;
+ } else {
+ bit_buf = value << (32 - bit_cnt);
+ }
+ }
+
+ s->bit_buf = bit_buf;
+ s->bit_cnt = bit_cnt;
+}
+
+/* pad the end of the output stream with zeros */
+void jflush_put_bits(PutBitContext *s)
+{
+ unsigned int b;
+
+ while (s->bit_cnt > 0) {
+ b = s->bit_buf >> 24;
+ *s->buf_ptr++ = b;
+ if (b == 0xff)
+ *s->buf_ptr++ = 0;
+ s->bit_buf<<=8;
+ s->bit_cnt-=8;
+ }
+ flush_buffer(s);
+ s->bit_cnt=0;
+ s->bit_buf=0;
+}
+
+/* bit input functions */
+
+void init_get_bits(GetBitContext *s,
+ UINT8 *buffer, int buffer_size)
+{
+ s->buf = buffer;
+ s->buf_ptr = buffer;
+ s->buf_end = buffer + buffer_size;
+ s->bit_cnt = 0;
+ s->bit_buf = 0;
+ while (s->buf_ptr < s->buf_end &&
+ s->bit_cnt < 32) {
+ s->bit_buf |= (*s->buf_ptr++ << (24 - s->bit_cnt));
+ s->bit_cnt += 8;
+ }
+}
+
+/* n must be >= 1 and <= 32 */
+unsigned int get_bits(GetBitContext *s, int n)
+{
+ unsigned int val;
+ int bit_cnt;
+ unsigned int bit_buf;
+ UINT8 *buf_ptr;
+
+#ifdef STATS
+ st_bit_counts[st_current_index] += n;
+#endif
+
+ bit_cnt = s->bit_cnt;
+ bit_buf = s->bit_buf;
+
+ bit_cnt -= n;
+ if (bit_cnt >= 0) {
+ /* most common case here */
+ val = bit_buf >> (32 - n);
+ bit_buf <<= n;
+ } else {
+ val = bit_buf >> (32 - n);
+ buf_ptr = s->buf_ptr;
+ buf_ptr += 4;
+ /* handle common case: we can read everything */
+ if (buf_ptr <= s->buf_end) {
+ bit_buf = (buf_ptr[-4] << 24) |
+ (buf_ptr[-3] << 16) |
+ (buf_ptr[-2] << 8) |
+ (buf_ptr[-1]);
+ } else {
+ buf_ptr -= 4;
+ bit_buf = 0;
+ if (buf_ptr < s->buf_end)
+ bit_buf |= *buf_ptr++ << 24;
+ if (buf_ptr < s->buf_end)
+ bit_buf |= *buf_ptr++ << 16;
+ if (buf_ptr < s->buf_end)
+ bit_buf |= *buf_ptr++ << 8;
+ if (buf_ptr < s->buf_end)
+ bit_buf |= *buf_ptr++;
+ }
+ s->buf_ptr = buf_ptr;
+ val |= bit_buf >> (32 + bit_cnt);
+ bit_buf <<= - bit_cnt;
+ bit_cnt += 32;
+ }
+ s->bit_buf = bit_buf;
+ s->bit_cnt = bit_cnt;
+ return val;
+}
+
+void align_get_bits(GetBitContext *s)
+{
+ int n;
+ n = s->bit_cnt & 7;
+ if (n > 0) {
+ get_bits(s, n);
+ }
+}
+
+/* VLC decoding */
+
+//#define DEBUG_VLC
+
+#define GET_DATA(v, table, i, wrap, size) \
+{\
+ UINT8 *ptr = (UINT8 *)table + i * wrap;\
+ switch(size) {\
+ case 1:\
+ v = *(UINT8 *)ptr;\
+ break;\
+ case 2:\
+ v = *(UINT16 *)ptr;\
+ break;\
+ default:\
+ v = *(UINT32 *)ptr;\
+ break;\
+ }\
+}
+
+
+static int alloc_table(VLC *vlc, int size)
+{
+ int index;
+ index = vlc->table_size;
+ vlc->table_size += size;
+ if (vlc->table_size > vlc->table_allocated) {
+ vlc->table_allocated += (1 << vlc->bits);
+ vlc->table_bits = realloc(vlc->table_bits,
+ sizeof(INT8) * vlc->table_allocated);
+ vlc->table_codes = realloc(vlc->table_codes,
+ sizeof(INT16) * vlc->table_allocated);
+ if (!vlc->table_bits ||
+ !vlc->table_codes)
+ return -1;
+ }
+ return index;
+}
+
+static int build_table(VLC *vlc, int table_nb_bits,
+ int nb_codes,
+ const void *bits, int bits_wrap, int bits_size,
+ const void *codes, int codes_wrap, int codes_size,
+ UINT32 code_prefix, int n_prefix)
+{
+ int i, j, k, n, table_size, table_index, nb, n1, index;
+ UINT32 code;
+ INT8 *table_bits;
+ INT16 *table_codes;
+
+ table_size = 1 << table_nb_bits;
+ table_index = alloc_table(vlc, table_size);
+#ifdef DEBUG_VLC
+ printf("new table index=%d size=%d code_prefix=%x n=%d\n",
+ table_index, table_size, code_prefix, n_prefix);
+#endif
+ if (table_index < 0)
+ return -1;
+ table_bits = &vlc->table_bits[table_index];
+ table_codes = &vlc->table_codes[table_index];
+
+ for(i=0;i<table_size;i++) {
+ table_bits[i] = 0;
+ table_codes[i] = -1;
+ }
+
+ /* first pass: map codes and compute auxillary table sizes */
+ for(i=0;i<nb_codes;i++) {
+ GET_DATA(n, bits, i, bits_wrap, bits_size);
+ GET_DATA(code, codes, i, codes_wrap, codes_size);
+ /* we accept tables with holes */
+ if (n <= 0)
+ continue;
+#if defined(DEBUG_VLC) && 0
+ printf("i=%d n=%d code=0x%x\n", i, n, code);
+#endif
+ /* if code matches the prefix, it is in the table */
+ n -= n_prefix;
+ if (n > 0 && (code >> n) == code_prefix) {
+ if (n <= table_nb_bits) {
+ /* no need to add another table */
+ j = (code << (table_nb_bits - n)) & (table_size - 1);
+ nb = 1 << (table_nb_bits - n);
+ for(k=0;k<nb;k++) {
+#ifdef DEBUG_VLC
+ printf("%4x: code=%d n=%d\n",
+ j, i, n);
+#endif
+ if (table_bits[j] != 0) {
+ fprintf(stderr, "incorrect codes\n");
+ exit(1);
+ }
+ table_bits[j] = n;
+ table_codes[j] = i;
+ j++;
+ }
+ } else {
+ n -= table_nb_bits;
+ j = (code >> n) & ((1 << table_nb_bits) - 1);
+#ifdef DEBUG_VLC
+ printf("%4x: n=%d (subtable)\n",
+ j, n);
+#endif
+ /* compute table size */
+ n1 = -table_bits[j];
+ if (n > n1)
+ n1 = n;
+ table_bits[j] = -n1;
+ }
+ }
+ }
+
+ /* second pass : fill auxillary tables recursively */
+ for(i=0;i<table_size;i++) {
+ n = table_bits[i];
+ if (n < 0) {
+ n = -n;
+ if (n > table_nb_bits) {
+ n = table_nb_bits;
+ table_bits[i] = -n;
+ }
+ index = build_table(vlc, n, nb_codes,
+ bits, bits_wrap, bits_size,
+ codes, codes_wrap, codes_size,
+ (code_prefix << table_nb_bits) | i,
+ n_prefix + table_nb_bits);
+ if (index < 0)
+ return -1;
+ /* note: realloc has been done, so reload tables */
+ table_bits = &vlc->table_bits[table_index];
+ table_codes = &vlc->table_codes[table_index];
+ table_codes[i] = index;
+ }
+ }
+ return table_index;
+}
+
+
+/* wrap and size allow to handle most types of storage. */
+int init_vlc(VLC *vlc, int nb_bits, int nb_codes,
+ const void *bits, int bits_wrap, int bits_size,
+ const void *codes, int codes_wrap, int codes_size)
+{
+ vlc->bits = nb_bits;
+ vlc->table_bits = NULL;
+ vlc->table_codes = NULL;
+ vlc->table_allocated = 0;
+ vlc->table_size = 0;
+#ifdef DEBUG_VLC
+ printf("build table nb_codes=%d\n", nb_codes);
+#endif
+
+ if (build_table(vlc, nb_bits, nb_codes,
+ bits, bits_wrap, bits_size,
+ codes, codes_wrap, codes_size,
+ 0, 0) < 0) {
+ if (vlc->table_bits)
+ free(vlc->table_bits);
+ if (vlc->table_codes)
+ free(vlc->table_codes);
+ return -1;
+ }
+ return 0;
+}
+
+
+void free_vlc(VLC *vlc)
+{
+ free(vlc->table_bits);
+ free(vlc->table_codes);
+}
+
+int get_vlc(GetBitContext *s, VLC *vlc)
+{
+ int bit_cnt, code, n, nb_bits, index;
+ UINT32 bit_buf;
+ INT16 *table_codes;
+ INT8 *table_bits;
+ UINT8 *buf_ptr;
+
+ SAVE_BITS(s);
+ nb_bits = vlc->bits;
+ table_codes = vlc->table_codes;
+ table_bits = vlc->table_bits;
+ for(;;) {
+ SHOW_BITS(s, index, nb_bits);
+ code = table_codes[index];
+ n = table_bits[index];
+ if (n > 0) {
+ /* most common case */
+ FLUSH_BITS(n);
+#ifdef STATS
+ st_bit_counts[st_current_index] += n;
+#endif
+ break;
+ } else if (n == 0) {
+ return -1;
+ } else {
+ FLUSH_BITS(nb_bits);
+#ifdef STATS
+ st_bit_counts[st_current_index] += nb_bits;
+#endif
+ nb_bits = -n;
+ table_codes = vlc->table_codes + code;
+ table_bits = vlc->table_bits + code;
+ }
+ }
+ RESTORE_BITS(s);
+ return code;
+}
diff --git a/libavcodec/common.h b/libavcodec/common.h
new file mode 100644
index 0000000000..bba7d1fb9d
--- /dev/null
+++ b/libavcodec/common.h
@@ -0,0 +1,170 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "../config.h"
+
+#ifndef USE_LIBAVCODEC
+// workaround for typedef conflict in MPlayer
+typedef unsigned short UINT16;
+typedef signed short INT16;
+#endif
+
+typedef unsigned char UINT8;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+typedef signed char INT8;
+typedef signed int INT32;
+typedef signed long long INT64;
+
+/* bit output */
+
+struct PutBitContext;
+
+typedef void (*WriteDataFunc)(void *, UINT8 *, int);
+
+typedef struct PutBitContext {
+ UINT8 *buf, *buf_ptr, *buf_end;
+ int bit_cnt;
+ UINT32 bit_buf;
+ long long data_out_size; /* in bytes */
+ void *opaque;
+ WriteDataFunc write_data;
+} PutBitContext;
+
+void init_put_bits(PutBitContext *s,
+ UINT8 *buffer, int buffer_size,
+ void *opaque,
+ void (*write_data)(void *, UINT8 *, int));
+void put_bits(PutBitContext *s, int n, unsigned int value);
+long long get_bit_count(PutBitContext *s);
+void align_put_bits(PutBitContext *s);
+void flush_put_bits(PutBitContext *s);
+
+/* jpeg specific put_bits */
+void jput_bits(PutBitContext *s, int n, unsigned int value);
+void jflush_put_bits(PutBitContext *s);
+
+/* bit input */
+
+typedef struct GetBitContext {
+ UINT8 *buf, *buf_ptr, *buf_end;
+ int bit_cnt;
+ UINT32 bit_buf;
+} GetBitContext;
+
+typedef struct VLC {
+ int bits;
+ INT16 *table_codes;
+ INT8 *table_bits;
+ int table_size, table_allocated;
+} VLC;
+
+void init_get_bits(GetBitContext *s,
+ UINT8 *buffer, int buffer_size);
+
+unsigned int get_bits(GetBitContext *s, int n);
+void align_get_bits(GetBitContext *s);
+int init_vlc(VLC *vlc, int nb_bits, int nb_codes,
+ const void *bits, int bits_wrap, int bits_size,
+ const void *codes, int codes_wrap, int codes_size);
+void free_vlc(VLC *vlc);
+int get_vlc(GetBitContext *s, VLC *vlc);
+
+/* macro to go faster */
+/* n must be <= 24 */
+/* XXX: optimize buffer end test */
+#define SHOW_BITS(s, val, n)\
+{\
+ if (bit_cnt < n && buf_ptr < (s)->buf_end) {\
+ bit_buf |= *buf_ptr++ << (24 - bit_cnt);\
+ bit_cnt += 8;\
+ if (bit_cnt < n && buf_ptr < (s)->buf_end) {\
+ bit_buf |= *buf_ptr++ << (24 - bit_cnt);\
+ bit_cnt += 8;\
+ if (bit_cnt < n && buf_ptr < (s)->buf_end) {\
+ bit_buf |= *buf_ptr++ << (24 - bit_cnt);\
+ bit_cnt += 8;\
+ }\
+ }\
+ }\
+ val = bit_buf >> (32 - n);\
+}
+
+/* SHOW_BITS with n1 >= n must be been done before */
+#define FLUSH_BITS(n)\
+{\
+ bit_buf <<= n;\
+ bit_cnt -= n;\
+}
+
+#define SAVE_BITS(s) \
+{\
+ bit_cnt = (s)->bit_cnt;\
+ bit_buf = (s)->bit_buf;\
+ buf_ptr = (s)->buf_ptr;\
+}
+
+#define RESTORE_BITS(s) \
+{\
+ (s)->buf_ptr = buf_ptr;\
+ (s)->bit_buf = bit_buf;\
+ (s)->bit_cnt = bit_cnt;\
+}
+
+/* define it to include statistics code (useful only for optimizing
+ codec efficiency */
+//#define STATS
+
+#ifdef STATS
+
+enum {
+ ST_UNKNOWN,
+ ST_DC,
+ ST_INTRA_AC,
+ ST_INTER_AC,
+ ST_INTRA_MB,
+ ST_INTER_MB,
+ ST_MV,
+ ST_NB,
+};
+
+extern int st_current_index;
+extern unsigned int st_bit_counts[ST_NB];
+extern unsigned int st_out_bit_counts[ST_NB];
+
+void print_stats(void);
+#endif
+
+/* misc math functions */
+
+extern inline int log2(unsigned int v)
+{
+ int n;
+
+ n = 0;
+ if (v & 0xffff0000) {
+ v >>= 16;
+ n += 16;
+ }
+ if (v & 0xff00) {
+ v >>= 8;
+ n += 8;
+ }
+ if (v & 0xf0) {
+ v >>= 4;
+ n += 4;
+ }
+ if (v & 0xc) {
+ v >>= 2;
+ n += 2;
+ }
+ if (v & 0x2) {
+ n++;
+ }
+ return n;
+}
+
+/* memory */
+void *av_mallocz(int size);
+
+#endif
diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c
new file mode 100644
index 0000000000..1da23a1d8e
--- /dev/null
+++ b/libavcodec/dct-test.c
@@ -0,0 +1,105 @@
+/* DCT test. (c) 2001 Gerard Lantau.
+ Started from sample code by Juan J. Sierralta P.
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "dsputil.h"
+
+extern void fdct(DCTELEM *block);
+extern void init_fdct();
+
+#define AANSCALE_BITS 12
+static const unsigned short aanscales[64] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+};
+
+INT64 gettime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+#define NB_ITS 20000
+#define NB_ITS_SPEED 50000
+
+void dct_error(const char *name,
+ void (*fdct_func)(DCTELEM *block))
+{
+ int it, i, scale;
+ DCTELEM block[64], block1[64];
+ int err_inf, v;
+ INT64 err2, ti, ti1, it1;
+
+ srandom(0);
+
+ err_inf = 0;
+ err2 = 0;
+ for(it=0;it<NB_ITS;it++) {
+ for(i=0;i<64;i++)
+ block1[i] = random() % 256;
+ memcpy(block, block1, sizeof(DCTELEM) * 64);
+
+ fdct_func(block);
+ if (fdct_func == jpeg_fdct_ifast) {
+ for(i=0; i<64; i++) {
+ scale = (1 << (AANSCALE_BITS + 11)) / aanscales[i];
+ block[i] = (block[i] * scale) >> AANSCALE_BITS;
+ }
+ }
+
+ fdct(block1);
+
+ for(i=0;i<64;i++) {
+ v = abs(block[i] - block1[i]);
+ if (v > err_inf)
+ err_inf = v;
+ err2 += v * v;
+ }
+ }
+ printf("DCT %s: err_inf=%d err2=%0.2f\n",
+ name, err_inf, (double)err2 / NB_ITS / 64.0);
+
+ /* speed test */
+ for(i=0;i<64;i++)
+ block1[i] = 255 - 63 + i;
+
+ ti = gettime();
+ it1 = 0;
+ do {
+ for(it=0;it<NB_ITS_SPEED;it++) {
+ memcpy(block, block1, sizeof(DCTELEM) * 64);
+ fdct_func(block);
+ }
+ it1 += NB_ITS_SPEED;
+ ti1 = gettime() - ti;
+ } while (ti1 < 1000000);
+
+ printf("DCT %s: %0.1f kdct/s\n",
+ name, (double)it1 * 1000.0 / (double)ti1);
+}
+
+int main(int argc, char **argv)
+{
+ init_fdct();
+
+ printf("ffmpeg DCT test\n");
+
+ dct_error("REF", fdct); /* only to verify code ! */
+ dct_error("AAN", jpeg_fdct_ifast);
+ dct_error("MMX", fdct_mmx);
+ return 0;
+}
+
diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c
new file mode 100644
index 0000000000..7e544a4524
--- /dev/null
+++ b/libavcodec/dsputil.c
@@ -0,0 +1,383 @@
+/*
+ * DSP utils
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "avcodec.h"
+#include "dsputil.h"
+
+#ifdef CONFIG_MMX
+int mm_flags; /* multimedia extension flags */
+#endif
+
+void (*get_pixels)(DCTELEM *block, const UINT8 *pixels, int line_size);
+void (*put_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size);
+void (*add_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size);
+
+op_pixels_abs_func pix_abs16x16;
+op_pixels_abs_func pix_abs16x16_x2;
+op_pixels_abs_func pix_abs16x16_y2;
+op_pixels_abs_func pix_abs16x16_xy2;
+
+static UINT8 cropTbl[256 + 2 * MAX_NEG_CROP];
+UINT32 squareTbl[512];
+
+void get_pixels_c(DCTELEM *block, const UINT8 *pixels, int line_size)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ int i;
+
+ /* read the pixels */
+ p = block;
+ pix = pixels;
+ for(i=0;i<8;i++) {
+ p[0] = pix[0];
+ p[1] = pix[1];
+ p[2] = pix[2];
+ p[3] = pix[3];
+ p[4] = pix[4];
+ p[5] = pix[5];
+ p[6] = pix[6];
+ p[7] = pix[7];
+ pix += line_size;
+ p += 8;
+ }
+}
+
+void put_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size)
+{
+ const DCTELEM *p;
+ UINT8 *pix;
+ int i;
+ UINT8 *cm = cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ p = block;
+ pix = pixels;
+ for(i=0;i<8;i++) {
+ pix[0] = cm[p[0]];
+ pix[1] = cm[p[1]];
+ pix[2] = cm[p[2]];
+ pix[3] = cm[p[3]];
+ pix[4] = cm[p[4]];
+ pix[5] = cm[p[5]];
+ pix[6] = cm[p[6]];
+ pix[7] = cm[p[7]];
+ pix += line_size;
+ p += 8;
+ }
+}
+
+void add_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size)
+{
+ const DCTELEM *p;
+ UINT8 *pix;
+ int i;
+ UINT8 *cm = cropTbl + MAX_NEG_CROP;
+
+ /* read the pixels */
+ p = block;
+ pix = pixels;
+ for(i=0;i<8;i++) {
+ pix[0] = cm[pix[0] + p[0]];
+ pix[1] = cm[pix[1] + p[1]];
+ pix[2] = cm[pix[2] + p[2]];
+ pix[3] = cm[pix[3] + p[3]];
+ pix[4] = cm[pix[4] + p[4]];
+ pix[5] = cm[pix[5] + p[5]];
+ pix[6] = cm[pix[6] + p[6]];
+ pix[7] = cm[pix[7] + p[7]];
+ pix += line_size;
+ p += 8;
+ }
+}
+
+#define PIXOP(BTYPE, OPNAME, OP, INCR) \
+ \
+static void OPNAME ## _pixels(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
+{ \
+ BTYPE *p; \
+ const UINT8 *pix; \
+ \
+ p = block; \
+ pix = pixels; \
+ do { \
+ OP(p[0], pix[0]); \
+ OP(p[1], pix[1]); \
+ OP(p[2], pix[2]); \
+ OP(p[3], pix[3]); \
+ OP(p[4], pix[4]); \
+ OP(p[5], pix[5]); \
+ OP(p[6], pix[6]); \
+ OP(p[7], pix[7]); \
+ pix += line_size; \
+ p += INCR; \
+ } while (--h);; \
+} \
+ \
+static void OPNAME ## _pixels_x2(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
+{ \
+ BTYPE *p; \
+ const UINT8 *pix; \
+ \
+ p = block; \
+ pix = pixels; \
+ do { \
+ OP(p[0], avg2(pix[0], pix[1])); \
+ OP(p[1], avg2(pix[1], pix[2])); \
+ OP(p[2], avg2(pix[2], pix[3])); \
+ OP(p[3], avg2(pix[3], pix[4])); \
+ OP(p[4], avg2(pix[4], pix[5])); \
+ OP(p[5], avg2(pix[5], pix[6])); \
+ OP(p[6], avg2(pix[6], pix[7])); \
+ OP(p[7], avg2(pix[7], pix[8])); \
+ pix += line_size; \
+ p += INCR; \
+ } while (--h); \
+} \
+ \
+static void OPNAME ## _pixels_y2(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
+{ \
+ BTYPE *p; \
+ const UINT8 *pix; \
+ const UINT8 *pix1; \
+ \
+ p = block; \
+ pix = pixels; \
+ pix1 = pixels + line_size; \
+ do { \
+ OP(p[0], avg2(pix[0], pix1[0])); \
+ OP(p[1], avg2(pix[1], pix1[1])); \
+ OP(p[2], avg2(pix[2], pix1[2])); \
+ OP(p[3], avg2(pix[3], pix1[3])); \
+ OP(p[4], avg2(pix[4], pix1[4])); \
+ OP(p[5], avg2(pix[5], pix1[5])); \
+ OP(p[6], avg2(pix[6], pix1[6])); \
+ OP(p[7], avg2(pix[7], pix1[7])); \
+ pix += line_size; \
+ pix1 += line_size; \
+ p += INCR; \
+ } while(--h); \
+} \
+ \
+static void OPNAME ## _pixels_xy2(BTYPE *block, const UINT8 *pixels, int line_size, int h) \
+{ \
+ BTYPE *p; \
+ const UINT8 *pix; \
+ const UINT8 *pix1; \
+ \
+ p = block; \
+ pix = pixels; \
+ pix1 = pixels + line_size; \
+ do { \
+ OP(p[0], avg4(pix[0], pix[1], pix1[0], pix1[1])); \
+ OP(p[1], avg4(pix[1], pix[2], pix1[1], pix1[2])); \
+ OP(p[2], avg4(pix[2], pix[3], pix1[2], pix1[3])); \
+ OP(p[3], avg4(pix[3], pix[4], pix1[3], pix1[4])); \
+ OP(p[4], avg4(pix[4], pix[5], pix1[4], pix1[5])); \
+ OP(p[5], avg4(pix[5], pix[6], pix1[5], pix1[6])); \
+ OP(p[6], avg4(pix[6], pix[7], pix1[6], pix1[7])); \
+ OP(p[7], avg4(pix[7], pix[8], pix1[7], pix1[8])); \
+ pix += line_size; \
+ pix1 += line_size; \
+ p += INCR; \
+ } while(--h); \
+} \
+ \
+void (*OPNAME ## _pixels_tab[4])(BTYPE *block, const UINT8 *pixels, int line_size, int h) = { \
+ OPNAME ## _pixels, \
+ OPNAME ## _pixels_x2, \
+ OPNAME ## _pixels_y2, \
+ OPNAME ## _pixels_xy2, \
+};
+
+
+/* rounding primitives */
+#define avg2(a,b) ((a+b+1)>>1)
+#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
+
+#define op_put(a, b) a = b
+#define op_avg(a, b) a = avg2(a, b)
+#define op_sub(a, b) a -= b
+
+PIXOP(UINT8, put, op_put, line_size)
+PIXOP(UINT8, avg, op_avg, line_size)
+
+PIXOP(DCTELEM, sub, op_sub, 8)
+
+/* not rounding primitives */
+#undef avg2
+#undef avg4
+#define avg2(a,b) ((a+b)>>1)
+#define avg4(a,b,c,d) ((a+b+c+d+1)>>2)
+
+PIXOP(UINT8, put_no_rnd, op_put, line_size)
+PIXOP(UINT8, avg_no_rnd, op_avg, line_size)
+
+/* motion estimation */
+
+#undef avg2
+#undef avg4
+#define avg2(a,b) ((a+b+1)>>1)
+#define avg4(a,b,c,d) ((a+b+c+d+2)>>2)
+
+int pix_abs16x16_c(UINT8 *pix1, UINT8 *pix2, int line_size, int h)
+{
+ int s, i;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - pix2[0]);
+ s += abs(pix1[1] - pix2[1]);
+ s += abs(pix1[2] - pix2[2]);
+ s += abs(pix1[3] - pix2[3]);
+ s += abs(pix1[4] - pix2[4]);
+ s += abs(pix1[5] - pix2[5]);
+ s += abs(pix1[6] - pix2[6]);
+ s += abs(pix1[7] - pix2[7]);
+ s += abs(pix1[8] - pix2[8]);
+ s += abs(pix1[9] - pix2[9]);
+ s += abs(pix1[10] - pix2[10]);
+ s += abs(pix1[11] - pix2[11]);
+ s += abs(pix1[12] - pix2[12]);
+ s += abs(pix1[13] - pix2[13]);
+ s += abs(pix1[14] - pix2[14]);
+ s += abs(pix1[15] - pix2[15]);
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+int pix_abs16x16_x2_c(UINT8 *pix1, UINT8 *pix2, int line_size, int h)
+{
+ int s, i;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg2(pix2[0], pix2[1]));
+ s += abs(pix1[1] - avg2(pix2[1], pix2[2]));
+ s += abs(pix1[2] - avg2(pix2[2], pix2[3]));
+ s += abs(pix1[3] - avg2(pix2[3], pix2[4]));
+ s += abs(pix1[4] - avg2(pix2[4], pix2[5]));
+ s += abs(pix1[5] - avg2(pix2[5], pix2[6]));
+ s += abs(pix1[6] - avg2(pix2[6], pix2[7]));
+ s += abs(pix1[7] - avg2(pix2[7], pix2[8]));
+ s += abs(pix1[8] - avg2(pix2[8], pix2[9]));
+ s += abs(pix1[9] - avg2(pix2[9], pix2[10]));
+ s += abs(pix1[10] - avg2(pix2[10], pix2[11]));
+ s += abs(pix1[11] - avg2(pix2[11], pix2[12]));
+ s += abs(pix1[12] - avg2(pix2[12], pix2[13]));
+ s += abs(pix1[13] - avg2(pix2[13], pix2[14]));
+ s += abs(pix1[14] - avg2(pix2[14], pix2[15]));
+ s += abs(pix1[15] - avg2(pix2[15], pix2[16]));
+ pix1 += line_size;
+ pix2 += line_size;
+ }
+ return s;
+}
+
+int pix_abs16x16_y2_c(UINT8 *pix1, UINT8 *pix2, int line_size, int h)
+{
+ int s, i;
+ UINT8 *pix3 = pix2 + line_size;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg2(pix2[0], pix3[0]));
+ s += abs(pix1[1] - avg2(pix2[1], pix3[1]));
+ s += abs(pix1[2] - avg2(pix2[2], pix3[2]));
+ s += abs(pix1[3] - avg2(pix2[3], pix3[3]));
+ s += abs(pix1[4] - avg2(pix2[4], pix3[4]));
+ s += abs(pix1[5] - avg2(pix2[5], pix3[5]));
+ s += abs(pix1[6] - avg2(pix2[6], pix3[6]));
+ s += abs(pix1[7] - avg2(pix2[7], pix3[7]));
+ s += abs(pix1[8] - avg2(pix2[8], pix3[8]));
+ s += abs(pix1[9] - avg2(pix2[9], pix3[9]));
+ s += abs(pix1[10] - avg2(pix2[10], pix3[10]));
+ s += abs(pix1[11] - avg2(pix2[11], pix3[11]));
+ s += abs(pix1[12] - avg2(pix2[12], pix3[12]));
+ s += abs(pix1[13] - avg2(pix2[13], pix3[13]));
+ s += abs(pix1[14] - avg2(pix2[14], pix3[14]));
+ s += abs(pix1[15] - avg2(pix2[15], pix3[15]));
+ pix1 += line_size;
+ pix2 += line_size;
+ pix3 += line_size;
+ }
+ return s;
+}
+
+int pix_abs16x16_xy2_c(UINT8 *pix1, UINT8 *pix2, int line_size, int h)
+{
+ int s, i;
+ UINT8 *pix3 = pix2 + line_size;
+
+ s = 0;
+ for(i=0;i<h;i++) {
+ s += abs(pix1[0] - avg4(pix2[0], pix2[1], pix3[0], pix3[1]));
+ s += abs(pix1[1] - avg4(pix2[1], pix2[2], pix3[1], pix3[2]));
+ s += abs(pix1[2] - avg4(pix2[2], pix2[3], pix3[2], pix3[3]));
+ s += abs(pix1[3] - avg4(pix2[3], pix2[4], pix3[3], pix3[4]));
+ s += abs(pix1[4] - avg4(pix2[4], pix2[5], pix3[4], pix3[5]));
+ s += abs(pix1[5] - avg4(pix2[5], pix2[6], pix3[5], pix3[6]));
+ s += abs(pix1[6] - avg4(pix2[6], pix2[7], pix3[6], pix3[7]));
+ s += abs(pix1[7] - avg4(pix2[7], pix2[8], pix3[7], pix3[8]));
+ s += abs(pix1[8] - avg4(pix2[8], pix2[9], pix3[8], pix3[9]));
+ s += abs(pix1[9] - avg4(pix2[9], pix2[10], pix3[9], pix3[10]));
+ s += abs(pix1[10] - avg4(pix2[10], pix2[11], pix3[10], pix3[11]));
+ s += abs(pix1[11] - avg4(pix2[11], pix2[12], pix3[11], pix3[12]));
+ s += abs(pix1[12] - avg4(pix2[12], pix2[13], pix3[12], pix3[13]));
+ s += abs(pix1[13] - avg4(pix2[13], pix2[14], pix3[13], pix3[14]));
+ s += abs(pix1[14] - avg4(pix2[14], pix2[15], pix3[14], pix3[15]));
+ s += abs(pix1[15] - avg4(pix2[15], pix2[16], pix3[15], pix3[16]));
+ pix1 += line_size;
+ pix2 += line_size;
+ pix3 += line_size;
+ }
+ return s;
+}
+
+void dsputil_init(void)
+{
+ int i;
+
+ for(i=0;i<256;i++) cropTbl[i + MAX_NEG_CROP] = i;
+ for(i=0;i<MAX_NEG_CROP;i++) {
+ cropTbl[i] = 0;
+ cropTbl[i + MAX_NEG_CROP + 256] = 255;
+ }
+
+ for(i=0;i<512;i++) {
+ squareTbl[i] = (i - 256) * (i - 256);
+ }
+
+ get_pixels = get_pixels_c;
+ put_pixels_clamped = put_pixels_clamped_c;
+ add_pixels_clamped = add_pixels_clamped_c;
+
+ pix_abs16x16 = pix_abs16x16_c;
+ pix_abs16x16_x2 = pix_abs16x16_x2_c;
+ pix_abs16x16_y2 = pix_abs16x16_y2_c;
+ pix_abs16x16_xy2 = pix_abs16x16_xy2_c;
+ av_fdct = jpeg_fdct_ifast;
+
+#ifdef CONFIG_MMX
+ dsputil_init_mmx();
+#endif
+}
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
new file mode 100644
index 0000000000..717653e813
--- /dev/null
+++ b/libavcodec/dsputil.h
@@ -0,0 +1,91 @@
+#ifndef DSPUTIL_H
+#define DSPUTIL_H
+
+#include "common.h"
+#include <inttypes.h>
+
+/* dct code */
+typedef short DCTELEM;
+
+void jpeg_fdct_ifast (DCTELEM *data);
+
+void j_rev_dct (DCTELEM *data);
+
+void fdct_mmx(DCTELEM *block);
+
+void (*av_fdct)(DCTELEM *block);
+
+/* pixel operations */
+#define MAX_NEG_CROP 384
+
+/* temporary */
+extern UINT32 squareTbl[512];
+
+void dsputil_init(void);
+
+/* pixel ops : interface with DCT */
+
+extern void (*get_pixels)(DCTELEM *block, const UINT8 *pixels, int line_size);
+extern void (*put_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size);
+extern void (*add_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size);
+
+void get_pixels_c(DCTELEM *block, const UINT8 *pixels, int line_size);
+void put_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size);
+void add_pixels_clamped_c(const DCTELEM *block, UINT8 *pixels, int line_size);
+
+/* add and put pixel (decoding) */
+typedef void (*op_pixels_func)(UINT8 *block, const UINT8 *pixels, int line_size, int h);
+
+extern op_pixels_func put_pixels_tab[4];
+extern op_pixels_func avg_pixels_tab[4];
+extern op_pixels_func put_no_rnd_pixels_tab[4];
+extern op_pixels_func avg_no_rnd_pixels_tab[4];
+
+/* sub pixel (encoding) */
+extern void (*sub_pixels_tab[4])(DCTELEM *block, const UINT8 *pixels, int line_size, int h);
+
+#define sub_pixels_2(block, pixels, line_size, dxy) \
+ sub_pixels_tab[dxy](block, pixels, line_size, 8)
+
+/* motion estimation */
+
+typedef int (*op_pixels_abs_func)(UINT8 *blk1, UINT8 *blk2, int line_size, int h);
+
+extern op_pixels_abs_func pix_abs16x16;
+extern op_pixels_abs_func pix_abs16x16_x2;
+extern op_pixels_abs_func pix_abs16x16_y2;
+extern op_pixels_abs_func pix_abs16x16_xy2;
+
+int pix_abs16x16_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+int pix_abs16x16_x2_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+int pix_abs16x16_y2_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+int pix_abs16x16_xy2_c(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+
+#ifdef CONFIG_MMX
+
+#define MM_MMX 0x0001 /* standard MMX */
+#define MM_3DNOW 0x0004 /* AMD 3DNOW */
+#define MM_MMXEXT 0x0002 /* SSE integer functions or AMD MMX ext */
+#define MM_SSE 0x0008 /* SSE functions */
+#define MM_SSE2 0x0010 /* PIV SSE2 functions */
+
+extern int mm_flags;
+
+int mm_support(void);
+
+static inline void emms(void)
+{
+ asm volatile ("emms;");
+}
+
+#define __align8 __attribute__ ((aligned (8)))
+
+void dsputil_init_mmx(void);
+
+#else
+
+#define __align8
+
+#endif
+
+#endif
diff --git a/libavcodec/fdctref.c b/libavcodec/fdctref.c
new file mode 100644
index 0000000000..5038e67538
--- /dev/null
+++ b/libavcodec/fdctref.c
@@ -0,0 +1,120 @@
+/* fdctref.c, forward discrete cosine transform, double precision */
+
+/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
+
+/*
+ * Disclaimer of Warranty
+ *
+ * These software programs are available to the user without any license fee or
+ * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
+ * any and all warranties, whether express, implied, or statuary, including any
+ * implied warranties or merchantability or of fitness for a particular
+ * purpose. In no event shall the copyright-holder be liable for any
+ * incidental, punitive, or consequential damages of any kind whatsoever
+ * arising from the use of these programs.
+ *
+ * This disclaimer of warranty extends to the user of these programs and user's
+ * customers, employees, agents, transferees, successors, and assigns.
+ *
+ * The MPEG Software Simulation Group does not represent or warrant that the
+ * programs furnished hereunder are free of infringement of any third-party
+ * patents.
+ *
+ * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
+ * are subject to royalty fees to patent holders. Many of these patents are
+ * general enough such that they are unavoidable regardless of implementation
+ * design.
+ *
+ */
+
+#include <math.h>
+
+// #include "config.h"
+
+#ifndef PI
+# ifdef M_PI
+# define PI M_PI
+# else
+# define PI 3.14159265358979323846
+# endif
+#endif
+
+/* global declarations */
+void init_fdct (void);
+void fdct (short *block);
+
+/* private data */
+static double c[8][8]; /* transform coefficients */
+
+void init_fdct()
+{
+ int i, j;
+ double s;
+
+ for (i=0; i<8; i++)
+ {
+ s = (i==0) ? sqrt(0.125) : 0.5;
+
+ for (j=0; j<8; j++)
+ c[i][j] = s * cos((PI/8.0)*i*(j+0.5));
+ }
+}
+
+void fdct(block)
+short *block;
+{
+ register int i, j;
+ double s;
+ double tmp[64];
+
+ for(i = 0; i < 8; i++)
+ for(j = 0; j < 8; j++)
+ {
+ s = 0.0;
+
+/*
+ * for(k = 0; k < 8; k++)
+ * s += c[j][k] * block[8 * i + k];
+ */
+ s += c[j][0] * block[8 * i + 0];
+ s += c[j][1] * block[8 * i + 1];
+ s += c[j][2] * block[8 * i + 2];
+ s += c[j][3] * block[8 * i + 3];
+ s += c[j][4] * block[8 * i + 4];
+ s += c[j][5] * block[8 * i + 5];
+ s += c[j][6] * block[8 * i + 6];
+ s += c[j][7] * block[8 * i + 7];
+
+ tmp[8 * i + j] = s;
+ }
+
+ for(j = 0; j < 8; j++)
+ for(i = 0; i < 8; i++)
+ {
+ s = 0.0;
+
+/*
+ * for(k = 0; k < 8; k++)
+ * s += c[i][k] * tmp[8 * k + j];
+ */
+ s += c[i][0] * tmp[8 * 0 + j];
+ s += c[i][1] * tmp[8 * 1 + j];
+ s += c[i][2] * tmp[8 * 2 + j];
+ s += c[i][3] * tmp[8 * 3 + j];
+ s += c[i][4] * tmp[8 * 4 + j];
+ s += c[i][5] * tmp[8 * 5 + j];
+ s += c[i][6] * tmp[8 * 6 + j];
+ s += c[i][7] * tmp[8 * 7 + j];
+
+ block[8 * i + j] = (short)floor(s + 0.499999);
+/*
+ * reason for adding 0.499999 instead of 0.5:
+ * s is quite often x.5 (at least for i and/or j = 0 or 4)
+ * and setting the rounding threshold exactly to 0.5 leads to an
+ * extremely high arithmetic implementation dependency of the result;
+ * s being between x.5 and x.500001 (which is now incorrectly rounded
+ * downwards instead of upwards) is assumed to occur less often
+ * (if at all)
+ */
+ }
+}
diff --git a/libavcodec/h263.c b/libavcodec/h263.c
new file mode 100644
index 0000000000..35ecb15c2e
--- /dev/null
+++ b/libavcodec/h263.c
@@ -0,0 +1,1291 @@
+/*
+ * H263/MPEG4 backend for ffmpeg encoder and decoder
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ * H263+ support for custom picture format.
+ * Copyright (c) 2001 Juan J. Sierralta P.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "h263data.h"
+#include "mpeg4data.h"
+
+#define NDEBUG
+#include <assert.h>
+
+static void h263_encode_block(MpegEncContext * s, DCTELEM * block,
+ int n);
+static void h263_encode_motion(MpegEncContext * s, int val);
+static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
+ int n);
+static int h263_decode_motion(MpegEncContext * s, int pred);
+static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded);
+static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded);
+
+int h263_get_picture_format(int width, int height)
+{
+ int format;
+
+ if (width == 128 && height == 96)
+ format = 1;
+ else if (width == 176 && height == 144)
+ format = 2;
+ else if (width == 352 && height == 288)
+ format = 3;
+ else if (width == 704 && height == 576)
+ format = 4;
+ else if (width == 1408 && height == 1152)
+ format = 5;
+ else
+ format = 7;
+ return format;
+}
+
+void h263_encode_picture_header(MpegEncContext * s, int picture_number)
+{
+ int format, umvplus;
+
+ align_put_bits(&s->pb);
+ put_bits(&s->pb, 22, 0x20);
+ put_bits(&s->pb, 8, ((s->picture_number * 30 * FRAME_RATE_BASE) /
+ s->frame_rate) & 0xff);
+
+ put_bits(&s->pb, 1, 1); /* marker */
+ put_bits(&s->pb, 1, 0); /* h263 id */
+ put_bits(&s->pb, 1, 0); /* split screen off */
+ put_bits(&s->pb, 1, 0); /* camera off */
+ put_bits(&s->pb, 1, 0); /* freeze picture release off */
+
+ if (!s->h263_plus) {
+ /* H.263v1 */
+ format = h263_get_picture_format(s->width, s->height);
+ put_bits(&s->pb, 3, format);
+ put_bits(&s->pb, 1, (s->pict_type == P_TYPE));
+ /* By now UMV IS DISABLED ON H.263v1, since the restrictions
+ of H.263v1 UMV implies to check the predicted MV after
+ calculation of the current MB to see if we're on the limits */
+ put_bits(&s->pb, 1, 0); /* unrestricted motion vector: off */
+ put_bits(&s->pb, 1, 0); /* SAC: off */
+ put_bits(&s->pb, 1, 0); /* advanced prediction mode: off */
+ put_bits(&s->pb, 1, 0); /* not PB frame */
+ put_bits(&s->pb, 5, s->qscale);
+ put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */
+ } else {
+ /* H.263v2 */
+ /* H.263 Plus PTYPE */
+ put_bits(&s->pb, 3, 7);
+ put_bits(&s->pb,3,1); /* Update Full Extended PTYPE */
+ put_bits(&s->pb,3,6); /* Custom Source Format */
+ put_bits(&s->pb,1,0); /* Custom PCF: off */
+ umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv;
+ put_bits(&s->pb, 1, umvplus); /* Unrestricted Motion Vector */
+ put_bits(&s->pb,1,0); /* SAC: off */
+ put_bits(&s->pb,1,0); /* Advanced Prediction Mode: off */
+ put_bits(&s->pb,1,0); /* Advanced Intra Coding: off */
+ put_bits(&s->pb,1,0); /* Deblocking Filter: off */
+ put_bits(&s->pb,1,0); /* Slice Structured: off */
+ put_bits(&s->pb,1,0); /* Reference Picture Selection: off */
+ put_bits(&s->pb,1,0); /* Independent Segment Decoding: off */
+ put_bits(&s->pb,1,0); /* Alternative Inter VLC: off */
+ put_bits(&s->pb,1,0); /* Modified Quantization: off */
+ put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
+ put_bits(&s->pb,3,0); /* Reserved */
+
+ put_bits(&s->pb, 3, s->pict_type == P_TYPE);
+
+ put_bits(&s->pb,1,0); /* Reference Picture Resampling: off */
+ put_bits(&s->pb,1,0); /* Reduced-Resolution Update: off */
+ put_bits(&s->pb,1,0); /* Rounding Type */
+ put_bits(&s->pb,2,0); /* Reserved */
+ put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
+
+ /* This should be here if PLUSPTYPE */
+ put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */
+
+ /* Custom Picture Format (CPFMT) */
+
+ put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */
+ put_bits(&s->pb,9,(s->width >> 2) - 1);
+ put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
+ put_bits(&s->pb,9,(s->height >> 2));
+ /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */
+ if (umvplus)
+ put_bits(&s->pb,1,1); /* Limited according tables of Annex D */
+ put_bits(&s->pb, 5, s->qscale);
+ }
+
+ put_bits(&s->pb, 1, 0); /* no PEI */
+}
+
+void h263_encode_mb(MpegEncContext * s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y)
+{
+ int cbpc, cbpy, i, cbp, pred_x, pred_y;
+
+ // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
+ if (!s->mb_intra) {
+ /* compute cbp */
+ cbp = 0;
+ for (i = 0; i < 6; i++) {
+ if (s->block_last_index[i] >= 0)
+ cbp |= 1 << (5 - i);
+ }
+ if ((cbp | motion_x | motion_y) == 0) {
+ /* skip macroblock */
+ put_bits(&s->pb, 1, 1);
+ return;
+ }
+ put_bits(&s->pb, 1, 0); /* mb coded */
+ cbpc = cbp & 3;
+ put_bits(&s->pb,
+ inter_MCBPC_bits[cbpc],
+ inter_MCBPC_code[cbpc]);
+ cbpy = cbp >> 2;
+ cbpy ^= 0xf;
+ put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
+
+ /* motion vectors: 16x16 mode only now */
+ h263_pred_motion(s, 0, &pred_x, &pred_y);
+
+ h263_encode_motion(s, motion_x - pred_x);
+ h263_encode_motion(s, motion_y - pred_y);
+ } else {
+ /* compute cbp */
+ cbp = 0;
+ for (i = 0; i < 6; i++) {
+ if (s->block_last_index[i] >= 1)
+ cbp |= 1 << (5 - i);
+ }
+
+ cbpc = cbp & 3;
+ if (s->pict_type == I_TYPE) {
+ put_bits(&s->pb,
+ intra_MCBPC_bits[cbpc],
+ intra_MCBPC_code[cbpc]);
+ } else {
+ put_bits(&s->pb, 1, 0); /* mb coded */
+ put_bits(&s->pb,
+ inter_MCBPC_bits[cbpc + 4],
+ inter_MCBPC_code[cbpc + 4]);
+ }
+ if (s->h263_pred) {
+ /* XXX: currently, we do not try to use ac prediction */
+ put_bits(&s->pb, 1, 0); /* no ac prediction */
+ }
+ cbpy = cbp >> 2;
+ put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
+ }
+
+ /* encode each block */
+ if (s->h263_pred) {
+ for (i = 0; i < 6; i++) {
+ mpeg4_encode_block(s, block[i], i);
+ }
+ } else {
+ for (i = 0; i < 6; i++) {
+ h263_encode_block(s, block[i], i);
+ }
+ }
+}
+
+static inline int mid_pred(int a, int b, int c)
+{
+ int vmin, vmax;
+ vmin = a;
+ if (b < vmin)
+ vmin = b;
+ if (c < vmin)
+ vmin = c;
+
+ vmax = a;
+ if (b > vmax)
+ vmax = b;
+ if (c > vmax)
+ vmax = c;
+
+ return a + b + c - vmin - vmax;
+}
+
+INT16 *h263_pred_motion(MpegEncContext * s, int block,
+ int *px, int *py)
+{
+ int x, y, wrap;
+ INT16 *A, *B, *C, *mot_val;
+
+ x = 2 * s->mb_x + 1 + (block & 1);
+ y = 2 * s->mb_y + 1 + ((block >> 1) & 1);
+ wrap = 2 * s->mb_width + 2;
+
+ mot_val = s->motion_val[(x) + (y) * wrap];
+
+ /* special case for first line */
+ if (y == 1 || s->first_slice_line) {
+ A = s->motion_val[(x-1) + (y) * wrap];
+ *px = A[0];
+ *py = A[1];
+ } else {
+ switch(block) {
+ default:
+ case 0:
+ A = s->motion_val[(x-1) + (y) * wrap];
+ B = s->motion_val[(x) + (y-1) * wrap];
+ C = s->motion_val[(x+2) + (y-1) * wrap];
+ break;
+ case 1:
+ case 2:
+ A = s->motion_val[(x-1) + (y) * wrap];
+ B = s->motion_val[(x) + (y-1) * wrap];
+ C = s->motion_val[(x+1) + (y-1) * wrap];
+ break;
+ case 3:
+ A = s->motion_val[(x-1) + (y) * wrap];
+ B = s->motion_val[(x-1) + (y-1) * wrap];
+ C = s->motion_val[(x) + (y-1) * wrap];
+ break;
+ }
+ *px = mid_pred(A[0], B[0], C[0]);
+ *py = mid_pred(A[1], B[1], C[1]);
+ }
+ return mot_val;
+}
+
+
+static void h263_encode_motion(MpegEncContext * s, int val)
+{
+ int range, l, m, bit_size, sign, code, bits;
+
+ if (val == 0) {
+ /* zero vector */
+ code = 0;
+ put_bits(&s->pb, mvtab[code][1], mvtab[code][0]);
+ } else {
+ bit_size = s->f_code - 1;
+ range = 1 << bit_size;
+ /* modulo encoding */
+ l = range * 32;
+ m = 2 * l;
+ if (val < -l) {
+ val += m;
+ } else if (val >= l) {
+ val -= m;
+ }
+
+ if (val >= 0) {
+ val--;
+ code = (val >> bit_size) + 1;
+ bits = val & (range - 1);
+ sign = 0;
+ } else {
+ val = -val;
+ val--;
+ code = (val >> bit_size) + 1;
+ bits = val & (range - 1);
+ sign = 1;
+ }
+
+ put_bits(&s->pb, mvtab[code][1] + 1, (mvtab[code][0] << 1) | sign);
+ if (bit_size > 0) {
+ put_bits(&s->pb, bit_size, bits);
+ }
+ }
+}
+
+void h263_encode_init_vlc(MpegEncContext *s)
+{
+ static int done = 0;
+
+ if (!done) {
+ done = 1;
+ init_rl(&rl_inter);
+ init_rl(&rl_intra);
+ }
+}
+
+static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n)
+{
+ int level, run, last, i, j, last_index, last_non_zero, sign, slevel;
+ int code;
+ RLTable *rl = &rl_inter;
+
+ if (s->mb_intra) {
+ /* DC coef */
+ level = block[0];
+ /* 255 cannot be represented, so we clamp */
+ if (level > 254) {
+ level = 254;
+ block[0] = 254;
+ }
+ if (level == 128)
+ put_bits(&s->pb, 8, 0xff);
+ else
+ put_bits(&s->pb, 8, level & 0xff);
+ i = 1;
+ } else {
+ i = 0;
+ }
+
+ /* AC coefs */
+ last_index = s->block_last_index[n];
+ last_non_zero = i - 1;
+ for (; i <= last_index; i++) {
+ j = zigzag_direct[i];
+ level = block[j];
+ if (level) {
+ run = i - last_non_zero - 1;
+ last = (i == last_index);
+ sign = 0;
+ slevel = level;
+ if (level < 0) {
+ sign = 1;
+ level = -level;
+ }
+ code = get_rl_index(rl, last, run, level);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ if (code == rl->n) {
+ put_bits(&s->pb, 1, last);
+ put_bits(&s->pb, 6, run);
+ put_bits(&s->pb, 8, slevel & 0xff);
+ } else {
+ put_bits(&s->pb, 1, sign);
+ }
+ last_non_zero = i;
+ }
+ }
+}
+
+/***************************************************/
+
+/* write mpeg4 VOP header */
+void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
+{
+ align_put_bits(&s->pb);
+
+ put_bits(&s->pb, 32, 0x1B6); /* vop header */
+ put_bits(&s->pb, 2, s->pict_type - 1); /* pict type: I = 0 , P = 1 */
+ /* XXX: time base + 1 not always correct */
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, 1, 0);
+
+ put_bits(&s->pb, 1, 1); /* marker */
+ put_bits(&s->pb, 4, 1); /* XXX: correct time increment */
+ put_bits(&s->pb, 1, 1); /* marker */
+ put_bits(&s->pb, 1, 1); /* vop coded */
+ if (s->pict_type == P_TYPE) {
+ s->no_rounding = 0;
+ put_bits(&s->pb, 1, s->no_rounding); /* rounding type */
+ }
+ put_bits(&s->pb, 3, 0); /* intra dc VLC threshold */
+
+ put_bits(&s->pb, 5, s->qscale);
+
+ if (s->pict_type != I_TYPE)
+ put_bits(&s->pb, 3, s->f_code); /* fcode_for */
+ // printf("****frame %d\n", picture_number);
+}
+
+void h263_dc_scale(MpegEncContext * s)
+{
+ int quant;
+
+ quant = s->qscale;
+ /* luminance */
+ if (quant < 5)
+ s->y_dc_scale = 8;
+ else if (quant > 4 && quant < 9)
+ s->y_dc_scale = (2 * quant);
+ else if (quant > 8 && quant < 25)
+ s->y_dc_scale = (quant + 8);
+ else
+ s->y_dc_scale = (2 * quant - 16);
+ /* chrominance */
+ if (quant < 5)
+ s->c_dc_scale = 8;
+ else if (quant > 4 && quant < 25)
+ s->c_dc_scale = ((quant + 13) / 2);
+ else
+ s->c_dc_scale = (quant - 6);
+}
+
+static int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr)
+{
+ int a, b, c, x, y, wrap, pred, scale;
+ UINT16 *dc_val;
+
+ /* find prediction */
+ if (n < 4) {
+ x = 2 * s->mb_x + 1 + (n & 1);
+ y = 2 * s->mb_y + 1 + ((n & 2) >> 1);
+ wrap = s->mb_width * 2 + 2;
+ dc_val = s->dc_val[0];
+ scale = s->y_dc_scale;
+ } else {
+ x = s->mb_x + 1;
+ y = s->mb_y + 1;
+ wrap = s->mb_width + 2;
+ dc_val = s->dc_val[n - 4 + 1];
+ scale = s->c_dc_scale;
+ }
+
+ /* B C
+ * A X
+ */
+ a = dc_val[(x - 1) + (y) * wrap];
+ b = dc_val[(x - 1) + (y - 1) * wrap];
+ c = dc_val[(x) + (y - 1) * wrap];
+
+ if (abs(a - b) < abs(b - c)) {
+ pred = c;
+ *dir_ptr = 1; /* top */
+ } else {
+ pred = a;
+ *dir_ptr = 0; /* left */
+ }
+ /* we assume pred is positive */
+ pred = (pred + (scale >> 1)) / scale;
+
+ /* prepare address for prediction update */
+ *dc_val_ptr = &dc_val[(x) + (y) * wrap];
+
+ return pred;
+}
+
+void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
+ int dir)
+{
+ int x, y, wrap, i;
+ INT16 *ac_val, *ac_val1;
+
+ /* find prediction */
+ if (n < 4) {
+ x = 2 * s->mb_x + 1 + (n & 1);
+ y = 2 * s->mb_y + 1 + ((n & 2) >> 1);
+ wrap = s->mb_width * 2 + 2;
+ ac_val = s->ac_val[0][0];
+ } else {
+ x = s->mb_x + 1;
+ y = s->mb_y + 1;
+ wrap = s->mb_width + 2;
+ ac_val = s->ac_val[n - 4 + 1][0];
+ }
+ ac_val += ((y) * wrap + (x)) * 16;
+ ac_val1 = ac_val;
+ if (s->ac_pred) {
+ if (dir == 0) {
+ /* left prediction */
+ ac_val -= 16;
+ for(i=1;i<8;i++) {
+ block[i*8] += ac_val[i];
+ }
+ } else {
+ /* top prediction */
+ ac_val -= 16 * wrap;
+ for(i=1;i<8;i++) {
+ block[i] += ac_val[i + 8];
+ }
+ }
+ }
+ /* left copy */
+ for(i=1;i<8;i++)
+ ac_val1[i] = block[i * 8];
+ /* top copy */
+ for(i=1;i<8;i++)
+ ac_val1[8 + i] = block[i];
+}
+
+static inline void mpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr)
+{
+ int size, v, pred;
+ UINT16 *dc_val;
+
+ pred = mpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+ if (n < 4) {
+ *dc_val = level * s->y_dc_scale;
+ } else {
+ *dc_val = level * s->c_dc_scale;
+ }
+
+ /* do the prediction */
+ level -= pred;
+ /* find number of bits */
+ size = 0;
+ v = abs(level);
+ while (v) {
+ v >>= 1;
+ size++;
+ }
+
+ if (n < 4) {
+ /* luminance */
+ put_bits(&s->pb, DCtab_lum[size][1], DCtab_lum[size][0]);
+ } else {
+ /* chrominance */
+ put_bits(&s->pb, DCtab_chrom[size][1], DCtab_chrom[size][0]);
+ }
+
+ /* encode remaining bits */
+ if (size > 0) {
+ if (level < 0)
+ level = (-level) ^ ((1 << size) - 1);
+ put_bits(&s->pb, size, level);
+ if (size > 8)
+ put_bits(&s->pb, 1, 1);
+ }
+}
+
+static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
+{
+ int level, run, last, i, j, last_index, last_non_zero, sign, slevel;
+ int code, dc_pred_dir;
+ const RLTable *rl;
+
+ if (s->mb_intra) {
+ /* mpeg4 based DC predictor */
+ mpeg4_encode_dc(s, block[0], n, &dc_pred_dir);
+ i = 1;
+ rl = &rl_intra;
+ } else {
+ i = 0;
+ rl = &rl_inter;
+ }
+
+ /* AC coefs */
+ last_index = s->block_last_index[n];
+ last_non_zero = i - 1;
+ for (; i <= last_index; i++) {
+ j = zigzag_direct[i];
+ level = block[j];
+ if (level) {
+ run = i - last_non_zero - 1;
+ last = (i == last_index);
+ sign = 0;
+ slevel = level;
+ if (level < 0) {
+ sign = 1;
+ level = -level;
+ }
+ code = get_rl_index(rl, last, run, level);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ if (code == rl->n) {
+ int level1, run1;
+ level1 = level - rl->max_level[last][run];
+ if (level1 < 1)
+ goto esc2;
+ code = get_rl_index(rl, last, run, level1);
+ if (code == rl->n) {
+ esc2:
+ put_bits(&s->pb, 1, 1);
+ if (level > MAX_LEVEL)
+ goto esc3;
+ run1 = run - rl->max_run[last][level] - 1;
+ if (run1 < 0)
+ goto esc3;
+ code = get_rl_index(rl, last, run1, level);
+ if (code == rl->n) {
+ esc3:
+ /* third escape */
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, 1, last);
+ put_bits(&s->pb, 6, run);
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, 12, slevel & 0xfff);
+ put_bits(&s->pb, 1, 1);
+ } else {
+ /* second escape */
+ put_bits(&s->pb, 1, 0);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ put_bits(&s->pb, 1, sign);
+ }
+ } else {
+ /* first escape */
+ put_bits(&s->pb, 1, 0);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ put_bits(&s->pb, 1, sign);
+ }
+ } else {
+ put_bits(&s->pb, 1, sign);
+ }
+ last_non_zero = i;
+ }
+ }
+}
+
+
+
+/***********************************************/
+/* decoding */
+
+static VLC intra_MCBPC_vlc;
+static VLC inter_MCBPC_vlc;
+static VLC cbpy_vlc;
+static VLC mv_vlc;
+static VLC dc_lum, dc_chrom;
+
+void init_rl(RLTable *rl)
+{
+ INT8 max_level[MAX_RUN+1], max_run[MAX_LEVEL+1];
+ UINT8 index_run[MAX_RUN+1];
+ int last, run, level, start, end, i;
+
+ /* compute max_level[], max_run[] and index_run[] */
+ for(last=0;last<2;last++) {
+ if (last == 0) {
+ start = 0;
+ end = rl->last;
+ } else {
+ start = rl->last;
+ end = rl->n;
+ }
+
+ memset(max_level, 0, MAX_RUN + 1);
+ memset(max_run, 0, MAX_LEVEL + 1);
+ memset(index_run, rl->n, MAX_RUN + 1);
+ for(i=start;i<end;i++) {
+ run = rl->table_run[i];
+ level = rl->table_level[i];
+ if (index_run[run] == rl->n)
+ index_run[run] = i;
+ if (level > max_level[run])
+ max_level[run] = level;
+ if (run > max_run[level])
+ max_run[level] = run;
+ }
+ rl->max_level[last] = malloc(MAX_RUN + 1);
+ memcpy(rl->max_level[last], max_level, MAX_RUN + 1);
+ rl->max_run[last] = malloc(MAX_LEVEL + 1);
+ memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1);
+ rl->index_run[last] = malloc(MAX_RUN + 1);
+ memcpy(rl->index_run[last], index_run, MAX_RUN + 1);
+ }
+}
+
+void init_vlc_rl(RLTable *rl)
+{
+ init_vlc(&rl->vlc, 9, rl->n + 1,
+ &rl->table_vlc[0][1], 4, 2,
+ &rl->table_vlc[0][0], 4, 2);
+}
+
+/* init vlcs */
+
+/* XXX: find a better solution to handle static init */
+void h263_decode_init_vlc(MpegEncContext *s)
+{
+ static int done = 0;
+
+ if (!done) {
+ done = 1;
+
+ init_vlc(&intra_MCBPC_vlc, 6, 8,
+ intra_MCBPC_bits, 1, 1,
+ intra_MCBPC_code, 1, 1);
+ init_vlc(&inter_MCBPC_vlc, 9, 20,
+ inter_MCBPC_bits, 1, 1,
+ inter_MCBPC_code, 1, 1);
+ init_vlc(&cbpy_vlc, 6, 16,
+ &cbpy_tab[0][1], 2, 1,
+ &cbpy_tab[0][0], 2, 1);
+ init_vlc(&mv_vlc, 9, 33,
+ &mvtab[0][1], 2, 1,
+ &mvtab[0][0], 2, 1);
+ init_rl(&rl_inter);
+ init_rl(&rl_intra);
+ init_vlc_rl(&rl_inter);
+ init_vlc_rl(&rl_intra);
+ init_vlc(&dc_lum, 9, 13,
+ &DCtab_lum[0][1], 2, 1,
+ &DCtab_lum[0][0], 2, 1);
+ init_vlc(&dc_chrom, 9, 13,
+ &DCtab_chrom[0][1], 2, 1,
+ &DCtab_chrom[0][0], 2, 1);
+ }
+}
+
+int h263_decode_mb(MpegEncContext *s,
+ DCTELEM block[6][64])
+{
+ int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant;
+ INT16 *mot_val;
+ static UINT8 quant_tab[4] = { -1, -2, 1, 2 };
+
+ if (s->pict_type == P_TYPE) {
+ if (get_bits(&s->gb, 1)) {
+ /* skip mb */
+ s->mb_intra = 0;
+ for(i=0;i<6;i++)
+ s->block_last_index[i] = -1;
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ s->mv[0][0][0] = 0;
+ s->mv[0][0][1] = 0;
+ return 0;
+ }
+ cbpc = get_vlc(&s->gb, &inter_MCBPC_vlc);
+ if (cbpc < 0)
+ return -1;
+ dquant = cbpc & 8;
+ s->mb_intra = ((cbpc & 4) != 0);
+ } else {
+ cbpc = get_vlc(&s->gb, &intra_MCBPC_vlc);
+ if (cbpc < 0)
+ return -1;
+ dquant = cbpc & 4;
+ s->mb_intra = 1;
+ }
+
+ if (!s->mb_intra) {
+ cbpy = get_vlc(&s->gb, &cbpy_vlc);
+ cbp = (cbpc & 3) | ((cbpy ^ 0xf) << 2);
+ if (dquant) {
+ s->qscale += quant_tab[get_bits(&s->gb, 2)];
+ if (s->qscale < 1)
+ s->qscale = 1;
+ else if (s->qscale > 31)
+ s->qscale = 31;
+ }
+ s->mv_dir = MV_DIR_FORWARD;
+ if ((cbpc & 16) == 0) {
+ /* 16x16 motion prediction */
+ s->mv_type = MV_TYPE_16X16;
+ h263_pred_motion(s, 0, &pred_x, &pred_y);
+ mx = h263_decode_motion(s, pred_x);
+ if (mx >= 0xffff)
+ return -1;
+ my = h263_decode_motion(s, pred_y);
+ if (my >= 0xffff)
+ return -1;
+ s->mv[0][0][0] = mx;
+ s->mv[0][0][1] = my;
+ } else {
+ s->mv_type = MV_TYPE_8X8;
+ for(i=0;i<4;i++) {
+ mot_val = h263_pred_motion(s, i, &pred_x, &pred_y);
+ mx = h263_decode_motion(s, pred_x);
+ if (mx >= 0xffff)
+ return -1;
+ my = h263_decode_motion(s, pred_y);
+ if (my >= 0xffff)
+ return -1;
+ s->mv[0][i][0] = mx;
+ s->mv[0][i][1] = my;
+ mot_val[0] = mx;
+ mot_val[1] = my;
+ }
+ }
+ } else {
+ s->ac_pred = 0;
+ if (s->h263_pred) {
+ s->ac_pred = get_bits(&s->gb, 1);
+ }
+ cbpy = get_vlc(&s->gb, &cbpy_vlc);
+ cbp = (cbpc & 3) | (cbpy << 2);
+ if (dquant) {
+ s->qscale += quant_tab[get_bits(&s->gb, 2)];
+ if (s->qscale < 1)
+ s->qscale = 1;
+ else if (s->qscale > 31)
+ s->qscale = 31;
+ }
+ }
+
+ /* decode each block */
+ if (s->h263_pred) {
+ for (i = 0; i < 6; i++) {
+ if (mpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0)
+ return -1;
+ }
+ } else {
+ for (i = 0; i < 6; i++) {
+ if (h263_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int h263_decode_motion(MpegEncContext * s, int pred)
+{
+ int code, val, sign, shift, l, m;
+
+ code = get_vlc(&s->gb, &mv_vlc);
+ if (code < 0)
+ return 0xffff;
+
+ if (code == 0)
+ return pred;
+ sign = get_bits(&s->gb, 1);
+ shift = s->f_code - 1;
+ val = (code - 1) << shift;
+ if (shift > 0)
+ val |= get_bits(&s->gb, shift);
+ val++;
+ if (sign)
+ val = -val;
+ val += pred;
+
+ /* modulo decoding */
+ if (!s->h263_long_vectors) {
+ l = (1 << (s->f_code - 1)) * 32;
+ m = 2 * l;
+ if (val < -l) {
+ val += m;
+ } else if (val >= l) {
+ val -= m;
+ }
+ } else {
+ /* horrible h263 long vector mode */
+ if (pred < -31 && val < -63)
+ val += 64;
+ if (pred > 32 && val > 63)
+ val -= 64;
+ }
+ return val;
+}
+
+static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded)
+{
+ int code, level, i, j, last, run;
+ RLTable *rl = &rl_inter;
+
+ if (s->mb_intra) {
+ /* DC coef */
+ if (s->h263_rv10 && s->rv10_version == 3 && s->pict_type == I_TYPE) {
+ int component, diff;
+ component = (n <= 3 ? 0 : n - 4 + 1);
+ level = s->last_dc[component];
+ if (s->rv10_first_dc_coded[component]) {
+ diff = rv_decode_dc(s, n);
+ if (diff == 0xffff)
+ return -1;
+ level += diff;
+ level = level & 0xff; /* handle wrap round */
+ s->last_dc[component] = level;
+ } else {
+ s->rv10_first_dc_coded[component] = 1;
+ }
+ } else {
+ level = get_bits(&s->gb, 8);
+ if (level == 255)
+ level = 128;
+ }
+ block[0] = level;
+ i = 1;
+ } else {
+ i = 0;
+ }
+ if (!coded) {
+ s->block_last_index[n] = i - 1;
+ return 0;
+ }
+
+ for(;;) {
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0)
+ return -1;
+ if (code == rl->n) {
+ /* escape */
+ last = get_bits(&s->gb, 1);
+ run = get_bits(&s->gb, 6);
+ level = (INT8)get_bits(&s->gb, 8);
+ if (s->h263_rv10 && level == -128) {
+ /* XXX: should patch encoder too */
+ level = get_bits(&s->gb, 12);
+ level = (level << 20) >> 20;
+ }
+ } else {
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ last = code >= rl->last;
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ i += run;
+ if (i >= 64)
+ return -1;
+ j = zigzag_direct[i];
+ block[j] = level;
+ if (last)
+ break;
+ i++;
+ }
+ s->block_last_index[n] = i;
+ return 0;
+}
+
+static int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
+{
+ int level, pred, code;
+ UINT16 *dc_val;
+
+ if (n < 4)
+ code = get_vlc(&s->gb, &dc_lum);
+ else
+ code = get_vlc(&s->gb, &dc_chrom);
+ if (code < 0)
+ return -1;
+ if (code == 0) {
+ level = 0;
+ } else {
+ level = get_bits(&s->gb, code);
+ if ((level >> (code - 1)) == 0) /* if MSB not set it is negative*/
+ level = - (level ^ ((1 << code) - 1));
+ if (code > 8)
+ get_bits(&s->gb, 1); /* marker */
+ }
+
+ pred = mpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+ level += pred;
+ if (level < 0)
+ level = 0;
+ if (n < 4) {
+ *dc_val = level * s->y_dc_scale;
+ } else {
+ *dc_val = level * s->c_dc_scale;
+ }
+ return level;
+}
+
+static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded)
+{
+ int code, level, i, j, last, run;
+ int dc_pred_dir;
+ RLTable *rl;
+ const UINT8 *scan_table;
+
+ if (s->mb_intra) {
+ /* DC coef */
+ level = mpeg4_decode_dc(s, n, &dc_pred_dir);
+ if (level < 0)
+ return -1;
+ block[0] = level;
+ i = 1;
+ if (!coded)
+ goto not_coded;
+ rl = &rl_intra;
+ if (s->ac_pred) {
+ if (dc_pred_dir == 0)
+ scan_table = ff_alternate_vertical_scan; /* left */
+ else
+ scan_table = ff_alternate_horizontal_scan; /* top */
+ } else {
+ scan_table = zigzag_direct;
+ }
+ } else {
+ i = 0;
+ if (!coded) {
+ s->block_last_index[n] = i - 1;
+ return 0;
+ }
+ rl = &rl_inter;
+ scan_table = zigzag_direct;
+ }
+
+ for(;;) {
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0)
+ return -1;
+ if (code == rl->n) {
+ /* escape */
+ if (get_bits(&s->gb, 1) != 0) {
+ if (get_bits(&s->gb, 1) != 0) {
+ /* third escape */
+ last = get_bits(&s->gb, 1);
+ run = get_bits(&s->gb, 6);
+ get_bits(&s->gb, 1); /* marker */
+ level = get_bits(&s->gb, 12);
+ level = (level << 20) >> 20; /* sign extend */
+ get_bits(&s->gb, 1); /* marker */
+ } else {
+ /* second escape */
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0 || code >= rl->n)
+ return -1;
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ last = code >= rl->last;
+ run += rl->max_run[last][level] + 1;
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ } else {
+ /* first escape */
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0 || code >= rl->n)
+ return -1;
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ last = code >= rl->last;
+ level += rl->max_level[last][run];
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ } else {
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ last = code >= rl->last;
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ i += run;
+ if (i >= 64)
+ return -1;
+ j = scan_table[i];
+ block[j] = level;
+ i++;
+ if (last)
+ break;
+ }
+ not_coded:
+ if (s->mb_intra) {
+ mpeg4_pred_ac(s, block, n, dc_pred_dir);
+ if (s->ac_pred) {
+ i = 64; /* XXX: not optimal */
+ }
+ }
+ s->block_last_index[n] = i - 1;
+ return 0;
+}
+
+/* most is hardcoded. should extend to handle all h263 streams */
+int h263_decode_picture_header(MpegEncContext *s)
+{
+ int format, width, height;
+
+ /* picture header */
+ if (get_bits(&s->gb, 22) != 0x20)
+ return -1;
+ get_bits(&s->gb, 8); /* picture timestamp */
+
+ if (get_bits(&s->gb, 1) != 1)
+ return -1; /* marker */
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* h263 id */
+ get_bits(&s->gb, 1); /* split screen off */
+ get_bits(&s->gb, 1); /* camera off */
+ get_bits(&s->gb, 1); /* freeze picture release off */
+
+ format = get_bits(&s->gb, 3);
+
+ if (format != 7) {
+ s->h263_plus = 0;
+ /* H.263v1 */
+ width = h263_format[format][0];
+ height = h263_format[format][1];
+ if (!width)
+ return -1;
+
+ s->pict_type = I_TYPE + get_bits(&s->gb, 1);
+
+ s->unrestricted_mv = get_bits(&s->gb, 1);
+ s->h263_long_vectors = s->unrestricted_mv;
+
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* SAC: off */
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* advanced prediction mode: off */
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* not PB frame */
+
+ s->qscale = get_bits(&s->gb, 5);
+ get_bits(&s->gb, 1); /* Continuous Presence Multipoint mode: off */
+ } else {
+ s->h263_plus = 1;
+ /* H.263v2 */
+ if (get_bits(&s->gb, 3) != 1)
+ return -1;
+ if (get_bits(&s->gb, 3) != 6) /* custom source format */
+ return -1;
+ get_bits(&s->gb, 12);
+ get_bits(&s->gb, 3);
+ s->pict_type = get_bits(&s->gb, 3) + 1;
+ if (s->pict_type != I_TYPE &&
+ s->pict_type != P_TYPE)
+ return -1;
+ get_bits(&s->gb, 7);
+ get_bits(&s->gb, 4); /* aspect ratio */
+ width = (get_bits(&s->gb, 9) + 1) * 4;
+ get_bits(&s->gb, 1);
+ height = get_bits(&s->gb, 9) * 4;
+ if (height == 0)
+ return -1;
+ s->qscale = get_bits(&s->gb, 5);
+ }
+ /* PEI */
+ while (get_bits(&s->gb, 1) != 0) {
+ get_bits(&s->gb, 8);
+ }
+ s->f_code = 1;
+ s->width = width;
+ s->height = height;
+ return 0;
+}
+
+/* decode mpeg4 VOP header */
+int mpeg4_decode_picture_header(MpegEncContext * s)
+{
+ int time_incr, startcode, state, v;
+
+ redo:
+ /* search next start code */
+ align_get_bits(&s->gb);
+ state = 0xff;
+ for(;;) {
+ v = get_bits(&s->gb, 8);
+ if (state == 0x000001) {
+ state = ((state << 8) | v) & 0xffffff;
+ startcode = state;
+ break;
+ }
+ state = ((state << 8) | v) & 0xffffff;
+ /* XXX: really detect end of frame */
+ if (state == 0)
+ return -1;
+ }
+
+ if (startcode == 0x120) {
+ int time_increment_resolution, width, height;
+
+ /* vol header */
+ get_bits(&s->gb, 1); /* random access */
+ get_bits(&s->gb, 8); /* vo_type */
+ get_bits(&s->gb, 1); /* is_ol_id */
+ get_bits(&s->gb, 4); /* vo_ver_id */
+ get_bits(&s->gb, 3); /* vo_priority */
+
+ get_bits(&s->gb, 4); /* aspect_ratio_info */
+ get_bits(&s->gb, 1); /* vol control parameter */
+ get_bits(&s->gb, 2); /* vol shape */
+ get_bits(&s->gb, 1); /* marker */
+
+ time_increment_resolution = get_bits(&s->gb, 16);
+ s->time_increment_bits = log2(time_increment_resolution - 1) + 1;
+ get_bits(&s->gb, 1); /* marker */
+
+ get_bits(&s->gb, 1); /* vop rate */
+ get_bits(&s->gb, s->time_increment_bits);
+ get_bits(&s->gb, 1); /* marker */
+
+ width = get_bits(&s->gb, 13);
+ get_bits(&s->gb, 1); /* marker */
+ height = get_bits(&s->gb, 13);
+ get_bits(&s->gb, 1); /* marker */
+
+ get_bits(&s->gb, 1); /* interfaced */
+ get_bits(&s->gb, 1); /* OBMC */
+ get_bits(&s->gb, 2); /* vol_sprite_usage */
+ get_bits(&s->gb, 1); /* not_8_bit */
+
+ get_bits(&s->gb, 1); /* vol_quant_type */
+ get_bits(&s->gb, 1); /* vol_quarter_pixel */
+ get_bits(&s->gb, 1); /* complexity_estimation_disabled */
+ get_bits(&s->gb, 1); /* resync_marker_disabled */
+ get_bits(&s->gb, 1); /* data_partioning_enabled */
+ goto redo;
+ } else if (startcode != 0x1b6) {
+ goto redo;
+ }
+
+ s->pict_type = get_bits(&s->gb, 2) + 1; /* pict type: I = 0 , P = 1 */
+ if (s->pict_type != I_TYPE &&
+ s->pict_type != P_TYPE)
+ return -1;
+
+ /* XXX: parse time base */
+ time_incr = 0;
+ while (get_bits(&s->gb, 1) != 0)
+ time_incr++;
+
+ get_bits(&s->gb, 1); /* marker */
+ get_bits(&s->gb, s->time_increment_bits);
+ get_bits(&s->gb, 1); /* marker */
+ /* vop coded */
+ if (get_bits(&s->gb, 1) != 1)
+ return -1;
+
+ if (s->pict_type == P_TYPE) {
+ /* rounding type for motion estimation */
+ s->no_rounding = get_bits(&s->gb, 1);
+ }
+
+ if (get_bits(&s->gb, 3) != 0)
+ return -1; /* intra dc VLC threshold */
+
+ s->qscale = get_bits(&s->gb, 5);
+
+ if (s->pict_type != I_TYPE) {
+ s->f_code = get_bits(&s->gb, 3); /* fcode_for */
+ }
+ return 0;
+}
+
+/* don't understand why they choose a different header ! */
+int intel_h263_decode_picture_header(MpegEncContext *s)
+{
+ int format;
+
+ /* picture header */
+ if (get_bits(&s->gb, 22) != 0x20)
+ return -1;
+ get_bits(&s->gb, 8); /* picture timestamp */
+
+ if (get_bits(&s->gb, 1) != 1)
+ return -1; /* marker */
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* h263 id */
+ get_bits(&s->gb, 1); /* split screen off */
+ get_bits(&s->gb, 1); /* camera off */
+ get_bits(&s->gb, 1); /* freeze picture release off */
+
+ format = get_bits(&s->gb, 3);
+ if (format != 7)
+ return -1;
+
+ s->h263_plus = 0;
+
+ s->pict_type = I_TYPE + get_bits(&s->gb, 1);
+
+ s->unrestricted_mv = get_bits(&s->gb, 1);
+ s->h263_long_vectors = s->unrestricted_mv;
+
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* SAC: off */
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* advanced prediction mode: off */
+ if (get_bits(&s->gb, 1) != 0)
+ return -1; /* not PB frame */
+
+ /* skip unknown header garbage */
+ get_bits(&s->gb, 41);
+
+ s->qscale = get_bits(&s->gb, 5);
+ get_bits(&s->gb, 1); /* Continuous Presence Multipoint mode: off */
+
+ /* PEI */
+ while (get_bits(&s->gb, 1) != 0) {
+ get_bits(&s->gb, 8);
+ }
+ s->f_code = 1;
+ return 0;
+}
diff --git a/libavcodec/h263data.h b/libavcodec/h263data.h
new file mode 100644
index 0000000000..4fd9d36298
--- /dev/null
+++ b/libavcodec/h263data.h
@@ -0,0 +1,115 @@
+
+/* intra MCBPC, mb_type = (intra), then (intraq) */
+static const UINT8 intra_MCBPC_code[8] = { 1, 1, 2, 3, 1, 1, 2, 3 };
+static const UINT8 intra_MCBPC_bits[8] = { 1, 3, 3, 3, 4, 6, 6, 6 };
+
+/* inter MCBPC, mb_type = (inter), (intra), (interq), (intraq), (inter4v) */
+static const UINT8 inter_MCBPC_code[20] = {
+ 1, 3, 2, 5,
+ 3, 4, 3, 3,
+ 0, 1, 2, 3,
+ 4, 4, 3, 2,
+ 2, 5, 4, 5,
+};
+static const UINT8 inter_MCBPC_bits[20] = {
+ 1, 4, 4, 6,
+ 5, 8, 8, 7,
+ 12, 12, 12, 12,
+ 6, 9, 9, 9,
+ 3, 7, 7, 8,
+};
+
+static const UINT8 cbpy_tab[16][2] =
+{
+ {3,4}, {5,5}, {4,5}, {9,4}, {3,5}, {7,4}, {2,6}, {11,4},
+ {2,5}, {3,6}, {5,4}, {10,4}, {4,4}, {8,4}, {6,4}, {3,2}
+};
+
+static const UINT8 mvtab[33][2] =
+{
+ {1,1}, {1,2}, {1,3}, {1,4}, {3,6}, {5,7}, {4,7}, {3,7},
+ {11,9}, {10,9}, {9,9}, {17,10}, {16,10}, {15,10}, {14,10}, {13,10},
+ {12,10}, {11,10}, {10,10}, {9,10}, {8,10}, {7,10}, {6,10}, {5,10},
+ {4,10}, {7,11}, {6,11}, {5,11}, {4,11}, {3,11}, {2,11}, {3,12},
+ {2,12}
+};
+
+/* third non intra table */
+const UINT16 inter_vlc[103][2] = {
+{ 0x2, 2 },{ 0xf, 4 },{ 0x15, 6 },{ 0x17, 7 },
+{ 0x1f, 8 },{ 0x25, 9 },{ 0x24, 9 },{ 0x21, 10 },
+{ 0x20, 10 },{ 0x7, 11 },{ 0x6, 11 },{ 0x20, 11 },
+{ 0x6, 3 },{ 0x14, 6 },{ 0x1e, 8 },{ 0xf, 10 },
+{ 0x21, 11 },{ 0x50, 12 },{ 0xe, 4 },{ 0x1d, 8 },
+{ 0xe, 10 },{ 0x51, 12 },{ 0xd, 5 },{ 0x23, 9 },
+{ 0xd, 10 },{ 0xc, 5 },{ 0x22, 9 },{ 0x52, 12 },
+{ 0xb, 5 },{ 0xc, 10 },{ 0x53, 12 },{ 0x13, 6 },
+{ 0xb, 10 },{ 0x54, 12 },{ 0x12, 6 },{ 0xa, 10 },
+{ 0x11, 6 },{ 0x9, 10 },{ 0x10, 6 },{ 0x8, 10 },
+{ 0x16, 7 },{ 0x55, 12 },{ 0x15, 7 },{ 0x14, 7 },
+{ 0x1c, 8 },{ 0x1b, 8 },{ 0x21, 9 },{ 0x20, 9 },
+{ 0x1f, 9 },{ 0x1e, 9 },{ 0x1d, 9 },{ 0x1c, 9 },
+{ 0x1b, 9 },{ 0x1a, 9 },{ 0x22, 11 },{ 0x23, 11 },
+{ 0x56, 12 },{ 0x57, 12 },{ 0x7, 4 },{ 0x19, 9 },
+{ 0x5, 11 },{ 0xf, 6 },{ 0x4, 11 },{ 0xe, 6 },
+{ 0xd, 6 },{ 0xc, 6 },{ 0x13, 7 },{ 0x12, 7 },
+{ 0x11, 7 },{ 0x10, 7 },{ 0x1a, 8 },{ 0x19, 8 },
+{ 0x18, 8 },{ 0x17, 8 },{ 0x16, 8 },{ 0x15, 8 },
+{ 0x14, 8 },{ 0x13, 8 },{ 0x18, 9 },{ 0x17, 9 },
+{ 0x16, 9 },{ 0x15, 9 },{ 0x14, 9 },{ 0x13, 9 },
+{ 0x12, 9 },{ 0x11, 9 },{ 0x7, 10 },{ 0x6, 10 },
+{ 0x5, 10 },{ 0x4, 10 },{ 0x24, 11 },{ 0x25, 11 },
+{ 0x26, 11 },{ 0x27, 11 },{ 0x58, 12 },{ 0x59, 12 },
+{ 0x5a, 12 },{ 0x5b, 12 },{ 0x5c, 12 },{ 0x5d, 12 },
+{ 0x5e, 12 },{ 0x5f, 12 },{ 0x3, 7 },
+};
+
+const INT8 inter_level[102] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 1, 2, 3, 4,
+ 5, 6, 1, 2, 3, 4, 1, 2,
+ 3, 1, 2, 3, 1, 2, 3, 1,
+ 2, 3, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 3, 1, 2, 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,
+};
+
+const INT8 inter_run[102] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 3, 3,
+ 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 8, 8, 9, 9,
+ 10, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 0, 0, 0, 1, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40,
+};
+
+static RLTable rl_inter = {
+ 102,
+ 58,
+ inter_vlc,
+ inter_run,
+ inter_level,
+};
+
+static const UINT16 h263_format[8][2] = {
+ { 0, 0 },
+ { 128, 96 },
+ { 176, 144 },
+ { 352, 288 },
+ { 704, 576 },
+ { 1408, 1152 },
+};
+
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
new file mode 100644
index 0000000000..2af76199ab
--- /dev/null
+++ b/libavcodec/h263dec.c
@@ -0,0 +1,205 @@
+/*
+ * H263 decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+//#define DEBUG
+
+static int h263_decode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ s->out_format = FMT_H263;
+
+ s->width = avctx->width;
+ s->height = avctx->height;
+
+ /* select sub codec */
+ switch(avctx->codec->id) {
+ case CODEC_ID_H263:
+ break;
+ case CODEC_ID_OPENDIVX:
+ s->time_increment_bits = 4; /* default value for broken headers */
+ s->h263_pred = 1;
+ break;
+ case CODEC_ID_MSMPEG4:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ break;
+ case CODEC_ID_H263I:
+ s->h263_intel = 1;
+ break;
+ default:
+ return -1;
+ }
+
+ /* for h263, we allocate the images after having read the header */
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ if (s->h263_msmpeg4)
+ msmpeg4_decode_init_vlc(s);
+ else
+ h263_decode_init_vlc(s);
+
+ return 0;
+}
+
+static int h263_decode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ MPV_common_end(s);
+ return 0;
+}
+
+static int h263_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ UINT8 *buf, int buf_size)
+{
+ MpegEncContext *s = avctx->priv_data;
+ int ret;
+ DCTELEM block[6][64];
+ AVPicture *pict = data;
+
+#ifdef DEBUG
+ printf("*****frame %d size=%d\n", avctx->frame_number, buf_size);
+ printf("bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
+#endif
+
+ /* no supplementary picture */
+ if (buf_size == 0) {
+ *data_size = 0;
+ return 0;
+ }
+
+ init_get_bits(&s->gb, buf, buf_size);
+
+ /* let's go :-) */
+ if (s->h263_msmpeg4) {
+ ret = msmpeg4_decode_picture_header(s);
+ } else if (s->h263_pred) {
+ ret = mpeg4_decode_picture_header(s);
+ } else if (s->h263_intel) {
+ ret = intel_h263_decode_picture_header(s);
+ } else {
+ ret = h263_decode_picture_header(s);
+ }
+ if (ret < 0)
+ return -1;
+
+ MPV_frame_start(s);
+
+#ifdef DEBUG
+ printf("qscale=%d\n", s->qscale);
+#endif
+
+ /* decode each macroblock */
+ for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) {
+ for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
+#ifdef DEBUG
+ printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
+#endif
+ /* DCT & quantize */
+ if (s->h263_msmpeg4) {
+ msmpeg4_dc_scale(s);
+ } else if (s->h263_pred) {
+ h263_dc_scale(s);
+ } else {
+ /* default quantization values */
+ s->y_dc_scale = 8;
+ s->c_dc_scale = 8;
+ }
+
+ memset(block, 0, sizeof(block));
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ if (s->h263_msmpeg4) {
+ if (msmpeg4_decode_mb(s, block) < 0)
+ return -1;
+ } else {
+ if (h263_decode_mb(s, block) < 0)
+ return -1;
+ }
+ MPV_decode_mb(s, block);
+ }
+ }
+
+ MPV_frame_end(s);
+
+ pict->data[0] = s->current_picture[0];
+ pict->data[1] = s->current_picture[1];
+ pict->data[2] = s->current_picture[2];
+ pict->linesize[0] = s->linesize;
+ pict->linesize[1] = s->linesize / 2;
+ pict->linesize[2] = s->linesize / 2;
+
+ avctx->quality = s->qscale;
+ *data_size = sizeof(AVPicture);
+ return buf_size;
+}
+
+AVCodec opendivx_decoder = {
+ "opendivx",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_OPENDIVX,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+
+AVCodec h263_decoder = {
+ "h263",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+
+AVCodec msmpeg4_decoder = {
+ "msmpeg4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+
+AVCodec h263i_decoder = {
+ "h263i",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263I,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+
diff --git a/libavcodec/i386/cputest.c b/libavcodec/i386/cputest.c
new file mode 100644
index 0000000000..9181f413d5
--- /dev/null
+++ b/libavcodec/i386/cputest.c
@@ -0,0 +1,102 @@
+/* Cpu detection code, extracted from mmx.h ((c)1997-99 by H. Dietz
+ and R. Fisher). Converted to C and improved by Gerard Lantau */
+
+#include <stdlib.h>
+#include "../dsputil.h"
+
+#define cpuid(index,eax,ebx,ecx,edx) \
+ asm ("cpuid" \
+ : "=a" (eax), "=b" (ebx), \
+ "=c" (ecx), "=d" (edx) \
+ : "a" (index) \
+ : "cc")
+
+/* Function to test if multimedia instructions are supported... */
+int mm_support(void)
+{
+ int rval;
+ int eax, ebx, ecx, edx;
+
+
+ __asm__ __volatile__ (
+ /* See if CPUID instruction is supported ... */
+ /* ... Get copies of EFLAGS into eax and ecx */
+ "pushf\n\t"
+ "popl %0\n\t"
+ "movl %0, %1\n\t"
+
+ /* ... Toggle the ID bit in one copy and store */
+ /* to the EFLAGS reg */
+ "xorl $0x200000, %0\n\t"
+ "push %0\n\t"
+ "popf\n\t"
+
+ /* ... Get the (hopefully modified) EFLAGS */
+ "pushf\n\t"
+ "popl %0\n\t"
+ : "=a" (eax), "=c" (ecx)
+ :
+ : "cc"
+ );
+
+ if (eax == ecx)
+ return 0; /* CPUID not supported */
+
+ cpuid(0, eax, ebx, ecx, edx);
+
+ if (ebx == 0x756e6547 &&
+ edx == 0x49656e69 &&
+ ecx == 0x6c65746e) {
+
+ /* intel */
+ inteltest:
+ cpuid(1, eax, ebx, ecx, edx);
+ if ((edx & 0x00800000) == 0)
+ return 0;
+ rval = MM_MMX;
+ if (edx & 0x02000000)
+ rval |= MM_MMXEXT | MM_SSE;
+ if (edx & 0x04000000)
+ rval |= MM_SSE2;
+ return rval;
+ } else if (ebx == 0x68747541 &&
+ edx == 0x69746e65 &&
+ ecx == 0x444d4163) {
+ /* AMD */
+ cpuid(0x80000000, eax, ebx, ecx, edx);
+ if ((unsigned)eax < 0x80000001)
+ goto inteltest;
+ cpuid(0x80000001, eax, ebx, ecx, edx);
+ if ((edx & 0x00800000) == 0)
+ return 0;
+ rval = MM_MMX;
+ if (edx & 0x80000000)
+ rval |= MM_3DNOW;
+ if (edx & 0x00400000)
+ rval |= MM_MMXEXT;
+ return rval;
+ } else if (ebx == 0x69727943 &&
+ edx == 0x736e4978 &&
+ ecx == 0x64616574) {
+ /* Cyrix Section */
+ /* See if extended CPUID level 80000001 is supported */
+ /* The value of CPUID/80000001 for the 6x86MX is undefined
+ according to the Cyrix CPU Detection Guide (Preliminary
+ Rev. 1.01 table 1), so we'll check the value of eax for
+ CPUID/0 to see if standard CPUID level 2 is supported.
+ According to the table, the only CPU which supports level
+ 2 is also the only one which supports extended CPUID levels.
+ */
+ if (eax != 2)
+ goto inteltest;
+ cpuid(0x80000001, eax, ebx, ecx, edx);
+ if ((eax & 0x00800000) == 0)
+ return 0;
+ rval = MM_MMX;
+ if (eax & 0x01000000)
+ rval |= MM_MMXEXT;
+ return rval;
+ } else {
+ return 0;
+ }
+}
diff --git a/libavcodec/i386/dsputil_mmx.c b/libavcodec/i386/dsputil_mmx.c
new file mode 100644
index 0000000000..701b70283d
--- /dev/null
+++ b/libavcodec/i386/dsputil_mmx.c
@@ -0,0 +1,1061 @@
+/*
+ * MMX optimized DSP utils
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
+ */
+
+#include "../dsputil.h"
+
+int pix_abs16x16_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+int pix_abs16x16_sse(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+int pix_abs16x16_x2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+int pix_abs16x16_y2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+int pix_abs16x16_xy2_mmx(UINT8 *blk1, UINT8 *blk2, int lx, int h);
+
+/* pixel operations */
+static const unsigned short mm_wone[4] __attribute__ ((aligned(8))) = { 0x1, 0x1, 0x1, 0x1 };
+static const unsigned short mm_wtwo[4] __attribute__ ((aligned(8))) = { 0x2, 0x2, 0x2, 0x2 };
+
+/***********************************/
+/* 3Dnow specific */
+
+#define DEF(x) x ## _3dnow
+/* for Athlons PAVGUSB is prefered */
+#define PAVGB "pavgusb"
+
+#include "dsputil_mmx_avg.h"
+
+#undef DEF
+#undef PAVGB
+
+/***********************************/
+/* MMX2 specific */
+
+#define DEF(x) x ## _sse
+
+/* Introduced only in MMX2 set */
+#define PAVGB "pavgb"
+
+#include "dsputil_mmx_avg.h"
+
+#undef DEF
+#undef PAVGB
+
+/***********************************/
+/* standard MMX */
+
+static void get_pixels_mmx(DCTELEM *block, const UINT8 *pixels, int line_size)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ int i;
+
+ /* read the pixels */
+ p = block;
+ pix = pixels;
+ __asm __volatile("pxor %%mm7, %%mm7":::"memory");
+ for(i=0;i<4;i++) {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm2, 8%0\n\t"
+ "movq %%mm1, 16%0\n\t"
+ "movq %%mm3, 24%0\n\t"
+ :"=m"(*p)
+ :"m"(*pix), "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size*2;
+ p += 16;
+ }
+ emms();
+}
+
+static void put_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size)
+{
+ const DCTELEM *p;
+ UINT8 *pix;
+ int i;
+
+ /* read the pixels */
+ p = block;
+ pix = pixels;
+ for(i=0;i<2;i++) {
+ __asm __volatile(
+ "movq %4, %%mm0\n\t"
+ "movq 8%4, %%mm1\n\t"
+ "movq 16%4, %%mm2\n\t"
+ "movq 24%4, %%mm3\n\t"
+ "movq 32%4, %%mm4\n\t"
+ "movq 40%4, %%mm5\n\t"
+ "movq 48%4, %%mm6\n\t"
+ "movq 56%4, %%mm7\n\t"
+ "packuswb %%mm1, %%mm0\n\t"
+ "packuswb %%mm3, %%mm2\n\t"
+ "packuswb %%mm5, %%mm4\n\t"
+ "packuswb %%mm7, %%mm6\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm2, %1\n\t"
+ "movq %%mm4, %2\n\t"
+ "movq %%mm6, %3\n\t"
+ :"=m"(*pix), "=m"(*(pix+line_size))
+ ,"=m"(*(pix+line_size*2)), "=m"(*(pix+line_size*3))
+ :"m"(*p)
+ :"memory");
+ pix += line_size*4;
+ p += 32;
+ }
+ emms();
+}
+
+static void add_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line_size)
+{
+ const DCTELEM *p;
+ UINT8 *pix;
+ int i;
+
+ /* read the pixels */
+ p = block;
+ pix = pixels;
+ __asm __volatile("pxor %%mm7, %%mm7":::"memory");
+ for(i=0;i<4;i++) {
+ __asm __volatile(
+ "movq %2, %%mm0\n\t"
+ "movq 8%2, %%mm1\n\t"
+ "movq 16%2, %%mm2\n\t"
+ "movq 24%2, %%mm3\n\t"
+ "movq %0, %%mm4\n\t"
+ "movq %1, %%mm6\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "paddsw %%mm4, %%mm0\n\t"
+ "paddsw %%mm5, %%mm1\n\t"
+ "movq %%mm6, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm6\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "paddsw %%mm6, %%mm2\n\t"
+ "paddsw %%mm5, %%mm3\n\t"
+ "packuswb %%mm1, %%mm0\n\t"
+ "packuswb %%mm3, %%mm2\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm2, %1\n\t"
+ :"=m"(*pix), "=m"(*(pix+line_size))
+ :"m"(*p)
+ :"memory");
+ pix += line_size*2;
+ p += 16;
+ }
+ emms();
+}
+
+static void put_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ int dh, hh;
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ hh=h>>2;
+ dh=h&3;
+ while(hh--) {
+ __asm __volatile(
+ "movq %4, %%mm0\n\t"
+ "movq %5, %%mm1\n\t"
+ "movq %6, %%mm2\n\t"
+ "movq %7, %%mm3\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, %1\n\t"
+ "movq %%mm2, %2\n\t"
+ "movq %%mm3, %3\n\t"
+ :"=m"(*p), "=m"(*(p+line_size)), "=m"(*(p+line_size*2)), "=m"(*(p+line_size*3))
+ :"m"(*pix), "m"(*(pix+line_size)), "m"(*(pix+line_size*2)), "m"(*(pix+line_size*3))
+ :"memory");
+ pix = pix + line_size*4;
+ p = p + line_size*4;
+ }
+ while(dh--) {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix = pix + line_size;
+ p = p + line_size;
+ }
+ emms();
+}
+
+static void put_pixels_x2_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm4\n\t"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq 1%1, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm4, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size; p += line_size;
+ } while (--h);
+ emms();
+}
+
+static void put_pixels_y2_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm4\n\t"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm4, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while (--h);
+ emms();
+}
+
+static void put_pixels_xy2_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wtwo[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq 1%2, %%mm5\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "movq %%mm4, %%mm1\n\t"
+ "movq %%mm5, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpcklbw %%mm7, %%mm5\n\t"
+ "punpckhbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm5, %%mm4\n\t"
+ "paddusw %%mm3, %%mm1\n\t"
+ "paddusw %%mm6, %%mm4\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm1, %%mm2\n\t"
+ "psrlw $2, %%mm0\n\t"
+ "psrlw $2, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while(--h);
+ emms();
+}
+
+static void put_no_rnd_pixels_x2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile("pxor %%mm7, %%mm7\n\t":::"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq 1%1, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while (--h);
+ emms();
+}
+
+static void put_no_rnd_pixels_y2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile("pxor %%mm7, %%mm7\n\t":::"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while(--h);
+ emms();
+}
+
+static void put_no_rnd_pixels_xy2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq 1%2, %%mm5\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "movq %%mm4, %%mm1\n\t"
+ "movq %%mm5, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpcklbw %%mm7, %%mm5\n\t"
+ "punpckhbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm5, %%mm4\n\t"
+ "paddusw %%mm3, %%mm1\n\t"
+ "paddusw %%mm6, %%mm4\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm1, %%mm2\n\t"
+ "psrlw $2, %%mm0\n\t"
+ "psrlw $2, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while(--h);
+ emms();
+}
+
+static void avg_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "paddusw %%mm6, %%mm0\n\t"
+ "paddusw %%mm6, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ }
+ while (--h);
+ emms();
+}
+
+static void avg_pixels_x2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm1\n\t"
+ "movq %0, %%mm0\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "paddusw %%mm4, %%mm1\n\t"
+ "paddusw %%mm5, %%mm3\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm6, %%mm3\n\t"
+ "psrlw $1, %%mm1\n\t"
+ "psrlw $1, %%mm3\n\t"
+ "paddusw %%mm6, %%mm0\n\t"
+ "paddusw %%mm6, %%mm2\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while (--h);
+ emms();
+}
+
+static void avg_pixels_y2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm1\n\t"
+ "movq %0, %%mm0\n\t"
+ "movq %2, %%mm4\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "paddusw %%mm4, %%mm1\n\t"
+ "paddusw %%mm5, %%mm3\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm6, %%mm3\n\t"
+ "psrlw $1, %%mm1\n\t"
+ "psrlw $1, %%mm3\n\t"
+ "paddusw %%mm6, %%mm0\n\t"
+ "paddusw %%mm6, %%mm2\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix), "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size ;
+ } while(--h);
+ emms();
+}
+
+static void avg_pixels_xy2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wtwo[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq 1%2, %%mm5\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "movq %%mm4, %%mm1\n\t"
+ "movq %%mm5, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpcklbw %%mm7, %%mm5\n\t"
+ "punpckhbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm5, %%mm4\n\t"
+ "paddusw %%mm3, %%mm1\n\t"
+ "paddusw %%mm6, %%mm4\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm1, %%mm2\n\t"
+ "movq %3, %%mm5\n\t"
+ "psrlw $2, %%mm0\n\t"
+ "movq %0, %%mm1\n\t"
+ "psrlw $2, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "paddusw %%mm5, %%mm0\n\t"
+ "paddusw %%mm5, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size)), "m"(mm_wone[0])
+ :"memory");
+ pix += line_size;
+ p += line_size ;
+ } while(--h);
+ emms();
+}
+
+static void avg_no_rnd_pixels_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile("pxor %%mm7, %%mm7\n\t":::"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %0, %%mm1\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += line_size ;
+ } while (--h);
+ emms();
+}
+
+static void avg_no_rnd_pixels_x2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t":::"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq 1%1, %%mm1\n\t"
+ "movq %0, %%mm4\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm5, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while (--h);
+ emms();
+}
+
+static void avg_no_rnd_pixels_y2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t":::"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq %0, %%mm4\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm5, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix), "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size ;
+ } while(--h);
+ emms();
+}
+
+static void avg_no_rnd_pixels_xy2_mmx( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq 1%2, %%mm5\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "movq %%mm4, %%mm1\n\t"
+ "movq %%mm5, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpcklbw %%mm7, %%mm5\n\t"
+ "punpckhbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm5, %%mm4\n\t"
+ "paddusw %%mm3, %%mm1\n\t"
+ "paddusw %%mm6, %%mm4\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm1, %%mm2\n\t"
+ "movq %0, %%mm1\n\t"
+ "psrlw $2, %%mm0\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "psrlw $2, %%mm2\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "psrlw $1, %%mm0\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size;
+ } while(--h);
+ emms();
+}
+
+static void sub_pixels_mmx( DCTELEM *block, const UINT8 *pixels, int line_size, int h)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile("pxor %%mm7, %%mm7":::"memory");
+ do {
+ __asm __volatile(
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm2\n\t"
+ "movq 8%0, %%mm1\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "psubsw %%mm2, %%mm0\n\t"
+ "psubsw %%mm3, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, 8%0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += 8;
+ } while (--h);
+ emms();
+}
+
+static void sub_pixels_x2_mmx( DCTELEM *block, const UINT8 *pixels, int line_size, int h)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm2\n\t"
+ "movq 8%0, %%mm1\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "paddusw %%mm4, %%mm2\n\t"
+ "paddusw %%mm5, %%mm3\n\t"
+ "paddusw %%mm6, %%mm2\n\t"
+ "paddusw %%mm6, %%mm3\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "psrlw $1, %%mm3\n\t"
+ "psubsw %%mm2, %%mm0\n\t"
+ "psubsw %%mm3, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, 8%0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += 8;
+ } while (--h);
+ emms();
+}
+
+static void sub_pixels_y2_mmx( DCTELEM *block, const UINT8 *pixels, int line_size, int h)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6"
+ ::"m"(mm_wone[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm2\n\t"
+ "movq 8%0, %%mm1\n\t"
+ "movq %2, %%mm4\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "movq %%mm4, %%mm5\n\t"
+ "punpcklbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpckhbw %%mm7, %%mm5\n\t"
+ "paddusw %%mm4, %%mm2\n\t"
+ "paddusw %%mm5, %%mm3\n\t"
+ "paddusw %%mm6, %%mm2\n\t"
+ "paddusw %%mm6, %%mm3\n\t"
+ "psrlw $1, %%mm2\n\t"
+ "psrlw $1, %%mm3\n\t"
+ "psubsw %%mm2, %%mm0\n\t"
+ "psubsw %%mm3, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, 8%0\n\t"
+ :"=m"(*p)
+ :"m"(*pix), "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += 8;
+ } while (--h);
+ emms();
+}
+
+static void sub_pixels_xy2_mmx( DCTELEM *block, const UINT8 *pixels, int line_size, int h)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wtwo[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq 1%2, %%mm5\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "movq %%mm4, %%mm1\n\t"
+ "movq %%mm5, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpcklbw %%mm7, %%mm5\n\t"
+ "punpckhbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm5, %%mm4\n\t"
+ "paddusw %%mm3, %%mm1\n\t"
+ "paddusw %%mm6, %%mm4\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm1, %%mm2\n\t"
+ "movq %0, %%mm1\n\t"
+ "movq 8%0, %%mm3\n\t"
+ "psrlw $2, %%mm0\n\t"
+ "psrlw $2, %%mm2\n\t"
+ "psubsw %%mm0, %%mm1\n\t"
+ "psubsw %%mm2, %%mm3\n\t"
+ "movq %%mm1, %0\n\t"
+ "movq %%mm3, 8%0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += 8 ;
+ } while(--h);
+ emms();
+}
+
+void dsputil_init_mmx(void)
+{
+ mm_flags = mm_support();
+#if 0
+ printf("CPU flags:");
+ if (mm_flags & MM_MMX)
+ printf(" mmx");
+ if (mm_flags & MM_MMXEXT)
+ printf(" mmxext");
+ if (mm_flags & MM_3DNOW)
+ printf(" 3dnow");
+ if (mm_flags & MM_SSE)
+ printf(" sse");
+ if (mm_flags & MM_SSE2)
+ printf(" sse2");
+ printf("\n");
+#endif
+
+ if (mm_flags & MM_MMX) {
+ get_pixels = get_pixels_mmx;
+ put_pixels_clamped = put_pixels_clamped_mmx;
+ add_pixels_clamped = add_pixels_clamped_mmx;
+
+ pix_abs16x16 = pix_abs16x16_mmx;
+ pix_abs16x16_x2 = pix_abs16x16_x2_mmx;
+ pix_abs16x16_y2 = pix_abs16x16_y2_mmx;
+ pix_abs16x16_xy2 = pix_abs16x16_xy2_mmx;
+ av_fdct = fdct_mmx;
+
+ put_pixels_tab[0] = put_pixels_mmx;
+ put_pixels_tab[1] = put_pixels_x2_mmx;
+ put_pixels_tab[2] = put_pixels_y2_mmx;
+ put_pixels_tab[3] = put_pixels_xy2_mmx;
+
+ put_no_rnd_pixels_tab[0] = put_pixels_mmx;
+ put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_mmx;
+ put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_mmx;
+ put_no_rnd_pixels_tab[3] = put_no_rnd_pixels_xy2_mmx;
+
+ avg_pixels_tab[0] = avg_pixels_mmx;
+ avg_pixels_tab[1] = avg_pixels_x2_mmx;
+ avg_pixels_tab[2] = avg_pixels_y2_mmx;
+ avg_pixels_tab[3] = avg_pixels_xy2_mmx;
+
+ avg_no_rnd_pixels_tab[0] = avg_no_rnd_pixels_mmx;
+ avg_no_rnd_pixels_tab[1] = avg_no_rnd_pixels_x2_mmx;
+ avg_no_rnd_pixels_tab[2] = avg_no_rnd_pixels_y2_mmx;
+ avg_no_rnd_pixels_tab[3] = avg_no_rnd_pixels_xy2_mmx;
+
+ sub_pixels_tab[0] = sub_pixels_mmx;
+ sub_pixels_tab[1] = sub_pixels_x2_mmx;
+ sub_pixels_tab[2] = sub_pixels_y2_mmx;
+ sub_pixels_tab[3] = sub_pixels_xy2_mmx;
+
+ if (mm_flags & MM_MMXEXT) {
+ pix_abs16x16 = pix_abs16x16_sse;
+ }
+
+ if (mm_flags & MM_SSE) {
+ put_pixels_tab[1] = put_pixels_x2_sse;
+ put_pixels_tab[2] = put_pixels_y2_sse;
+
+ avg_pixels_tab[0] = avg_pixels_sse;
+ avg_pixels_tab[1] = avg_pixels_x2_sse;
+ avg_pixels_tab[2] = avg_pixels_y2_sse;
+ avg_pixels_tab[3] = avg_pixels_xy2_sse;
+
+ sub_pixels_tab[1] = sub_pixels_x2_sse;
+ sub_pixels_tab[2] = sub_pixels_y2_sse;
+ } else if (mm_flags & MM_3DNOW) {
+ put_pixels_tab[1] = put_pixels_x2_3dnow;
+ put_pixels_tab[2] = put_pixels_y2_3dnow;
+
+ avg_pixels_tab[0] = avg_pixels_3dnow;
+ avg_pixels_tab[1] = avg_pixels_x2_3dnow;
+ avg_pixels_tab[2] = avg_pixels_y2_3dnow;
+ avg_pixels_tab[3] = avg_pixels_xy2_3dnow;
+
+ sub_pixels_tab[1] = sub_pixels_x2_3dnow;
+ sub_pixels_tab[2] = sub_pixels_y2_3dnow;
+ }
+ }
+}
diff --git a/libavcodec/i386/dsputil_mmx_avg.h b/libavcodec/i386/dsputil_mmx_avg.h
new file mode 100644
index 0000000000..e47b83f62d
--- /dev/null
+++ b/libavcodec/i386/dsputil_mmx_avg.h
@@ -0,0 +1,352 @@
+/*
+ * DSP utils : average functions are compiled twice for 3dnow/mmx2
+ * Copyright (c) 2000, 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
+ */
+
+static void DEF(put_pixels_x2)(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ int dh, hh;
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ hh=h>>2;
+ dh=h&3;
+ while(hh--) {
+ __asm __volatile(
+ "movq %4, %%mm0\n\t"
+ "movq 1%4, %%mm1\n\t"
+ "movq %5, %%mm2\n\t"
+ "movq 1%5, %%mm3\n\t"
+ "movq %6, %%mm4\n\t"
+ "movq 1%6, %%mm5\n\t"
+ "movq %7, %%mm6\n\t"
+ "movq 1%7, %%mm7\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ PAVGB" %%mm3, %%mm2\n\t"
+ PAVGB" %%mm5, %%mm4\n\t"
+ PAVGB" %%mm7, %%mm6\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm2, %1\n\t"
+ "movq %%mm4, %2\n\t"
+ "movq %%mm6, %3\n\t"
+ :"=m"(*p), "=m"(*(p+line_size)), "=m"(*(p+line_size*2)), "=m"(*(p+line_size*3))
+ :"m"(*pix), "m"(*(pix+line_size)), "m"(*(pix+line_size*2)), "m"(*(pix+line_size*3))
+ :"memory");
+ pix += line_size*4; p += line_size*4;
+ }
+ while(dh--) {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq 1%1, %%mm1\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size; p += line_size;
+ }
+ emms();
+}
+
+static void DEF(put_pixels_y2)(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ int dh, hh;
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+
+ hh=h>>1;
+ dh=h&1;
+ while(hh--) {
+ __asm __volatile(
+ "movq %2, %%mm0\n\t"
+ "movq %3, %%mm1\n\t"
+ "movq %4, %%mm2\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ PAVGB" %%mm2, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, %1\n\t"
+ :"=m"(*p), "=m"(*(p+line_size))
+ :"m"(*pix), "m"(*(pix+line_size)),
+ "m"(*(pix+line_size*2))
+ :"memory");
+ pix += line_size*2;
+ p += line_size*2;
+ }
+ if(dh) {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ }
+ emms();
+}
+
+static void DEF(avg_pixels)(UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ int dh, hh;
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ hh=h>>2;
+ dh=h&3;
+ while(hh--) {
+ __asm __volatile(
+ "movq %0, %%mm0\n\t"
+ "movq %4, %%mm1\n\t"
+ "movq %1, %%mm2\n\t"
+ "movq %5, %%mm3\n\t"
+ "movq %2, %%mm4\n\t"
+ "movq %6, %%mm5\n\t"
+ "movq %3, %%mm6\n\t"
+ "movq %7, %%mm7\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ PAVGB" %%mm3, %%mm2\n\t"
+ PAVGB" %%mm5, %%mm4\n\t"
+ PAVGB" %%mm7, %%mm6\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm2, %1\n\t"
+ "movq %%mm4, %2\n\t"
+ "movq %%mm6, %3\n\t"
+ :"=m"(*p), "=m"(*(p+line_size)), "=m"(*(p+line_size*2)), "=m"(*(p+line_size*3))
+ :"m"(*pix), "m"(*(pix+line_size)), "m"(*(pix+line_size*2)), "m"(*(pix+line_size*3))
+ :"memory");
+ pix += line_size*4; p += line_size*4;
+ }
+ while(dh--) {
+ __asm __volatile(
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size; p += line_size;
+ }
+ emms();
+}
+
+static void DEF(avg_pixels_x2)( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ int dh, hh;
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ hh=h>>1;
+ dh=h&1;
+ while(hh--) {
+ __asm __volatile(
+ "movq %2, %%mm2\n\t"
+ "movq 1%2, %%mm3\n\t"
+ "movq %3, %%mm4\n\t"
+ "movq 1%3, %%mm5\n\t"
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ PAVGB" %%mm3, %%mm2\n\t"
+ PAVGB" %%mm2, %%mm0\n\t"
+ PAVGB" %%mm5, %%mm4\n\t"
+ PAVGB" %%mm4, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, %1\n\t"
+ :"=m"(*p), "=m"(*(p+line_size))
+ :"m"(*pix), "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size*2;
+ p += line_size*2;
+ }
+ if(dh) {
+ __asm __volatile(
+ "movq %1, %%mm1\n\t"
+ "movq 1%1, %%mm2\n\t"
+ "movq %0, %%mm0\n\t"
+ PAVGB" %%mm2, %%mm1\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ }
+ emms();
+}
+
+static void DEF(avg_pixels_y2)( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ int dh, hh;
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ hh=h>>1;
+ dh=h&1;
+ while(hh--) {
+ __asm __volatile(
+ "movq %2, %%mm2\n\t"
+ "movq %3, %%mm3\n\t"
+ "movq %3, %%mm4\n\t"
+ "movq %4, %%mm5\n\t"
+ "movq %0, %%mm0\n\t"
+ "movq %1, %%mm1\n\t"
+ PAVGB" %%mm3, %%mm2\n\t"
+ PAVGB" %%mm2, %%mm0\n\t"
+ PAVGB" %%mm5, %%mm4\n\t"
+ PAVGB" %%mm4, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, %1\n\t"
+ :"=m"(*p), "=m"(*(p+line_size))
+ :"m"(*pix), "m"(*(pix+line_size)), "m"(*(pix+line_size*2))
+ :"memory");
+ pix += line_size*2;
+ p += line_size*2;
+ }
+ if(dh) {
+ __asm __volatile(
+ "movq %1, %%mm1\n\t"
+ "movq %2, %%mm2\n\t"
+ "movq %0, %%mm0\n\t"
+ PAVGB" %%mm2, %%mm1\n\t"
+ PAVGB" %%mm1, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix), "m"(*(pix+line_size))
+ :"memory");
+ }
+ emms();
+}
+
+static void DEF(avg_pixels_xy2)( UINT8 *block, const UINT8 *pixels, int line_size, int h)
+{
+ UINT8 *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7\n\t"
+ "movq %0, %%mm6\n\t"
+ ::"m"(mm_wtwo[0]):"memory");
+ do {
+ __asm __volatile(
+ "movq %1, %%mm0\n\t"
+ "movq %2, %%mm1\n\t"
+ "movq 1%1, %%mm4\n\t"
+ "movq 1%2, %%mm5\n\t"
+ "movq %%mm0, %%mm2\n\t"
+ "movq %%mm1, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm0\n\t"
+ "punpcklbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm1, %%mm0\n\t"
+ "paddusw %%mm3, %%mm2\n\t"
+ "movq %%mm4, %%mm1\n\t"
+ "movq %%mm5, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm4\n\t"
+ "punpcklbw %%mm7, %%mm5\n\t"
+ "punpckhbw %%mm7, %%mm1\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "paddusw %%mm5, %%mm4\n\t"
+ "paddusw %%mm3, %%mm1\n\t"
+ "paddusw %%mm6, %%mm4\n\t"
+ "paddusw %%mm6, %%mm1\n\t"
+ "paddusw %%mm4, %%mm0\n\t"
+ "paddusw %%mm1, %%mm2\n\t"
+ "psrlw $2, %%mm0\n\t"
+ "psrlw $2, %%mm2\n\t"
+ "packuswb %%mm2, %%mm0\n\t"
+ PAVGB" %0, %%mm0\n\t"
+ "movq %%mm0, %0\n\t"
+ :"=m"(*p)
+ :"m"(*pix),
+ "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += line_size ;
+ } while(--h);
+ emms();
+}
+
+static void DEF(sub_pixels_x2)( DCTELEM *block, const UINT8 *pixels, int line_size, int h)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7":::"memory");
+ do {
+ __asm __volatile(
+ "movq 1%1, %%mm2\n\t"
+ "movq %0, %%mm0\n\t"
+ PAVGB" %1, %%mm2\n\t"
+ "movq 8%0, %%mm1\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "psubsw %%mm2, %%mm0\n\t"
+ "psubsw %%mm3, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, 8%0\n\t"
+ :"=m"(*p)
+ :"m"(*pix)
+ :"memory");
+ pix += line_size;
+ p += 8;
+ } while (--h);
+ emms();
+}
+
+static void DEF(sub_pixels_y2)( DCTELEM *block, const UINT8 *pixels, int line_size, int h)
+{
+ DCTELEM *p;
+ const UINT8 *pix;
+ p = block;
+ pix = pixels;
+ __asm __volatile(
+ "pxor %%mm7, %%mm7":::"memory");
+ do {
+ __asm __volatile(
+ "movq %2, %%mm2\n\t"
+ "movq %0, %%mm0\n\t"
+ PAVGB" %1, %%mm2\n\t"
+ "movq 8%0, %%mm1\n\t"
+ "movq %%mm2, %%mm3\n\t"
+ "punpcklbw %%mm7, %%mm2\n\t"
+ "punpckhbw %%mm7, %%mm3\n\t"
+ "psubsw %%mm2, %%mm0\n\t"
+ "psubsw %%mm3, %%mm1\n\t"
+ "movq %%mm0, %0\n\t"
+ "movq %%mm1, 8%0\n\t"
+ :"=m"(*p)
+ :"m"(*pix), "m"(*(pix+line_size))
+ :"memory");
+ pix += line_size;
+ p += 8;
+ } while (--h);
+ emms();
+}
+
diff --git a/libavcodec/i386/fdct_mmx.s b/libavcodec/i386/fdct_mmx.s
new file mode 100644
index 0000000000..75c67bfe5e
--- /dev/null
+++ b/libavcodec/i386/fdct_mmx.s
@@ -0,0 +1,507 @@
+; //////////////////////////////////////////////////////////////////////////////
+; //
+; // fdctam32.c - AP922 MMX(3D-Now) forward-DCT
+; // ----------
+; // Intel Application Note AP-922 - fast, precise implementation of DCT
+; // http://developer.intel.com/vtune/cbts/appnotes.htm
+; // ----------
+; //
+; // This routine can use a 3D-Now/MMX enhancement to increase the
+; // accuracy of the fdct_col_4 macro. The dct_col function uses 3D-Now's
+; // PMHULHRW instead of MMX's PMHULHW(and POR). The substitution improves
+; // accuracy very slightly with performance penalty. If the target CPU
+; // does not support 3D-Now, then this function cannot be executed.
+; //
+; // For a fast, precise MMX implementation of inverse-DCT
+; // visit http://www.elecard.com/peter
+; //
+; // v1.0 07/22/2000 (initial release)
+; //
+; // liaor@iname.com http://members.tripod.com/~liaor
+; //////////////////////////////////////////////////////////////////////////////
+
+;;;
+;;; A.Stevens Jul 2000: ported to nasm syntax and disentangled from
+;;; from Win**** compiler specific stuff.
+;;; All the real work was done above though.
+;;; See above for how to optimise quality on 3DNow! CPU's
+
+ ;;
+ ;; Macros for code-readability...
+ ;;
+%define INP eax ; pointer to (short *blk)
+%define OUT ecx ; pointer to output (temporary store space qwTemp[])
+%define TABLE ebx ; pointer to tab_frw_01234567[]
+%define TABLEF ebx ; pointer to tg_all_16
+%define round_frw_row edx
+
+
+%define x0 INP + 0*16
+%define x1 INP + 1*16
+%define x2 INP + 2*16
+%define x3 INP + 3*16
+%define x4 INP + 4*16
+%define x5 INP + 5*16
+%define x6 INP + 6*16
+%define x7 INP + 7*16
+%define y0 OUT + 0*16
+%define y1 OUT + 1*16
+%define y2 OUT + 2*16
+%define y3 OUT + 3*16
+%define y4 OUT + 4*16
+%define y5 OUT + 5*16
+%define y6 OUT + 6*16
+%define y7 OUT + 7*16
+
+ ;;
+ ;; Constants for DCT
+ ;;
+%define BITS_FRW_ACC 3 ; 2 or 3 for accuracy
+%define SHIFT_FRW_COL BITS_FRW_ACC
+%define SHIFT_FRW_ROW (BITS_FRW_ACC + 17)
+%define RND_FRW_ROW (1 << (SHIFT_FRW_ROW-1))
+%define RND_FRW_COL (1 << (SHIFT_FRW_COL-1))
+
+extern fdct_one_corr
+extern fdct_r_row ; Defined in C for convenience
+ ;;
+ ;; Concatenated table of forward dct transformation coeffs.
+ ;;
+extern fdct_tg_all_16 ; Defined in C for convenience
+ ;; Offsets into table..
+
+%define tg_1_16 (TABLEF + 0)
+%define tg_2_16 (TABLEF + 8)
+%define tg_3_16 (TABLEF + 16)
+%define cos_4_16 (TABLEF + 24)
+%define ocos_4_16 (TABLEF + 32)
+
+ ;;
+ ;; Concatenated table of forward dct coefficients
+ ;;
+extern tab_frw_01234567 ; Defined in C for convenience
+
+ ;; Offsets into table..
+SECTION .text
+
+global fdct_mmx
+
+;;;
+;;; void fdct_mmx( short *blk )
+;;;
+
+
+
+; ////////////////////////////////////////////////////////////////////////
+; //
+; // The high-level pseudocode for the fdct_am32() routine :
+; //
+; // fdct_am32()
+; // {
+; // forward_dct_col03(); // dct_column transform on cols 0-3
+; // forward_dct_col47(); // dct_column transform on cols 4-7
+; // for ( j = 0; j < 8; j=j+1 )
+; // forward_dct_row1(j); // dct_row transform on row #j
+; // }
+; //
+;
+
+align 32
+fdct_mmx:
+ push ebp ; save stack pointer
+ mov ebp, esp ; link
+
+ push ebx
+ push ecx
+ push edx
+ push edi
+
+ mov INP, [ebp+8]; ; input data is row 0 of blk[]
+ ;// transform the left half of the matrix (4 columns)
+
+ lea TABLEF, [fdct_tg_all_16];
+ mov OUT, INP;
+
+; lea round_frw_col, [r_frw_col]
+ ; for ( i = 0; i < 2; i = i + 1)
+ ; the for-loop is executed twice. We are better off unrolling the
+ ; loop to avoid branch misprediction.
+.mmx32_fdct_col03:
+ movq mm0, [x1] ; 0 ; x1
+ ;;
+
+ movq mm1, [x6] ; 1 ; x6
+ movq mm2, mm0 ; 2 ; x1
+
+ movq mm3, [x2] ; 3 ; x2
+ paddsw mm0, mm1 ; t1 = x[1] + x[6]
+
+ movq mm4, [x5] ; 4 ; x5
+ psllw mm0, SHIFT_FRW_COL ; t1
+
+ movq mm5, [x0] ; 5 ; x0
+ paddsw mm4, mm3 ; t2 = x[2] + x[5]
+
+ paddsw mm5, [x7] ; t0 = x[0] + x[7]
+ psllw mm4, SHIFT_FRW_COL ; t2
+
+ movq mm6, mm0 ; 6 ; t1
+ psubsw mm2, mm1 ; 1 ; t6 = x[1] - x[6]
+
+ movq mm1, [tg_2_16] ; 1 ; tg_2_16
+ psubsw mm0, mm4 ; tm12 = t1 - t2
+
+ movq mm7, [x3] ; 7 ; x3
+ pmulhw mm1, mm0 ; tm12*tg_2_16
+
+ paddsw mm7, [x4] ; t3 = x[3] + x[4]
+ psllw mm5, SHIFT_FRW_COL ; t0
+
+ paddsw mm6, mm4 ; 4 ; tp12 = t1 + t2
+ psllw mm7, SHIFT_FRW_COL ; t3
+
+ movq mm4, mm5 ; 4 ; t0
+ psubsw mm5, mm7 ; tm03 = t0 - t3
+
+ paddsw mm1, mm5 ; y2 = tm03 + tm12*tg_2_16
+ paddsw mm4, mm7 ; 7 ; tp03 = t0 + t3
+
+ por mm1, [fdct_one_corr] ; correction y2 +0.5
+ psllw mm2, SHIFT_FRW_COL+1 ; t6
+
+ pmulhw mm5, [tg_2_16] ; tm03*tg_2_16
+ movq mm7, mm4 ; 7 ; tp03
+
+ psubsw mm3, [x5] ; t5 = x[2] - x[5]
+ psubsw mm4, mm6 ; y4 = tp03 - tp12
+
+ movq [y2], mm1 ; 1 ; save y2
+ paddsw mm7, mm6 ; 6 ; y0 = tp03 + tp12
+
+ movq mm1, [x3] ; 1 ; x3
+ psllw mm3, SHIFT_FRW_COL+1 ; t5
+
+ psubsw mm1, [x4] ; t4 = x[3] - x[4]
+ movq mm6, mm2 ; 6 ; t6
+
+ movq [y4], mm4 ; 4 ; save y4
+ paddsw mm2, mm3 ; t6 + t5
+
+ pmulhw mm2, [ocos_4_16] ; tp65 = (t6 + t5)*cos_4_16
+ psubsw mm6, mm3 ; 3 ; t6 - t5
+
+ pmulhw mm6, [ocos_4_16] ; tm65 = (t6 - t5)*cos_4_16
+ psubsw mm5, mm0 ; 0 ; y6 = tm03*tg_2_16 - tm12
+
+ por mm5, [fdct_one_corr] ; correction y6 +0.5
+ psllw mm1, SHIFT_FRW_COL ; t4
+
+ por mm2, [fdct_one_corr] ; correction tp65 +0.5
+ movq mm4, mm1 ; 4 ; t4
+
+ movq mm3, [x0] ; 3 ; x0
+ paddsw mm1, mm6 ; tp465 = t4 + tm65
+
+ psubsw mm3, [x7] ; t7 = x[0] - x[7]
+ psubsw mm4, mm6 ; 6 ; tm465 = t4 - tm65
+
+ movq mm0, [tg_1_16] ; 0 ; tg_1_16
+ psllw mm3, SHIFT_FRW_COL ; t7
+
+ movq mm6, [tg_3_16] ; 6 ; tg_3_16
+ pmulhw mm0, mm1 ; tp465*tg_1_16
+
+ movq [y0], mm7 ; 7 ; save y0
+ pmulhw mm6, mm4 ; tm465*tg_3_16
+
+ movq [y6], mm5 ; 5 ; save y6
+ movq mm7, mm3 ; 7 ; t7
+
+ movq mm5, [tg_3_16] ; 5 ; tg_3_16
+ psubsw mm7, mm2 ; tm765 = t7 - tp65
+
+ paddsw mm3, mm2 ; 2 ; tp765 = t7 + tp65
+ pmulhw mm5, mm7 ; tm765*tg_3_16
+
+ paddsw mm0, mm3 ; y1 = tp765 + tp465*tg_1_16
+ paddsw mm6, mm4 ; tm465*tg_3_16
+
+ pmulhw mm3, [tg_1_16] ; tp765*tg_1_16
+ ;;
+
+ por mm0, [fdct_one_corr] ; correction y1 +0.5
+ paddsw mm5, mm7 ; tm765*tg_3_16
+
+ psubsw mm7, mm6 ; 6 ; y3 = tm765 - tm465*tg_3_16
+ add INP, 0x08 ; ; increment pointer
+
+ movq [y1], mm0 ; 0 ; save y1
+ paddsw mm5, mm4 ; 4 ; y5 = tm765*tg_3_16 + tm465
+
+ movq [y3], mm7 ; 7 ; save y3
+ psubsw mm3, mm1 ; 1 ; y7 = tp765*tg_1_16 - tp465
+
+ movq [y5], mm5 ; 5 ; save y5
+
+
+.mmx32_fdct_col47: ; begin processing last four columns
+ movq mm0, [x1] ; 0 ; x1
+ ;;
+ movq [y7], mm3 ; 3 ; save y7 (columns 0-4)
+ ;;
+
+ movq mm1, [x6] ; 1 ; x6
+ movq mm2, mm0 ; 2 ; x1
+
+ movq mm3, [x2] ; 3 ; x2
+ paddsw mm0, mm1 ; t1 = x[1] + x[6]
+
+ movq mm4, [x5] ; 4 ; x5
+ psllw mm0, SHIFT_FRW_COL ; t1
+
+ movq mm5, [x0] ; 5 ; x0
+ paddsw mm4, mm3 ; t2 = x[2] + x[5]
+
+ paddsw mm5, [x7] ; t0 = x[0] + x[7]
+ psllw mm4, SHIFT_FRW_COL ; t2
+
+ movq mm6, mm0 ; 6 ; t1
+ psubsw mm2, mm1 ; 1 ; t6 = x[1] - x[6]
+
+ movq mm1, [tg_2_16] ; 1 ; tg_2_16
+ psubsw mm0, mm4 ; tm12 = t1 - t2
+
+ movq mm7, [x3] ; 7 ; x3
+ pmulhw mm1, mm0 ; tm12*tg_2_16
+
+ paddsw mm7, [x4] ; t3 = x[3] + x[4]
+ psllw mm5, SHIFT_FRW_COL ; t0
+
+ paddsw mm6, mm4 ; 4 ; tp12 = t1 + t2
+ psllw mm7, SHIFT_FRW_COL ; t3
+
+ movq mm4, mm5 ; 4 ; t0
+ psubsw mm5, mm7 ; tm03 = t0 - t3
+
+ paddsw mm1, mm5 ; y2 = tm03 + tm12*tg_2_16
+ paddsw mm4, mm7 ; 7 ; tp03 = t0 + t3
+
+ por mm1, [fdct_one_corr] ; correction y2 +0.5
+ psllw mm2, SHIFT_FRW_COL+1 ; t6
+
+ pmulhw mm5, [tg_2_16] ; tm03*tg_2_16
+ movq mm7, mm4 ; 7 ; tp03
+
+ psubsw mm3, [x5] ; t5 = x[2] - x[5]
+ psubsw mm4, mm6 ; y4 = tp03 - tp12
+
+ movq [y2+8], mm1 ; 1 ; save y2
+ paddsw mm7, mm6 ; 6 ; y0 = tp03 + tp12
+
+ movq mm1, [x3] ; 1 ; x3
+ psllw mm3, SHIFT_FRW_COL+1 ; t5
+
+ psubsw mm1, [x4] ; t4 = x[3] - x[4]
+ movq mm6, mm2 ; 6 ; t6
+
+ movq [y4+8], mm4 ; 4 ; save y4
+ paddsw mm2, mm3 ; t6 + t5
+
+ pmulhw mm2, [ocos_4_16] ; tp65 = (t6 + t5)*cos_4_16
+ psubsw mm6, mm3 ; 3 ; t6 - t5
+
+ pmulhw mm6, [ocos_4_16] ; tm65 = (t6 - t5)*cos_4_16
+ psubsw mm5, mm0 ; 0 ; y6 = tm03*tg_2_16 - tm12
+
+ por mm5, [fdct_one_corr] ; correction y6 +0.5
+ psllw mm1, SHIFT_FRW_COL ; t4
+
+ por mm2, [fdct_one_corr] ; correction tp65 +0.5
+ movq mm4, mm1 ; 4 ; t4
+
+ movq mm3, [x0] ; 3 ; x0
+ paddsw mm1, mm6 ; tp465 = t4 + tm65
+
+ psubsw mm3, [x7] ; t7 = x[0] - x[7]
+ psubsw mm4, mm6 ; 6 ; tm465 = t4 - tm65
+
+ movq mm0, [tg_1_16] ; 0 ; tg_1_16
+ psllw mm3, SHIFT_FRW_COL ; t7
+
+ movq mm6, [tg_3_16] ; 6 ; tg_3_16
+ pmulhw mm0, mm1 ; tp465*tg_1_16
+
+ movq [y0+8], mm7 ; 7 ; save y0
+ pmulhw mm6, mm4 ; tm465*tg_3_16
+
+ movq [y6+8], mm5 ; 5 ; save y6
+ movq mm7, mm3 ; 7 ; t7
+
+ movq mm5, [tg_3_16] ; 5 ; tg_3_16
+ psubsw mm7, mm2 ; tm765 = t7 - tp65
+
+ paddsw mm3, mm2 ; 2 ; tp765 = t7 + tp65
+ pmulhw mm5, mm7 ; tm765*tg_3_16
+
+ paddsw mm0, mm3 ; y1 = tp765 + tp465*tg_1_16
+ paddsw mm6, mm4 ; tm465*tg_3_16
+
+ pmulhw mm3, [tg_1_16] ; tp765*tg_1_16
+ ;;
+
+ por mm0, [fdct_one_corr] ; correction y1 +0.5
+ paddsw mm5, mm7 ; tm765*tg_3_16
+
+ psubsw mm7, mm6 ; 6 ; y3 = tm765 - tm465*tg_3_16
+ ;;
+
+ movq [y1+8], mm0 ; 0 ; save y1
+ paddsw mm5, mm4 ; 4 ; y5 = tm765*tg_3_16 + tm465
+
+ movq [y3+8], mm7 ; 7 ; save y3
+ psubsw mm3, mm1 ; 1 ; y7 = tp765*tg_1_16 - tp465
+
+ movq [y5+8], mm5 ; 5 ; save y5
+
+ movq [y7+8], mm3 ; 3 ; save y7
+
+; emms;
+; } ; end of forward_dct_col07()
+ ; done with dct_row transform
+
+
+ ; fdct_mmx32_cols() --
+ ; the following subroutine repeats the row-transform operation,
+ ; except with different shift&round constants. This version
+ ; does NOT transpose the output again. Thus the final output
+ ; is transposed with respect to the source.
+ ;
+ ; The output is stored into blk[], which destroys the original
+ ; input data.
+ mov INP, [ebp+8]; ;; row 0
+ mov edi, 0x08; ;x = 8
+
+ lea TABLE, [tab_frw_01234567]; ; row 0
+ mov OUT, INP;
+
+ lea round_frw_row, [fdct_r_row];
+ ; for ( x = 8; x > 0; --x ) ; transform one row per iteration
+
+; ---------- loop begin
+ .lp_mmx_fdct_row1:
+ movd mm5, [INP+12]; ; mm5 = 7 6
+
+ punpcklwd mm5, [INP+8] ; mm5 = 5 7 4 6
+
+ movq mm2, mm5; ; mm2 = 5 7 4 6
+ psrlq mm5, 32; ; mm5 = _ _ 5 7
+
+ movq mm0, [INP]; ; mm0 = 3 2 1 0
+ punpcklwd mm5, mm2;; mm5 = 4 5 6 7
+
+ movq mm1, mm0; ; mm1 = 3 2 1 0
+ paddsw mm0, mm5; ; mm0 = [3+4, 2+5, 1+6, 0+7] (xt3, xt2, xt1, xt0)
+
+ psubsw mm1, mm5; ; mm1 = [3-4, 2-5, 1-6, 0-7] (xt7, xt6, xt5, xt4)
+ movq mm2, mm0; ; mm2 = [ xt3 xt2 xt1 xt0 ]
+
+ ;movq [ xt3xt2xt1xt0 ], mm0;
+ ;movq [ xt7xt6xt5xt4 ], mm1;
+
+ punpcklwd mm0, mm1;; mm0 = [ xt5 xt1 xt4 xt0 ]
+
+ punpckhwd mm2, mm1;; mm2 = [ xt7 xt3 xt6 xt2 ]
+ movq mm1, mm2; ; mm1
+
+ ;; shuffle bytes around
+
+; movq mm0, [INP] ; 0 ; x3 x2 x1 x0
+
+; movq mm1, [INP+8] ; 1 ; x7 x6 x5 x4
+ movq mm2, mm0 ; 2 ; x3 x2 x1 x0
+
+ movq mm3, [TABLE] ; 3 ; w06 w04 w02 w00
+ punpcklwd mm0, mm1 ; x5 x1 x4 x0
+
+ movq mm5, mm0 ; 5 ; x5 x1 x4 x0
+ punpckldq mm0, mm0 ; x4 x0 x4 x0 [ xt2 xt0 xt2 xt0 ]
+
+ movq mm4, [TABLE+8] ; 4 ; w07 w05 w03 w01
+ punpckhwd mm2, mm1 ; 1 ; x7 x3 x6 x2
+
+ pmaddwd mm3, mm0 ; x4*w06+x0*w04 x4*w02+x0*w00
+ movq mm6, mm2 ; 6 ; x7 x3 x6 x2
+
+ movq mm1, [TABLE+32] ; 1 ; w22 w20 w18 w16
+ punpckldq mm2, mm2 ; x6 x2 x6 x2 [ xt3 xt1 xt3 xt1 ]
+
+ pmaddwd mm4, mm2 ; x6*w07+x2*w05 x6*w03+x2*w01
+ punpckhdq mm5, mm5 ; x5 x1 x5 x1 [ xt6 xt4 xt6 xt4 ]
+
+ pmaddwd mm0, [TABLE+16] ; x4*w14+x0*w12 x4*w10+x0*w08
+ punpckhdq mm6, mm6 ; x7 x3 x7 x3 [ xt7 xt5 xt7 xt5 ]
+
+ movq mm7, [TABLE+40] ; 7 ; w23 w21 w19 w17
+ pmaddwd mm1, mm5 ; x5*w22+x1*w20 x5*w18+x1*w16
+;mm3 = a1, a0 (y2,y0)
+;mm1 = b1, b0 (y3,y1)
+;mm0 = a3,a2 (y6,y4)
+;mm5 = b3,b2 (y7,y5)
+
+ paddd mm3, [round_frw_row] ; +rounder (y2,y0)
+ pmaddwd mm7, mm6 ; x7*w23+x3*w21 x7*w19+x3*w17
+
+ pmaddwd mm2, [TABLE+24] ; x6*w15+x2*w13 x6*w11+x2*w09
+ paddd mm3, mm4 ; 4 ; a1=sum(even1) a0=sum(even0) ; now ( y2, y0)
+
+ pmaddwd mm5, [TABLE+48] ; x5*w30+x1*w28 x5*w26+x1*w24
+ ;;
+
+ pmaddwd mm6, [TABLE+56] ; x7*w31+x3*w29 x7*w27+x3*w25
+ paddd mm1, mm7 ; 7 ; b1=sum(odd1) b0=sum(odd0) ; now ( y3, y1)
+
+ paddd mm0, [round_frw_row] ; +rounder (y6,y4)
+ psrad mm3, SHIFT_FRW_ROW ; (y2, y0)
+
+ paddd mm1, [round_frw_row] ; +rounder (y3,y1)
+ paddd mm0, mm2 ; 2 ; a3=sum(even3) a2=sum(even2) ; now (y6, y4)
+
+ paddd mm5, [round_frw_row] ; +rounder (y7,y5)
+ psrad mm1, SHIFT_FRW_ROW ; y1=a1+b1 y0=a0+b0
+
+ paddd mm5, mm6 ; 6 ; b3=sum(odd3) b2=sum(odd2) ; now ( y7, y5)
+ psrad mm0, SHIFT_FRW_ROW ;y3=a3+b3 y2=a2+b2
+
+ add OUT, 16; ; increment row-output address by 1 row
+ psrad mm5, SHIFT_FRW_ROW ; y4=a3-b3 y5=a2-b2
+
+ add INP, 16; ; increment row-address by 1 row
+ packssdw mm3, mm0 ; 0 ; y6 y4 y2 y0
+
+ packssdw mm1, mm5 ; 3 ; y7 y5 y3 y1
+ movq mm6, mm3; ; mm0 = y6 y4 y2 y0
+
+ punpcklwd mm3, mm1; ; y3 y2 y1 y0
+ sub edi, 0x01; ; i = i - 1
+
+ punpckhwd mm6, mm1; ; y7 y6 y5 y4
+ add TABLE,64; ; increment to next table
+
+ movq [OUT-16], mm3 ; 1 ; save y3 y2 y1 y0
+
+ movq [OUT-8], mm6 ; 7 ; save y7 y6 y5 y4
+
+ cmp edi, 0x00;
+ jg near .lp_mmx_fdct_row1; ; begin fdct processing on next row
+ ;;
+ ;; Tidy up and return
+ ;;
+ pop edi
+ pop edx
+ pop ecx
+ pop ebx
+
+ pop ebp ; restore stack pointer
+ emms
+ ret
+ \ No newline at end of file
diff --git a/libavcodec/i386/fdctdata.c b/libavcodec/i386/fdctdata.c
new file mode 100644
index 0000000000..e095d0f4e4
--- /dev/null
+++ b/libavcodec/i386/fdctdata.c
@@ -0,0 +1,143 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// fdctam32.c - AP922 MMX(3D-Now) forward-DCT
+// ----------
+// Intel Application Note AP-922 - fast, precise implementation of DCT
+// http://developer.intel.com/vtune/cbts/appnotes.htm
+// ----------
+//
+// This routine uses a 3D-Now/MMX enhancement to increase the
+// accuracy of the fdct_col_4 macro. The dct_col function uses 3D-Now's
+// PMHULHRW instead of MMX's PMHULHW(and POR). The substitution improves
+// accuracy very slightly with performance penalty. If the target CPU
+// does not support 3D-Now, then this function cannot be executed.
+// fdctmm32.c contains the standard MMX implementation of AP-922.
+//
+// For a fast, precise MMX implementation of inverse-DCT
+// visit http://www.elecard.com/peter
+//
+// v1.0 07/22/2000 (initial release)
+// Initial release of AP922 MMX(3D-Now) forward_DCT.
+// This code was tested with Visual C++ 6.0Pro + service_pack4 +
+// processor_pack_beta! If you have the processor_pack_beta, you can
+// remove the #include for amd3dx.h, and substitute the 'normal'
+// assembly lines for the macro'd versions. Otherwise, this
+// code should compile 'as is', under Visual C++ 6.0 Pro.
+//
+// liaor@iname.com http://members.tripod.com/~liaor
+//////////////////////////////////////////////////////////////////////////////
+
+#include <inttypes.h>
+
+//////////////////////////////////////////////////////////////////////
+//
+// constants for the forward DCT
+// -----------------------------
+//
+// Be sure to check that your compiler is aligning all constants to QWORD
+// (8-byte) memory boundaries! Otherwise the unaligned memory access will
+// severely stall MMX execution.
+//
+//////////////////////////////////////////////////////////////////////
+
+#define BITS_FRW_ACC 3 //; 2 or 3 for accuracy
+#define SHIFT_FRW_COL BITS_FRW_ACC
+#define SHIFT_FRW_ROW (BITS_FRW_ACC + 17)
+//#define RND_FRW_ROW (262144 * (BITS_FRW_ACC - 1)) //; 1 << (SHIFT_FRW_ROW-1)
+#define RND_FRW_ROW (1 << (SHIFT_FRW_ROW-1))
+//#define RND_FRW_COL (2 * (BITS_FRW_ACC - 1)) //; 1 << (SHIFT_FRW_COL-1)
+#define RND_FRW_COL (1 << (SHIFT_FRW_COL-1))
+
+//concatenated table, for forward DCT transformation
+const int16_t fdct_tg_all_16[] = {
+ 13036, 13036, 13036, 13036, // tg * (2<<16) + 0.5
+ 27146, 27146, 27146, 27146, // tg * (2<<16) + 0.5
+ -21746, -21746, -21746, -21746, // tg * (2<<16) + 0.5
+ -19195, -19195, -19195, -19195, //cos * (2<<16) + 0.5
+ 23170, 23170, 23170, 23170 }; //cos * (2<<15) + 0.5
+const long long fdct_one_corr = 0x0001000100010001LL;
+const long fdct_r_row[2] = {RND_FRW_ROW, RND_FRW_ROW };
+
+const int16_t tab_frw_01234567[] = { // forward_dct coeff table
+ //row0
+ 16384, 16384, 21407, -8867, // w09 w01 w08 w00
+ 16384, 16384, 8867, -21407, // w13 w05 w12 w04
+ 16384, -16384, 8867, 21407, // w11 w03 w10 w02
+ -16384, 16384, -21407, -8867, // w15 w07 w14 w06
+ 22725, 12873, 19266, -22725, // w22 w20 w18 w16
+ 19266, 4520, -4520, -12873, // w23 w21 w19 w17
+ 12873, 4520, 4520, 19266, // w30 w28 w26 w24
+ -22725, 19266, -12873, -22725, // w31 w29 w27 w25
+
+ //row1
+ 22725, 22725, 29692, -12299, // w09 w01 w08 w00
+ 22725, 22725, 12299, -29692, // w13 w05 w12 w04
+ 22725, -22725, 12299, 29692, // w11 w03 w10 w02
+ -22725, 22725, -29692, -12299, // w15 w07 w14 w06
+ 31521, 17855, 26722, -31521, // w22 w20 w18 w16
+ 26722, 6270, -6270, -17855, // w23 w21 w19 w17
+ 17855, 6270, 6270, 26722, // w30 w28 w26 w24
+ -31521, 26722, -17855, -31521, // w31 w29 w27 w25
+
+ //row2
+ 21407, 21407, 27969, -11585, // w09 w01 w08 w00
+ 21407, 21407, 11585, -27969, // w13 w05 w12 w04
+ 21407, -21407, 11585, 27969, // w11 w03 w10 w02
+ -21407, 21407, -27969, -11585, // w15 w07 w14 w06
+ 29692, 16819, 25172, -29692, // w22 w20 w18 w16
+ 25172, 5906, -5906, -16819, // w23 w21 w19 w17
+ 16819, 5906, 5906, 25172, // w30 w28 w26 w24
+ -29692, 25172, -16819, -29692, // w31 w29 w27 w25
+
+ //row3
+ 19266, 19266, 25172, -10426, // w09 w01 w08 w00
+ 19266, 19266, 10426, -25172, // w13 w05 w12 w04
+ 19266, -19266, 10426, 25172, // w11 w03 w10 w02
+ -19266, 19266, -25172, -10426, // w15 w07 w14 w06,
+ 26722, 15137, 22654, -26722, // w22 w20 w18 w16
+ 22654, 5315, -5315, -15137, // w23 w21 w19 w17
+ 15137, 5315, 5315, 22654, // w30 w28 w26 w24
+ -26722, 22654, -15137, -26722, // w31 w29 w27 w25,
+
+ //row4
+ 16384, 16384, 21407, -8867, // w09 w01 w08 w00
+ 16384, 16384, 8867, -21407, // w13 w05 w12 w04
+ 16384, -16384, 8867, 21407, // w11 w03 w10 w02
+ -16384, 16384, -21407, -8867, // w15 w07 w14 w06
+ 22725, 12873, 19266, -22725, // w22 w20 w18 w16
+ 19266, 4520, -4520, -12873, // w23 w21 w19 w17
+ 12873, 4520, 4520, 19266, // w30 w28 w26 w24
+ -22725, 19266, -12873, -22725, // w31 w29 w27 w25
+
+ //row5
+ 19266, 19266, 25172, -10426, // w09 w01 w08 w00
+ 19266, 19266, 10426, -25172, // w13 w05 w12 w04
+ 19266, -19266, 10426, 25172, // w11 w03 w10 w02
+ -19266, 19266, -25172, -10426, // w15 w07 w14 w06
+ 26722, 15137, 22654, -26722, // w22 w20 w18 w16
+ 22654, 5315, -5315, -15137, // w23 w21 w19 w17
+ 15137, 5315, 5315, 22654, // w30 w28 w26 w24
+ -26722, 22654, -15137, -26722, // w31 w29 w27 w25
+
+ //row6
+ 21407, 21407, 27969, -11585, // w09 w01 w08 w00
+ 21407, 21407, 11585, -27969, // w13 w05 w12 w04
+ 21407, -21407, 11585, 27969, // w11 w03 w10 w02
+ -21407, 21407, -27969, -11585, // w15 w07 w14 w06,
+ 29692, 16819, 25172, -29692, // w22 w20 w18 w16
+ 25172, 5906, -5906, -16819, // w23 w21 w19 w17
+ 16819, 5906, 5906, 25172, // w30 w28 w26 w24
+ -29692, 25172, -16819, -29692, // w31 w29 w27 w25,
+
+ //row7
+ 22725, 22725, 29692, -12299, // w09 w01 w08 w00
+ 22725, 22725, 12299, -29692, // w13 w05 w12 w04
+ 22725, -22725, 12299, 29692, // w11 w03 w10 w02
+ -22725, 22725, -29692, -12299, // w15 w07 w14 w06,
+ 31521, 17855, 26722, -31521, // w22 w20 w18 w16
+ 26722, 6270, -6270, -17855, // w23 w21 w19 w17
+ 17855, 6270, 6270, 26722, // w30 w28 w26 w24
+ -31521, 26722, -17855, -31521 // w31 w29 w27 w25
+};
+
+
diff --git a/libavcodec/i386/mmx.h b/libavcodec/i386/mmx.h
new file mode 100644
index 0000000000..a82c0eda32
--- /dev/null
+++ b/libavcodec/i386/mmx.h
@@ -0,0 +1,536 @@
+/* mmx.h
+
+ MultiMedia eXtensions GCC interface library for IA32.
+
+ To use this library, simply include this header file
+ and compile with GCC. You MUST have inlining enabled
+ in order for mmx_ok() to work; this can be done by
+ simply using -O on the GCC command line.
+
+ Compiling with -DMMX_TRACE will cause detailed trace
+ output to be sent to stderr for each mmx operation.
+ This adds lots of code, and obviously slows execution to
+ a crawl, but can be very useful for debugging.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR ANY PARTICULAR PURPOSE.
+
+ 1997-99 by H. Dietz and R. Fisher
+
+ Notes:
+ It appears that the latest gas has the pand problem fixed, therefore
+ I'll undefine BROKEN_PAND by default.
+*/
+
+#ifndef _MMX_H
+#define _MMX_H
+
+
+/* Warning: at this writing, the version of GAS packaged
+ with most Linux distributions does not handle the
+ parallel AND operation mnemonic correctly. If the
+ symbol BROKEN_PAND is defined, a slower alternative
+ coding will be used. If execution of mmxtest results
+ in an illegal instruction fault, define this symbol.
+*/
+#undef BROKEN_PAND
+
+
+/* The type of an value that fits in an MMX register
+ (note that long long constant values MUST be suffixed
+ by LL and unsigned long long values by ULL, lest
+ they be truncated by the compiler)
+*/
+typedef union {
+ long long q; /* Quadword (64-bit) value */
+ unsigned long long uq; /* Unsigned Quadword */
+ int d[2]; /* 2 Doubleword (32-bit) values */
+ unsigned int ud[2]; /* 2 Unsigned Doubleword */
+ short w[4]; /* 4 Word (16-bit) values */
+ unsigned short uw[4]; /* 4 Unsigned Word */
+ char b[8]; /* 8 Byte (8-bit) values */
+ unsigned char ub[8]; /* 8 Unsigned Byte */
+ float s[2]; /* Single-precision (32-bit) value */
+} __attribute__ ((aligned (8))) mmx_t; /* On an 8-byte (64-bit) boundary */
+
+
+/* Helper functions for the instruction macros that follow...
+ (note that memory-to-register, m2r, instructions are nearly
+ as efficient as register-to-register, r2r, instructions;
+ however, memory-to-memory instructions are really simulated
+ as a convenience, and are only 1/3 as efficient)
+*/
+#ifdef MMX_TRACE
+
+/* Include the stuff for printing a trace to stderr...
+*/
+
+#include <stdio.h>
+
+#define mmx_i2r(op, imm, reg) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace.uq = (imm); \
+ fprintf(stderr, #op "_i2r(" #imm "=0x%08x%08x, ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%08x%08x) => ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (imm)); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%08x%08x\n", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ }
+
+#define mmx_m2r(op, mem, reg) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (mem); \
+ fprintf(stderr, #op "_m2r(" #mem "=0x%08x%08x, ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%08x%08x) => ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (mem)); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%08x%08x\n", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ }
+
+#define mmx_r2m(op, reg, mem) \
+ { \
+ mmx_t mmx_trace; \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #op "_r2m(" #reg "=0x%08x%08x, ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ mmx_trace = (mem); \
+ fprintf(stderr, #mem "=0x%08x%08x) => ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=X" (mem) \
+ : /* nothing */ ); \
+ mmx_trace = (mem); \
+ fprintf(stderr, #mem "=0x%08x%08x\n", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ }
+
+#define mmx_r2r(op, regs, regd) \
+ { \
+ mmx_t mmx_trace; \
+ __asm__ __volatile__ ("movq %%" #regs ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #op "_r2r(" #regs "=0x%08x%08x, ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ ("movq %%" #regd ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #regd "=0x%08x%08x) => ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd); \
+ __asm__ __volatile__ ("movq %%" #regd ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #regd "=0x%08x%08x\n", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ }
+
+#define mmx_m2m(op, mems, memd) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (mems); \
+ fprintf(stderr, #op "_m2m(" #mems "=0x%08x%08x, ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ mmx_trace = (memd); \
+ fprintf(stderr, #memd "=0x%08x%08x) => ", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+ #op " %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (memd) \
+ : "X" (mems)); \
+ mmx_trace = (memd); \
+ fprintf(stderr, #memd "=0x%08x%08x\n", \
+ mmx_trace.d[1], mmx_trace.d[0]); \
+ }
+
+#else
+
+/* These macros are a lot simpler without the tracing...
+*/
+
+#define mmx_i2r(op, imm, reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "i" (imm) )
+
+#define mmx_m2r(op, mem, reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "m" (mem))
+
+#define mmx_r2m(op, reg, mem) \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=m" (mem) \
+ : /* nothing */ )
+
+#define mmx_r2r(op, regs, regd) \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+#define mmx_m2m(op, mems, memd) \
+ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+ #op " %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=m" (memd) \
+ : "m" (mems))
+
+#endif
+
+
+/* 1x64 MOVe Quadword
+ (this is both a load and a store...
+ in fact, it is the only way to store)
+*/
+#define movq_m2r(var, reg) mmx_m2r(movq, var, reg)
+#define movq_r2m(reg, var) mmx_r2m(movq, reg, var)
+#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd)
+#define movq(vars, vard) \
+ __asm__ __volatile__ ("movq %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (vard) \
+ : "X" (vars))
+
+
+/* 1x32 MOVe Doubleword
+ (like movq, this is both load and store...
+ but is most useful for moving things between
+ mmx registers and ordinary registers)
+*/
+#define movd_m2r(var, reg) mmx_m2r(movd, var, reg)
+#define movd_r2m(reg, var) mmx_r2m(movd, reg, var)
+#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd)
+#define movd(vars, vard) \
+ __asm__ __volatile__ ("movd %1, %%mm0\n\t" \
+ "movd %%mm0, %0" \
+ : "=X" (vard) \
+ : "X" (vars))
+
+
+/* 2x32, 4x16, and 8x8 Parallel ADDs
+*/
+#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg)
+#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd)
+#define paddd(vars, vard) mmx_m2m(paddd, vars, vard)
+
+#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg)
+#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd)
+#define paddw(vars, vard) mmx_m2m(paddw, vars, vard)
+
+#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg)
+#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd)
+#define paddb(vars, vard) mmx_m2m(paddb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic
+*/
+#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg)
+#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd)
+#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard)
+
+#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg)
+#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd)
+#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
+*/
+#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg)
+#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd)
+#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard)
+
+#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg)
+#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd)
+#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel SUBs
+*/
+#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg)
+#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd)
+#define psubd(vars, vard) mmx_m2m(psubd, vars, vard)
+
+#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg)
+#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd)
+#define psubw(vars, vard) mmx_m2m(psubw, vars, vard)
+
+#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg)
+#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd)
+#define psubb(vars, vard) mmx_m2m(psubb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic
+*/
+#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg)
+#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd)
+#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard)
+
+#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg)
+#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd)
+#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
+*/
+#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg)
+#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd)
+#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard)
+
+#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg)
+#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd)
+#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard)
+
+
+/* 4x16 Parallel MULs giving Low 4x16 portions of results
+*/
+#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg)
+#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd)
+#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard)
+
+
+/* 4x16 Parallel MULs giving High 4x16 portions of results
+*/
+#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg)
+#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd)
+#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard)
+
+
+/* 4x16->2x32 Parallel Mul-ADD
+ (muls like pmullw, then adds adjacent 16-bit fields
+ in the multiply result to make the final 2x32 result)
+*/
+#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg)
+#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd)
+#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard)
+
+
+/* 1x64 bitwise AND
+*/
+#ifdef BROKEN_PAND
+#define pand_m2r(var, reg) \
+ { \
+ mmx_m2r(pandn, (mmx_t) -1LL, reg); \
+ mmx_m2r(pandn, var, reg); \
+ }
+#define pand_r2r(regs, regd) \
+ { \
+ mmx_m2r(pandn, (mmx_t) -1LL, regd); \
+ mmx_r2r(pandn, regs, regd) \
+ }
+#define pand(vars, vard) \
+ { \
+ movq_m2r(vard, mm0); \
+ mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
+ mmx_m2r(pandn, vars, mm0); \
+ movq_r2m(mm0, vard); \
+ }
+#else
+#define pand_m2r(var, reg) mmx_m2r(pand, var, reg)
+#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd)
+#define pand(vars, vard) mmx_m2m(pand, vars, vard)
+#endif
+
+
+/* 1x64 bitwise AND with Not the destination
+*/
+#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg)
+#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd)
+#define pandn(vars, vard) mmx_m2m(pandn, vars, vard)
+
+
+/* 1x64 bitwise OR
+*/
+#define por_m2r(var, reg) mmx_m2r(por, var, reg)
+#define por_r2r(regs, regd) mmx_r2r(por, regs, regd)
+#define por(vars, vard) mmx_m2m(por, vars, vard)
+
+
+/* 1x64 bitwise eXclusive OR
+*/
+#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg)
+#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd)
+#define pxor(vars, vard) mmx_m2m(pxor, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
+ (resulting fields are either 0 or -1)
+*/
+#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg)
+#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd)
+#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard)
+
+#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg)
+#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd)
+#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard)
+
+#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg)
+#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd)
+#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
+ (resulting fields are either 0 or -1)
+*/
+#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg)
+#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd)
+#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard)
+
+#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg)
+#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd)
+#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard)
+
+#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg)
+#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd)
+#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard)
+
+
+/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical
+*/
+#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg)
+#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg)
+#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd)
+#define psllq(vars, vard) mmx_m2m(psllq, vars, vard)
+
+#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg)
+#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg)
+#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd)
+#define pslld(vars, vard) mmx_m2m(pslld, vars, vard)
+
+#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg)
+#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg)
+#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd)
+#define psllw(vars, vard) mmx_m2m(psllw, vars, vard)
+
+
+/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical
+*/
+#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg)
+#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg)
+#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd)
+#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard)
+
+#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg)
+#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg)
+#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd)
+#define psrld(vars, vard) mmx_m2m(psrld, vars, vard)
+
+#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg)
+#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg)
+#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd)
+#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard)
+
+
+/* 2x32 and 4x16 Parallel Shift Right Arithmetic
+*/
+#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg)
+#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg)
+#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd)
+#define psrad(vars, vard) mmx_m2m(psrad, vars, vard)
+
+#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg)
+#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg)
+#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd)
+#define psraw(vars, vard) mmx_m2m(psraw, vars, vard)
+
+
+/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
+ (packs source and dest fields into dest in that order)
+*/
+#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg)
+#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
+#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard)
+
+#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg)
+#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
+#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard)
+
+
+/* 4x16->8x8 PACK and Unsigned Saturate
+ (packs source and dest fields into dest in that order)
+*/
+#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg)
+#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
+#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard)
+
+
+/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
+ (interleaves low half of dest with low half of source
+ as padding in each result field)
+*/
+#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg)
+#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
+#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard)
+
+#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg)
+#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
+#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard)
+
+#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg)
+#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
+#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard)
+
+
+/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
+ (interleaves high half of dest with high half of source
+ as padding in each result field)
+*/
+#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg)
+#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
+#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard)
+
+#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg)
+#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
+#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard)
+
+#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg)
+#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
+#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard)
+
+
+/* Empty MMx State
+ (used to clean-up when going from mmx to float use
+ of the registers that are shared by both; note that
+ there is no float-to-mmx operation needed, because
+ only the float tag word info is corruptible)
+*/
+#ifdef MMX_TRACE
+
+#define emms() \
+ { \
+ fprintf(stderr, "emms()\n"); \
+ __asm__ __volatile__ ("emms"); \
+ }
+
+#else
+
+#define emms() __asm__ __volatile__ ("emms")
+
+#endif
+
+#endif
+
diff --git a/libavcodec/i386/sad_mmx.s b/libavcodec/i386/sad_mmx.s
new file mode 100644
index 0000000000..b512639c25
--- /dev/null
+++ b/libavcodec/i386/sad_mmx.s
@@ -0,0 +1,798 @@
+; MMX/SSE optimized routines for SAD of 16*16 macroblocks
+; Copyright (C) Juan J. Sierralta P. <juanjo@atmlab.utfsm.cl>
+;
+; dist1_* Original Copyright (C) 2000 Chris Atenasio <chris@crud.net>
+; Enhancements and rest Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
+
+;
+; 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 program 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.
+;
+
+global pix_abs16x16_mmx
+
+; int pix_abs16x16_mmx(unsigned char *pix1,unsigned char *pix2, int lx, int h);
+; esi = p1 (init: blk1)
+; edi = p2 (init: blk2)
+; ecx = rowsleft (init: h)
+; edx = lx;
+
+; mm0 = distance accumulators (4 words)
+; mm1 = distance accumulators (4 words)
+; mm2 = temp
+; mm3 = temp
+; mm4 = temp
+; mm5 = temp
+; mm6 = 0
+; mm7 = temp
+
+
+align 32
+pix_abs16x16_mmx:
+ push ebp ; save frame pointer
+ mov ebp, esp
+
+ push ebx ; Saves registers (called saves convention in
+ push ecx ; x86 GCC it seems)
+ push edx ;
+ push esi
+ push edi
+
+ pxor mm0, mm0 ; zero acculumators
+ pxor mm1, mm1
+ pxor mm6, mm6
+ mov esi, [ebp+8] ; get pix1
+ mov edi, [ebp+12] ; get pix2
+ mov edx, [ebp+16] ; get lx
+ mov ecx, [ebp+20] ; get rowsleft
+ jmp .nextrow
+align 32
+
+.nextrow:
+ ; First 8 bytes of the row
+
+ movq mm4, [edi] ; load first 8 bytes of pix2 row
+ movq mm5, [esi] ; load first 8 bytes of pix1 row
+ movq mm3, mm4 ; mm4 := abs(mm4-mm5)
+ movq mm2,[esi+8] ; load last 8 bytes of pix1 row
+ psubusb mm4, mm5
+ movq mm7,[edi+8] ; load last 8 bytes of pix2 row
+ psubusb mm5, mm3
+ por mm4, mm5
+
+ ; Last 8 bytes of the row
+
+ movq mm3, mm7 ; mm7 := abs(mm7-mm2)
+ psubusb mm7, mm2
+ psubusb mm2, mm3
+ por mm7, mm2
+
+ ; Now mm4 and mm7 have 16 absdiffs to add
+
+ ; First 8 bytes of the row2
+
+
+ add edi, edx
+ movq mm2, [edi] ; load first 8 bytes of pix2 row
+ add esi, edx
+ movq mm5, [esi] ; load first 8 bytes of pix1 row
+
+
+
+ movq mm3, mm2 ; mm2 := abs(mm2-mm5)
+ psubusb mm2, mm5
+ movq mm6,[esi+8] ; load last 8 bytes of pix1 row
+ psubusb mm5, mm3
+ por mm2, mm5
+
+ ; Last 8 bytes of the row2
+
+ movq mm5,[edi+8] ; load last 8 bytes of pix2 row
+
+
+ movq mm3, mm5 ; mm5 := abs(mm5-mm6)
+ psubusb mm5, mm6
+ psubusb mm6, mm3
+ por mm5, mm6
+
+ ; Now mm2, mm4, mm5, mm7 have 32 absdiffs
+
+ movq mm3, mm7
+
+ pxor mm6, mm6 ; Zero mm6
+
+ punpcklbw mm3, mm6 ; Unpack to words and add
+ punpckhbw mm7, mm6
+ paddusw mm7, mm3
+
+ movq mm3, mm5
+
+ punpcklbw mm3, mm6 ; Unpack to words and add
+ punpckhbw mm5, mm6
+ paddusw mm5, mm3
+
+ paddusw mm0, mm7 ; Add to the acumulator (mm0)
+ paddusw mm1, mm5 ; Add to the acumulator (mm1)
+
+ movq mm3, mm4
+
+ punpcklbw mm3, mm6 ; Unpack to words and add
+ punpckhbw mm4, mm6
+ movq mm5, mm2
+ paddusw mm4, mm3
+
+
+
+ punpcklbw mm5, mm6 ; Unpack to words and add
+ punpckhbw mm2, mm6
+ paddusw mm2, mm5
+
+ ; Loop termination
+
+ add esi, edx ; update pointers to next row
+ paddusw mm0, mm4 ; Add to the acumulator (mm0)
+ add edi, edx
+ sub ecx,2
+ paddusw mm1, mm2 ; Add to the acumulator (mm1)
+ test ecx, ecx ; check rowsleft
+ jnz near .nextrow
+
+ paddusw mm0, mm1
+ movq mm2, mm0 ; Copy mm0 to mm2
+ psrlq mm2, 32
+ paddusw mm0, mm2 ; Add
+ movq mm3, mm0
+ psrlq mm3, 16
+ paddusw mm0, mm3
+ movd eax, mm0 ; Store return value
+ and eax, 0xffff
+
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop ebx
+
+ pop ebp ; restore stack pointer
+
+ ;emms ; clear mmx registers
+ ret ; return
+
+global pix_abs16x16_sse
+
+; int pix_abs16x16_mmx(unsigned char *pix1,unsigned char *pix2, int lx, int h);
+; esi = p1 (init: blk1)
+; edi = p2 (init: blk2)
+; ecx = rowsleft (init: h)
+; edx = lx;
+
+; mm0 = distance accumulators (4 words)
+; mm1 = distance accumulators (4 words)
+; mm2 = temp
+; mm3 = temp
+; mm4 = temp
+; mm5 = temp
+; mm6 = temp
+; mm7 = temp
+
+
+align 32
+pix_abs16x16_sse:
+ push ebp ; save frame pointer
+ mov ebp, esp
+
+ push ebx ; Saves registers (called saves convention in
+ push ecx ; x86 GCC it seems)
+ push edx ;
+ push esi
+ push edi
+
+ pxor mm0, mm0 ; zero acculumators
+ pxor mm1, mm1
+ mov esi, [ebp+8] ; get pix1
+ mov edi, [ebp+12] ; get pix2
+ mov edx, [ebp+16] ; get lx
+ mov ecx, [ebp+20] ; get rowsleft
+ jmp .next4row
+align 32
+
+.next4row:
+ ; First row
+
+ movq mm4, [edi] ; load first 8 bytes of pix2 row
+ movq mm5, [edi+8] ; load last 8 bytes of pix2 row
+ psadbw mm4, [esi] ; SAD of first 8 bytes
+ psadbw mm5, [esi+8] ; SAD of last 8 bytes
+ paddw mm0, mm4 ; Add to acumulators
+ paddw mm1, mm5
+
+ ; Second row
+
+ add edi, edx;
+ add esi, edx;
+
+ movq mm6, [edi] ; load first 8 bytes of pix2 row
+ movq mm7, [edi+8] ; load last 8 bytes of pix2 row
+ psadbw mm6, [esi] ; SAD of first 8 bytes
+ psadbw mm7, [esi+8] ; SAD of last 8 bytes
+ paddw mm0, mm6 ; Add to acumulators
+ paddw mm1, mm7
+
+ ; Third row
+
+ add edi, edx;
+ add esi, edx;
+
+ movq mm4, [edi] ; load first 8 bytes of pix2 row
+ movq mm5, [edi+8] ; load last 8 bytes of pix2 row
+ psadbw mm4, [esi] ; SAD of first 8 bytes
+ psadbw mm5, [esi+8] ; SAD of last 8 bytes
+ paddw mm0, mm4 ; Add to acumulators
+ paddw mm1, mm5
+
+ ; Fourth row
+
+ add edi, edx;
+ add esi, edx;
+
+ movq mm6, [edi] ; load first 8 bytes of pix2 row
+ movq mm7, [edi+8] ; load last 8 bytes of pix2 row
+ psadbw mm6, [esi] ; SAD of first 8 bytes
+ psadbw mm7, [esi+8] ; SAD of last 8 bytes
+ paddw mm0, mm6 ; Add to acumulators
+ paddw mm1, mm7
+
+ ; Loop termination
+
+ add esi, edx ; update pointers to next row
+ add edi, edx
+ sub ecx,4
+ test ecx, ecx ; check rowsleft
+ jnz near .next4row
+
+ paddd mm0, mm1 ; Sum acumulators
+ movd eax, mm0 ; Store return value
+
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop ebx
+
+ pop ebp ; restore stack pointer
+
+ ;emms ; clear mmx registers
+ ret ; return
+
+global pix_abs16x16_x2_mmx
+
+; int pix_abs16x16_x2_mmx(unsigned char *pix1,unsigned char *pix2, int lx, int h);
+; esi = p1 (init: blk1)
+; edi = p2 (init: blk2)
+; ecx = rowsleft (init: h)
+; edx = lx;
+
+; mm0 = distance accumulators (4 words)
+; mm1 = distance accumulators (4 words)
+; mm2 = temp
+; mm3 = temp
+; mm4 = temp
+; mm5 = temp
+; mm6 = 0
+; mm7 = temp
+
+
+align 32
+pix_abs16x16_x2_mmx:
+ push ebp ; save frame pointer
+ mov ebp, esp
+
+ push ebx ; Saves registers (called saves convention in
+ push ecx ; x86 GCC it seems)
+ push edx ;
+ push esi
+ push edi
+
+ pxor mm0, mm0 ; zero acculumators
+ pxor mm1, mm1
+ pxor mm6, mm6
+ mov esi, [ebp+8] ; get pix1
+ mov edi, [ebp+12] ; get pix2
+ mov edx, [ebp+16] ; get lx
+ mov ecx, [ebp+20] ; get rowsleft
+ jmp .nextrow_x2
+align 32
+
+.nextrow_x2:
+ ; First 8 bytes of the row
+
+ movq mm4, [edi] ; load first 8 bytes of pix2 row
+ movq mm5, [edi+1] ; load bytes 1-8 of pix2 row
+
+ movq mm2, mm4 ; copy mm4 on mm2
+ movq mm3, mm5 ; copy mm5 on mm3
+ punpcklbw mm4, mm6 ; first 4 bytes of [edi] on mm4
+ punpcklbw mm5, mm6 ; first 4 bytes of [edi+1] on mm5
+ paddusw mm4, mm5 ; mm4 := first 4 bytes interpolated in words
+ psrlw mm4, 1
+
+ punpckhbw mm2, mm6 ; last 4 bytes of [edi] on mm2
+ punpckhbw mm3, mm6 ; last 4 bytes of [edi+1] on mm3
+ paddusw mm2, mm3 ; mm2 := last 4 bytes interpolated in words
+ psrlw mm2, 1
+
+ packuswb mm4, mm2 ; pack 8 bytes interpolated on mm4
+ movq mm5,[esi] ; load first 8 bytes of pix1 row
+
+ movq mm3, mm4 ; mm4 := abs(mm4-mm5)
+ psubusb mm4, mm5
+ psubusb mm5, mm3
+ por mm4, mm5
+
+ ; Last 8 bytes of the row
+
+ movq mm7, [edi+8] ; load last 8 bytes of pix2 row
+ movq mm5, [edi+9] ; load bytes 10-17 of pix2 row
+
+ movq mm2, mm7 ; copy mm7 on mm2
+ movq mm3, mm5 ; copy mm5 on mm3
+ punpcklbw mm7, mm6 ; first 4 bytes of [edi+8] on mm7
+ punpcklbw mm5, mm6 ; first 4 bytes of [edi+9] on mm5
+ paddusw mm7, mm5 ; mm1 := first 4 bytes interpolated in words
+ psrlw mm7, 1
+
+ punpckhbw mm2, mm6 ; last 4 bytes of [edi] on mm2
+ punpckhbw mm3, mm6 ; last 4 bytes of [edi+1] on mm3
+ paddusw mm2, mm3 ; mm2 := last 4 bytes interpolated in words
+ psrlw mm2, 1
+
+ packuswb mm7, mm2 ; pack 8 bytes interpolated on mm1
+ movq mm5,[esi+8] ; load last 8 bytes of pix1 row
+
+ movq mm3, mm7 ; mm7 := abs(mm1-mm5)
+ psubusb mm7, mm5
+ psubusb mm5, mm3
+ por mm7, mm5
+
+ ; Now mm4 and mm7 have 16 absdiffs to add
+
+ movq mm3, mm4 ; Make copies of these bytes
+ movq mm2, mm7
+
+ punpcklbw mm4, mm6 ; Unpack to words and add
+ punpcklbw mm7, mm6
+ paddusw mm4, mm7
+ paddusw mm0, mm4 ; Add to the acumulator (mm0)
+
+ punpckhbw mm3, mm6 ; Unpack to words and add
+ punpckhbw mm2, mm6
+ paddusw mm3, mm2
+ paddusw mm1, mm3 ; Add to the acumulator (mm1)
+
+ ; Loop termination
+
+ add esi, edx ; update pointers to next row
+ add edi, edx
+
+ sub ecx,1
+ test ecx, ecx ; check rowsleft
+ jnz near .nextrow_x2
+
+ paddusw mm0, mm1
+
+ movq mm1, mm0 ; Copy mm0 to mm1
+ psrlq mm1, 32
+ paddusw mm0, mm1 ; Add
+ movq mm2, mm0
+ psrlq mm2, 16
+ paddusw mm0, mm2
+ movd eax, mm0 ; Store return value
+ and eax, 0xffff
+
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop ebx
+
+ pop ebp ; restore stack pointer
+
+ emms ; clear mmx registers
+ ret ; return
+
+global pix_abs16x16_y2_mmx
+
+; int pix_abs16x16_y2_mmx(unsigned char *pix1,unsigned char *pix2, int lx, int h);
+; esi = p1 (init: blk1)
+; edi = p2 (init: blk2)
+; ebx = p2 + lx
+; ecx = rowsleft (init: h)
+; edx = lx;
+
+; mm0 = distance accumulators (4 words)
+; mm1 = distance accumulators (4 words)
+; mm2 = temp
+; mm3 = temp
+; mm4 = temp
+; mm5 = temp
+; mm6 = 0
+; mm7 = temp
+
+
+align 32
+pix_abs16x16_y2_mmx:
+ push ebp ; save frame pointer
+ mov ebp, esp
+
+ push ebx ; Saves registers (called saves convention in
+ push ecx ; x86 GCC it seems)
+ push edx ;
+ push esi
+ push edi
+
+ pxor mm0, mm0 ; zero acculumators
+ pxor mm1, mm1
+ pxor mm6, mm6
+ mov esi, [ebp+8] ; get pix1
+ mov edi, [ebp+12] ; get pix2
+ mov edx, [ebp+16] ; get lx
+ mov ecx, [ebp+20] ; get rowsleft
+ mov ebx, edi
+ add ebx, edx
+ jmp .nextrow_y2
+align 32
+
+.nextrow_y2:
+ ; First 8 bytes of the row
+
+ movq mm4, [edi] ; load first 8 bytes of pix2 row
+ movq mm5, [ebx] ; load bytes 1-8 of pix2 row
+
+ movq mm2, mm4 ; copy mm4 on mm2
+ movq mm3, mm5 ; copy mm5 on mm3
+ punpcklbw mm4, mm6 ; first 4 bytes of [edi] on mm4
+ punpcklbw mm5, mm6 ; first 4 bytes of [ebx] on mm5
+ paddusw mm4, mm5 ; mm4 := first 4 bytes interpolated in words
+ psrlw mm4, 1
+
+ punpckhbw mm2, mm6 ; last 4 bytes of [edi] on mm2
+ punpckhbw mm3, mm6 ; last 4 bytes of [edi+1] on mm3
+ paddusw mm2, mm3 ; mm2 := last 4 bytes interpolated in words
+ psrlw mm2, 1
+
+ packuswb mm4, mm2 ; pack 8 bytes interpolated on mm4
+ movq mm5,[esi] ; load first 8 bytes of pix1 row
+
+ movq mm3, mm4 ; mm4 := abs(mm4-mm5)
+ psubusb mm4, mm5
+ psubusb mm5, mm3
+ por mm4, mm5
+
+ ; Last 8 bytes of the row
+
+ movq mm7, [edi+8] ; load last 8 bytes of pix2 row
+ movq mm5, [ebx+8] ; load bytes 10-17 of pix2 row
+
+ movq mm2, mm7 ; copy mm7 on mm2
+ movq mm3, mm5 ; copy mm5 on mm3
+ punpcklbw mm7, mm6 ; first 4 bytes of [edi+8] on mm7
+ punpcklbw mm5, mm6 ; first 4 bytes of [ebx+8] on mm5
+ paddusw mm7, mm5 ; mm1 := first 4 bytes interpolated in words
+ psrlw mm7, 1
+
+ punpckhbw mm2, mm6 ; last 4 bytes of [edi+8] on mm2
+ punpckhbw mm3, mm6 ; last 4 bytes of [ebx+8] on mm3
+ paddusw mm2, mm3 ; mm2 := last 4 bytes interpolated in words
+ psrlw mm2, 1
+
+ packuswb mm7, mm2 ; pack 8 bytes interpolated on mm1
+ movq mm5,[esi+8] ; load last 8 bytes of pix1 row
+
+ movq mm3, mm7 ; mm7 := abs(mm1-mm5)
+ psubusb mm7, mm5
+ psubusb mm5, mm3
+ por mm7, mm5
+
+ ; Now mm4 and mm7 have 16 absdiffs to add
+
+ movq mm3, mm4 ; Make copies of these bytes
+ movq mm2, mm7
+
+ punpcklbw mm4, mm6 ; Unpack to words and add
+ punpcklbw mm7, mm6
+ paddusw mm4, mm7
+ paddusw mm0, mm4 ; Add to the acumulator (mm0)
+
+ punpckhbw mm3, mm6 ; Unpack to words and add
+ punpckhbw mm2, mm6
+ paddusw mm3, mm2
+ paddusw mm1, mm3 ; Add to the acumulator (mm1)
+
+ ; Loop termination
+
+ add esi, edx ; update pointers to next row
+ add edi, edx
+ add ebx, edx
+ sub ecx,1
+ test ecx, ecx ; check rowsleft
+ jnz near .nextrow_y2
+
+ paddusw mm0, mm1
+
+ movq mm1, mm0 ; Copy mm0 to mm1
+ psrlq mm1, 32
+ paddusw mm0, mm1 ; Add
+ movq mm2, mm0
+ psrlq mm2, 16
+ paddusw mm0, mm2
+ movd eax, mm0 ; Store return value
+ and eax, 0xffff
+
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop ebx
+
+ pop ebp ; restore stack pointer
+
+ emms ; clear mmx registers
+ ret ; return
+
+global pix_abs16x16_xy2_mmx
+
+; int pix_abs16x16_xy2_mmx(unsigned char *p1,unsigned char *p2,int lx,int h);
+
+; esi = p1 (init: blk1)
+; edi = p2 (init: blk2)
+; ebx = p1+lx
+; ecx = rowsleft (init: h)
+; edx = lx;
+
+; mm0 = distance accumulators (4 words)
+; mm1 = bytes p2
+; mm2 = bytes p1
+; mm3 = bytes p1+lx
+; I'd love to find someplace to stash p1+1 and p1+lx+1's bytes
+; but I don't think thats going to happen in iA32-land...
+; mm4 = temp 4 bytes in words interpolating p1, p1+1
+; mm5 = temp 4 bytes in words from p2
+; mm6 = temp comparison bit mask p1,p2
+; mm7 = temp comparison bit mask p2,p1
+
+
+align 32
+pix_abs16x16_xy2_mmx:
+ push ebp ; save stack pointer
+ mov ebp, esp ; so that we can do this
+
+ push ebx ; Saves registers (called saves convention in
+ push ecx ; x86 GCC it seems)
+ push edx ;
+ push esi
+ push edi
+
+ pxor mm0, mm0 ; zero acculumators
+
+ mov esi, [ebp+12] ; get p1
+ mov edi, [ebp+8] ; get p2
+ mov edx, [ebp+16] ; get lx
+ mov ecx, [ebp+20] ; rowsleft := h
+ mov ebx, esi
+ add ebx, edx
+ jmp .nextrowmm11 ; snap to it
+align 32
+.nextrowmm11:
+
+ ;;
+ ;; First 8 bytes of row
+ ;;
+
+ ;; First 4 bytes of 8
+
+ movq mm4, [esi] ; mm4 := first 4 bytes p1
+ pxor mm7, mm7
+ movq mm2, mm4 ; mm2 records all 8 bytes
+ punpcklbw mm4, mm7 ; First 4 bytes p1 in Words...
+
+ movq mm6, [ebx] ; mm6 := first 4 bytes p1+lx
+ movq mm3, mm6 ; mm3 records all 8 bytes
+ punpcklbw mm6, mm7
+ paddw mm4, mm6
+
+
+ movq mm5, [esi+1] ; mm5 := first 4 bytes p1+1
+ punpcklbw mm5, mm7 ; First 4 bytes p1 in Words...
+ paddw mm4, mm5
+ movq mm6, [ebx+1] ; mm6 := first 4 bytes p1+lx+1
+ punpcklbw mm6, mm7
+ paddw mm4, mm6
+
+ psrlw mm4, 2 ; mm4 := First 4 bytes interpolated in words
+
+ movq mm5, [edi] ; mm5:=first 4 bytes of p2 in words
+ movq mm1, mm5
+ punpcklbw mm5, mm7
+
+ movq mm7,mm4
+ pcmpgtw mm7,mm5 ; mm7 := [i : W0..3,mm4>mm5]
+
+ movq mm6,mm4 ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
+ psubw mm6,mm5
+ pand mm6, mm7
+
+ paddw mm0, mm6 ; Add to accumulator
+
+ movq mm6,mm5 ; mm6 := [i : W0..3,mm5>mm4]
+ pcmpgtw mm6,mm4
+ psubw mm5,mm4 ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
+ pand mm5, mm6
+
+ paddw mm0, mm5 ; Add to accumulator
+
+ ;; Second 4 bytes of 8
+
+ movq mm4, mm2 ; mm4 := Second 4 bytes p1 in words
+ pxor mm7, mm7
+ punpckhbw mm4, mm7
+ movq mm6, mm3 ; mm6 := Second 4 bytes p1+1 in words
+ punpckhbw mm6, mm7
+ paddw mm4, mm6
+
+ movq mm5, [esi+1] ; mm5 := first 4 bytes p1+1
+ punpckhbw mm5, mm7 ; First 4 bytes p1 in Words...
+ paddw mm4, mm5
+ movq mm6, [ebx+1] ; mm6 := first 4 bytes p1+lx+1
+ punpckhbw mm6, mm7
+ paddw mm4, mm6
+
+ psrlw mm4, 2 ; mm4 := First 4 bytes interpolated in words
+
+ movq mm5, mm1 ; mm5:= second 4 bytes of p2 in words
+ punpckhbw mm5, mm7
+
+ movq mm7,mm4
+ pcmpgtw mm7,mm5 ; mm7 := [i : W0..3,mm4>mm5]
+
+ movq mm6,mm4 ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
+ psubw mm6,mm5
+ pand mm6, mm7
+
+ paddw mm0, mm6 ; Add to accumulator
+
+ movq mm6,mm5 ; mm6 := [i : W0..3,mm5>mm4]
+ pcmpgtw mm6,mm4
+ psubw mm5,mm4 ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
+ pand mm5, mm6
+
+ paddw mm0, mm5 ; Add to accumulator
+
+
+ ;;
+ ;; Second 8 bytes of row
+ ;;
+ ;; First 4 bytes of 8
+
+ movq mm4, [esi+8] ; mm4 := first 4 bytes p1+8
+ pxor mm7, mm7
+ movq mm2, mm4 ; mm2 records all 8 bytes
+ punpcklbw mm4, mm7 ; First 4 bytes p1 in Words...
+
+ movq mm6, [ebx+8] ; mm6 := first 4 bytes p1+lx+8
+ movq mm3, mm6 ; mm3 records all 8 bytes
+ punpcklbw mm6, mm7
+ paddw mm4, mm6
+
+
+ movq mm5, [esi+9] ; mm5 := first 4 bytes p1+9
+ punpcklbw mm5, mm7 ; First 4 bytes p1 in Words...
+ paddw mm4, mm5
+ movq mm6, [ebx+9] ; mm6 := first 4 bytes p1+lx+9
+ punpcklbw mm6, mm7
+ paddw mm4, mm6
+
+ psrlw mm4, 2 ; mm4 := First 4 bytes interpolated in words
+
+ movq mm5, [edi+8] ; mm5:=first 4 bytes of p2+8 in words
+ movq mm1, mm5
+ punpcklbw mm5, mm7
+
+ movq mm7,mm4
+ pcmpgtw mm7,mm5 ; mm7 := [i : W0..3,mm4>mm5]
+
+ movq mm6,mm4 ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
+ psubw mm6,mm5
+ pand mm6, mm7
+
+ paddw mm0, mm6 ; Add to accumulator
+
+ movq mm6,mm5 ; mm6 := [i : W0..3,mm5>mm4]
+ pcmpgtw mm6,mm4
+ psubw mm5,mm4 ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
+ pand mm5, mm6
+
+ paddw mm0, mm5 ; Add to accumulator
+
+ ;; Second 4 bytes of 8
+
+ movq mm4, mm2 ; mm4 := Second 4 bytes p1 in words
+ pxor mm7, mm7
+ punpckhbw mm4, mm7
+ movq mm6, mm3 ; mm6 := Second 4 bytes p1+1 in words
+ punpckhbw mm6, mm7
+ paddw mm4, mm6
+
+ movq mm5, [esi+9] ; mm5 := first 4 bytes p1+1
+ punpckhbw mm5, mm7 ; First 4 bytes p1 in Words...
+ paddw mm4, mm5
+ movq mm6, [ebx+9] ; mm6 := first 4 bytes p1+lx+1
+ punpckhbw mm6, mm7
+ paddw mm4, mm6
+
+ psrlw mm4, 2 ; mm4 := First 4 bytes interpolated in words
+
+ movq mm5, mm1 ; mm5:= second 4 bytes of p2 in words
+ punpckhbw mm5, mm7
+
+ movq mm7,mm4
+ pcmpgtw mm7,mm5 ; mm7 := [i : W0..3,mm4>mm5]
+
+ movq mm6,mm4 ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
+ psubw mm6,mm5
+ pand mm6, mm7
+
+ paddw mm0, mm6 ; Add to accumulator
+
+ movq mm6,mm5 ; mm6 := [i : W0..3,mm5>mm4]
+ pcmpgtw mm6,mm4
+ psubw mm5,mm4 ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
+ pand mm5, mm6
+
+ paddw mm0, mm5 ; Add to accumulator
+
+
+ ;;
+ ;; Loop termination condition... and stepping
+ ;;
+
+ add esi, edx ; update pointer to next row
+ add edi, edx ; ditto
+ add ebx, edx
+
+ sub ecx,1
+ test ecx, ecx ; check rowsleft
+ jnz near .nextrowmm11
+
+ ;; Sum the Accumulators
+ movq mm4, mm0
+ psrlq mm4, 32
+ paddw mm0, mm4
+ movq mm6, mm0
+ psrlq mm6, 16
+ paddw mm0, mm6
+ movd eax, mm0 ; store return value
+ and eax, 0xffff
+
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop ebx
+
+ pop ebp ; restore stack pointer
+
+ emms ; clear mmx registers
+ ret ; we now return you to your regular programming
+
+
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c
new file mode 100644
index 0000000000..01289d4d83
--- /dev/null
+++ b/libavcodec/imgconvert.c
@@ -0,0 +1,214 @@
+/*
+ * Misc image convertion routines
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "avcodec.h"
+
+/* XXX: totally non optimized */
+
+static void yuv422_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
+ UINT8 *src, int width, int height)
+{
+ int x, y;
+ UINT8 *p = src;
+
+ for(y=0;y<height;y+=2) {
+ for(x=0;x<width;x+=2) {
+ lum[0] = p[0];
+ cb[0] = p[1];
+ lum[1] = p[2];
+ cr[0] = p[3];
+ p += 4;
+ lum += 2;
+ cb++;
+ cr++;
+ }
+ for(x=0;x<width;x+=2) {
+ lum[0] = p[0];
+ lum[1] = p[2];
+ p += 4;
+ lum += 2;
+ }
+ }
+}
+
+#define SCALEBITS 8
+#define ONE_HALF (1 << (SCALEBITS - 1))
+#define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
+
+static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
+ UINT8 *src, int width, int height)
+{
+ int wrap, wrap3, x, y;
+ int r, g, b, r1, g1, b1;
+ UINT8 *p;
+
+ wrap = width;
+ wrap3 = width * 3;
+ p = src;
+ for(y=0;y<height;y+=2) {
+ for(x=0;x<width;x+=2) {
+ r = p[0];
+ g = p[1];
+ b = p[2];
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ r = p[3];
+ g = p[4];
+ b = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ p += wrap3;
+ lum += wrap;
+
+ r = p[0];
+ g = p[1];
+ b = p[2];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ r = p[3];
+ g = p[4];
+ b = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+
+ cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
+ FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+ cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
+ FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+
+ cb++;
+ cr++;
+ p += -wrap3 + 2 * 3;
+ lum += -wrap + 2;
+ }
+ p += wrap3;
+ lum += wrap;
+ }
+}
+
+static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
+ UINT8 *src, int width, int height)
+{
+ int wrap, wrap3, x, y;
+ int r, g, b, r1, g1, b1;
+ UINT8 *p;
+
+ wrap = width;
+ wrap3 = width * 3;
+ p = src;
+ for(y=0;y<height;y+=2) {
+ for(x=0;x<width;x+=2) {
+ b = p[0];
+ g = p[1];
+ r = p[2];
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ b = p[3];
+ g = p[4];
+ r = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ p += wrap3;
+ lum += wrap;
+
+ b = p[0];
+ g = p[1];
+ r = p[2];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+ b = p[3];
+ g = p[4];
+ r = p[5];
+ r1 += r;
+ g1 += g;
+ b1 += b;
+ lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
+ FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
+
+ cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
+ FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+ cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
+ FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
+
+ cb++;
+ cr++;
+ p += -wrap3 + 2 * 3;
+ lum += -wrap + 2;
+ }
+ p += wrap3;
+ lum += wrap;
+ }
+}
+
+int img_convert_to_yuv420(UINT8 *img_out, UINT8 *img,
+ int pix_fmt, int width, int height)
+{
+ UINT8 *pict;
+ int size, size_out;
+ UINT8 *picture[3];
+
+ pict = img_out;
+ size = width * height;
+ size_out = (size * 3) / 2;
+ picture[0] = pict;
+ picture[1] = pict + size;
+ picture[2] = picture[1] + (size / 4);
+
+ switch(pix_fmt) {
+ case PIX_FMT_YUV420P:
+ memcpy(pict, img, size_out);
+ break;
+ case PIX_FMT_YUV422:
+ yuv422_to_yuv420p(picture[0], picture[1], picture[2],
+ img, width, height);
+ break;
+ case PIX_FMT_RGB24:
+ rgb24_to_yuv420p(picture[0], picture[1], picture[2],
+ img, width, height);
+ break;
+ case PIX_FMT_BGR24:
+ bgr24_to_yuv420p(picture[0], picture[1], picture[2],
+ img, width, height);
+ break;
+ }
+ return size_out;
+}
diff --git a/libavcodec/imgresample.c b/libavcodec/imgresample.c
new file mode 100644
index 0000000000..99153013cf
--- /dev/null
+++ b/libavcodec/imgresample.c
@@ -0,0 +1,614 @@
+/*
+ * High quality image resampling with polyphase filters
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "dsputil.h"
+#include "avcodec.h"
+
+#define NB_COMPONENTS 3
+
+#define PHASE_BITS 4
+#define NB_PHASES (1 << PHASE_BITS)
+#define NB_TAPS 4
+#define FCENTER 1 /* index of the center of the filter */
+
+#define POS_FRAC_BITS 16
+#define POS_FRAC (1 << POS_FRAC_BITS)
+/* 6 bits precision is needed for MMX */
+#define FILTER_BITS 8
+
+#define LINE_BUF_HEIGHT (NB_TAPS * 4)
+
+struct ImgReSampleContext {
+ int iwidth, iheight, owidth, oheight;
+ int h_incr, v_incr;
+ INT16 h_filters[NB_PHASES][NB_TAPS] __align8; /* horizontal filters */
+ INT16 v_filters[NB_PHASES][NB_TAPS] __align8; /* vertical filters */
+ UINT8 *line_buf;
+};
+
+static inline int get_phase(int pos)
+{
+ return ((pos) >> (POS_FRAC_BITS - PHASE_BITS)) & ((1 << PHASE_BITS) - 1);
+}
+
+/* This function must be optimized */
+static void h_resample_fast(UINT8 *dst, int dst_width, UINT8 *src, int src_width,
+ int src_start, int src_incr, INT16 *filters)
+{
+ int src_pos, phase, sum, i;
+ UINT8 *s;
+ INT16 *filter;
+
+ src_pos = src_start;
+ for(i=0;i<dst_width;i++) {
+#ifdef TEST
+ /* test */
+ if ((src_pos >> POS_FRAC_BITS) < 0 ||
+ (src_pos >> POS_FRAC_BITS) > (src_width - NB_TAPS))
+ abort();
+#endif
+ s = src + (src_pos >> POS_FRAC_BITS);
+ phase = get_phase(src_pos);
+ filter = filters + phase * NB_TAPS;
+#if NB_TAPS == 4
+ sum = s[0] * filter[0] +
+ s[1] * filter[1] +
+ s[2] * filter[2] +
+ s[3] * filter[3];
+#else
+ {
+ int j;
+ sum = 0;
+ for(j=0;j<NB_TAPS;j++)
+ sum += s[j] * filter[j];
+ }
+#endif
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ src_pos += src_incr;
+ dst++;
+ }
+}
+
+/* This function must be optimized */
+static void v_resample(UINT8 *dst, int dst_width, UINT8 *src, int wrap,
+ INT16 *filter)
+{
+ int sum, i;
+ UINT8 *s;
+
+ s = src;
+ for(i=0;i<dst_width;i++) {
+#if NB_TAPS == 4
+ sum = s[0 * wrap] * filter[0] +
+ s[1 * wrap] * filter[1] +
+ s[2 * wrap] * filter[2] +
+ s[3 * wrap] * filter[3];
+#else
+ {
+ int j;
+ UINT8 *s1 = s;
+
+ sum = 0;
+ for(j=0;j<NB_TAPS;j++) {
+ sum += s1[0] * filter[j];
+ s1 += wrap;
+ }
+ }
+#endif
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ dst++;
+ s++;
+ }
+}
+
+#ifdef CONFIG_MMX
+
+#include "i386/mmx.h"
+
+#define FILTER4(reg) \
+{\
+ s = src + (src_pos >> POS_FRAC_BITS);\
+ phase = get_phase(src_pos);\
+ filter = filters + phase * NB_TAPS;\
+ movq_m2r(*s, reg);\
+ punpcklbw_r2r(mm7, reg);\
+ movq_m2r(*filter, mm6);\
+ pmaddwd_r2r(reg, mm6);\
+ movq_r2r(mm6, reg);\
+ psrlq_i2r(32, reg);\
+ paddd_r2r(mm6, reg);\
+ psrad_i2r(FILTER_BITS, reg);\
+ src_pos += src_incr;\
+}
+
+#define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016Lx\n", tmp.uq);
+
+/* XXX: do four pixels at a time */
+static void h_resample_fast4_mmx(UINT8 *dst, int dst_width, UINT8 *src, int src_width,
+ int src_start, int src_incr, INT16 *filters)
+{
+ int src_pos, phase;
+ UINT8 *s;
+ INT16 *filter;
+ mmx_t tmp;
+
+ src_pos = src_start;
+ pxor_r2r(mm7, mm7);
+
+ while (dst_width >= 4) {
+
+ FILTER4(mm0);
+ FILTER4(mm1);
+ FILTER4(mm2);
+ FILTER4(mm3);
+
+ packuswb_r2r(mm7, mm0);
+ packuswb_r2r(mm7, mm1);
+ packuswb_r2r(mm7, mm3);
+ packuswb_r2r(mm7, mm2);
+ movq_r2m(mm0, tmp);
+ dst[0] = tmp.ub[0];
+ movq_r2m(mm1, tmp);
+ dst[1] = tmp.ub[0];
+ movq_r2m(mm2, tmp);
+ dst[2] = tmp.ub[0];
+ movq_r2m(mm3, tmp);
+ dst[3] = tmp.ub[0];
+ dst += 4;
+ dst_width -= 4;
+ }
+ while (dst_width > 0) {
+ FILTER4(mm0);
+ packuswb_r2r(mm7, mm0);
+ movq_r2m(mm0, tmp);
+ dst[0] = tmp.ub[0];
+ dst++;
+ dst_width--;
+ }
+ emms();
+}
+
+static void v_resample4_mmx(UINT8 *dst, int dst_width, UINT8 *src, int wrap,
+ INT16 *filter)
+{
+ int sum, i, v;
+ UINT8 *s;
+ mmx_t tmp;
+ mmx_t coefs[4];
+
+ for(i=0;i<4;i++) {
+ v = filter[i];
+ coefs[i].uw[0] = v;
+ coefs[i].uw[1] = v;
+ coefs[i].uw[2] = v;
+ coefs[i].uw[3] = v;
+ }
+
+ pxor_r2r(mm7, mm7);
+ s = src;
+ while (dst_width >= 4) {
+ movq_m2r(s[0 * wrap], mm0);
+ punpcklbw_r2r(mm7, mm0);
+ movq_m2r(s[1 * wrap], mm1);
+ punpcklbw_r2r(mm7, mm1);
+ movq_m2r(s[2 * wrap], mm2);
+ punpcklbw_r2r(mm7, mm2);
+ movq_m2r(s[3 * wrap], mm3);
+ punpcklbw_r2r(mm7, mm3);
+
+ pmullw_m2r(coefs[0], mm0);
+ pmullw_m2r(coefs[1], mm1);
+ pmullw_m2r(coefs[2], mm2);
+ pmullw_m2r(coefs[3], mm3);
+
+ paddw_r2r(mm1, mm0);
+ paddw_r2r(mm3, mm2);
+ paddw_r2r(mm2, mm0);
+ psraw_i2r(FILTER_BITS, mm0);
+
+ packuswb_r2r(mm7, mm0);
+ movq_r2m(mm0, tmp);
+
+ *(UINT32 *)dst = tmp.ud[0];
+ dst += 4;
+ s += 4;
+ dst_width -= 4;
+ }
+ while (dst_width > 0) {
+ sum = s[0 * wrap] * filter[0] +
+ s[1 * wrap] * filter[1] +
+ s[2 * wrap] * filter[2] +
+ s[3 * wrap] * filter[3];
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ dst++;
+ s++;
+ dst_width--;
+ }
+ emms();
+}
+#endif
+
+/* slow version to handle limit cases. Does not need optimisation */
+static void h_resample_slow(UINT8 *dst, int dst_width, UINT8 *src, int src_width,
+ int src_start, int src_incr, INT16 *filters)
+{
+ int src_pos, phase, sum, j, v, i;
+ UINT8 *s, *src_end;
+ INT16 *filter;
+
+ src_end = src + src_width;
+ src_pos = src_start;
+ for(i=0;i<dst_width;i++) {
+ s = src + (src_pos >> POS_FRAC_BITS);
+ phase = get_phase(src_pos);
+ filter = filters + phase * NB_TAPS;
+ sum = 0;
+ for(j=0;j<NB_TAPS;j++) {
+ if (s < src)
+ v = src[0];
+ else if (s >= src_end)
+ v = src_end[-1];
+ else
+ v = s[0];
+ sum += v * filter[j];
+ s++;
+ }
+ sum = sum >> FILTER_BITS;
+ if (sum < 0)
+ sum = 0;
+ else if (sum > 255)
+ sum = 255;
+ dst[0] = sum;
+ src_pos += src_incr;
+ dst++;
+ }
+}
+
+static void h_resample(UINT8 *dst, int dst_width, UINT8 *src, int src_width,
+ int src_start, int src_incr, INT16 *filters)
+{
+ int n, src_end;
+
+ if (src_start < 0) {
+ n = (0 - src_start + src_incr - 1) / src_incr;
+ h_resample_slow(dst, n, src, src_width, src_start, src_incr, filters);
+ dst += n;
+ dst_width -= n;
+ src_start += n * src_incr;
+ }
+ src_end = src_start + dst_width * src_incr;
+ if (src_end > ((src_width - NB_TAPS) << POS_FRAC_BITS)) {
+ n = (((src_width - NB_TAPS + 1) << POS_FRAC_BITS) - 1 - src_start) /
+ src_incr;
+ } else {
+ n = dst_width;
+ }
+#ifdef CONFIG_MMX
+ if ((mm_flags & MM_MMX) && NB_TAPS == 4)
+ h_resample_fast4_mmx(dst, n,
+ src, src_width, src_start, src_incr, filters);
+ else
+#endif
+ h_resample_fast(dst, n,
+ src, src_width, src_start, src_incr, filters);
+ if (n < dst_width) {
+ dst += n;
+ dst_width -= n;
+ src_start += n * src_incr;
+ h_resample_slow(dst, dst_width,
+ src, src_width, src_start, src_incr, filters);
+ }
+}
+
+static void component_resample(ImgReSampleContext *s,
+ UINT8 *output, int owrap, int owidth, int oheight,
+ UINT8 *input, int iwrap, int iwidth, int iheight)
+{
+ int src_y, src_y1, last_src_y, ring_y, phase_y, y1, y;
+ UINT8 *new_line, *src_line;
+
+ last_src_y = - FCENTER - 1;
+ /* position of the bottom of the filter in the source image */
+ src_y = (last_src_y + NB_TAPS) * POS_FRAC;
+ ring_y = NB_TAPS; /* position in ring buffer */
+ for(y=0;y<oheight;y++) {
+ /* apply horizontal filter on new lines from input if needed */
+ src_y1 = src_y >> POS_FRAC_BITS;
+ while (last_src_y < src_y1) {
+ if (++ring_y >= LINE_BUF_HEIGHT + NB_TAPS)
+ ring_y = NB_TAPS;
+ last_src_y++;
+ /* handle limit conditions : replicate line (slighly
+ inefficient because we filter multiple times */
+ y1 = last_src_y;
+ if (y1 < 0) {
+ y1 = 0;
+ } else if (y1 >= iheight) {
+ y1 = iheight - 1;
+ }
+ src_line = input + y1 * iwrap;
+ new_line = s->line_buf + ring_y * owidth;
+ /* apply filter and handle limit cases correctly */
+ h_resample(new_line, owidth,
+ src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
+ &s->h_filters[0][0]);
+ /* handle ring buffer wraping */
+ if (ring_y >= LINE_BUF_HEIGHT) {
+ memcpy(s->line_buf + (ring_y - LINE_BUF_HEIGHT) * owidth,
+ new_line, owidth);
+ }
+ }
+ /* apply vertical filter */
+ phase_y = get_phase(src_y);
+#ifdef CONFIG_MMX
+ /* desactivated MMX because loss of precision */
+ if ((mm_flags & MM_MMX) && NB_TAPS == 4 && 0)
+ v_resample4_mmx(output, owidth,
+ s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
+ &s->v_filters[phase_y][0]);
+ else
+#endif
+ v_resample(output, owidth,
+ s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
+ &s->v_filters[phase_y][0]);
+
+ src_y += s->v_incr;
+ output += owrap;
+ }
+}
+
+/* XXX: the following filter is quite naive, but it seems to suffice
+ for 4 taps */
+static void build_filter(INT16 *filter, float factor)
+{
+ int ph, i, v;
+ float x, y, tab[NB_TAPS], norm, mult;
+
+ /* if upsampling, only need to interpolate, no filter */
+ if (factor > 1.0)
+ factor = 1.0;
+
+ for(ph=0;ph<NB_PHASES;ph++) {
+ norm = 0;
+ for(i=0;i<NB_TAPS;i++) {
+
+ x = M_PI * ((float)(i - FCENTER) - (float)ph / NB_PHASES) * factor;
+ if (x == 0)
+ y = 1.0;
+ else
+ y = sin(x) / x;
+ tab[i] = y;
+ norm += y;
+ }
+
+ /* normalize so that an uniform color remains the same */
+ mult = (float)(1 << FILTER_BITS) / norm;
+ for(i=0;i<NB_TAPS;i++) {
+ v = (int)(tab[i] * mult);
+ filter[ph * NB_TAPS + i] = v;
+ }
+ }
+}
+
+ImgReSampleContext *img_resample_init(int owidth, int oheight,
+ int iwidth, int iheight)
+{
+ ImgReSampleContext *s;
+
+ s = av_mallocz(sizeof(ImgReSampleContext));
+ if (!s)
+ return NULL;
+ s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
+ if (!s->line_buf)
+ goto fail;
+
+ s->owidth = owidth;
+ s->oheight = oheight;
+ s->iwidth = iwidth;
+ s->iheight = iheight;
+
+ s->h_incr = (iwidth * POS_FRAC) / owidth;
+ s->v_incr = (iheight * POS_FRAC) / oheight;
+
+ build_filter(&s->h_filters[0][0], (float)owidth / (float)iwidth);
+ build_filter(&s->v_filters[0][0], (float)oheight / (float)iheight);
+
+ return s;
+ fail:
+ free(s);
+ return NULL;
+}
+
+void img_resample(ImgReSampleContext *s,
+ AVPicture *output, AVPicture *input)
+{
+ int i, shift;
+
+ for(i=0;i<3;i++) {
+ shift = (i == 0) ? 0 : 1;
+ component_resample(s, output->data[i], output->linesize[i],
+ s->owidth >> shift, s->oheight >> shift,
+ input->data[i], input->linesize[i],
+ s->iwidth >> shift, s->iheight >> shift);
+ }
+}
+
+void img_resample_close(ImgReSampleContext *s)
+{
+ free(s->line_buf);
+ free(s);
+}
+
+#ifdef TEST
+
+void *av_mallocz(int size)
+{
+ void *ptr;
+ ptr = malloc(size);
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+/* input */
+#define XSIZE 256
+#define YSIZE 256
+UINT8 img[XSIZE * YSIZE];
+
+/* output */
+#define XSIZE1 512
+#define YSIZE1 512
+UINT8 img1[XSIZE1 * YSIZE1];
+UINT8 img2[XSIZE1 * YSIZE1];
+
+void save_pgm(const char *filename, UINT8 *img, int xsize, int ysize)
+{
+ FILE *f;
+ f=fopen(filename,"w");
+ fprintf(f,"P5\n%d %d\n%d\n", xsize, ysize, 255);
+ fwrite(img,1, xsize * ysize,f);
+ fclose(f);
+}
+
+static void dump_filter(INT16 *filter)
+{
+ int i, ph;
+
+ for(ph=0;ph<NB_PHASES;ph++) {
+ printf("%2d: ", ph);
+ for(i=0;i<NB_TAPS;i++) {
+ printf(" %5.2f", filter[ph * NB_TAPS + i] / 256.0);
+ }
+ printf("\n");
+ }
+}
+
+#ifdef CONFIG_MMX
+int mm_flags;
+#endif
+
+int main(int argc, char **argv)
+{
+ int x, y, v, i, xsize, ysize;
+ ImgReSampleContext *s;
+ float fact, factors[] = { 1/2.0, 3.0/4.0, 1.0, 4.0/3.0, 16.0/9.0, 2.0 };
+ char buf[256];
+
+ /* build test image */
+ for(y=0;y<YSIZE;y++) {
+ for(x=0;x<XSIZE;x++) {
+ if (x < XSIZE/2 && y < YSIZE/2) {
+ if (x < XSIZE/4 && y < YSIZE/4) {
+ if ((x % 10) <= 6 &&
+ (y % 10) <= 6)
+ v = 0xff;
+ else
+ v = 0x00;
+ } else if (x < XSIZE/4) {
+ if (x & 1)
+ v = 0xff;
+ else
+ v = 0;
+ } else if (y < XSIZE/4) {
+ if (y & 1)
+ v = 0xff;
+ else
+ v = 0;
+ } else {
+ if (y < YSIZE*3/8) {
+ if ((y+x) & 1)
+ v = 0xff;
+ else
+ v = 0;
+ } else {
+ if (((x+3) % 4) <= 1 &&
+ ((y+3) % 4) <= 1)
+ v = 0xff;
+ else
+ v = 0x00;
+ }
+ }
+ } else if (x < XSIZE/2) {
+ v = ((x - (XSIZE/2)) * 255) / (XSIZE/2);
+ } else if (y < XSIZE/2) {
+ v = ((y - (XSIZE/2)) * 255) / (XSIZE/2);
+ } else {
+ v = ((x + y - XSIZE) * 255) / XSIZE;
+ }
+ img[y * XSIZE + x] = v;
+ }
+ }
+ save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE);
+ for(i=0;i<sizeof(factors)/sizeof(float);i++) {
+ fact = factors[i];
+ xsize = (int)(XSIZE * fact);
+ ysize = (int)(YSIZE * fact);
+ s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
+ printf("Factor=%0.2f\n", fact);
+ dump_filter(&s->h_filters[0][0]);
+ component_resample(s, img1, xsize, xsize, ysize,
+ img, XSIZE, XSIZE, YSIZE);
+ img_resample_close(s);
+
+ sprintf(buf, "/tmp/out%d.pgm", i);
+ save_pgm(buf, img1, xsize, ysize);
+ }
+
+ /* mmx test */
+#ifdef CONFIG_MMX
+ printf("MMX test\n");
+ fact = 0.72;
+ xsize = (int)(XSIZE * fact);
+ ysize = (int)(YSIZE * fact);
+ mm_flags = MM_MMX;
+ s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
+ component_resample(s, img1, xsize, xsize, ysize,
+ img, XSIZE, XSIZE, YSIZE);
+
+ mm_flags = 0;
+ s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
+ component_resample(s, img2, xsize, xsize, ysize,
+ img, XSIZE, XSIZE, YSIZE);
+ if (memcmp(img1, img2, xsize * ysize) != 0) {
+ fprintf(stderr, "mmx error\n");
+ exit(1);
+ }
+ printf("MMX OK\n");
+#endif
+ return 0;
+}
+
+#endif
diff --git a/libavcodec/jfdctfst.c b/libavcodec/jfdctfst.c
new file mode 100644
index 0000000000..cdc3b47f99
--- /dev/null
+++ b/libavcodec/jfdctfst.c
@@ -0,0 +1,224 @@
+/*
+ * jfdctfst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values. The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "common.h"
+#include "dsputil.h"
+
+#define DCTSIZE 8
+#define GLOBAL(x) x
+#define RIGHT_SHIFT(x, n) ((x) >> (n))
+#define SHIFT_TEMPS
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jfdctint.c for more details. However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * Again to save a few shifts, the intermediate results between pass 1 and
+ * pass 2 are not upscaled, but are represented only to integral precision.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13. This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#define CONST_BITS 8
+
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */
+#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */
+#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */
+#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */
+#else
+#define FIX_0_382683433 FIX(0.382683433)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_707106781 FIX(0.707106781)
+#define FIX_1_306562965 FIX(1.306562965)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift. This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_ifast (DCTELEM * data)
+{
+ DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ DCTELEM tmp10, tmp11, tmp12, tmp13;
+ DCTELEM z1, z2, z3, z4, z5, z11, z13;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = dataptr[0] - dataptr[7];
+ tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = dataptr[2] - dataptr[5];
+ tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = dataptr[3] - dataptr[4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[2] = tmp13 + z1; /* phase 5 */
+ dataptr[6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[5] = z13 + z2; /* phase 6 */
+ dataptr[3] = z13 - z2;
+ dataptr[1] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE*4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE*6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE*3] = z13 - z2;
+ dataptr[DCTSIZE*1] = z11 + z4;
+ dataptr[DCTSIZE*7] = z11 - z4;
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
diff --git a/libavcodec/jrevdct.c b/libavcodec/jrevdct.c
new file mode 100644
index 0000000000..2ef40f38e5
--- /dev/null
+++ b/libavcodec/jrevdct.c
@@ -0,0 +1,1167 @@
+/*
+ * jrevdct.c
+ *
+ * Copyright (C) 1991, 1992, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the basic inverse-DCT transformation subroutine.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ *
+ * I've made lots of modifications to attempt to take advantage of the
+ * sparse nature of the DCT matrices we're getting. Although the logic
+ * is cumbersome, it's straightforward and the resulting code is much
+ * faster.
+ *
+ * A better way to do this would be to pass in the DCT block as a sparse
+ * matrix, perhaps with the difference cases encoded.
+ */
+#include "common.h"
+#include "dsputil.h"
+
+#define EIGHT_BIT_SAMPLES
+
+#define DCTSIZE 8
+#define DCTSIZE2 64
+
+#define GLOBAL
+
+#define RIGHT_SHIFT(x, n) ((x) >> (n))
+
+typedef DCTELEM DCTBLOCK[DCTSIZE2];
+
+#define CONST_BITS 13
+
+/*
+ * This routine is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true IDCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D IDCT,
+ * because the y0 and y4 inputs need not be divided by sqrt(N).
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (To scale up 12-bit sample data further, an
+ * intermediate int32 array would be needed.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#ifdef EIGHT_BIT_SAMPLES
+#define PASS1_BITS 2
+#else
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+#define ONE ((INT32) 1)
+
+#define CONST_SCALE (ONE << CONST_BITS)
+
+/* Convert a positive real constant to an integer scaled by CONST_SCALE.
+ * IMPORTANT: if your compiler doesn't do this arithmetic at compile time,
+ * you will pay a significant penalty in run time. In that case, figure
+ * the correct integer constant values and insert them by hand.
+ */
+
+/* Actually FIX is no longer used, we precomputed them all */
+#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
+
+/* Descale and correctly round an INT32 value that's scaled by N bits.
+ * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
+ * the fudge factor is correct for either sign of X.
+ */
+
+#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
+ * this provides a useful speedup on many machines.
+ * There is no way to specify a 16x16->32 multiply in portable C, but
+ * some C compilers will do the right thing if you provide the correct
+ * combination of casts.
+ * NB: for 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#ifdef EIGHT_BIT_SAMPLES
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
+#endif
+#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
+#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
+#endif
+#endif
+
+#ifndef MULTIPLY /* default definition */
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/*
+ Unlike our decoder where we approximate the FIXes, we need to use exact
+ones here or successive P-frames will drift too much with Reference frame coding
+*/
+#define FIX_0_211164243 1730
+#define FIX_0_275899380 2260
+#define FIX_0_298631336 2446
+#define FIX_0_390180644 3196
+#define FIX_0_509795579 4176
+#define FIX_0_541196100 4433
+#define FIX_0_601344887 4926
+#define FIX_0_765366865 6270
+#define FIX_0_785694958 6436
+#define FIX_0_899976223 7373
+#define FIX_1_061594337 8697
+#define FIX_1_111140466 9102
+#define FIX_1_175875602 9633
+#define FIX_1_306562965 10703
+#define FIX_1_387039845 11363
+#define FIX_1_451774981 11893
+#define FIX_1_501321110 12299
+#define FIX_1_662939225 13623
+#define FIX_1_847759065 15137
+#define FIX_1_961570560 16069
+#define FIX_2_053119869 16819
+#define FIX_2_172734803 17799
+#define FIX_2_562915447 20995
+#define FIX_3_072711026 25172
+
+/*
+ * Perform the inverse DCT on one block of coefficients.
+ */
+
+void j_rev_dct(DCTBLOCK data)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3, z4, z5;
+ INT32 d0, d1, d2, d3, d4, d5, d6, d7;
+ register DCTELEM *dataptr;
+ int rowctr;
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = data;
+
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any row in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * row DCT calculations can be simplified this way.
+ */
+
+ register int *idataptr = (int*)dataptr;
+
+ d0 = dataptr[0];
+ d1 = dataptr[1];
+ d2 = dataptr[2];
+ d3 = dataptr[3];
+ d4 = dataptr[4];
+ d5 = dataptr[5];
+ d6 = dataptr[6];
+ d7 = dataptr[7];
+
+ if ((d1 == 0) && (idataptr[1] | idataptr[2] | idataptr[3]) == 0) {
+ /* AC terms all zero */
+ if (d0) {
+ /* Compute a 32 bit value to assign. */
+ DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS);
+ register int v = (dcval & 0xffff) | ((dcval << 16) & 0xffff0000);
+
+ idataptr[0] = v;
+ idataptr[1] = v;
+ idataptr[2] = v;
+ idataptr[3] = v;
+ }
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+{
+ if (d6) {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ }
+ } else {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
+ tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = d4 << CONST_BITS;
+ tmp11 = tmp12 = -tmp10;
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = 0;
+ }
+ }
+ }
+ }
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ if (d7) {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-z1, FIX_0_899976223);
+ z2 = MULTIPLY(-z2, FIX_2_562915447);
+ z3 = MULTIPLY(-z3, FIX_1_961570560);
+ z4 = MULTIPLY(-z4, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d5, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ z1 = MULTIPLY(-d7, FIX_0_899976223);
+ z2 = MULTIPLY(-z2, FIX_2_562915447);
+ z3 = MULTIPLY(-z3, FIX_1_961570560);
+ z4 = MULTIPLY(-d5, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d7 + z4, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-z1, FIX_0_899976223);
+ z2 = MULTIPLY(-d5, FIX_2_562915447);
+ z3 = MULTIPLY(-d7, FIX_1_961570560);
+ z4 = MULTIPLY(-z4, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 = z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
+ tmp0 = MULTIPLY(-d7, FIX_0_601344887);
+ z1 = MULTIPLY(-d7, FIX_0_899976223);
+ z3 = MULTIPLY(-d7, FIX_1_961570560);
+ tmp1 = MULTIPLY(-d5, FIX_0_509795579);
+ z2 = MULTIPLY(-d5, FIX_2_562915447);
+ z4 = MULTIPLY(-d5, FIX_0_390180644);
+ z5 = MULTIPLY(d5 + d7, FIX_1_175875602);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z3;
+ tmp1 += z4;
+ tmp2 = z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d1, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-z1, FIX_0_899976223);
+ z2 = MULTIPLY(-d3, FIX_2_562915447);
+ z3 = MULTIPLY(-z3, FIX_1_961570560);
+ z4 = MULTIPLY(-d1, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 = z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
+ z3 = d7 + d3;
+
+ tmp0 = MULTIPLY(-d7, FIX_0_601344887);
+ z1 = MULTIPLY(-d7, FIX_0_899976223);
+ tmp2 = MULTIPLY(d3, FIX_0_509795579);
+ z2 = MULTIPLY(-d3, FIX_2_562915447);
+ z5 = MULTIPLY(z3, FIX_1_175875602);
+ z3 = MULTIPLY(-z3, FIX_0_785694958);
+
+ tmp0 += z3;
+ tmp1 = z2 + z5;
+ tmp2 += z3;
+ tmp3 = z1 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z5 = MULTIPLY(z1, FIX_1_175875602);
+
+ z1 = MULTIPLY(z1, FIX_0_275899380);
+ z3 = MULTIPLY(-d7, FIX_1_961570560);
+ tmp0 = MULTIPLY(-d7, FIX_1_662939225);
+ z4 = MULTIPLY(-d1, FIX_0_390180644);
+ tmp3 = MULTIPLY(d1, FIX_1_111140466);
+
+ tmp0 += z1;
+ tmp1 = z4 + z5;
+ tmp2 = z3 + z5;
+ tmp3 += z1;
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
+ tmp0 = MULTIPLY(-d7, FIX_1_387039845);
+ tmp1 = MULTIPLY(d7, FIX_1_175875602);
+ tmp2 = MULTIPLY(-d7, FIX_0_785694958);
+ tmp3 = MULTIPLY(d7, FIX_0_275899380);
+ }
+ }
+ }
+ } else {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d3 + z4, FIX_1_175875602);
+
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-d1, FIX_0_899976223);
+ z2 = MULTIPLY(-z2, FIX_2_562915447);
+ z3 = MULTIPLY(-d3, FIX_1_961570560);
+ z4 = MULTIPLY(-z4, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 = z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+
+ z5 = MULTIPLY(z2, FIX_1_175875602);
+ tmp1 = MULTIPLY(d5, FIX_1_662939225);
+ z4 = MULTIPLY(-d5, FIX_0_390180644);
+ z2 = MULTIPLY(-z2, FIX_1_387039845);
+ tmp2 = MULTIPLY(d3, FIX_1_111140466);
+ z3 = MULTIPLY(-d3, FIX_1_961570560);
+
+ tmp0 = z3 + z5;
+ tmp1 += z2;
+ tmp2 += z2;
+ tmp3 = z4 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
+ z4 = d5 + d1;
+
+ z5 = MULTIPLY(z4, FIX_1_175875602);
+ z1 = MULTIPLY(-d1, FIX_0_899976223);
+ tmp3 = MULTIPLY(d1, FIX_0_601344887);
+ tmp1 = MULTIPLY(-d5, FIX_0_509795579);
+ z2 = MULTIPLY(-d5, FIX_2_562915447);
+ z4 = MULTIPLY(z4, FIX_0_785694958);
+
+ tmp0 = z1 + z5;
+ tmp1 += z4;
+ tmp2 = z2 + z5;
+ tmp3 += z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
+ tmp0 = MULTIPLY(d5, FIX_1_175875602);
+ tmp1 = MULTIPLY(d5, FIX_0_275899380);
+ tmp2 = MULTIPLY(-d5, FIX_1_387039845);
+ tmp3 = MULTIPLY(d5, FIX_0_785694958);
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
+ z5 = d1 + d3;
+ tmp3 = MULTIPLY(d1, FIX_0_211164243);
+ tmp2 = MULTIPLY(-d3, FIX_1_451774981);
+ z1 = MULTIPLY(d1, FIX_1_061594337);
+ z2 = MULTIPLY(-d3, FIX_2_172734803);
+ z4 = MULTIPLY(z5, FIX_0_785694958);
+ z5 = MULTIPLY(z5, FIX_1_175875602);
+
+ tmp0 = z1 - z4;
+ tmp1 = z2 + z4;
+ tmp2 += z5;
+ tmp3 += z5;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(-d3, FIX_0_785694958);
+ tmp1 = MULTIPLY(-d3, FIX_1_387039845);
+ tmp2 = MULTIPLY(-d3, FIX_0_275899380);
+ tmp3 = MULTIPLY(d3, FIX_1_175875602);
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d1, FIX_0_275899380);
+ tmp1 = MULTIPLY(d1, FIX_0_785694958);
+ tmp2 = MULTIPLY(d1, FIX_1_175875602);
+ tmp3 = MULTIPLY(d1, FIX_1_387039845);
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = tmp1 = tmp2 = tmp3 = 0;
+ }
+ }
+ }
+ }
+}
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ dataptr = data;
+ for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
+ /* Columns of zeroes can be exploited in the same way as we did with rows.
+ * However, the row calculation has created many nonzero AC terms, so the
+ * simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+ d0 = dataptr[DCTSIZE*0];
+ d1 = dataptr[DCTSIZE*1];
+ d2 = dataptr[DCTSIZE*2];
+ d3 = dataptr[DCTSIZE*3];
+ d4 = dataptr[DCTSIZE*4];
+ d5 = dataptr[DCTSIZE*5];
+ d6 = dataptr[DCTSIZE*6];
+ d7 = dataptr[DCTSIZE*7];
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+ if (d6) {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */
+ z1 = MULTIPLY(d2 + d6, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865);
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */
+ tmp2 = MULTIPLY(-d6, FIX_1_306562965);
+ tmp3 = MULTIPLY(d6, FIX_0_541196100);
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ }
+ }
+ } else {
+ if (d4) {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp0 = (d0 + d4) << CONST_BITS;
+ tmp1 = (d0 - d4) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp0 = d4 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp2 - tmp0;
+ tmp12 = -(tmp0 + tmp2);
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = (d0 + d4) << CONST_BITS;
+ tmp11 = tmp12 = (d0 - d4) << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */
+ tmp10 = tmp13 = d4 << CONST_BITS;
+ tmp11 = tmp12 = -tmp10;
+ }
+ }
+ } else {
+ if (d2) {
+ if (d0) {
+ /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp0 = d0 << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+ } else {
+ /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */
+ tmp2 = MULTIPLY(d2, FIX_0_541196100);
+ tmp3 = MULTIPLY(d2, FIX_1_306562965);
+
+ tmp10 = tmp3;
+ tmp13 = -tmp3;
+ tmp11 = tmp2;
+ tmp12 = -tmp2;
+ }
+ } else {
+ if (d0) {
+ /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS;
+ } else {
+ /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */
+ tmp10 = tmp13 = tmp11 = tmp12 = 0;
+ }
+ }
+ }
+ }
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+ if (d7) {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-z1, FIX_0_899976223);
+ z2 = MULTIPLY(-z2, FIX_2_562915447);
+ z3 = MULTIPLY(-z3, FIX_1_961570560);
+ z4 = MULTIPLY(-z4, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */
+ z1 = d7;
+ z2 = d5 + d3;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d5, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ z1 = MULTIPLY(-d7, FIX_0_899976223);
+ z2 = MULTIPLY(-z2, FIX_2_562915447);
+ z3 = MULTIPLY(-z3, FIX_1_961570560);
+ z4 = MULTIPLY(-d5, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */
+ z1 = d7 + d1;
+ z2 = d5;
+ z3 = d7;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-z1, FIX_0_899976223);
+ z2 = MULTIPLY(-d5, FIX_2_562915447);
+ z3 = MULTIPLY(-d7, FIX_1_961570560);
+ z4 = MULTIPLY(-z4, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 = z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */
+ tmp0 = MULTIPLY(-d7, FIX_0_601344887);
+ z1 = MULTIPLY(-d7, FIX_0_899976223);
+ z3 = MULTIPLY(-d7, FIX_1_961570560);
+ tmp1 = MULTIPLY(-d5, FIX_0_509795579);
+ z2 = MULTIPLY(-d5, FIX_2_562915447);
+ z4 = MULTIPLY(-d5, FIX_0_390180644);
+ z5 = MULTIPLY(d5 + d7, FIX_1_175875602);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z3;
+ tmp1 += z4;
+ tmp2 = z2 + z3;
+ tmp3 = z1 + z4;
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z3 = d7 + d3;
+ z5 = MULTIPLY(z3 + d1, FIX_1_175875602);
+
+ tmp0 = MULTIPLY(d7, FIX_0_298631336);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-z1, FIX_0_899976223);
+ z2 = MULTIPLY(-d3, FIX_2_562915447);
+ z3 = MULTIPLY(-z3, FIX_1_961570560);
+ z4 = MULTIPLY(-d1, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 = z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */
+ z3 = d7 + d3;
+
+ tmp0 = MULTIPLY(-d7, FIX_0_601344887);
+ z1 = MULTIPLY(-d7, FIX_0_899976223);
+ tmp2 = MULTIPLY(d3, FIX_0_509795579);
+ z2 = MULTIPLY(-d3, FIX_2_562915447);
+ z5 = MULTIPLY(z3, FIX_1_175875602);
+ z3 = MULTIPLY(-z3, FIX_0_785694958);
+
+ tmp0 += z3;
+ tmp1 = z2 + z5;
+ tmp2 += z3;
+ tmp3 = z1 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */
+ z1 = d7 + d1;
+ z5 = MULTIPLY(z1, FIX_1_175875602);
+
+ z1 = MULTIPLY(z1, FIX_0_275899380);
+ z3 = MULTIPLY(-d7, FIX_1_961570560);
+ tmp0 = MULTIPLY(-d7, FIX_1_662939225);
+ z4 = MULTIPLY(-d1, FIX_0_390180644);
+ tmp3 = MULTIPLY(d1, FIX_1_111140466);
+
+ tmp0 += z1;
+ tmp1 = z4 + z5;
+ tmp2 = z3 + z5;
+ tmp3 += z1;
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */
+ tmp0 = MULTIPLY(-d7, FIX_1_387039845);
+ tmp1 = MULTIPLY(d7, FIX_1_175875602);
+ tmp2 = MULTIPLY(-d7, FIX_0_785694958);
+ tmp3 = MULTIPLY(d7, FIX_0_275899380);
+ }
+ }
+ }
+ } else {
+ if (d5) {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+ z4 = d5 + d1;
+ z5 = MULTIPLY(d3 + z4, FIX_1_175875602);
+
+ tmp1 = MULTIPLY(d5, FIX_2_053119869);
+ tmp2 = MULTIPLY(d3, FIX_3_072711026);
+ tmp3 = MULTIPLY(d1, FIX_1_501321110);
+ z1 = MULTIPLY(-d1, FIX_0_899976223);
+ z2 = MULTIPLY(-z2, FIX_2_562915447);
+ z3 = MULTIPLY(-d3, FIX_1_961570560);
+ z4 = MULTIPLY(-z4, FIX_0_390180644);
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 = z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+ } else {
+ /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */
+ z2 = d5 + d3;
+
+ z5 = MULTIPLY(z2, FIX_1_175875602);
+ tmp1 = MULTIPLY(d5, FIX_1_662939225);
+ z4 = MULTIPLY(-d5, FIX_0_390180644);
+ z2 = MULTIPLY(-z2, FIX_1_387039845);
+ tmp2 = MULTIPLY(d3, FIX_1_111140466);
+ z3 = MULTIPLY(-d3, FIX_1_961570560);
+
+ tmp0 = z3 + z5;
+ tmp1 += z2;
+ tmp2 += z2;
+ tmp3 = z4 + z5;
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */
+ z4 = d5 + d1;
+
+ z5 = MULTIPLY(z4, FIX_1_175875602);
+ z1 = MULTIPLY(-d1, FIX_0_899976223);
+ tmp3 = MULTIPLY(d1, FIX_0_601344887);
+ tmp1 = MULTIPLY(-d5, FIX_0_509795579);
+ z2 = MULTIPLY(-d5, FIX_2_562915447);
+ z4 = MULTIPLY(z4, FIX_0_785694958);
+
+ tmp0 = z1 + z5;
+ tmp1 += z4;
+ tmp2 = z2 + z5;
+ tmp3 += z4;
+ } else {
+ /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */
+ tmp0 = MULTIPLY(d5, FIX_1_175875602);
+ tmp1 = MULTIPLY(d5, FIX_0_275899380);
+ tmp2 = MULTIPLY(-d5, FIX_1_387039845);
+ tmp3 = MULTIPLY(d5, FIX_0_785694958);
+ }
+ }
+ } else {
+ if (d3) {
+ if (d1) {
+ /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */
+ z5 = d1 + d3;
+ tmp3 = MULTIPLY(d1, FIX_0_211164243);
+ tmp2 = MULTIPLY(-d3, FIX_1_451774981);
+ z1 = MULTIPLY(d1, FIX_1_061594337);
+ z2 = MULTIPLY(-d3, FIX_2_172734803);
+ z4 = MULTIPLY(z5, FIX_0_785694958);
+ z5 = MULTIPLY(z5, FIX_1_175875602);
+
+ tmp0 = z1 - z4;
+ tmp1 = z2 + z4;
+ tmp2 += z5;
+ tmp3 += z5;
+ } else {
+ /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(-d3, FIX_0_785694958);
+ tmp1 = MULTIPLY(-d3, FIX_1_387039845);
+ tmp2 = MULTIPLY(-d3, FIX_0_275899380);
+ tmp3 = MULTIPLY(d3, FIX_1_175875602);
+ }
+ } else {
+ if (d1) {
+ /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = MULTIPLY(d1, FIX_0_275899380);
+ tmp1 = MULTIPLY(d1, FIX_0_785694958);
+ tmp2 = MULTIPLY(d1, FIX_1_175875602);
+ tmp3 = MULTIPLY(d1, FIX_1_387039845);
+ } else {
+ /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */
+ tmp0 = tmp1 = tmp2 = tmp3 = 0;
+ }
+ }
+ }
+ }
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
diff --git a/libavcodec/libac3/ac3.h b/libavcodec/libac3/ac3.h
new file mode 100644
index 0000000000..117071e7a1
--- /dev/null
+++ b/libavcodec/libac3/ac3.h
@@ -0,0 +1,108 @@
+/*
+ * ac3.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+typedef struct ac3_ba_s {
+ uint16_t fsnroffst; // fine SNR offset
+ uint16_t fgaincod; // fast gain
+ uint16_t deltbae; // delta bit allocation exists
+ int8_t deltba[50]; // per-band delta bit allocation
+} ac3_ba_t;
+
+typedef struct ac3_state_s {
+ uint8_t fscod; // sample rate
+ uint8_t halfrate; // halfrate factor
+ uint8_t acmod; // coded channels
+ float clev; // centre channel mix level
+ float slev; // surround channels mix level
+ uint8_t lfeon; // coded lfe channel
+
+ int output; // type of output
+ float level; // output level
+ float bias; // output bias
+
+ uint16_t cplinu; // coupling in use
+ uint16_t chincpl[5]; // channel coupled
+ uint16_t phsflginu; // phase flags in use (stereo only)
+ uint16_t cplbndstrc[18]; // coupling band structure
+ uint16_t cplstrtmant; // coupling channel start mantissa
+ uint16_t cplendmant; // coupling channel end mantissa
+ float cplco[5][18]; // coupling coordinates
+
+ // derived information
+ uint16_t cplstrtbnd; // coupling start band (for bit allocation)
+ uint16_t ncplbnd; // number of coupling bands
+
+ uint16_t rematflg[4]; // stereo rematrixing
+
+ uint16_t endmant[5]; // channel end mantissa
+
+ uint8_t cpl_exp[256]; // decoded coupling channel exponents
+ uint8_t fbw_exp[5][256]; // decoded channel exponents
+ uint8_t lfe_exp[7]; // decoded lfe channel exponents
+
+ uint16_t sdcycod; // slow decay
+ uint16_t fdcycod; // fast decay
+ uint16_t sgaincod; // slow gain
+ uint16_t dbpbcod; // dB per bit - encodes the dbknee value
+ uint16_t floorcod; // masking floor
+
+ uint16_t csnroffst; // coarse SNR offset
+ ac3_ba_t cplba; // coupling bit allocation parameters
+ ac3_ba_t ba[5]; // channel bit allocation parameters
+ ac3_ba_t lfeba; // lfe bit allocation parameters
+
+ uint16_t cplfleak; // coupling fast leak init
+ uint16_t cplsleak; // coupling slow leak init
+
+ // derived bit allocation information
+ int8_t fbw_bap[5][256];
+ int8_t cpl_bap[256];
+ int8_t lfe_bap[7];
+} ac3_state_t;
+
+/* samples work structure */
+typedef float stream_samples_t[6][256];
+
+#define AC3_CHANNEL 0
+#define AC3_MONO 1
+#define AC3_STEREO 2
+#define AC3_3F 3
+#define AC3_2F1R 4
+#define AC3_3F1R 5
+#define AC3_2F2R 6
+#define AC3_3F2R 7
+#define AC3_CHANNEL1 8
+#define AC3_CHANNEL2 9
+#define AC3_DOLBY 10
+#define AC3_CHANNEL_MASK 15
+
+#define AC3_LFE 16
+#define AC3_ADJUST_LEVEL 32
+
+void ac3_init (void);
+int ac3_syncinfo (uint8_t * buf, int * flags,
+ int * sample_rate, int * bit_rate);
+int ac3_frame (ac3_state_t * state, uint8_t * buf, int * flags,
+ float * level, float bias);
+int ac3_block (ac3_state_t * state);
diff --git a/libavcodec/libac3/ac3_internal.h b/libavcodec/libac3/ac3_internal.h
new file mode 100644
index 0000000000..1dce513f4c
--- /dev/null
+++ b/libavcodec/libac3/ac3_internal.h
@@ -0,0 +1,51 @@
+/*
+ * ac3_internal.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define LEVEL_PLUS3DB 1.4142135623730951
+#define LEVEL_3DB 0.7071067811865476
+#define LEVEL_45DB 0.5946035575013605
+#define LEVEL_6DB 0.5
+
+/* Exponent strategy constants */
+#define EXP_REUSE (0)
+#define EXP_D15 (1)
+#define EXP_D25 (2)
+#define EXP_D45 (3)
+
+/* Delta bit allocation constants */
+#define DELTA_BIT_REUSE (0)
+#define DELTA_BIT_NEW (1)
+#define DELTA_BIT_NONE (2)
+#define DELTA_BIT_RESERVED (3)
+
+void bit_allocate (ac3_state_t * state, ac3_ba_t * ba, int bndstart,
+ int start, int end, int fastleak, int slowleak,
+ uint8_t * exp, int8_t * bap);
+
+int downmix_init (int input, int flags, float * level, float clev, float slev);
+void downmix (float * samples, int acmod, int output, float level, float bias,
+ float clev, float slev);
+
+void imdct_init (void);
+extern void (* imdct_256) (float data[], float delay[]);
+extern void (* imdct_512) (float data[], float delay[]);
diff --git a/libavcodec/libac3/bit_allocate.c b/libavcodec/libac3/bit_allocate.c
new file mode 100644
index 0000000000..307c0074c6
--- /dev/null
+++ b/libavcodec/libac3/bit_allocate.c
@@ -0,0 +1,255 @@
+/*
+ * bit_allocate.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+static int hthtab[3][50] = {
+ {0x730, 0x730, 0x7c0, 0x800, 0x820, 0x840, 0x850, 0x850, 0x860, 0x860,
+ 0x860, 0x860, 0x860, 0x870, 0x870, 0x870, 0x880, 0x880, 0x890, 0x890,
+ 0x8a0, 0x8a0, 0x8b0, 0x8b0, 0x8c0, 0x8c0, 0x8d0, 0x8e0, 0x8f0, 0x900,
+ 0x910, 0x910, 0x910, 0x910, 0x900, 0x8f0, 0x8c0, 0x870, 0x820, 0x7e0,
+ 0x7a0, 0x770, 0x760, 0x7a0, 0x7c0, 0x7c0, 0x6e0, 0x400, 0x3c0, 0x3c0},
+ {0x710, 0x710, 0x7a0, 0x7f0, 0x820, 0x830, 0x840, 0x850, 0x850, 0x860,
+ 0x860, 0x860, 0x860, 0x860, 0x870, 0x870, 0x870, 0x880, 0x880, 0x880,
+ 0x890, 0x890, 0x8a0, 0x8a0, 0x8b0, 0x8b0, 0x8c0, 0x8c0, 0x8e0, 0x8f0,
+ 0x900, 0x910, 0x910, 0x910, 0x910, 0x900, 0x8e0, 0x8b0, 0x870, 0x820,
+ 0x7e0, 0x7b0, 0x760, 0x770, 0x7a0, 0x7c0, 0x780, 0x5d0, 0x3c0, 0x3c0},
+ {0x680, 0x680, 0x750, 0x7b0, 0x7e0, 0x810, 0x820, 0x830, 0x840, 0x850,
+ 0x850, 0x850, 0x860, 0x860, 0x860, 0x860, 0x860, 0x860, 0x860, 0x860,
+ 0x870, 0x870, 0x870, 0x870, 0x880, 0x880, 0x880, 0x890, 0x8a0, 0x8b0,
+ 0x8c0, 0x8d0, 0x8e0, 0x8f0, 0x900, 0x910, 0x910, 0x910, 0x900, 0x8f0,
+ 0x8d0, 0x8b0, 0x840, 0x7f0, 0x790, 0x760, 0x7a0, 0x7c0, 0x7b0, 0x720}
+};
+
+static int8_t baptab[305] = {
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, // 93 padding entries
+
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 14, 14, 14, 14,
+ 14, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9,
+ 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5,
+ 5, 4, 4, -3, -3, 3, 3, 3, -2, -2, -1, -1, -1, -1, -1, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0 // 148 padding entries
+};
+
+static int bndtab[30] = {21, 22, 23, 24, 25, 26, 27, 28, 31, 34,
+ 37, 40, 43, 46, 49, 55, 61, 67, 73, 79,
+ 85, 97, 109, 121, 133, 157, 181, 205, 229, 253};
+
+static int8_t latab[256] = {
+ -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, -53,
+ -52, -52, -51, -50, -49, -48, -47, -47, -46, -45, -44, -44,
+ -43, -42, -41, -41, -40, -39, -38, -38, -37, -36, -36, -35,
+ -35, -34, -33, -33, -32, -32, -31, -30, -30, -29, -29, -28,
+ -28, -27, -27, -26, -26, -25, -25, -24, -24, -23, -23, -22,
+ -22, -21, -21, -21, -20, -20, -19, -19, -19, -18, -18, -18,
+ -17, -17, -17, -16, -16, -16, -15, -15, -15, -14, -14, -14,
+ -13, -13, -13, -13, -12, -12, -12, -12, -11, -11, -11, -11,
+ -10, -10, -10, -10, -10, -9, -9, -9, -9, -9, -8, -8,
+ -8, -8, -8, -8, -7, -7, -7, -7, -7, -7, -6, -6,
+ -6, -6, -6, -6, -6, -6, -5, -5, -5, -5, -5, -5,
+ -5, -5, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
+ -4, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+ -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+#define UPDATE_LEAK() \
+do { \
+ fastleak += fdecay; \
+ if (fastleak > psd + fgain) \
+ fastleak = psd + fgain; \
+ slowleak += sdecay; \
+ if (slowleak > psd + sgain) \
+ slowleak = psd + sgain; \
+} while (0)
+
+#define COMPUTE_MASK() \
+do { \
+ if (psd > dbknee) \
+ mask -= (psd - dbknee) >> 2; \
+ if (mask > hth [i >> halfrate]) \
+ mask = hth [i >> halfrate]; \
+ mask -= snroffset + 128 * deltba[i]; \
+ mask = (mask > 0) ? 0 : ((-mask) >> 5); \
+ mask -= floor; \
+} while (0)
+
+void bit_allocate (ac3_state_t * state, ac3_ba_t * ba, int bndstart,
+ int start, int end, int fastleak, int slowleak,
+ uint8_t * exp, int8_t * bap)
+{
+ static int slowgain[4] = {0x540, 0x4d8, 0x478, 0x410};
+ static int dbpbtab[4] = {0xc00, 0x500, 0x300, 0x100};
+ static int floortab[8] = {0x910, 0x950, 0x990, 0x9d0,
+ 0xa10, 0xa90, 0xb10, 0x1400};
+
+ int i, j;
+ int fdecay, fgain, sdecay, sgain, dbknee, floor, snroffset;
+ int psd, mask;
+ int8_t * deltba;
+ int * hth;
+ int halfrate;
+
+ halfrate = state->halfrate;
+ fdecay = (63 + 20 * state->fdcycod) >> halfrate;
+ fgain = 128 + 128 * ba->fgaincod;
+ sdecay = (15 + 2 * state->sdcycod) >> halfrate;
+ sgain = slowgain[state->sgaincod];
+ dbknee = dbpbtab[state->dbpbcod];
+ hth = hthtab[state->fscod];
+ /*
+ * if there is no delta bit allocation, make deltba point to an area
+ * known to contain zeroes. baptab+156 here.
+ */
+ deltba = (ba->deltbae == DELTA_BIT_NONE) ? baptab + 156 : ba->deltba;
+ floor = floortab[state->floorcod];
+ snroffset = 960 - 64 * state->csnroffst - 4 * ba->fsnroffst + floor;
+ floor >>= 5;
+
+ i = bndstart;
+ j = start;
+ if (start == 0) { // not the coupling channel
+ int lowcomp;
+
+ lowcomp = 0;
+ j = end - 1;
+ do {
+ if (i < j) {
+ if (exp[i+1] == exp[i] - 2)
+ lowcomp = 384;
+ else if (lowcomp && (exp[i+1] > exp[i]))
+ lowcomp -= 64;
+ }
+ psd = 128 * exp[i];
+ mask = psd + fgain + lowcomp;
+ COMPUTE_MASK ();
+ bap[i++] = (baptab+156)[mask + 4 * exp[i]];
+ } while ((i < 3) || ((i < 7) && (exp[i] > exp[i-1])));
+ fastleak = psd + fgain;
+ slowleak = psd + sgain;
+
+ while (i < 7) {
+ if (i < j) {
+ if (exp[i+1] == exp[i] - 2)
+ lowcomp = 384;
+ else if (lowcomp && (exp[i+1] > exp[i]))
+ lowcomp -= 64;
+ }
+ psd = 128 * exp[i];
+ UPDATE_LEAK ();
+ mask = ((fastleak + lowcomp < slowleak) ?
+ fastleak + lowcomp : slowleak);
+ COMPUTE_MASK ();
+ bap[i++] = (baptab+156)[mask + 4 * exp[i]];
+ }
+
+ if (end == 7) // lfe channel
+ return;
+
+ do {
+ if (exp[i+1] == exp[i] - 2)
+ lowcomp = 320;
+ else if (lowcomp && (exp[i+1] > exp[i]))
+ lowcomp -= 64;
+ psd = 128 * exp[i];
+ UPDATE_LEAK ();
+ mask = ((fastleak + lowcomp < slowleak) ?
+ fastleak + lowcomp : slowleak);
+ COMPUTE_MASK ();
+ bap[i++] = (baptab+156)[mask + 4 * exp[i]];
+ } while (i < 20);
+
+ while (lowcomp > 128) { // two iterations maximum
+ lowcomp -= 128;
+ psd = 128 * exp[i];
+ UPDATE_LEAK ();
+ mask = ((fastleak + lowcomp < slowleak) ?
+ fastleak + lowcomp : slowleak);
+ COMPUTE_MASK ();
+ bap[i++] = (baptab+156)[mask + 4 * exp[i]];
+ }
+ j = i;
+ }
+
+ do {
+ int startband, endband;
+
+ startband = j;
+ endband = ((bndtab-20)[i] < end) ? (bndtab-20)[i] : end;
+ psd = 128 * exp[j++];
+ while (j < endband) {
+ int next, delta;
+
+ next = 128 * exp[j++];
+ delta = next - psd;
+ switch (delta >> 9) {
+ case -6: case -5: case -4: case -3: case -2:
+ psd = next;
+ break;
+ case -1:
+ psd = next + latab[(-delta) >> 1];
+ break;
+ case 0:
+ psd += latab[delta >> 1];
+ break;
+ }
+ }
+ // minpsd = -289
+ UPDATE_LEAK ();
+ mask = (fastleak < slowleak) ? fastleak : slowleak;
+ COMPUTE_MASK ();
+ i++;
+ j = startband;
+ do {
+ // max(mask+4*exp)=147=-(minpsd+fgain-deltba-snroffset)>>5+4*exp
+ // min(mask+4*exp)=-156=-(sgain-deltba-snroffset)>>5
+ bap[j++] = (baptab+156)[mask + 4 * exp[j]];
+ } while (j < endband);
+ } while (j < end);
+}
diff --git a/libavcodec/libac3/bitstream.c b/libavcodec/libac3/bitstream.c
new file mode 100644
index 0000000000..7e9bd1f66a
--- /dev/null
+++ b/libavcodec/libac3/bitstream.c
@@ -0,0 +1,77 @@
+/*
+ * bitstream.c
+ *
+ * Copyright (C) Aaron Holtzman - Dec 1999
+ *
+ * This file is part of ac3dec, a free AC-3 audio decoder
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ac3.h"
+#include "ac3_internal.h"
+#include "bitstream.h"
+
+#define BUFFER_SIZE 4096
+
+static uint8_t *buffer_start;
+
+uint32_t bits_left;
+uint32_t current_word;
+
+void bitstream_set_ptr (uint8_t * buf)
+{
+ buffer_start = buf;
+ bits_left = 0;
+}
+
+static inline void
+bitstream_fill_current()
+{
+ current_word = *((uint32_t*)buffer_start)++;
+ current_word = swab32(current_word);
+}
+
+//
+// The fast paths for _get is in the
+// bitstream.h header file so it can be inlined.
+//
+// The "bottom half" of this routine is suffixed _bh
+//
+// -ah
+//
+
+uint32_t
+bitstream_get_bh(uint32_t num_bits)
+{
+ uint32_t result;
+
+ num_bits -= bits_left;
+ result = (current_word << (32 - bits_left)) >> (32 - bits_left);
+
+ bitstream_fill_current();
+
+ if(num_bits != 0)
+ result = (result << num_bits) | (current_word >> (32 - num_bits));
+
+ bits_left = 32 - num_bits;
+
+ return result;
+}
diff --git a/libavcodec/libac3/bitstream.h b/libavcodec/libac3/bitstream.h
new file mode 100644
index 0000000000..84f3287c87
--- /dev/null
+++ b/libavcodec/libac3/bitstream.h
@@ -0,0 +1,68 @@
+/*
+ * bitstream.h
+ *
+ * Copyright (C) Aaron Holtzman - Dec 1999
+ *
+ * This file is part of ac3dec, a free AC-3 audio decoder
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+//My new and improved vego-matic endian swapping routine
+//(stolen from the kernel)
+#ifdef WORDS_BIGENDIAN
+
+# define swab32(x) (x)
+
+#else
+
+# if defined (__i386__)
+
+# define swab32(x) __i386_swab32(x)
+ static inline const uint32_t __i386_swab32(uint32_t x)
+ {
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+ return x;
+ }
+
+# else
+
+# define swab32(x)\
+((((uint8_t*)&x)[0] << 24) | (((uint8_t*)&x)[1] << 16) | \
+ (((uint8_t*)&x)[2] << 8) | (((uint8_t*)&x)[3]))
+
+# endif
+#endif
+
+extern uint32_t bits_left;
+extern uint32_t current_word;
+
+void bitstream_set_ptr (uint8_t * buf);
+uint32_t bitstream_get_bh(uint32_t num_bits);
+
+static inline uint32_t
+bitstream_get(uint32_t num_bits)
+{
+ uint32_t result;
+
+ if(num_bits < bits_left) {
+ result = (current_word << (32 - bits_left)) >> (32 - num_bits);
+ bits_left -= num_bits;
+ return result;
+ }
+
+ return bitstream_get_bh(num_bits);
+}
diff --git a/libavcodec/libac3/downmix.c b/libavcodec/libac3/downmix.c
new file mode 100644
index 0000000000..9e7fbfb8b6
--- /dev/null
+++ b/libavcodec/libac3/downmix.c
@@ -0,0 +1,533 @@
+/*
+ *
+ * downmix.c
+ *
+ * Copyright (C) Aaron Holtzman - Sept 1999
+ *
+ * Originally based on code by Yuqing Deng.
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+
+#define CONVERT(acmod,output) (((output) << 3) + (acmod))
+
+int downmix_init (int input, int flags, float * level, float clev, float slev)
+{
+ static uint8_t table[11][8] = {
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_STEREO,
+ AC3_STEREO, AC3_STEREO, AC3_STEREO, AC3_STEREO},
+ {AC3_MONO, AC3_MONO, AC3_MONO, AC3_MONO,
+ AC3_MONO, AC3_MONO, AC3_MONO, AC3_MONO},
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_STEREO,
+ AC3_STEREO, AC3_STEREO, AC3_STEREO, AC3_STEREO},
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_3F,
+ AC3_STEREO, AC3_3F, AC3_STEREO, AC3_3F},
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_STEREO,
+ AC3_2F1R, AC3_2F1R, AC3_2F1R, AC3_2F1R},
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_STEREO,
+ AC3_2F1R, AC3_3F1R, AC3_2F1R, AC3_3F1R},
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_3F,
+ AC3_2F2R, AC3_2F2R, AC3_2F2R, AC3_2F2R},
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_3F,
+ AC3_2F2R, AC3_3F2R, AC3_2F2R, AC3_3F2R},
+ {AC3_CHANNEL1, AC3_MONO, AC3_MONO, AC3_MONO,
+ AC3_MONO, AC3_MONO, AC3_MONO, AC3_MONO},
+ {AC3_CHANNEL2, AC3_MONO, AC3_MONO, AC3_MONO,
+ AC3_MONO, AC3_MONO, AC3_MONO, AC3_MONO},
+ {AC3_CHANNEL, AC3_DOLBY, AC3_STEREO, AC3_DOLBY,
+ AC3_DOLBY, AC3_DOLBY, AC3_DOLBY, AC3_DOLBY}
+ };
+ int output;
+
+ output = flags & AC3_CHANNEL_MASK;
+ if (output > AC3_DOLBY)
+ return -1;
+
+ output = table[output][input & 7];
+
+ if ((output == AC3_STEREO) &&
+ ((input == AC3_DOLBY) || ((input == AC3_3F) && (clev == LEVEL_3DB))))
+ output = AC3_DOLBY;
+
+ if (flags & AC3_ADJUST_LEVEL)
+ switch (CONVERT (input & 7, output)) {
+
+ case CONVERT (AC3_3F, AC3_MONO):
+ *level *= LEVEL_3DB / (1 + clev);
+ break;
+
+ case CONVERT (AC3_STEREO, AC3_MONO):
+ case CONVERT (AC3_2F2R, AC3_2F1R):
+ case CONVERT (AC3_3F2R, AC3_3F1R):
+ level_3db:
+ *level *= LEVEL_3DB;
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_2F1R):
+ if (clev < LEVEL_PLUS3DB - 1)
+ goto level_3db;
+ // break thru
+ case CONVERT (AC3_3F, AC3_STEREO):
+ case CONVERT (AC3_3F1R, AC3_2F1R):
+ case CONVERT (AC3_3F1R, AC3_2F2R):
+ case CONVERT (AC3_3F2R, AC3_2F2R):
+ *level /= 1 + clev;
+ break;
+
+ case CONVERT (AC3_2F1R, AC3_MONO):
+ *level *= LEVEL_PLUS3DB / (2 + slev);
+ break;
+
+ case CONVERT (AC3_2F1R, AC3_STEREO):
+ case CONVERT (AC3_3F1R, AC3_3F):
+ *level /= 1 + slev * LEVEL_3DB;
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_MONO):
+ *level *= LEVEL_3DB / (1 + clev + 0.5 * slev);
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_STEREO):
+ *level /= 1 + clev + slev * LEVEL_3DB;
+ break;
+
+ case CONVERT (AC3_2F2R, AC3_MONO):
+ *level *= LEVEL_3DB / (1 + slev);
+ break;
+
+ case CONVERT (AC3_2F2R, AC3_STEREO):
+ case CONVERT (AC3_3F2R, AC3_3F):
+ *level /= (1 + slev);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_MONO):
+ *level *= LEVEL_3DB / (1 + clev + slev);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_STEREO):
+ *level /= 1 + clev + slev;
+ break;
+
+ case CONVERT (AC3_MONO, AC3_DOLBY):
+ *level *= LEVEL_PLUS3DB;
+ break;
+
+ case CONVERT (AC3_3F, AC3_DOLBY):
+ case CONVERT (AC3_2F1R, AC3_DOLBY):
+ *level *= 1 / (1 + LEVEL_3DB);
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_DOLBY):
+ case CONVERT (AC3_2F2R, AC3_DOLBY):
+ *level *= 1 / (1 + 2 * LEVEL_3DB);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_DOLBY):
+ *level *= 1 / (1 + 3 * LEVEL_3DB);
+ break;
+ }
+
+ return output;
+}
+
+static void mix1to1 (float * samples, float level, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = samples[i] * level + bias;
+}
+
+static void move1to1 (float * src, float * dest, float level, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ dest[i] = src[i] * level + bias;
+}
+
+static void mix2to1 (float * samples, float level, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = (samples[i] + samples[i + 256]) * level + bias;
+}
+
+static void move2to1 (float * src, float * dest, float level, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ dest[i] = (src[i] + src[i + 256]) * level + bias;
+}
+
+static void mix3to1 (float * samples, float level, float clev, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = ((samples[i] + samples[i + 512]) * level +
+ samples[i + 256] * clev + bias);
+}
+
+static void mix21to1 (float * samples, float level, float slev, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = ((samples[i] + samples[i + 256]) * level +
+ samples[i + 512] * slev + bias);
+}
+
+static void mix31to1 (float * samples, float level, float clev, float slev,
+ float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = ((samples[i] + samples[i + 512]) * level +
+ samples[i + 256] * clev + samples[i + 768] * slev +
+ bias);
+}
+
+static void mix22to1 (float * samples, float level, float slev, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = ((samples[i] + samples[i + 256]) * level +
+ (samples[i + 512] + samples[i + 768]) * slev + bias);
+}
+
+static void mix32to1 (float * samples, float level, float clev, float slev,
+ float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ samples[i] = ((samples[i] + samples[i + 512]) * level +
+ samples[i + 256] * clev +
+ (samples[i + 768] + samples[i + 1024]) * slev + bias);
+}
+
+static void mix1to2 (float * src, float * dest, float level, float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ dest[i] = src[i] = src[i] * level + bias;
+}
+
+static void mix3to2 (float * samples, float level, float clev, float bias)
+{
+ int i;
+ float common;
+
+ for (i = 0; i < 256; i++) {
+ common = samples[i + 256] * clev + bias;
+ samples[i] = samples[i] * level + common;
+ samples[i + 256] = samples[i + 512] * level + common;
+ }
+}
+
+static void mix21to2 (float * left, float * right, float level, float slev,
+ float bias)
+{
+ int i;
+ float common;
+
+ for (i = 0; i < 256; i++) {
+ common = right[i + 256] * slev + bias;
+ left[i] = left[i] * level + common;
+ right[i] = right[i] * level + common;
+ }
+}
+
+static void mix11to1 (float * front, float * rear, float level, float slev,
+ float bias)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ front[i] = front[i] * level + rear[i] * slev + bias;
+}
+
+static void mix31to2 (float * samples, float level, float clev, float slev,
+ float bias)
+{
+ int i;
+ float common;
+
+ for (i = 0; i < 256; i++) {
+ common = samples[i + 256] * clev + samples[i + 768] * slev + bias;
+ samples[i] = samples[i] * level + common;
+ samples[i + 256] = samples[i + 512] * level + common;
+ }
+}
+
+static void mix32to2 (float * samples, float level, float clev, float slev,
+ float bias)
+{
+ int i;
+ float common;
+
+ for (i = 0; i < 256; i++) {
+ common = samples[i + 256] * clev + bias;
+ samples[i] = samples[i] * level + common + samples[i + 768] * slev;
+ samples[i + 256] = (samples[i + 512] * level + common +
+ samples[i + 1024] * slev);
+ }
+}
+
+static void mix21toS (float * samples, float level, float level3db, float bias)
+{
+ int i;
+ float surround;
+
+ for (i = 0; i < 256; i++) {
+ surround = samples[i + 512] * level3db;
+ samples[i] = samples[i] * level - surround + bias;
+ samples[i + 256] = samples[i + 256] * level + surround + bias;
+ }
+}
+
+static void mix22toS (float * samples, float level, float level3db, float bias)
+{
+ int i;
+ float surround;
+
+ for (i = 0; i < 256; i++) {
+ surround = (samples[i + 512] + samples[i + 768]) * level3db;
+ samples[i] = samples[i] * level - surround + bias;
+ samples[i + 256] = samples[i + 256] * level + surround + bias;
+ }
+}
+
+static void mix31toS (float * samples, float level, float level3db, float bias)
+{
+ int i;
+ float common, surround;
+
+ for (i = 0; i < 256; i++) {
+ common = samples[i + 256] * level3db + bias;
+ surround = samples[i + 768] * level3db;
+ samples[i] = samples[i] * level + common - surround;
+ samples[i + 256] = samples[i + 512] * level + common + surround;
+ }
+}
+
+static void mix32toS (float * samples, float level, float level3db, float bias)
+{
+ int i;
+ float common, surround;
+
+ for (i = 0; i < 256; i++) {
+ common = samples[i + 256] * level3db + bias;
+ surround = (samples[i + 768] + samples[i + 1024]) * level3db;
+ samples[i] = samples[i] * level + common - surround;
+ samples[i + 256] = samples[i + 512] * level + common + surround;
+ }
+}
+
+void downmix (float * samples, int acmod, int output, float level, float bias,
+ float clev, float slev)
+{
+ switch (CONVERT (acmod, output & AC3_CHANNEL_MASK)) {
+
+ case CONVERT (AC3_3F2R, AC3_3F2R):
+ mix1to1 (samples + 1024, level, bias);
+ case CONVERT (AC3_3F1R, AC3_3F1R):
+ case CONVERT (AC3_2F2R, AC3_2F2R):
+ mix1to1 (samples + 768, level, bias);
+ case CONVERT (AC3_3F, AC3_3F):
+ case CONVERT (AC3_2F1R, AC3_2F1R):
+ mix_3to3:
+ mix1to1 (samples + 512, level, bias);
+ case CONVERT (AC3_CHANNEL, AC3_CHANNEL):
+ case CONVERT (AC3_STEREO, AC3_STEREO):
+ case CONVERT (AC3_STEREO, AC3_DOLBY):
+ mix_2to2:
+ mix1to1 (samples + 256, level, bias);
+ case CONVERT (AC3_CHANNEL, AC3_CHANNEL1):
+ case CONVERT (AC3_MONO, AC3_MONO):
+ mix1to1 (samples, level, bias);
+ break;
+
+ case CONVERT (AC3_CHANNEL, AC3_CHANNEL2):
+ mix_1to1_b:
+ mix1to1 (samples + 256, level, bias);
+ break;
+
+ case CONVERT (AC3_STEREO, AC3_MONO):
+ mix_2to1:
+ mix2to1 (samples, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_2F1R, AC3_MONO):
+ if (slev == 0)
+ goto mix_2to1;
+ mix21to1 (samples, level * LEVEL_3DB, level * slev * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_2F2R, AC3_MONO):
+ if (slev == 0)
+ goto mix_2to1;
+ mix22to1 (samples, level * LEVEL_3DB, level * slev * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_3F, AC3_MONO):
+ mix_3to1:
+ mix3to1 (samples, level * LEVEL_3DB, level * clev * LEVEL_PLUS3DB,
+ bias);
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_MONO):
+ if (slev == 0)
+ goto mix_3to1;
+ mix31to1 (samples, level * LEVEL_3DB, level * clev * LEVEL_PLUS3DB,
+ level * slev * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_MONO):
+ if (slev == 0)
+ goto mix_3to1;
+ mix32to1 (samples, level * LEVEL_3DB, level * clev * LEVEL_PLUS3DB,
+ level * slev * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_CHANNEL, AC3_MONO):
+ mix2to1 (samples, level * LEVEL_6DB, bias);
+ break;
+
+ case CONVERT (AC3_MONO, AC3_DOLBY):
+ mix1to2 (samples, samples + 256, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_3F, AC3_DOLBY):
+ clev = LEVEL_3DB;
+ case CONVERT (AC3_3F, AC3_STEREO):
+ mix_3to2:
+ mix3to2 (samples, level, level * clev, bias);
+ break;
+
+ case CONVERT (AC3_2F1R, AC3_DOLBY):
+ mix21toS (samples, level, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_DOLBY):
+ mix31toS (samples, level, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_2F2R, AC3_DOLBY):
+ mix22toS (samples, level, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_DOLBY):
+ mix32toS (samples, level, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_2F1R, AC3_STEREO):
+ if (slev == 0)
+ goto mix_2to2;
+ mix21to2 (samples, samples + 256, level, level * slev * LEVEL_3DB,
+ bias);
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_STEREO):
+ if (slev == 0)
+ goto mix_3to2;
+ mix31to2 (samples, level, level * clev, level * slev * LEVEL_3DB,
+ bias);
+ break;
+
+ case CONVERT (AC3_2F2R, AC3_STEREO):
+ if (slev == 0)
+ goto mix_2to2;
+ mix11to1 (samples, samples + 512, level, level * slev, bias);
+ mix11to1 (samples + 256, samples + 768, level, level * slev, bias);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_STEREO):
+ if (slev == 0)
+ goto mix_3to2;
+ mix32to2 (samples, level, level * clev, level * slev, bias);
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_3F):
+ if (slev == 0)
+ goto mix_3to3;
+ mix21to2 (samples, samples + 512, level, level * slev * LEVEL_3DB,
+ bias);
+
+ case CONVERT (AC3_3F2R, AC3_3F):
+ if (slev == 0)
+ goto mix_3to3;
+ mix11to1 (samples, samples + 768, level, level * slev, bias);
+ mix11to1 (samples + 512, samples + 1024, level, level * slev, bias);
+ goto mix_1to1_b;
+
+ case CONVERT (AC3_2F1R, AC3_2F2R):
+ mix1to2 (samples + 512, samples + 768, level * LEVEL_3DB, bias);
+ goto mix_2to2;
+
+ case CONVERT (AC3_3F1R, AC3_3F2R):
+ mix1to2 (samples + 768, samples + 1024, level * LEVEL_3DB, bias);
+ goto mix_3to3;
+
+ case CONVERT (AC3_2F2R, AC3_2F1R):
+ mix2to1 (samples + 512, level * LEVEL_3DB, bias);
+ goto mix_2to2;
+
+ case CONVERT (AC3_3F2R, AC3_3F1R):
+ mix2to1 (samples + 768, level * LEVEL_3DB, bias);
+ goto mix_3to3;
+
+ case CONVERT (AC3_3F1R, AC3_2F2R):
+ mix3to2 (samples, level, level * clev, bias);
+ mix1to2 (samples + 768, samples + 512, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_3F1R, AC3_2F1R):
+ mix3to2 (samples, level, level * clev, bias);
+ move1to1 (samples + 768, samples + 512, level, bias);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_2F1R):
+ mix3to2 (samples, level, level * clev, bias);
+ move2to1 (samples + 768, samples + 512, level * LEVEL_3DB, bias);
+ break;
+
+ case CONVERT (AC3_3F2R, AC3_2F2R):
+ mix3to2 (samples, level, level * clev, bias);
+ move1to1 (samples + 768, samples + 512, level, bias);
+ move1to1 (samples + 1024, samples + 768, level, bias);
+ break;
+
+ }
+}
diff --git a/libavcodec/libac3/imdct.c b/libavcodec/libac3/imdct.c
new file mode 100644
index 0000000000..7be33897f5
--- /dev/null
+++ b/libavcodec/libac3/imdct.c
@@ -0,0 +1,408 @@
+/*
+ * imdct.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+//#include "config.h"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+void (* imdct_256) (float data[], float delay[]);
+void (* imdct_512) (float data[], float delay[]);
+
+typedef struct complex_s
+{
+ float real;
+ float imag;
+} complex_t;
+
+
+/* 128 point bit-reverse LUT */
+static uint8_t bit_reverse_512[] = {
+ 0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70,
+ 0x08, 0x48, 0x28, 0x68, 0x18, 0x58, 0x38, 0x78,
+ 0x04, 0x44, 0x24, 0x64, 0x14, 0x54, 0x34, 0x74,
+ 0x0c, 0x4c, 0x2c, 0x6c, 0x1c, 0x5c, 0x3c, 0x7c,
+ 0x02, 0x42, 0x22, 0x62, 0x12, 0x52, 0x32, 0x72,
+ 0x0a, 0x4a, 0x2a, 0x6a, 0x1a, 0x5a, 0x3a, 0x7a,
+ 0x06, 0x46, 0x26, 0x66, 0x16, 0x56, 0x36, 0x76,
+ 0x0e, 0x4e, 0x2e, 0x6e, 0x1e, 0x5e, 0x3e, 0x7e,
+ 0x01, 0x41, 0x21, 0x61, 0x11, 0x51, 0x31, 0x71,
+ 0x09, 0x49, 0x29, 0x69, 0x19, 0x59, 0x39, 0x79,
+ 0x05, 0x45, 0x25, 0x65, 0x15, 0x55, 0x35, 0x75,
+ 0x0d, 0x4d, 0x2d, 0x6d, 0x1d, 0x5d, 0x3d, 0x7d,
+ 0x03, 0x43, 0x23, 0x63, 0x13, 0x53, 0x33, 0x73,
+ 0x0b, 0x4b, 0x2b, 0x6b, 0x1b, 0x5b, 0x3b, 0x7b,
+ 0x07, 0x47, 0x27, 0x67, 0x17, 0x57, 0x37, 0x77,
+ 0x0f, 0x4f, 0x2f, 0x6f, 0x1f, 0x5f, 0x3f, 0x7f};
+
+static uint8_t bit_reverse_256[] = {
+ 0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38,
+ 0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c,
+ 0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a,
+ 0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e,
+ 0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39,
+ 0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d,
+ 0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b,
+ 0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f};
+
+static complex_t buf[128];
+
+/* Twiddle factor LUT */
+static complex_t w_1[1];
+static complex_t w_2[2];
+static complex_t w_4[4];
+static complex_t w_8[8];
+static complex_t w_16[16];
+static complex_t w_32[32];
+static complex_t w_64[64];
+static complex_t * w[7] = {w_1, w_2, w_4, w_8, w_16, w_32, w_64};
+
+/* Twiddle factors for IMDCT */
+static float xcos1[128];
+static float xsin1[128];
+static float xcos2[64];
+static float xsin2[64];
+
+/* Windowing function for Modified DCT - Thank you acroread */
+float imdct_window[] = {
+ 0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130,
+ 0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443,
+ 0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061,
+ 0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121,
+ 0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770,
+ 0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153,
+ 0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389,
+ 0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563,
+ 0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699,
+ 0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757,
+ 0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626,
+ 0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126,
+ 0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019,
+ 0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031,
+ 0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873,
+ 0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269,
+ 0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981,
+ 0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831,
+ 0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716,
+ 0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610,
+ 0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560,
+ 0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674,
+ 0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099,
+ 0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994,
+ 0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513,
+ 0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788,
+ 0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919,
+ 0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974,
+ 0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993,
+ 0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999,
+ 0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000,
+ 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000 };
+
+
+static inline void swap_cmplx(complex_t *a, complex_t *b)
+{
+ complex_t tmp;
+
+ tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+
+
+static inline complex_t cmplx_mult(complex_t a, complex_t b)
+{
+ complex_t ret;
+
+ ret.real = a.real * b.real - a.imag * b.imag;
+ ret.imag = a.real * b.imag + a.imag * b.real;
+
+ return ret;
+}
+
+void
+imdct_do_512(float data[],float delay[])
+{
+ int i,k;
+ int p,q;
+ int m;
+ int two_m;
+ int two_m_plus_one;
+
+ float tmp_a_i;
+ float tmp_a_r;
+ float tmp_b_i;
+ float tmp_b_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ //
+ // 512 IMDCT with source and dest data in 'data'
+ //
+
+ // Pre IFFT complex multiply plus IFFT cmplx conjugate
+ for( i=0; i < 128; i++) {
+ /* z[i] = (X[256-2*i-1] + j * X[2*i]) * (xcos1[i] + j * xsin1[i]) ; */
+ buf[i].real = (data[256-2*i-1] * xcos1[i]) - (data[2*i] * xsin1[i]);
+ buf[i].imag = -1.0 * ((data[2*i] * xcos1[i]) + (data[256-2*i-1] * xsin1[i]));
+ }
+
+ //Bit reversed shuffling
+ for(i=0; i<128; i++) {
+ k = bit_reverse_512[i];
+ if (k < i)
+ swap_cmplx(&buf[i],&buf[k]);
+ }
+
+ /* FFT Merge */
+ for (m=0; m < 7; m++) {
+ if(m)
+ two_m = (1 << m);
+ else
+ two_m = 1;
+
+ two_m_plus_one = (1 << (m+1));
+
+ for(k = 0; k < two_m; k++) {
+ for(i = 0; i < 128; i += two_m_plus_one) {
+ p = k + i;
+ q = p + two_m;
+ tmp_a_r = buf[p].real;
+ tmp_a_i = buf[p].imag;
+ tmp_b_r = buf[q].real * w[m][k].real - buf[q].imag * w[m][k].imag;
+ tmp_b_i = buf[q].imag * w[m][k].real + buf[q].real * w[m][k].imag;
+ buf[p].real = tmp_a_r + tmp_b_r;
+ buf[p].imag = tmp_a_i + tmp_b_i;
+ buf[q].real = tmp_a_r - tmp_b_r;
+ buf[q].imag = tmp_a_i - tmp_b_i;
+ }
+ }
+ }
+
+ /* Post IFFT complex multiply plus IFFT complex conjugate*/
+ for( i=0; i < 128; i++) {
+ /* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ; */
+ tmp_a_r = buf[i].real;
+ tmp_a_i = -1.0 * buf[i].imag;
+ buf[i].real =(tmp_a_r * xcos1[i]) - (tmp_a_i * xsin1[i]);
+ buf[i].imag =(tmp_a_r * xsin1[i]) + (tmp_a_i * xcos1[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = imdct_window;
+
+ /* Window and convert to real valued signal */
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = 2.0f * (-buf[64+i].imag * *window_ptr++ + *delay_ptr++);
+ *data_ptr++ = 2.0f * ( buf[64-i-1].real * *window_ptr++ + *delay_ptr++);
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = 2.0f * (-buf[i].real * *window_ptr++ + *delay_ptr++);
+ *data_ptr++ = 2.0f * ( buf[128-i-1].imag * *window_ptr++ + *delay_ptr++);
+ }
+
+ /* The trailing edge of the window goes into the delay line */
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf[64+i].real * *--window_ptr;
+ *delay_ptr++ = buf[64-i-1].imag * *--window_ptr;
+ }
+
+ for(i=0; i<64; i++) {
+ *delay_ptr++ = buf[i].imag * *--window_ptr;
+ *delay_ptr++ = -buf[128-i-1].real * *--window_ptr;
+ }
+}
+
+void
+imdct_do_256(float data[],float delay[])
+{
+ int i,k;
+ int p,q;
+ int m;
+ int two_m;
+ int two_m_plus_one;
+
+ float tmp_a_i;
+ float tmp_a_r;
+ float tmp_b_i;
+ float tmp_b_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ complex_t *buf_1, *buf_2;
+
+ buf_1 = &buf[0];
+ buf_2 = &buf[64];
+
+ /* Pre IFFT complex multiply plus IFFT cmplx conjugate */
+ for(k=0; k<64; k++) {
+ /* X1[k] = X[2*k] */
+ /* X2[k] = X[2*k+1] */
+
+ p = 2 * (128-2*k-1);
+ q = 2 * (2 * k);
+
+ /* Z1[k] = (X1[128-2*k-1] + j * X1[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf_1[k].real = data[p] * xcos2[k] - data[q] * xsin2[k];
+ buf_1[k].imag = -1.0f * (data[q] * xcos2[k] + data[p] * xsin2[k]);
+ /* Z2[k] = (X2[128-2*k-1] + j * X2[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf_2[k].real = data[p + 1] * xcos2[k] - data[q + 1] * xsin2[k];
+ buf_2[k].imag = -1.0f * ( data[q + 1] * xcos2[k] + data[p + 1] * xsin2[k]);
+ }
+
+ //IFFT Bit reversed shuffling
+ for(i=0; i<64; i++) {
+ k = bit_reverse_256[i];
+ if (k < i) {
+ swap_cmplx(&buf_1[i],&buf_1[k]);
+ swap_cmplx(&buf_2[i],&buf_2[k]);
+ }
+ }
+
+ /* FFT Merge */
+ for (m=0; m < 6; m++) {
+ two_m = (1 << m);
+ two_m_plus_one = (1 << (m+1));
+
+ //FIXME
+ if(m)
+ two_m = (1 << m);
+ else
+ two_m = 1;
+
+ for(k = 0; k < two_m; k++) {
+ for(i = 0; i < 64; i += two_m_plus_one) {
+ p = k + i;
+ q = p + two_m;
+ //Do block 1
+ tmp_a_r = buf_1[p].real;
+ tmp_a_i = buf_1[p].imag;
+ tmp_b_r = buf_1[q].real * w[m][k].real - buf_1[q].imag * w[m][k].imag;
+ tmp_b_i = buf_1[q].imag * w[m][k].real + buf_1[q].real * w[m][k].imag;
+ buf_1[p].real = tmp_a_r + tmp_b_r;
+ buf_1[p].imag = tmp_a_i + tmp_b_i;
+ buf_1[q].real = tmp_a_r - tmp_b_r;
+ buf_1[q].imag = tmp_a_i - tmp_b_i;
+
+ //Do block 2
+ tmp_a_r = buf_2[p].real;
+ tmp_a_i = buf_2[p].imag;
+ tmp_b_r = buf_2[q].real * w[m][k].real - buf_2[q].imag * w[m][k].imag;
+ tmp_b_i = buf_2[q].imag * w[m][k].real + buf_2[q].real * w[m][k].imag;
+ buf_2[p].real = tmp_a_r + tmp_b_r;
+ buf_2[p].imag = tmp_a_i + tmp_b_i;
+ buf_2[q].real = tmp_a_r - tmp_b_r;
+ buf_2[q].imag = tmp_a_i - tmp_b_i;
+ }
+ }
+ }
+
+ /* Post IFFT complex multiply */
+ for( i=0; i < 64; i++) {
+ /* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */
+ tmp_a_r = buf_1[i].real;
+ tmp_a_i = -buf_1[i].imag;
+ buf_1[i].real =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]);
+ buf_1[i].imag =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]);
+ /* y2[n] = z2[n] * (xcos2[n] + j * xsin2[n]) ; */
+ tmp_a_r = buf_2[i].real;
+ tmp_a_i = -buf_2[i].imag;
+ buf_2[i].real =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]);
+ buf_2[i].imag =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = imdct_window;
+
+ /* Window and convert to real valued signal */
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = 2.0f * (-buf_1[i].imag * *window_ptr++ + *delay_ptr++);
+ *data_ptr++ = 2.0f * ( buf_1[64-i-1].real * *window_ptr++ + *delay_ptr++);
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = 2.0f * (-buf_1[i].real * *window_ptr++ + *delay_ptr++);
+ *data_ptr++ = 2.0f * ( buf_1[64-i-1].imag * *window_ptr++ + *delay_ptr++);
+ }
+
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf_2[i].real * *--window_ptr;
+ *delay_ptr++ = buf_2[64-i-1].imag * *--window_ptr;
+ }
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = buf_2[i].imag * *--window_ptr;
+ *delay_ptr++ = -buf_2[64-i-1].real * *--window_ptr;
+ }
+}
+
+void imdct_init (void)
+{
+#ifdef LIBAC3_MLIB
+ void imdct_do_256_mlib(float data[],float delay[]);
+ void imdct_do_512_mlib(float data[],float delay[]);
+
+ imdct_512 = imdct_do_512_mlib;
+ imdct_256 = imdct_do_256_mlib;
+#else
+ int i, j, k;
+
+ /* Twiddle factors to turn IFFT into IMDCT */
+ for (i = 0; i < 128; i++) {
+ xcos1[i] = -cos ((M_PI / 2048) * (8 * i + 1));
+ xsin1[i] = -sin ((M_PI / 2048) * (8 * i + 1));
+ }
+
+ /* More twiddle factors to turn IFFT into IMDCT */
+ for (i = 0; i < 64; i++) {
+ xcos2[i] = -cos ((M_PI / 1024) * (8 * i + 1));
+ xsin2[i] = -sin ((M_PI / 1024) * (8 * i + 1));
+ }
+
+ for (i = 0; i < 7; i++) {
+ j = 1 << i;
+ for (k = 0; k < j; k++) {
+ w[i][k].real = cos (-M_PI * k / j);
+ w[i][k].imag = sin (-M_PI * k / j);
+ }
+ }
+ imdct_512 = imdct_do_512;
+ imdct_256 = imdct_do_256;
+#endif
+}
diff --git a/libavcodec/libac3/parse.c b/libavcodec/libac3/parse.c
new file mode 100644
index 0000000000..c6eae00ba5
--- /dev/null
+++ b/libavcodec/libac3/parse.c
@@ -0,0 +1,684 @@
+/*
+ * parse.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#include <inttypes.h>
+#include <string.h>
+
+#include "ac3.h"
+#include "ac3_internal.h"
+
+#include "bitstream.h"
+#include "tables.h"
+
+extern stream_samples_t samples; // FIXME
+static float delay[6][256];
+
+void ac3_init (void)
+{
+ imdct_init ();
+}
+
+static uint8_t halfrate[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3};
+
+int ac3_syncinfo (uint8_t * buf, int * flags,
+ int * sample_rate, int * bit_rate)
+{
+ static int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
+ 128, 160, 192, 224, 256, 320, 384, 448,
+ 512, 576, 640};
+ static uint8_t lfeon[8] = {0x10, 0x10, 0x04, 0x04, 0x04, 0x01, 0x04, 0x01};
+ int frmsizecod;
+ int bitrate;
+ int half;
+ int acmod;
+
+ if ((buf[0] != 0x0b) || (buf[1] != 0x77)) // syncword
+ return 0;
+
+ if (buf[5] >= 0x60) // bsid >= 12
+ return 0;
+ half = halfrate[buf[5] >> 3];
+
+ // acmod, dsurmod and lfeon
+ acmod = buf[6] >> 5;
+ *flags = (((buf[6] & 0xf8) == 0x50) ? AC3_DOLBY : acmod) |
+ ((buf[6] & lfeon[acmod]) ? AC3_LFE : 0);
+
+ frmsizecod = buf[4] & 63;
+ if (frmsizecod >= 38)
+ return 0;
+ bitrate = rate [frmsizecod >> 1];
+ *bit_rate = (bitrate * 1000) >> half;
+
+ switch (buf[4] & 0xc0) {
+ case 0: // 48 KHz
+ *sample_rate = 48000 >> half;
+ return 4 * bitrate;
+ case 0x40:
+ *sample_rate = 44100 >> half;
+ return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
+ case 0x80:
+ *sample_rate = 32000 >> half;
+ return 6 * bitrate;
+ default:
+ return 0;
+ }
+}
+
+int ac3_frame (ac3_state_t * state, uint8_t * buf, int * flags, float * level,
+ float bias)
+{
+ static float clev[4] = {LEVEL_3DB, LEVEL_45DB, LEVEL_6DB, LEVEL_45DB};
+ static float slev[4] = {LEVEL_3DB, LEVEL_6DB, 0, LEVEL_6DB};
+ int chaninfo;
+ int acmod;
+
+ state->fscod = buf[4] >> 6;
+ state->halfrate = halfrate[buf[5] >> 3];
+ state->acmod = acmod = buf[6] >> 5;
+
+ bitstream_set_ptr (buf + 6);
+ bitstream_get (3); // skip acmod we already parsed
+
+ if ((acmod == 2) && (bitstream_get (2) == 2)) // dsurmod
+ acmod = AC3_DOLBY;
+
+ if ((acmod & 1) && (acmod != 1))
+ state->clev = clev[bitstream_get (2)]; // cmixlev
+
+ if (acmod & 4)
+ state->slev = slev[bitstream_get (2)]; // surmixlev
+
+ state->lfeon = bitstream_get (1);
+
+ state->output = downmix_init (acmod, *flags, level,
+ state->clev, state->slev);
+ if (state->output < 0)
+ return 1;
+ *flags = state->output;
+ state->level = *level;
+ state->bias = bias;
+
+ chaninfo = !acmod;
+ do {
+ bitstream_get (5); // dialnorm
+ if (bitstream_get (1)) // compre
+ bitstream_get (8); // compr
+ if (bitstream_get (1)) // langcode
+ bitstream_get (8); // langcod
+ if (bitstream_get (1)) // audprodie
+ bitstream_get (7); // mixlevel + roomtyp
+ } while (chaninfo--);
+
+ bitstream_get (2); // copyrightb + origbs
+
+ if (bitstream_get (1)) // timecod1e
+ bitstream_get (14); // timecod1
+ if (bitstream_get (1)) // timecod2e
+ bitstream_get (14); // timecod2
+
+ if (bitstream_get (1)) { // addbsie
+ int addbsil;
+
+ addbsil = bitstream_get (6);
+ do {
+ bitstream_get (8); // addbsi
+ } while (addbsil--);
+ }
+
+ return 0;
+}
+
+static int parse_exponents (int expstr, int ngrps, uint8_t exponent,
+ uint8_t * dest)
+{
+ int exps;
+
+ while (ngrps--) {
+ exps = bitstream_get (7);
+
+ exponent += exp_1[exps];
+ if (exponent > 24)
+ return 1;
+
+ switch (expstr) {
+ case EXP_D45:
+ *(dest++) = exponent;
+ *(dest++) = exponent;
+ case EXP_D25:
+ *(dest++) = exponent;
+ case EXP_D15:
+ *(dest++) = exponent;
+ }
+
+ exponent += exp_2[exps];
+ if (exponent > 24)
+ return 1;
+
+ switch (expstr) {
+ case EXP_D45:
+ *(dest++) = exponent;
+ *(dest++) = exponent;
+ case EXP_D25:
+ *(dest++) = exponent;
+ case EXP_D15:
+ *(dest++) = exponent;
+ }
+
+ exponent += exp_3[exps];
+ if (exponent > 24)
+ return 1;
+
+ switch (expstr) {
+ case EXP_D45:
+ *(dest++) = exponent;
+ *(dest++) = exponent;
+ case EXP_D25:
+ *(dest++) = exponent;
+ case EXP_D15:
+ *(dest++) = exponent;
+ }
+ }
+
+ return 0;
+}
+
+static int parse_deltba (int8_t * deltba)
+{
+ int deltnseg, deltlen, delta, j;
+
+ memset (deltba, 0, 50);
+
+ deltnseg = bitstream_get (3);
+ j = 0;
+ do {
+ j += bitstream_get (5);
+ deltlen = bitstream_get (4);
+ delta = bitstream_get (3);
+ delta -= (delta >= 4) ? 3 : 4;
+ if (!deltlen)
+ continue;
+ if (j + deltlen >= 50)
+ return 1;
+ while (deltlen--)
+ deltba[j++] = delta;
+ } while (deltnseg--);
+
+ return 0;
+}
+
+static inline int zero_snr_offsets (int nfchans, ac3_state_t * state)
+{
+ int i;
+
+ if ((state->csnroffst) || (state->cplinu && state->cplba.fsnroffst) ||
+ (state->lfeon && state->lfeba.fsnroffst))
+ return 0;
+ for (i = 0; i < nfchans; i++)
+ if (state->ba[i].fsnroffst)
+ return 0;
+ return 1;
+}
+
+static float q_1[2];
+static float q_2[2];
+static float q_4;
+static int q_1_pointer;
+static int q_2_pointer;
+static int q_4_pointer;
+
+#define GET_COEFF(COEFF,DITHER) \
+ switch (bap[i]) { \
+ case 0: \
+ DITHER (scale_factor[exp[i]]); \
+ \
+ case -1: \
+ if (q_1_pointer >= 0) { \
+ COEFF (q_1[q_1_pointer--] * scale_factor[exp[i]]); \
+ } else { \
+ int code; \
+ \
+ code = bitstream_get (5); \
+ \
+ q_1_pointer = 1; \
+ q_1[0] = q_1_2[code]; \
+ q_1[1] = q_1_1[code]; \
+ COEFF (q_1_0[code] * scale_factor[exp[i]]); \
+ } \
+ \
+ case -2: \
+ if (q_2_pointer >= 0) { \
+ COEFF (q_2[q_2_pointer--] * scale_factor[exp[i]]); \
+ } else { \
+ int code; \
+ \
+ code = bitstream_get (7); \
+ \
+ q_2_pointer = 1; \
+ q_2[0] = q_2_2[code]; \
+ q_2[1] = q_2_1[code]; \
+ COEFF (q_2_0[code] * scale_factor[exp[i]]); \
+ } \
+ \
+ case 3: \
+ COEFF (q_3[bitstream_get (3)] * scale_factor[exp[i]]); \
+ \
+ case -3: \
+ if (q_4_pointer == 0) { \
+ q_4_pointer = -1; \
+ COEFF (q_4 * scale_factor[exp[i]]); \
+ } else { \
+ int code; \
+ \
+ code = bitstream_get (7); \
+ \
+ q_4_pointer = 0; \
+ q_4 = q_4_1[code]; \
+ COEFF (q_4_0[code] * scale_factor[exp[i]]); \
+ } \
+ \
+ case 4: \
+ COEFF (q_5[bitstream_get (4)] * scale_factor[exp[i]]); \
+ \
+ default: \
+ COEFF (((int16_t)(bitstream_get(bap[i]) << (16 - bap[i]))) * \
+ scale_factor[exp[i]]); \
+ }
+
+#define CHANNEL_COEFF(val) \
+ coeff[i++] = val; \
+ continue;
+
+#define CHANNEL_DITHER(val) \
+ if (dither) { \
+ coeff[i++] = dither_gen () * val; \
+ continue; \
+ } else { \
+ coeff[i++] = 0; \
+ continue; \
+ }
+
+static uint16_t lfsr_state = 1;
+
+static inline int16_t dither_gen(void)
+{
+ int16_t state;
+
+ state = dither_lut[lfsr_state >> 8] ^ (lfsr_state << 8);
+
+ lfsr_state = (uint16_t) state;
+
+ return ((state * (int) (LEVEL_3DB * 256)) >> 8);
+}
+
+static void coeff_get (float * coeff, uint8_t * exp, int8_t * bap,
+ int dither, int end)
+{
+ int i;
+
+ i = 0;
+ while (i < end)
+ GET_COEFF (CHANNEL_COEFF, CHANNEL_DITHER);
+}
+
+#define COUPLING_COEFF(val) \
+ cplcoeff = val; \
+ break;
+
+#define COUPLING_DITHER(val) \
+ cplcoeff = val; \
+ for (ch = 0; ch < nfchans; ch++) \
+ if (state->chincpl[ch]) { \
+ if (dithflag[ch]) \
+ samples[ch][i] = \
+ state->cplco[ch][bnd] * dither_gen () * cplcoeff; \
+ else \
+ samples[ch][i] = 0; \
+ } \
+ i++; \
+ continue;
+
+int ac3_block (ac3_state_t * state)
+{
+ static const uint8_t nfchans_tbl[8] = {2, 1, 2, 3, 3, 4, 4, 5};
+ static int rematrix_band[4] = {25, 37, 61, 253};
+ int i, nfchans, chaninfo;
+ uint8_t cplexpstr, chexpstr[5], lfeexpstr, do_bit_alloc, done_cpl;
+ uint8_t blksw[5], dithflag[5];
+
+ nfchans = nfchans_tbl[state->acmod];
+
+ for (i = 0; i < nfchans; i++)
+ blksw[i] = bitstream_get (1);
+
+ for (i = 0; i < nfchans; i++)
+ dithflag[i] = bitstream_get (1);
+
+ chaninfo = !(state->acmod);
+ do {
+ if (bitstream_get (1)) // dynrnge
+ bitstream_get (8); // dynrng
+ } while (chaninfo--);
+
+ if (bitstream_get (1)) { // cplstre
+ state->cplinu = bitstream_get (1);
+ if (state->cplinu) {
+ static int bndtab[16] = {31, 35, 37, 39, 41, 42, 43, 44,
+ 45, 45, 46, 46, 47, 47, 48, 48};
+ int cplbegf;
+ int cplendf;
+ int ncplsubnd;
+
+ for (i = 0; i < nfchans; i++)
+ state->chincpl[i] = bitstream_get (1);
+ switch (state->acmod) {
+ case 0: case 1:
+ return 1;
+ case 2:
+ state->phsflginu = bitstream_get (1);
+ }
+ cplbegf = bitstream_get (4);
+ cplendf = bitstream_get (4);
+
+ if (cplendf + 3 - cplbegf < 0)
+ return 1;
+ state->ncplbnd = ncplsubnd = cplendf + 3 - cplbegf;
+ state->cplstrtbnd = bndtab[cplbegf];
+ state->cplstrtmant = cplbegf * 12 + 37;
+ state->cplendmant = cplendf * 12 + 73;
+
+ for (i = 0; i < ncplsubnd - 1; i++) {
+ state->cplbndstrc[i] = bitstream_get (1);
+ state->ncplbnd -= state->cplbndstrc[i];
+ }
+ state->cplbndstrc[i] = 0; // last value is a sentinel
+ }
+ }
+
+ if (state->cplinu) {
+ int j, cplcoe;
+
+ cplcoe = 0;
+ for (i = 0; i < nfchans; i++)
+ if (state->chincpl[i])
+ if (bitstream_get (1)) { // cplcoe
+ int mstrcplco, cplcoexp, cplcomant;
+
+ cplcoe = 1;
+ mstrcplco = 3 * bitstream_get (2);
+ for (j = 0; j < state->ncplbnd; j++) {
+ cplcoexp = bitstream_get (4);
+ cplcomant = bitstream_get (4);
+ if (cplcoexp == 15)
+ cplcomant <<= 14;
+ else
+ cplcomant = (cplcomant | 0x10) << 13;
+ state->cplco[i][j] =
+ cplcomant * scale_factor[cplcoexp + mstrcplco];
+ }
+ }
+ if ((state->acmod == 2) && state->phsflginu && cplcoe)
+ for (j = 0; j < state->ncplbnd; j++)
+ if (bitstream_get (1)) // phsflg
+ state->cplco[1][j] = -state->cplco[1][j];
+ }
+
+ if ((state->acmod == 2) && (bitstream_get (1))) { // rematstr
+ int end;
+
+ end = (state->cplinu) ? state->cplstrtmant : 253;
+ i = 0;
+ do
+ state->rematflg[i] = bitstream_get (1);
+ while (rematrix_band[i++] < end);
+ }
+
+ cplexpstr = EXP_REUSE;
+ lfeexpstr = EXP_REUSE;
+ if (state->cplinu)
+ cplexpstr = bitstream_get (2);
+ for (i = 0; i < nfchans; i++)
+ chexpstr[i] = bitstream_get (2);
+ if (state->lfeon)
+ lfeexpstr = bitstream_get (1);
+
+ for (i = 0; i < nfchans; i++)
+ if (chexpstr[i] != EXP_REUSE) {
+ if (state->cplinu && state->chincpl[i])
+ state->endmant[i] = state->cplstrtmant;
+ else {
+ int chbwcod;
+
+ chbwcod = bitstream_get (6);
+ if (chbwcod > 60)
+ return 1;
+ state->endmant[i] = chbwcod * 3 + 73;
+ }
+ }
+
+ do_bit_alloc = 0;
+
+ if (cplexpstr != EXP_REUSE) {
+ int cplabsexp, ncplgrps;
+
+ do_bit_alloc = 1;
+ ncplgrps = ((state->cplendmant - state->cplstrtmant) /
+ (3 << (cplexpstr - 1)));
+ cplabsexp = bitstream_get (4) << 1;
+ if (parse_exponents (cplexpstr, ncplgrps, cplabsexp,
+ state->cpl_exp + state->cplstrtmant))
+ return 1;
+ }
+ for (i = 0; i < nfchans; i++)
+ if (chexpstr[i] != EXP_REUSE) {
+ int grp_size, nchgrps;
+
+ do_bit_alloc = 1;
+ grp_size = 3 << (chexpstr[i] - 1);
+ nchgrps = (state->endmant[i] + grp_size - 4) / grp_size;
+ state->fbw_exp[i][0] = bitstream_get (4);
+ if (parse_exponents (chexpstr[i], nchgrps, state->fbw_exp[i][0],
+ state->fbw_exp[i] + 1))
+ return 1;
+ bitstream_get (2); // gainrng
+ }
+ if (lfeexpstr != EXP_REUSE) {
+ do_bit_alloc = 1;
+ state->lfe_exp[0] = bitstream_get (4);
+ if (parse_exponents (lfeexpstr, 2, state->lfe_exp[0],
+ state->lfe_exp + 1))
+ return 1;
+ }
+
+ if (bitstream_get (1)) { // baie
+ do_bit_alloc = 1;
+ state->sdcycod = bitstream_get (2);
+ state->fdcycod = bitstream_get (2);
+ state->sgaincod = bitstream_get (2);
+ state->dbpbcod = bitstream_get (2);
+ state->floorcod = bitstream_get (3);
+ }
+ if (bitstream_get (1)) { //snroffste
+ do_bit_alloc = 1;
+ state->csnroffst = bitstream_get (6);
+ if (state->cplinu) {
+ state->cplba.fsnroffst = bitstream_get (4);
+ state->cplba.fgaincod = bitstream_get (3);
+ }
+ for (i = 0; i < nfchans; i++) {
+ state->ba[i].fsnroffst = bitstream_get (4);
+ state->ba[i].fgaincod = bitstream_get (3);
+ }
+ if (state->lfeon) {
+ state->lfeba.fsnroffst = bitstream_get (4);
+ state->lfeba.fgaincod = bitstream_get (3);
+ }
+ }
+ if ((state->cplinu) && (bitstream_get (1))) { // cplleake
+ do_bit_alloc = 1;
+ state->cplfleak = 2304 - (bitstream_get (3) << 8);
+ state->cplsleak = 2304 - (bitstream_get (3) << 8);
+ }
+
+ if (bitstream_get (1)) { // deltbaie
+ do_bit_alloc = 1;
+ if (state->cplinu)
+ state->cplba.deltbae = bitstream_get (2);
+ for (i = 0; i < nfchans; i++)
+ state->ba[i].deltbae = bitstream_get (2);
+ if (state->cplinu && (state->cplba.deltbae == DELTA_BIT_NEW) &&
+ parse_deltba (state->cplba.deltba))
+ return 1;
+ for (i = 0; i < nfchans; i++)
+ if ((state->ba[i].deltbae == DELTA_BIT_NEW) &&
+ parse_deltba (state->ba[i].deltba))
+ return 1;
+ }
+
+ if (do_bit_alloc) {
+ if (zero_snr_offsets (nfchans, state)) {
+ memset (state->cpl_bap, 0, sizeof (state->cpl_bap));
+ memset (state->fbw_bap, 0, sizeof (state->fbw_bap));
+ memset (state->lfe_bap, 0, sizeof (state->lfe_bap));
+ } else {
+ if (state->cplinu)
+ bit_allocate (state, &state->cplba, state->cplstrtbnd,
+ state->cplstrtmant, state->cplendmant,
+ state->cplfleak, state->cplsleak,
+ state->cpl_exp, state->cpl_bap);
+ for (i = 0; i < nfchans; i++)
+ bit_allocate (state, state->ba + i, 0, 0, state->endmant[i],
+ 0, 0, state->fbw_exp[i], state->fbw_bap[i]);
+ if (state->lfeon) {
+ state->lfeba.deltbae = DELTA_BIT_NONE;
+ bit_allocate (state, &state->lfeba, 0, 0, 7, 0, 0,
+ state->lfe_exp, state->lfe_bap);
+ }
+ }
+ }
+
+ if (bitstream_get (1)) { // skiple
+ i = bitstream_get (9); // skipl
+ while (i--)
+ bitstream_get (8);
+ }
+
+ q_1_pointer = q_2_pointer = q_4_pointer = -1;
+ done_cpl = 0;
+
+ for (i = 0; i < nfchans; i++) {
+ int j;
+
+ coeff_get (samples[i], state->fbw_exp[i], state->fbw_bap[i],
+ dithflag[i], state->endmant[i]);
+
+ if (state->cplinu && state->chincpl[i]) {
+ if (!done_cpl) {
+ int i, i_end, bnd, sub_bnd, ch;
+ float cplcoeff;
+
+ done_cpl = 1;
+
+#define bap state->cpl_bap
+#define exp state->cpl_exp
+
+ sub_bnd = bnd = 0;
+ i = state->cplstrtmant;
+ while (i < state->cplendmant) {
+ i_end = i + 12;
+ while (state->cplbndstrc[sub_bnd++])
+ i_end += 12;
+
+ while (i < i_end) {
+ GET_COEFF (COUPLING_COEFF, COUPLING_DITHER);
+ for (ch = 0; ch < nfchans; ch++)
+ if (state->chincpl[ch])
+ samples[ch][i] =
+ state->cplco[ch][bnd] * cplcoeff;
+ i++;
+ }
+ bnd++;
+ }
+
+#undef bap
+#undef exp
+ }
+ j = state->cplendmant;
+ } else
+ j = state->endmant[i];
+ for (; j < 256; j++)
+ samples[i][j] = 0;
+ }
+
+ if (state->acmod == 2) {
+ int j, end, band;
+
+ end = ((state->endmant[0] < state->endmant[1]) ?
+ state->endmant[0] : state->endmant[1]);
+
+ i = 0;
+ j = 13;
+ do {
+ if (!state->rematflg[i]) {
+ j = rematrix_band[i++];
+ continue;
+ }
+ band = rematrix_band[i++];
+ if (band > end)
+ band = end;
+ do {
+ float tmp0, tmp1;
+
+ tmp0 = samples[0][j];
+ tmp1 = samples[1][j];
+ samples[0][j] = tmp0 + tmp1;
+ samples[1][j] = tmp0 - tmp1;
+ } while (++j < band);
+ } while (j < end);
+ }
+
+ if (state->lfeon) {
+ coeff_get (samples[5], state->lfe_exp, state->lfe_bap, 0, 7);
+#if 0
+ for (i = 7; i < 256; i++)
+ samples[5][i] = 0;
+#endif
+ }
+
+ for (i = 0; i < nfchans; i++)
+ if (blksw[i])
+ imdct_256 (samples[i], delay[i]);
+ else
+ imdct_512 (samples[i], delay[i]);
+
+#if 0
+ if (state->lfeon)
+ imdct_512 (samples[5], delay[5]);
+#endif
+
+ downmix (*samples, state->acmod, state->output, state->level, state->bias,
+ state->clev, state->slev);
+
+ return 0;
+}
diff --git a/libavcodec/libac3/tables.h b/libavcodec/libac3/tables.h
new file mode 100644
index 0000000000..5825f9326a
--- /dev/null
+++ b/libavcodec/libac3/tables.h
@@ -0,0 +1,250 @@
+/*
+ * parse.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec 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, or (at your option)
+ * any later version.
+ *
+ * ac3dec 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+static int8_t exp_1[128] = {
+ -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
+ -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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 25,25,25
+};
+static int8_t exp_2[128] = {
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+ 25,25,25
+};
+static int8_t exp_3[128] = {
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,
+ 25,25,25
+};
+
+#define Q0 ((-2 << 15) / 3.0)
+#define Q1 (0)
+#define Q2 ((2 << 15) / 3.0)
+
+static const float q_1_0[ 32 ] = {
+ Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
+ 0,0,0,0,0
+};
+
+static const float q_1_1[ 32 ] = {
+ Q0,Q0,Q0,Q1,Q1,Q1,Q2,Q2,Q2,
+ Q0,Q0,Q0,Q1,Q1,Q1,Q2,Q2,Q2,
+ Q0,Q0,Q0,Q1,Q1,Q1,Q2,Q2,Q2,
+ 0,0,0,0,0
+};
+
+static const float q_1_2[ 32 ] = {
+ Q0,Q1,Q2,Q0,Q1,Q2,Q0,Q1,Q2,
+ Q0,Q1,Q2,Q0,Q1,Q2,Q0,Q1,Q2,
+ Q0,Q1,Q2,Q0,Q1,Q2,Q0,Q1,Q2,
+ 0,0,0,0,0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+
+#define Q0 ((-4 << 15) / 5.0)
+#define Q1 ((-2 << 15) / 5.0)
+#define Q2 (0)
+#define Q3 ((2 << 15) / 5.0)
+#define Q4 ((4 << 15) / 5.0)
+
+static const float q_2_0[ 128 ] = {
+ Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
+ Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,
+ Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,
+ 0,0,0
+};
+
+static const float q_2_1[ 128 ] = {
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ 0,0,0
+};
+
+static const float q_2_2[ 128 ] = {
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ 0,0,0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+
+static const float q_3[8] = {
+ (-6 << 15)/7.0, (-4 << 15)/7.0, (-2 << 15)/7.0, 0,
+ ( 2 << 15)/7.0, ( 4 << 15)/7.0, ( 6 << 15)/7.0, 0
+};
+
+#define Q0 ((-10 << 15) / 11.0)
+#define Q1 ((-8 << 15) / 11.0)
+#define Q2 ((-6 << 15) / 11.0)
+#define Q3 ((-4 << 15) / 11.0)
+#define Q4 ((-2 << 15) / 11.0)
+#define Q5 (0)
+#define Q6 ((2 << 15) / 11.0)
+#define Q7 ((4 << 15) / 11.0)
+#define Q8 ((6 << 15) / 11.0)
+#define Q9 ((8 << 15) / 11.0)
+#define QA ((10 << 15) / 11.0)
+
+static const float q_4_0[ 128 ] = {
+ Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
+ Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
+ Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
+ Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3,
+ Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4,
+ Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5,
+ Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6,
+ Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7,
+ Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8,
+ Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9,
+ QA, QA, QA, QA, QA, QA, QA, QA, QA, QA, QA,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const float q_4_1[ 128 ] = {
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+#undef Q5
+#undef Q6
+#undef Q7
+#undef Q8
+#undef Q9
+#undef QA
+
+static const float q_5[16] = {
+ (-14 << 15)/15.0,(-12 << 15)/15.0,(-10 << 15)/15.0,
+ ( -8 << 15)/15.0,( -6 << 15)/15.0,( -4 << 15)/15.0,
+ ( -2 << 15)/15.0, 0 ,( 2 << 15)/15.0,
+ ( 4 << 15)/15.0,( 6 << 15)/15.0,( 8 << 15)/15.0,
+ ( 10 << 15)/15.0,( 12 << 15)/15.0,( 14 << 15)/15.0,
+ 0
+};
+
+static const uint32_t u32_scale_factors[25] =
+{
+ 0x38000000, //2 ^ -(0 + 15)
+ 0x37800000, //2 ^ -(1 + 15)
+ 0x37000000, //2 ^ -(2 + 15)
+ 0x36800000, //2 ^ -(3 + 15)
+ 0x36000000, //2 ^ -(4 + 15)
+ 0x35800000, //2 ^ -(5 + 15)
+ 0x35000000, //2 ^ -(6 + 15)
+ 0x34800000, //2 ^ -(7 + 15)
+ 0x34000000, //2 ^ -(8 + 15)
+ 0x33800000, //2 ^ -(9 + 15)
+ 0x33000000, //2 ^ -(10 + 15)
+ 0x32800000, //2 ^ -(11 + 15)
+ 0x32000000, //2 ^ -(12 + 15)
+ 0x31800000, //2 ^ -(13 + 15)
+ 0x31000000, //2 ^ -(14 + 15)
+ 0x30800000, //2 ^ -(15 + 15)
+ 0x30000000, //2 ^ -(16 + 15)
+ 0x2f800000, //2 ^ -(17 + 15)
+ 0x2f000000, //2 ^ -(18 + 15)
+ 0x2e800000, //2 ^ -(19 + 15)
+ 0x2e000000, //2 ^ -(20 + 15)
+ 0x2d800000, //2 ^ -(21 + 15)
+ 0x2d000000, //2 ^ -(22 + 15)
+ 0x2c800000, //2 ^ -(23 + 15)
+ 0x2c000000 //2 ^ -(24 + 15)
+};
+
+static float * scale_factor = (float *) u32_scale_factors;
+
+static const uint16_t dither_lut[256] = {
+ 0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055,
+ 0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb,
+ 0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198,
+ 0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176,
+ 0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf,
+ 0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321,
+ 0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202,
+ 0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec,
+ 0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761,
+ 0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f,
+ 0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac,
+ 0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642,
+ 0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb,
+ 0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415,
+ 0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536,
+ 0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8,
+ 0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c,
+ 0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2,
+ 0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1,
+ 0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f,
+ 0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6,
+ 0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58,
+ 0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b,
+ 0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95,
+ 0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918,
+ 0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6,
+ 0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5,
+ 0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b,
+ 0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82,
+ 0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c,
+ 0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f,
+ 0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1
+};
diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
new file mode 100644
index 0000000000..ead72605e6
--- /dev/null
+++ b/libavcodec/mjpegenc.c
@@ -0,0 +1,417 @@
+/*
+ * MJPEG encoder
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+typedef struct MJpegContext {
+ UINT8 huff_size_dc_luminance[12];
+ UINT16 huff_code_dc_luminance[12];
+ UINT8 huff_size_dc_chrominance[12];
+ UINT16 huff_code_dc_chrominance[12];
+
+ UINT8 huff_size_ac_luminance[256];
+ UINT16 huff_code_ac_luminance[256];
+ UINT8 huff_size_ac_chrominance[256];
+ UINT16 huff_code_ac_chrominance[256];
+} MJpegContext;
+
+#define SOF0 0xc0
+#define SOI 0xd8
+#define EOI 0xd9
+#define DQT 0xdb
+#define DHT 0xc4
+#define SOS 0xda
+
+#if 0
+/* These are the sample quantization tables given in JPEG spec section K.1.
+ * The spec says that the values given produce "good" quality, and
+ * when divided by 2, "very good" quality.
+ */
+static const unsigned char std_luminance_quant_tbl[64] = {
+ 16, 11, 10, 16, 24, 40, 51, 61,
+ 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56,
+ 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77,
+ 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101,
+ 72, 92, 95, 98, 112, 100, 103, 99
+};
+static const unsigned char std_chrominance_quant_tbl[64] = {
+ 17, 18, 24, 47, 99, 99, 99, 99,
+ 18, 21, 26, 66, 99, 99, 99, 99,
+ 24, 26, 56, 99, 99, 99, 99, 99,
+ 47, 66, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99
+};
+#endif
+
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+static const UINT8 bits_dc_luminance[17] =
+{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+static const UINT8 val_dc_luminance[] =
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+static const UINT8 bits_dc_chrominance[17] =
+{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+static const UINT8 val_dc_chrominance[] =
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+static const UINT8 bits_ac_luminance[17] =
+{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+static const UINT8 val_ac_luminance[] =
+{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+static const UINT8 bits_ac_chrominance[17] =
+{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+
+static const UINT8 val_ac_chrominance[] =
+{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+
+/* isn't this function nicer than the one in the libjpeg ? */
+static void build_huffman_codes(UINT8 *huff_size, UINT16 *huff_code,
+ const UINT8 *bits_table, const UINT8 *val_table)
+{
+ int i, j, k,nb, code, sym;
+
+ code = 0;
+ k = 0;
+ for(i=1;i<=16;i++) {
+ nb = bits_table[i];
+ for(j=0;j<nb;j++) {
+ sym = val_table[k++];
+ huff_size[sym] = i;
+ huff_code[sym] = code;
+ code++;
+ }
+ code <<= 1;
+ }
+}
+
+int mjpeg_init(MpegEncContext *s)
+{
+ MJpegContext *m;
+
+ m = malloc(sizeof(MJpegContext));
+ if (!m)
+ return -1;
+
+ /* build all the huffman tables */
+ build_huffman_codes(m->huff_size_dc_luminance,
+ m->huff_code_dc_luminance,
+ bits_dc_luminance,
+ val_dc_luminance);
+ build_huffman_codes(m->huff_size_dc_chrominance,
+ m->huff_code_dc_chrominance,
+ bits_dc_chrominance,
+ val_dc_chrominance);
+ build_huffman_codes(m->huff_size_ac_luminance,
+ m->huff_code_ac_luminance,
+ bits_ac_luminance,
+ val_ac_luminance);
+ build_huffman_codes(m->huff_size_ac_chrominance,
+ m->huff_code_ac_chrominance,
+ bits_ac_chrominance,
+ val_ac_chrominance);
+
+ s->mjpeg_ctx = m;
+ return 0;
+}
+
+void mjpeg_close(MpegEncContext *s)
+{
+ free(s->mjpeg_ctx);
+}
+
+static inline void put_marker(PutBitContext *p, int code)
+{
+ put_bits(p, 8, 0xff);
+ put_bits(p, 8, code);
+}
+
+/* table_class: 0 = DC coef, 1 = AC coefs */
+static int put_huffman_table(MpegEncContext *s, int table_class, int table_id,
+ const UINT8 *bits_table, const UINT8 *value_table)
+{
+ PutBitContext *p = &s->pb;
+ int n, i;
+
+ put_bits(p, 4, table_class);
+ put_bits(p, 4, table_id);
+
+ n = 0;
+ for(i=1;i<=16;i++) {
+ n += bits_table[i];
+ put_bits(p, 8, bits_table[i]);
+ }
+
+ for(i=0;i<n;i++)
+ put_bits(p, 8, value_table[i]);
+
+ return n + 17;
+}
+
+static void jpeg_table_header(MpegEncContext *s)
+{
+ PutBitContext *p = &s->pb;
+ int i, size;
+ UINT8 *ptr;
+
+ /* quant matrixes */
+ put_marker(p, DQT);
+ put_bits(p, 16, 2 + 1 * (1 + 64));
+ put_bits(p, 4, 0); /* 8 bit precision */
+ put_bits(p, 4, 0); /* table 0 */
+ for(i=0;i<64;i++) {
+ put_bits(p, 8, s->intra_matrix[i]);
+ }
+#if 0
+ put_bits(p, 4, 0); /* 8 bit precision */
+ put_bits(p, 4, 1); /* table 1 */
+ for(i=0;i<64;i++) {
+ put_bits(p, 8, s->chroma_intra_matrix[i]);
+ }
+#endif
+
+ /* huffman table */
+ put_marker(p, DHT);
+ flush_put_bits(p);
+ ptr = p->buf_ptr;
+ put_bits(p, 16, 0); /* patched later */
+ size = 2;
+ size += put_huffman_table(s, 0, 0, bits_dc_luminance, val_dc_luminance);
+ size += put_huffman_table(s, 0, 1, bits_dc_chrominance, val_dc_chrominance);
+
+ size += put_huffman_table(s, 1, 0, bits_ac_luminance, val_ac_luminance);
+ size += put_huffman_table(s, 1, 1, bits_ac_chrominance, val_ac_chrominance);
+ ptr[0] = size >> 8;
+ ptr[1] = size;
+}
+
+void mjpeg_picture_header(MpegEncContext *s)
+{
+ put_marker(&s->pb, SOI);
+
+ jpeg_table_header(s);
+
+ put_marker(&s->pb, SOF0);
+
+ put_bits(&s->pb, 16, 17);
+ put_bits(&s->pb, 8, 8); /* 8 bits/component */
+ put_bits(&s->pb, 16, s->height);
+ put_bits(&s->pb, 16, s->width);
+ put_bits(&s->pb, 8, 3); /* 3 components */
+
+ /* Y component */
+ put_bits(&s->pb, 8, 1); /* component number */
+ put_bits(&s->pb, 4, 2); /* H factor */
+ put_bits(&s->pb, 4, 2); /* V factor */
+ put_bits(&s->pb, 8, 0); /* select matrix */
+
+ /* Cb component */
+ put_bits(&s->pb, 8, 2); /* component number */
+ put_bits(&s->pb, 4, 1); /* H factor */
+ put_bits(&s->pb, 4, 1); /* V factor */
+ put_bits(&s->pb, 8, 0); /* select matrix */
+
+ /* Cr component */
+ put_bits(&s->pb, 8, 3); /* component number */
+ put_bits(&s->pb, 4, 1); /* H factor */
+ put_bits(&s->pb, 4, 1); /* V factor */
+ put_bits(&s->pb, 8, 0); /* select matrix */
+
+ /* scan header */
+ put_marker(&s->pb, SOS);
+ put_bits(&s->pb, 16, 12); /* length */
+ put_bits(&s->pb, 8, 3); /* 3 components */
+
+ /* Y component */
+ put_bits(&s->pb, 8, 1); /* index */
+ put_bits(&s->pb, 4, 0); /* DC huffman table index */
+ put_bits(&s->pb, 4, 0); /* AC huffman table index */
+
+ /* Cb component */
+ put_bits(&s->pb, 8, 2); /* index */
+ put_bits(&s->pb, 4, 1); /* DC huffman table index */
+ put_bits(&s->pb, 4, 1); /* AC huffman table index */
+
+ /* Cr component */
+ put_bits(&s->pb, 8, 3); /* index */
+ put_bits(&s->pb, 4, 1); /* DC huffman table index */
+ put_bits(&s->pb, 4, 1); /* AC huffman table index */
+
+ put_bits(&s->pb, 8, 0); /* Ss (not used) */
+ put_bits(&s->pb, 8, 63); /* Se (not used) */
+ put_bits(&s->pb, 8, 0); /* (not used) */
+}
+
+void mjpeg_picture_trailer(MpegEncContext *s)
+{
+ jflush_put_bits(&s->pb);
+ put_marker(&s->pb, EOI);
+}
+
+static inline void encode_dc(MpegEncContext *s, int val,
+ UINT8 *huff_size, UINT16 *huff_code)
+{
+ int mant, nbits;
+
+ if (val == 0) {
+ jput_bits(&s->pb, huff_size[0], huff_code[0]);
+ } else {
+ mant = val;
+ if (val < 0) {
+ val = -val;
+ mant--;
+ }
+
+ /* compute the log (XXX: optimize) */
+ nbits = 0;
+ while (val != 0) {
+ val = val >> 1;
+ nbits++;
+ }
+
+ jput_bits(&s->pb, huff_size[nbits], huff_code[nbits]);
+
+ jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
+ }
+}
+
+static void encode_block(MpegEncContext *s, DCTELEM *block, int n)
+{
+ int mant, nbits, code, i, j;
+ int component, dc, run, last_index, val;
+ MJpegContext *m = s->mjpeg_ctx;
+ UINT8 *huff_size_ac;
+ UINT16 *huff_code_ac;
+
+ /* DC coef */
+ component = (n <= 3 ? 0 : n - 4 + 1);
+ dc = block[0]; /* overflow is impossible */
+ val = dc - s->last_dc[component];
+ if (n < 4) {
+ encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance);
+ huff_size_ac = m->huff_size_ac_luminance;
+ huff_code_ac = m->huff_code_ac_luminance;
+ } else {
+ encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
+ huff_size_ac = m->huff_size_ac_chrominance;
+ huff_code_ac = m->huff_code_ac_chrominance;
+ }
+ s->last_dc[component] = dc;
+
+ /* AC coefs */
+
+ run = 0;
+ last_index = s->block_last_index[n];
+ for(i=1;i<=last_index;i++) {
+ j = zigzag_direct[i];
+ val = block[j];
+ if (val == 0) {
+ run++;
+ } else {
+ while (run >= 16) {
+ jput_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]);
+ run -= 16;
+ }
+ mant = val;
+ if (val < 0) {
+ val = -val;
+ mant--;
+ }
+
+ /* compute the log (XXX: optimize) */
+ nbits = 0;
+ while (val != 0) {
+ val = val >> 1;
+ nbits++;
+ }
+ code = (run << 4) | nbits;
+
+ jput_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]);
+
+ jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1));
+ run = 0;
+ }
+ }
+
+ /* output EOB only if not already 64 values */
+ if (last_index < 63 || run != 0)
+ jput_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
+}
+
+void mjpeg_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64])
+{
+ int i;
+ for(i=0;i<6;i++) {
+ encode_block(s, block[i], i);
+ }
+}
diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c
new file mode 100644
index 0000000000..09fe662613
--- /dev/null
+++ b/libavcodec/motion_est.c
@@ -0,0 +1,517 @@
+/*
+ * Motion estimation
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ *
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+static void halfpel_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int dmin,
+ int xmin, int ymin, int xmax, int ymax);
+
+/* config it to test motion vector encoding (send random vectors) */
+//#define CONFIG_TEST_MV_ENCODE
+
+static int pix_sum(UINT8 * pix, int line_size)
+{
+ int s, i, j;
+
+ s = 0;
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 16; j += 8) {
+ s += pix[0];
+ s += pix[1];
+ s += pix[2];
+ s += pix[3];
+ s += pix[4];
+ s += pix[5];
+ s += pix[6];
+ s += pix[7];
+ pix += 8;
+ }
+ pix += line_size - 16;
+ }
+ return s;
+}
+
+static int pix_norm1(UINT8 * pix, int line_size)
+{
+ int s, i, j;
+ UINT32 *sq = squareTbl + 256;
+
+ s = 0;
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 16; j += 8) {
+ s += sq[pix[0]];
+ s += sq[pix[1]];
+ s += sq[pix[2]];
+ s += sq[pix[3]];
+ s += sq[pix[4]];
+ s += sq[pix[5]];
+ s += sq[pix[6]];
+ s += sq[pix[7]];
+ pix += 8;
+ }
+ pix += line_size - 16;
+ }
+ return s;
+}
+
+static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
+{
+ int s, i, j;
+ UINT32 *sq = squareTbl + 256;
+
+ s = 0;
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 16; j += 8) {
+ s += sq[pix1[0] - pix2[0]];
+ s += sq[pix1[1] - pix2[1]];
+ s += sq[pix1[2] - pix2[2]];
+ s += sq[pix1[3] - pix2[3]];
+ s += sq[pix1[4] - pix2[4]];
+ s += sq[pix1[5] - pix2[5]];
+ s += sq[pix1[6] - pix2[6]];
+ s += sq[pix1[7] - pix2[7]];
+ pix1 += 8;
+ pix2 += 8;
+ }
+ pix1 += line_size - 16;
+ pix2 += line_size - 16;
+ }
+ return s;
+}
+
+static void no_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr)
+{
+ *mx_ptr = 16 * s->mb_x;
+ *my_ptr = 16 * s->mb_y;
+}
+
+static int full_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int range,
+ int xmin, int ymin, int xmax, int ymax)
+{
+ int x1, y1, x2, y2, xx, yy, x, y;
+ int mx, my, dmin, d;
+ UINT8 *pix;
+
+ xx = 16 * s->mb_x;
+ yy = 16 * s->mb_y;
+ x1 = xx - range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
+ if (x1 < xmin)
+ x1 = xmin;
+ x2 = xx + range - 1;
+ if (x2 > xmax)
+ x2 = xmax;
+ y1 = yy - range + 1;
+ if (y1 < ymin)
+ y1 = ymin;
+ y2 = yy + range - 1;
+ if (y2 > ymax)
+ y2 = ymax;
+ pix = s->new_picture[0] + (yy * s->linesize) + xx;
+ dmin = 0x7fffffff;
+ mx = 0;
+ my = 0;
+ for (y = y1; y <= y2; y++) {
+ for (x = x1; x <= x2; x++) {
+ d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x,
+ s->linesize, 16);
+ if (d < dmin ||
+ (d == dmin &&
+ (abs(x - xx) + abs(y - yy)) <
+ (abs(mx - xx) + abs(my - yy)))) {
+ dmin = d;
+ mx = x;
+ my = y;
+ }
+ }
+ }
+
+ *mx_ptr = mx;
+ *my_ptr = my;
+
+#if 0
+ if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
+ *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
+ fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
+ }
+#endif
+ return dmin;
+}
+
+
+static int log_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int range,
+ int xmin, int ymin, int xmax, int ymax)
+{
+ int x1, y1, x2, y2, xx, yy, x, y;
+ int mx, my, dmin, d;
+ UINT8 *pix;
+
+ xx = s->mb_x << 4;
+ yy = s->mb_y << 4;
+
+ /* Left limit */
+ x1 = xx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ /* Right limit */
+ x2 = xx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ /* Upper limit */
+ y1 = yy - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ /* Lower limit */
+ y2 = yy + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ pix = s->new_picture[0] + (yy * s->linesize) + xx;
+ dmin = 0x7fffffff;
+ mx = 0;
+ my = 0;
+
+ do {
+ for (y = y1; y <= y2; y += range) {
+ for (x = x1; x <= x2; x += range) {
+ d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
+ if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
+ dmin = d;
+ mx = x;
+ my = y;
+ }
+ }
+ }
+
+ range = range >> 1;
+
+ x1 = mx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ x2 = mx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ y1 = my - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ y2 = my + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ } while (range >= 1);
+
+#ifdef DEBUG
+ fprintf(stderr, "log - MX: %d\tMY: %d\n", mx, my);
+#endif
+ *mx_ptr = mx;
+ *my_ptr = my;
+ return dmin;
+}
+
+static int phods_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int range,
+ int xmin, int ymin, int xmax, int ymax)
+{
+ int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
+ int mx, my, dminx, dminy;
+ UINT8 *pix;
+
+ xx = s->mb_x << 4;
+ yy = s->mb_y << 4;
+
+ /* Left limit */
+ x1 = xx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ /* Right limit */
+ x2 = xx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ /* Upper limit */
+ y1 = yy - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ /* Lower limit */
+ y2 = yy + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ pix = s->new_picture[0] + (yy * s->linesize) + xx;
+ mx = 0;
+ my = 0;
+
+ x = xx;
+ y = yy;
+ do {
+ dminx = 0x7fffffff;
+ dminy = 0x7fffffff;
+
+ lastx = x;
+ for (x = x1; x <= x2; x += range) {
+ d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
+ if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
+ dminx = d;
+ mx = x;
+ }
+ }
+
+ x = lastx;
+ for (y = y1; y <= y2; y += range) {
+ d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
+ if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
+ dminy = d;
+ my = y;
+ }
+ }
+
+ range = range >> 1;
+
+ x = mx;
+ y = my;
+ x1 = mx - range;
+ if (x1 < xmin)
+ x1 = xmin;
+
+ x2 = mx + range;
+ if (x2 > xmax)
+ x2 = xmax;
+
+ y1 = my - range;
+ if (y1 < ymin)
+ y1 = ymin;
+
+ y2 = my + range;
+ if (y2 > ymax)
+ y2 = ymax;
+
+ } while (range >= 1);
+
+#ifdef DEBUG
+ fprintf(stderr, "phods - MX: %d\tMY: %d\n", mx, my);
+#endif
+
+ /* half pixel search */
+ *mx_ptr = mx;
+ *my_ptr = my;
+ return dminy;
+}
+
+/* The idea would be to make half pel ME after Inter/Intra decision to
+ save time. */
+static void halfpel_motion_search(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr, int dmin,
+ int xmin, int ymin, int xmax, int ymax)
+{
+ int mx, my, mx1, my1, d, xx, yy, dminh;
+ UINT8 *pix;
+
+ mx = *mx_ptr << 1;
+ my = *my_ptr << 1;
+
+ xx = 16 * s->mb_x;
+ yy = 16 * s->mb_y;
+
+ dminh = dmin;
+
+ /* Half pixel search */
+ mx1 = mx;
+ my1 = my;
+
+ pix = s->new_picture[0] + (yy * s->linesize) + xx;
+
+ if ((mx > (xmin << 1)) && mx < (xmax << 1) &&
+ (my > (ymin << 1)) && my < (ymax << 1)) {
+ int dx, dy, px, py;
+ UINT8 *ptr;
+ for (dy = -1; dy <= 1; dy++) {
+ for (dx = -1; dx <= 1; dx++) {
+ if (dx != 0 || dy != 0) {
+ px = mx1 + dx;
+ py = my1 + dy;
+ ptr = s->last_picture[0] + ((py >> 1) * s->linesize) + (px >> 1);
+ switch (((py & 1) << 1) | (px & 1)) {
+ default:
+ case 0:
+ d = pix_abs16x16(pix, ptr, s->linesize, 16);
+ break;
+ case 1:
+ d = pix_abs16x16_x2(pix, ptr, s->linesize, 16);
+ break;
+ case 2:
+ d = pix_abs16x16_y2(pix, ptr, s->linesize, 16);
+ break;
+ case 3:
+ d = pix_abs16x16_xy2(pix, ptr, s->linesize, 16);
+ break;
+ }
+ if (d < dminh) {
+ dminh = d;
+ mx = px;
+ my = py;
+ }
+ }
+ }
+ }
+ }
+
+ *mx_ptr = mx - (xx << 1);
+ *my_ptr = my - (yy << 1);
+ //fprintf(stderr,"half - MX: %d\tMY: %d\n",*mx_ptr ,*my_ptr);
+}
+
+#ifndef CONFIG_TEST_MV_ENCODE
+
+int estimate_motion(MpegEncContext * s,
+ int mb_x, int mb_y,
+ int *mx_ptr, int *my_ptr)
+{
+ UINT8 *pix, *ppix;
+ int sum, varc, vard, mx, my, range, dmin, xx, yy;
+ int xmin, ymin, xmax, ymax;
+
+ range = 8 * (1 << (s->f_code - 1));
+ /* XXX: temporary kludge to avoid overflow for msmpeg4 */
+ if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
+ range = range * 2;
+
+ if (s->unrestricted_mv) {
+ xmin = -16;
+ ymin = -16;
+ xmax = s->width;
+ ymax = s->height;
+ } else {
+ xmin = 0;
+ ymin = 0;
+ xmax = s->width - 16;
+ ymax = s->height - 16;
+ }
+
+ switch(s->full_search) {
+ case ME_ZERO:
+ default:
+ no_motion_search(s, &mx, &my);
+ dmin = 0;
+ break;
+ case ME_FULL:
+ dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax);
+ break;
+ case ME_LOG:
+ dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
+ break;
+ case ME_PHODS:
+ dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
+ break;
+ }
+#ifdef CONFIG_MMX
+ if (mm_flags & MM_MMX)
+ emms();
+#endif
+
+ /* intra / predictive decision */
+ xx = mb_x * 16;
+ yy = mb_y * 16;
+
+ pix = s->new_picture[0] + (yy * s->linesize) + xx;
+ /* At this point (mx,my) are full-pell and the absolute displacement */
+ ppix = s->last_picture[0] + (my * s->linesize) + mx;
+
+ sum = pix_sum(pix, s->linesize);
+ varc = pix_norm1(pix, s->linesize);
+ vard = pix_norm(pix, ppix, s->linesize);
+
+ vard = vard >> 8;
+ sum = sum >> 8;
+ varc = (varc >> 8) - (sum * sum);
+#if 0
+ printf("varc=%d (sum=%d) vard=%d mx=%d my=%d\n",
+ varc, sum, vard, mx - xx, my - yy);
+#endif
+ if (vard <= 64 || vard < varc) {
+ if (s->full_search != ME_ZERO) {
+ halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax);
+ } else {
+ mx -= 16 * s->mb_x;
+ my -= 16 * s->mb_y;
+ }
+ *mx_ptr = mx;
+ *my_ptr = my;
+ return 0;
+ } else {
+ *mx_ptr = 0;
+ *my_ptr = 0;
+ return 1;
+ }
+}
+
+#else
+
+/* test version which generates valid random vectors */
+int estimate_motion(MpegEncContext * s,
+ int mb_x, int mb_y,
+ int *mx_ptr, int *my_ptr)
+{
+ int xx, yy, x1, y1, x2, y2, range;
+
+ if ((random() % 10) >= 5) {
+ range = 8 * (1 << (s->f_code - 1));
+ if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
+ range = range * 2;
+
+ xx = 16 * s->mb_x;
+ yy = 16 * s->mb_y;
+ x1 = xx - range;
+ if (x1 < 0)
+ x1 = 0;
+ x2 = xx + range - 1;
+ if (x2 > (s->width - 16))
+ x2 = s->width - 16;
+ y1 = yy - range;
+ if (y1 < 0)
+ y1 = 0;
+ y2 = yy + range - 1;
+ if (y2 > (s->height - 16))
+ y2 = s->height - 16;
+
+ *mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx);
+ *my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy);
+ return 0;
+ } else {
+ *mx_ptr = 0;
+ *my_ptr = 0;
+ return 1;
+ }
+}
+
+#endif
diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c
new file mode 100644
index 0000000000..3e2e523560
--- /dev/null
+++ b/libavcodec/mpeg12.c
@@ -0,0 +1,1530 @@
+/*
+ * MPEG1 encoder / MPEG2 decoder
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+#include "mpeg12data.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define dprintf(fmt,args...) printf(fmt, ## args)
+#else
+#define dprintf(fmt,args...)
+#endif
+
+/* Start codes. */
+#define SEQ_END_CODE 0x000001b7
+#define SEQ_START_CODE 0x000001b3
+#define GOP_START_CODE 0x000001b8
+#define PICTURE_START_CODE 0x00000100
+#define SLICE_MIN_START_CODE 0x00000101
+#define SLICE_MAX_START_CODE 0x000001af
+#define EXT_START_CODE 0x000001b5
+#define USER_START_CODE 0x000001b2
+
+static void mpeg1_encode_block(MpegEncContext *s,
+ DCTELEM *block,
+ int component);
+static void mpeg1_encode_motion(MpegEncContext *s, int val);
+static void mpeg1_skip_picture(MpegEncContext *s, int pict_num);
+static int mpeg1_decode_block(MpegEncContext *s,
+ DCTELEM *block,
+ int n);
+static int mpeg2_decode_block_non_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n);
+static int mpeg2_decode_block_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n);
+static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred);
+
+static void put_header(MpegEncContext *s, int header)
+{
+ align_put_bits(&s->pb);
+ put_bits(&s->pb, 32, header);
+}
+
+/* put sequence header if needed */
+static void mpeg1_encode_sequence_header(MpegEncContext *s)
+{
+ unsigned int vbv_buffer_size;
+ unsigned int fps, n, v;
+ UINT64 time_code;
+
+ if ((s->picture_number % s->gop_size) == 0) {
+ /* mpeg1 header repeated every gop */
+ put_header(s, SEQ_START_CODE);
+
+ /* search closest frame rate */
+ {
+ int i, dmin, d;
+ s->frame_rate_index = 0;
+ dmin = 0x7fffffff;
+ for(i=1;i<9;i++) {
+ d = abs(s->frame_rate - frame_rate_tab[i]);
+ if (d < dmin) {
+ dmin = d;
+ s->frame_rate_index = i;
+ }
+ }
+ }
+
+ put_bits(&s->pb, 12, s->width);
+ put_bits(&s->pb, 12, s->height);
+ put_bits(&s->pb, 4, 1); /* 1/1 aspect ratio */
+ put_bits(&s->pb, 4, s->frame_rate_index);
+ v = s->bit_rate / 400;
+ if (v > 0x3ffff)
+ v = 0x3ffff;
+ put_bits(&s->pb, 18, v);
+ put_bits(&s->pb, 1, 1); /* marker */
+ /* vbv buffer size: slightly greater than an I frame. We add
+ some margin just in case */
+ vbv_buffer_size = (3 * s->I_frame_bits) / (2 * 8);
+ put_bits(&s->pb, 10, (vbv_buffer_size + 16383) / 16384);
+ put_bits(&s->pb, 1, 1); /* constrained parameter flag */
+ put_bits(&s->pb, 1, 0); /* no custom intra matrix */
+ put_bits(&s->pb, 1, 0); /* no custom non intra matrix */
+
+ put_header(s, GOP_START_CODE);
+ put_bits(&s->pb, 1, 0); /* do drop frame */
+ /* time code : we must convert from the real frame rate to a
+ fake mpeg frame rate in case of low frame rate */
+ fps = frame_rate_tab[s->frame_rate_index];
+ time_code = s->fake_picture_number * FRAME_RATE_BASE;
+ s->gop_picture_number = s->fake_picture_number;
+ put_bits(&s->pb, 5, (time_code / (fps * 3600)) % 24);
+ put_bits(&s->pb, 6, (time_code / (fps * 60)) % 60);
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, 6, (time_code / fps) % 60);
+ put_bits(&s->pb, 6, (time_code % fps) / FRAME_RATE_BASE);
+ put_bits(&s->pb, 1, 1); /* closed gop */
+ put_bits(&s->pb, 1, 0); /* broken link */
+ }
+
+ if (s->frame_rate < (24 * FRAME_RATE_BASE) && s->picture_number > 0) {
+ /* insert empty P pictures to slow down to the desired
+ frame rate. Each fake pictures takes about 20 bytes */
+ fps = frame_rate_tab[s->frame_rate_index];
+ n = ((s->picture_number * fps) / s->frame_rate) - 1;
+ while (s->fake_picture_number < n) {
+ mpeg1_skip_picture(s, s->fake_picture_number -
+ s->gop_picture_number);
+ s->fake_picture_number++;
+ }
+
+ }
+ s->fake_picture_number++;
+}
+
+
+/* insert a fake P picture */
+static void mpeg1_skip_picture(MpegEncContext *s, int pict_num)
+{
+ unsigned int mb_incr;
+
+ /* mpeg1 picture header */
+ put_header(s, PICTURE_START_CODE);
+ /* temporal reference */
+ put_bits(&s->pb, 10, pict_num & 0x3ff);
+
+ put_bits(&s->pb, 3, P_TYPE);
+ put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */
+
+ put_bits(&s->pb, 1, 1); /* integer coordinates */
+ put_bits(&s->pb, 3, 1); /* forward_f_code */
+
+ put_bits(&s->pb, 1, 0); /* extra bit picture */
+
+ /* only one slice */
+ put_header(s, SLICE_MIN_START_CODE);
+ put_bits(&s->pb, 5, 1); /* quantizer scale */
+ put_bits(&s->pb, 1, 0); /* slice extra information */
+
+ mb_incr = 1;
+ put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1],
+ mbAddrIncrTable[mb_incr - 1][0]);
+
+ /* empty macroblock */
+ put_bits(&s->pb, 3, 1); /* motion only */
+
+ /* zero motion x & y */
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, 1, 1);
+
+ /* output a number of empty slice */
+ mb_incr = s->mb_width * s->mb_height - 1;
+ while (mb_incr > 33) {
+ put_bits(&s->pb, 11, 0x008);
+ mb_incr -= 33;
+ }
+ put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1],
+ mbAddrIncrTable[mb_incr - 1][0]);
+
+ /* empty macroblock */
+ put_bits(&s->pb, 3, 1); /* motion only */
+
+ /* zero motion x & y */
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, 1, 1);
+}
+
+void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
+{
+ static int done;
+
+ if (!done) {
+ done = 1;
+ init_rl(&rl_mpeg1);
+ }
+ mpeg1_encode_sequence_header(s);
+
+ /* mpeg1 picture header */
+ put_header(s, PICTURE_START_CODE);
+ /* temporal reference */
+ put_bits(&s->pb, 10, (s->fake_picture_number -
+ s->gop_picture_number) & 0x3ff);
+
+ put_bits(&s->pb, 3, s->pict_type);
+ put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */
+
+ if (s->pict_type == P_TYPE) {
+ put_bits(&s->pb, 1, 0); /* half pel coordinates */
+ put_bits(&s->pb, 3, s->f_code); /* forward_f_code */
+ }
+
+ put_bits(&s->pb, 1, 0); /* extra bit picture */
+
+ /* only one slice */
+ put_header(s, SLICE_MIN_START_CODE);
+ put_bits(&s->pb, 5, s->qscale); /* quantizer scale */
+ put_bits(&s->pb, 1, 0); /* slice extra information */
+}
+
+void mpeg1_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y)
+{
+ int mb_incr, i, cbp, mb_x, mb_y;
+
+ mb_x = s->mb_x;
+ mb_y = s->mb_y;
+
+ /* compute cbp */
+ cbp = 0;
+ for(i=0;i<6;i++) {
+ if (s->block_last_index[i] >= 0)
+ cbp |= 1 << (5 - i);
+ }
+
+ /* skip macroblock, except if first or last macroblock of a slice */
+ if ((cbp | motion_x | motion_y) == 0 &&
+ (!((mb_x | mb_y) == 0 ||
+ (mb_x == s->mb_width - 1 && mb_y == s->mb_height - 1)))) {
+ s->mb_incr++;
+ } else {
+ /* output mb incr */
+ mb_incr = s->mb_incr;
+
+ while (mb_incr > 33) {
+ put_bits(&s->pb, 11, 0x008);
+ mb_incr -= 33;
+ }
+ put_bits(&s->pb, mbAddrIncrTable[mb_incr - 1][1],
+ mbAddrIncrTable[mb_incr - 1][0]);
+
+ if (s->pict_type == I_TYPE) {
+ put_bits(&s->pb, 1, 1); /* macroblock_type : macroblock_quant = 0 */
+ } else {
+ if (s->mb_intra) {
+ put_bits(&s->pb, 5, 0x03);
+ } else {
+ if (cbp != 0) {
+ if (motion_x == 0 && motion_y == 0) {
+ put_bits(&s->pb, 2, 1); /* macroblock_pattern only */
+ put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]);
+ } else {
+ put_bits(&s->pb, 1, 1); /* motion + cbp */
+ mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0]);
+ mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1]);
+ put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]);
+ }
+ } else {
+ put_bits(&s->pb, 3, 1); /* motion only */
+ mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0]);
+ mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1]);
+ }
+ }
+ }
+ for(i=0;i<6;i++) {
+ if (cbp & (1 << (5 - i))) {
+ mpeg1_encode_block(s, block[i], i);
+ }
+ }
+ s->mb_incr = 1;
+ }
+ s->last_mv[0][0][0] = motion_x;
+ s->last_mv[0][0][1] = motion_y;
+}
+
+static void mpeg1_encode_motion(MpegEncContext *s, int val)
+{
+ int code, bit_size, l, m, bits, range, sign;
+
+ if (val == 0) {
+ /* zero vector */
+ code = 0;
+ put_bits(&s->pb,
+ mbMotionVectorTable[0][1],
+ mbMotionVectorTable[0][0]);
+ } else {
+ bit_size = s->f_code - 1;
+ range = 1 << bit_size;
+ /* modulo encoding */
+ l = 16 * range;
+ m = 2 * l;
+ if (val < -l) {
+ val += m;
+ } else if (val >= l) {
+ val -= m;
+ }
+
+ if (val >= 0) {
+ val--;
+ code = (val >> bit_size) + 1;
+ bits = val & (range - 1);
+ sign = 0;
+ } else {
+ val = -val;
+ val--;
+ code = (val >> bit_size) + 1;
+ bits = val & (range - 1);
+ sign = 1;
+ }
+ put_bits(&s->pb,
+ mbMotionVectorTable[code][1],
+ mbMotionVectorTable[code][0]);
+ put_bits(&s->pb, 1, sign);
+ if (bit_size > 0) {
+ put_bits(&s->pb, bit_size, bits);
+ }
+ }
+}
+
+static inline void encode_dc(MpegEncContext *s, int diff, int component)
+{
+ int adiff, index;
+
+ adiff = abs(diff);
+ index = vlc_dc_table[adiff];
+ if (component == 0) {
+ put_bits(&s->pb, vlc_dc_lum_bits[index], vlc_dc_lum_code[index]);
+ } else {
+ put_bits(&s->pb, vlc_dc_chroma_bits[index], vlc_dc_chroma_code[index]);
+ }
+ if (diff > 0) {
+ put_bits(&s->pb, index, (diff & ((1 << index) - 1)));
+ } else if (diff < 0) {
+ put_bits(&s->pb, index, ((diff - 1) & ((1 << index) - 1)));
+ }
+}
+
+static void mpeg1_encode_block(MpegEncContext *s,
+ DCTELEM *block,
+ int n)
+{
+ int alevel, level, last_non_zero, dc, diff, i, j, run, last_index, sign;
+ int code, component;
+ RLTable *rl = &rl_mpeg1;
+
+ last_index = s->block_last_index[n];
+
+ /* DC coef */
+ if (s->mb_intra) {
+ component = (n <= 3 ? 0 : n - 4 + 1);
+ dc = block[0]; /* overflow is impossible */
+ diff = dc - s->last_dc[component];
+ encode_dc(s, diff, component);
+ s->last_dc[component] = dc;
+ i = 1;
+ } else {
+ /* encode the first coefficient : needs to be done here because
+ it is handled slightly differently */
+ level = block[0];
+ if (abs(level) == 1) {
+ code = ((UINT32)level >> 31); /* the sign bit */
+ put_bits(&s->pb, 2, code | 0x02);
+ i = 1;
+ } else {
+ i = 0;
+ last_non_zero = -1;
+ goto next_coef;
+ }
+ }
+
+ /* now quantify & encode AC coefs */
+ last_non_zero = i - 1;
+ for(;i<=last_index;i++) {
+ j = zigzag_direct[i];
+ level = block[j];
+ next_coef:
+#if 0
+ if (level != 0)
+ dprintf("level[%d]=%d\n", i, level);
+#endif
+ /* encode using VLC */
+ if (level != 0) {
+ run = i - last_non_zero - 1;
+ sign = 0;
+ alevel = level;
+ if (alevel < 0) {
+ sign = 1;
+ alevel = -alevel;
+ }
+ code = get_rl_index(rl, 0, run, alevel);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ if (code != rl->n) {
+ put_bits(&s->pb, 1, sign);
+ } else {
+ /* escape: only clip in this case */
+ put_bits(&s->pb, 6, run);
+ if (alevel < 128) {
+ put_bits(&s->pb, 8, level & 0xff);
+ } else {
+ if (level < 0) {
+ put_bits(&s->pb, 16, 0x8001 + level + 255);
+ } else {
+ put_bits(&s->pb, 16, level & 0xffff);
+ }
+ }
+ }
+ last_non_zero = i;
+ }
+ }
+ /* end of block */
+ put_bits(&s->pb, 2, 0x2);
+}
+
+/******************************************/
+/* decoding */
+
+static VLC dc_lum_vlc;
+static VLC dc_chroma_vlc;
+static VLC mv_vlc;
+static VLC mbincr_vlc;
+static VLC mb_ptype_vlc;
+static VLC mb_btype_vlc;
+static VLC mb_pat_vlc;
+
+void mpeg1_init_vlc(MpegEncContext *s)
+{
+ static int done = 0;
+
+ if (!done) {
+
+ init_vlc(&dc_lum_vlc, 9, 12,
+ vlc_dc_lum_bits, 1, 1,
+ vlc_dc_lum_code, 2, 2);
+ init_vlc(&dc_chroma_vlc, 9, 12,
+ vlc_dc_chroma_bits, 1, 1,
+ vlc_dc_chroma_code, 2, 2);
+ init_vlc(&mv_vlc, 9, 17,
+ &mbMotionVectorTable[0][1], 2, 1,
+ &mbMotionVectorTable[0][0], 2, 1);
+ init_vlc(&mbincr_vlc, 9, 34,
+ &mbAddrIncrTable[0][1], 2, 1,
+ &mbAddrIncrTable[0][0], 2, 1);
+ init_vlc(&mb_pat_vlc, 9, 63,
+ &mbPatTable[0][1], 2, 1,
+ &mbPatTable[0][0], 2, 1);
+
+ init_vlc(&mb_ptype_vlc, 6, 32,
+ &table_mb_ptype[0][1], 2, 1,
+ &table_mb_ptype[0][0], 2, 1);
+ init_vlc(&mb_btype_vlc, 6, 32,
+ &table_mb_btype[0][1], 2, 1,
+ &table_mb_btype[0][0], 2, 1);
+ init_rl(&rl_mpeg1);
+ init_rl(&rl_mpeg2);
+ /* cannot use generic init because we must add the EOB code */
+ init_vlc(&rl_mpeg1.vlc, 9, rl_mpeg1.n + 2,
+ &rl_mpeg1.table_vlc[0][1], 4, 2,
+ &rl_mpeg1.table_vlc[0][0], 4, 2);
+ init_vlc(&rl_mpeg2.vlc, 9, rl_mpeg2.n + 2,
+ &rl_mpeg2.table_vlc[0][1], 4, 2,
+ &rl_mpeg2.table_vlc[0][0], 4, 2);
+ }
+}
+
+static inline int get_dmv(MpegEncContext *s)
+{
+ if(get_bits(&s->gb, 1))
+ return 1 - (get_bits(&s->gb, 1) << 1);
+ else
+ return 0;
+}
+
+/* motion type (for mpeg2) */
+#define MT_FIELD 1
+#define MT_FRAME 2
+#define MT_16X8 2
+#define MT_DMV 3
+
+static int mpeg_decode_mb(MpegEncContext *s,
+ DCTELEM block[6][64])
+{
+ int i, j, k, cbp, val, code, mb_type, motion_type;
+
+ /* skip mb handling */
+ if (s->mb_incr == 0) {
+ /* read again increment */
+ s->mb_incr = 1;
+ for(;;) {
+ code = get_vlc(&s->gb, &mbincr_vlc);
+ if (code < 0)
+ return 1; /* error = end of slice */
+ if (code >= 33) {
+ if (code == 33) {
+ s->mb_incr += 33;
+ }
+ /* otherwise, stuffing, nothing to do */
+ } else {
+ s->mb_incr += code;
+ break;
+ }
+ }
+ }
+ if (++s->mb_x >= s->mb_width) {
+ s->mb_x = 0;
+ if (s->mb_y >= (s->mb_height - 1))
+ return -1;
+ s->mb_y++;
+ }
+ dprintf("decode_mb: x=%d y=%d\n", s->mb_x, s->mb_y);
+
+ if (--s->mb_incr != 0) {
+ /* skip mb */
+ s->mb_intra = 0;
+ for(i=0;i<6;i++)
+ s->block_last_index[i] = -1;
+ s->mv_type = MV_TYPE_16X16;
+ if (s->pict_type == P_TYPE) {
+ /* if P type, zero motion vector is implied */
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv[0][0][0] = s->mv[0][0][1] = 0;
+ s->last_mv[0][0][0] = s->last_mv[0][0][1] = 0;
+ } else {
+ /* if B type, reuse previous vectors and directions */
+ s->mv[0][0][0] = s->last_mv[0][0][0];
+ s->mv[0][0][1] = s->last_mv[0][0][1];
+ s->mv[1][0][0] = s->last_mv[1][0][0];
+ s->mv[1][0][1] = s->last_mv[1][0][1];
+ }
+ return 0;
+ }
+
+ switch(s->pict_type) {
+ default:
+ case I_TYPE:
+ if (get_bits(&s->gb, 1) == 0) {
+ if (get_bits(&s->gb, 1) == 0)
+ return -1;
+ mb_type = MB_QUANT | MB_INTRA;
+ } else {
+ mb_type = MB_INTRA;
+ }
+ break;
+ case P_TYPE:
+ mb_type = get_vlc(&s->gb, &mb_ptype_vlc);
+ if (mb_type < 0)
+ return -1;
+ break;
+ case B_TYPE:
+ mb_type = get_vlc(&s->gb, &mb_btype_vlc);
+ if (mb_type < 0)
+ return -1;
+ break;
+ }
+ dprintf("mb_type=%x\n", mb_type);
+ motion_type = 0; /* avoid warning */
+ if (mb_type & (MB_FOR|MB_BACK)) {
+ /* get additionnal motion vector type */
+ if (s->picture_structure == PICT_FRAME && s->frame_pred_frame_dct)
+ motion_type = MT_FRAME;
+ else
+ motion_type = get_bits(&s->gb, 2);
+ }
+ /* compute dct type */
+ if (s->picture_structure == PICT_FRAME &&
+ !s->frame_pred_frame_dct &&
+ (mb_type & (MB_PAT | MB_INTRA))) {
+ s->interlaced_dct = get_bits(&s->gb, 1);
+#ifdef DEBUG
+ if (s->interlaced_dct)
+ printf("interlaced_dct\n");
+#endif
+ } else {
+ s->interlaced_dct = 0; /* frame based */
+ }
+
+ if (mb_type & MB_QUANT) {
+ if (s->mpeg2) {
+ if (s->q_scale_type) {
+ s->qscale = non_linear_qscale[get_bits(&s->gb, 5)];
+ } else {
+ s->qscale = get_bits(&s->gb, 5) << 1;
+ }
+ } else {
+ /* for mpeg1, we use the generic unquant code */
+ s->qscale = get_bits(&s->gb, 5);
+ }
+ }
+ if (mb_type & MB_INTRA) {
+ if (s->concealment_motion_vectors) {
+ /* just parse them */
+ if (s->picture_structure != PICT_FRAME)
+ get_bits(&s->gb, 1); /* field select */
+ mpeg_decode_motion(s, s->mpeg_f_code[0][0], 0);
+ mpeg_decode_motion(s, s->mpeg_f_code[0][1], 0);
+ }
+ s->mb_intra = 1;
+ cbp = 0x3f;
+ memset(s->last_mv, 0, sizeof(s->last_mv)); /* reset mv prediction */
+ } else {
+ s->mb_intra = 0;
+ cbp = 0;
+ }
+ /* special case of implicit zero motion vector */
+ if (s->pict_type == P_TYPE && !(mb_type & MB_FOR)) {
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ s->last_mv[0][0][0] = 0;
+ s->last_mv[0][0][1] = 0;
+ s->mv[0][0][0] = 0;
+ s->mv[0][0][1] = 0;
+ } else if (mb_type & (MB_FOR | MB_BACK)) {
+ /* motion vectors */
+ s->mv_dir = 0;
+ for(i=0;i<2;i++) {
+ if (mb_type & (MB_FOR >> i)) {
+ s->mv_dir |= (MV_DIR_FORWARD >> i);
+ dprintf("mv_type=%d\n", motion_type);
+ switch(motion_type) {
+ case MT_FRAME: /* or MT_16X8 */
+ if (s->picture_structure == PICT_FRAME) {
+ /* MT_FRAME */
+ s->mv_type = MV_TYPE_16X16;
+ for(k=0;k<2;k++) {
+ val = mpeg_decode_motion(s, s->mpeg_f_code[i][k],
+ s->last_mv[i][0][k]);
+ s->last_mv[i][0][k] = val;
+ s->last_mv[i][1][k] = val;
+ /* full_pel: only for mpeg1 */
+ if (s->full_pel[i])
+ val = val << 1;
+ s->mv[i][0][k] = val;
+ dprintf("mv%d: %d\n", k, val);
+ }
+ } else {
+ /* MT_16X8 */
+ s->mv_type = MV_TYPE_16X8;
+ for(j=0;j<2;j++) {
+ s->field_select[i][j] = get_bits(&s->gb, 1);
+ for(k=0;k<2;k++) {
+ val = mpeg_decode_motion(s, s->mpeg_f_code[i][k],
+ s->last_mv[i][j][k]);
+ s->last_mv[i][j][k] = val;
+ s->mv[i][j][k] = val;
+ }
+ }
+ }
+ break;
+ case MT_FIELD:
+ if (s->picture_structure == PICT_FRAME) {
+ s->mv_type = MV_TYPE_FIELD;
+ for(j=0;j<2;j++) {
+ s->field_select[i][j] = get_bits(&s->gb, 1);
+ val = mpeg_decode_motion(s, s->mpeg_f_code[i][0],
+ s->last_mv[i][j][0]);
+ s->last_mv[i][j][0] = val;
+ s->mv[i][j][0] = val;
+ dprintf("fmx=%d\n", val);
+ val = mpeg_decode_motion(s, s->mpeg_f_code[i][1],
+ s->last_mv[i][j][1] >> 1);
+ s->last_mv[i][j][1] = val << 1;
+ s->mv[i][j][1] = val;
+ dprintf("fmy=%d\n", val);
+ }
+ } else {
+ s->mv_type = MV_TYPE_16X16;
+ s->field_select[i][0] = get_bits(&s->gb, 1);
+ for(k=0;k<2;k++) {
+ val = mpeg_decode_motion(s, s->mpeg_f_code[i][k],
+ s->last_mv[i][0][k]);
+ s->last_mv[i][0][k] = val;
+ s->last_mv[i][1][k] = val;
+ s->mv[i][0][k] = val;
+ }
+ }
+ break;
+ case MT_DMV:
+ {
+ int dmx, dmy, mx, my, m;
+
+ mx = mpeg_decode_motion(s, s->mpeg_f_code[i][0],
+ s->last_mv[i][0][0]);
+ s->last_mv[i][0][0] = mx;
+ s->last_mv[i][1][0] = mx;
+ dmx = get_dmv(s);
+ my = mpeg_decode_motion(s, s->mpeg_f_code[i][1],
+ s->last_mv[i][0][1] >> 1);
+ dmy = get_dmv(s);
+ s->mv_type = MV_TYPE_DMV;
+ /* XXX: totally broken */
+ if (s->picture_structure == PICT_FRAME) {
+ s->last_mv[i][0][1] = my << 1;
+ s->last_mv[i][1][1] = my << 1;
+
+ m = s->top_field_first ? 1 : 3;
+ /* top -> top pred */
+ s->mv[i][0][0] = mx;
+ s->mv[i][0][1] = my << 1;
+ s->mv[i][1][0] = ((mx * m + (mx > 0)) >> 1) + dmx;
+ s->mv[i][1][1] = ((my * m + (my > 0)) >> 1) + dmy - 1;
+ m = 4 - m;
+ s->mv[i][2][0] = mx;
+ s->mv[i][2][1] = my << 1;
+ s->mv[i][3][0] = ((mx * m + (mx > 0)) >> 1) + dmx;
+ s->mv[i][3][1] = ((my * m + (my > 0)) >> 1) + dmy + 1;
+ } else {
+ s->last_mv[i][0][1] = my;
+ s->last_mv[i][1][1] = my;
+ s->mv[i][0][0] = mx;
+ s->mv[i][0][1] = my;
+ s->mv[i][1][0] = ((mx + (mx > 0)) >> 1) + dmx;
+ s->mv[i][1][1] = ((my + (my > 0)) >> 1) + dmy - 1
+ /* + 2 * cur_field */;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if ((mb_type & MB_INTRA) && s->concealment_motion_vectors) {
+ get_bits(&s->gb, 1); /* marker */
+ }
+
+ if (mb_type & MB_PAT) {
+ cbp = get_vlc(&s->gb, &mb_pat_vlc);
+ if (cbp < 0)
+ return -1;
+ cbp++;
+ }
+ dprintf("cbp=%x\n", cbp);
+
+ if (s->mpeg2) {
+ if (s->mb_intra) {
+ for(i=0;i<6;i++) {
+ if (cbp & (1 << (5 - i))) {
+ if (mpeg2_decode_block_intra(s, block[i], i) < 0)
+ return -1;
+ }
+ }
+ } else {
+ for(i=0;i<6;i++) {
+ if (cbp & (1 << (5 - i))) {
+ if (mpeg2_decode_block_non_intra(s, block[i], i) < 0)
+ return -1;
+ }
+ }
+ }
+ } else {
+ for(i=0;i<6;i++) {
+ if (cbp & (1 << (5 - i))) {
+ if (mpeg1_decode_block(s, block[i], i) < 0)
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* as h263, but only 17 codes */
+static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred)
+{
+ int code, sign, val, m, l, shift;
+
+ code = get_vlc(&s->gb, &mv_vlc);
+ if (code < 0) {
+ return 0xffff;
+ }
+ if (code == 0) {
+ return pred;
+ }
+ sign = get_bits(&s->gb, 1);
+ shift = fcode - 1;
+ val = (code - 1) << shift;
+ if (shift > 0)
+ val |= get_bits(&s->gb, shift);
+ val++;
+ if (sign)
+ val = -val;
+ val += pred;
+
+ /* modulo decoding */
+ l = (1 << shift) * 16;
+ m = 2 * l;
+ if (val < -l) {
+ val += m;
+ } else if (val >= l) {
+ val -= m;
+ }
+ return val;
+}
+
+static inline int decode_dc(MpegEncContext *s, int component)
+{
+ int code, diff;
+
+ if (component == 0) {
+ code = get_vlc(&s->gb, &dc_lum_vlc);
+ } else {
+ code = get_vlc(&s->gb, &dc_chroma_vlc);
+ }
+ if (code < 0)
+ return 0xffff;
+ if (code == 0) {
+ diff = 0;
+ } else {
+ diff = get_bits(&s->gb, code);
+ if ((diff & (1 << (code - 1))) == 0)
+ diff = (-1 << code) | (diff + 1);
+ }
+ return diff;
+}
+
+static int mpeg1_decode_block(MpegEncContext *s,
+ DCTELEM *block,
+ int n)
+{
+ int level, dc, diff, i, j, run;
+ int code, component;
+ RLTable *rl = &rl_mpeg1;
+
+ if (s->mb_intra) {
+ /* DC coef */
+ component = (n <= 3 ? 0 : n - 4 + 1);
+ diff = decode_dc(s, component);
+ if (diff >= 0xffff)
+ return -1;
+ dc = s->last_dc[component];
+ dc += diff;
+ s->last_dc[component] = dc;
+ block[0] = dc;
+ dprintf("dc=%d diff=%d\n", dc, diff);
+ i = 1;
+ } else {
+ int bit_cnt, v;
+ UINT32 bit_buf;
+ UINT8 *buf_ptr;
+ i = 0;
+ /* special case for the first coef. no need to add a second vlc table */
+ SAVE_BITS(&s->gb);
+ SHOW_BITS(&s->gb, v, 2);
+ if (v & 2) {
+ run = 0;
+ level = 1 - ((v & 1) << 1);
+ FLUSH_BITS(2);
+ RESTORE_BITS(&s->gb);
+ goto add_coef;
+ }
+ RESTORE_BITS(&s->gb);
+ }
+
+ /* now quantify & encode AC coefs */
+ for(;;) {
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0) {
+ return -1;
+ }
+ if (code == 112) {
+ break;
+ } else if (code == 111) {
+ /* escape */
+ run = get_bits(&s->gb, 6);
+ level = get_bits(&s->gb, 8);
+ level = (level << 24) >> 24;
+ if (level == -128) {
+ level = get_bits(&s->gb, 8) - 256;
+ } else if (level == 0) {
+ level = get_bits(&s->gb, 8);
+ }
+ } else {
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ i += run;
+ if (i >= 64)
+ return -1;
+ add_coef:
+ dprintf("%d: run=%d level=%d\n", n, run, level);
+ j = zigzag_direct[i];
+ block[j] = level;
+ i++;
+ }
+ s->block_last_index[n] = i;
+ return 0;
+}
+
+/* Also does unquantization here, since I will never support mpeg2
+ encoding */
+static int mpeg2_decode_block_non_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n)
+{
+ int level, i, j, run;
+ int code;
+ RLTable *rl = &rl_mpeg1;
+ const UINT8 *scan_table;
+ const UINT16 *matrix;
+ int mismatch;
+
+ if (s->alternate_scan)
+ scan_table = ff_alternate_vertical_scan;
+ else
+ scan_table = zigzag_direct;
+ mismatch = 1;
+
+ {
+ int bit_cnt, v;
+ UINT32 bit_buf;
+ UINT8 *buf_ptr;
+ i = 0;
+ if (n < 4)
+ matrix = s->non_intra_matrix;
+ else
+ matrix = s->chroma_non_intra_matrix;
+
+ /* special case for the first coef. no need to add a second vlc table */
+ SAVE_BITS(&s->gb);
+ SHOW_BITS(&s->gb, v, 2);
+ if (v & 2) {
+ run = 0;
+ level = 1 - ((v & 1) << 1);
+ FLUSH_BITS(2);
+ RESTORE_BITS(&s->gb);
+ goto add_coef;
+ }
+ RESTORE_BITS(&s->gb);
+ }
+
+ /* now quantify & encode AC coefs */
+ for(;;) {
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0)
+ return -1;
+ if (code == 112) {
+ break;
+ } else if (code == 111) {
+ /* escape */
+ run = get_bits(&s->gb, 6);
+ level = get_bits(&s->gb, 12);
+ level = (level << 20) >> 20;
+ } else {
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ i += run;
+ if (i >= 64)
+ return -1;
+ add_coef:
+ j = scan_table[i];
+ dprintf("%d: run=%d level=%d\n", n, run, level);
+ level = ((level * 2 + 1) * s->qscale * matrix[j]) / 32;
+ /* XXX: is it really necessary to saturate since the encoder
+ knows whats going on ? */
+ mismatch ^= level;
+ block[j] = level;
+ i++;
+ }
+ block[63] ^= (mismatch & 1);
+ s->block_last_index[n] = i;
+ return 0;
+}
+
+static int mpeg2_decode_block_intra(MpegEncContext *s,
+ DCTELEM *block,
+ int n)
+{
+ int level, dc, diff, i, j, run;
+ int code, component;
+ RLTable *rl;
+ const UINT8 *scan_table;
+ const UINT16 *matrix;
+ int mismatch;
+
+ if (s->alternate_scan)
+ scan_table = ff_alternate_vertical_scan;
+ else
+ scan_table = zigzag_direct;
+ mismatch = 1;
+
+ /* DC coef */
+ component = (n <= 3 ? 0 : n - 4 + 1);
+ diff = decode_dc(s, component);
+ if (diff >= 0xffff)
+ return -1;
+ dc = s->last_dc[component];
+ dc += diff;
+ s->last_dc[component] = dc;
+ block[0] = dc << (3 - s->intra_dc_precision);
+ dprintf("dc=%d\n", block[0]);
+ i = 1;
+ if (s->intra_vlc_format)
+ rl = &rl_mpeg2;
+ else
+ rl = &rl_mpeg1;
+ if (n < 4)
+ matrix = s->intra_matrix;
+ else
+ matrix = s->chroma_intra_matrix;
+
+ /* now quantify & encode AC coefs */
+ for(;;) {
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0)
+ return -1;
+ if (code == 112) {
+ break;
+ } else if (code == 111) {
+ /* escape */
+ run = get_bits(&s->gb, 6);
+ level = get_bits(&s->gb, 12);
+ level = (level << 20) >> 20;
+ } else {
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ i += run;
+ if (i >= 64)
+ return -1;
+ j = scan_table[i];
+ dprintf("%d: run=%d level=%d\n", n, run, level);
+ level = (level * s->qscale * matrix[j]) / 16;
+ /* XXX: is it really necessary to saturate since the encoder
+ knows whats going on ? */
+ mismatch ^= level;
+ block[j] = level;
+ i++;
+ }
+ block[63] ^= (mismatch & 1);
+ s->block_last_index[n] = i;
+ return 0;
+}
+
+/* compressed picture size */
+#define PICTURE_BUFFER_SIZE 100000
+
+typedef struct Mpeg1Context {
+ MpegEncContext mpeg_enc_ctx;
+ UINT32 header_state;
+ int start_code; /* current start code */
+ UINT8 buffer[PICTURE_BUFFER_SIZE];
+ UINT8 *buf_ptr;
+ int buffer_size;
+ int mpeg_enc_ctx_allocated; /* true if decoding context allocated */
+} Mpeg1Context;
+
+static int mpeg_decode_init(AVCodecContext *avctx)
+{
+ Mpeg1Context *s = avctx->priv_data;
+
+ s->header_state = 0xff;
+ s->mpeg_enc_ctx_allocated = 0;
+ s->buffer_size = PICTURE_BUFFER_SIZE;
+ s->start_code = -1;
+ s->buf_ptr = s->buffer;
+ s->mpeg_enc_ctx.picture_number = 0;
+ return 0;
+}
+
+/* return the 8 bit start code value and update the search
+ state. Return -1 if no start code found */
+static int find_start_code(UINT8 **pbuf_ptr, UINT8 *buf_end,
+ UINT32 *header_state)
+{
+ UINT8 *buf_ptr;
+ unsigned int state, v;
+ int val;
+
+ state = *header_state;
+ buf_ptr = *pbuf_ptr;
+ while (buf_ptr < buf_end) {
+ v = *buf_ptr++;
+ if (state == 0x000001) {
+ state = ((state << 8) | v) & 0xffffff;
+ val = state;
+ goto found;
+ }
+ state = ((state << 8) | v) & 0xffffff;
+ }
+ val = -1;
+ found:
+ *pbuf_ptr = buf_ptr;
+ *header_state = state;
+ return val;
+}
+
+static int mpeg1_decode_picture(AVCodecContext *avctx,
+ UINT8 *buf, int buf_size)
+{
+ Mpeg1Context *s1 = avctx->priv_data;
+ MpegEncContext *s = &s1->mpeg_enc_ctx;
+ int ref, f_code;
+
+ init_get_bits(&s->gb, buf, buf_size);
+
+ ref = get_bits(&s->gb, 10); /* temporal ref */
+ s->pict_type = get_bits(&s->gb, 3);
+ dprintf("pict_type=%d\n", s->pict_type);
+ get_bits(&s->gb, 16);
+ if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) {
+ s->full_pel[0] = get_bits(&s->gb, 1);
+ f_code = get_bits(&s->gb, 3);
+ if (f_code == 0)
+ return -1;
+ s->mpeg_f_code[0][0] = f_code;
+ s->mpeg_f_code[0][1] = f_code;
+ }
+ if (s->pict_type == B_TYPE) {
+ s->full_pel[1] = get_bits(&s->gb, 1);
+ f_code = get_bits(&s->gb, 3);
+ if (f_code == 0)
+ return -1;
+ s->mpeg_f_code[1][0] = f_code;
+ s->mpeg_f_code[1][1] = f_code;
+ }
+ s->y_dc_scale = 8;
+ s->c_dc_scale = 8;
+ s->first_slice = 1;
+ return 0;
+}
+
+static void mpeg_decode_sequence_extension(MpegEncContext *s)
+{
+ int horiz_size_ext, vert_size_ext;
+ int bit_rate_ext, vbv_buf_ext, low_delay;
+ int frame_rate_ext_n, frame_rate_ext_d;
+
+ get_bits(&s->gb, 8); /* profil and level */
+ get_bits(&s->gb, 1); /* progressive_sequence */
+ get_bits(&s->gb, 2); /* chroma_format */
+ horiz_size_ext = get_bits(&s->gb, 2);
+ vert_size_ext = get_bits(&s->gb, 2);
+ s->width |= (horiz_size_ext << 12);
+ s->height |= (vert_size_ext << 12);
+ bit_rate_ext = get_bits(&s->gb, 12); /* XXX: handle it */
+ s->bit_rate = ((s->bit_rate / 400) | (bit_rate_ext << 12)) * 400;
+ get_bits(&s->gb, 1); /* marker */
+ vbv_buf_ext = get_bits(&s->gb, 8);
+ low_delay = get_bits(&s->gb, 1);
+ frame_rate_ext_n = get_bits(&s->gb, 2);
+ frame_rate_ext_d = get_bits(&s->gb, 5);
+ if (frame_rate_ext_d >= 1)
+ s->frame_rate = (s->frame_rate * frame_rate_ext_n) / frame_rate_ext_d;
+ dprintf("sequence extension\n");
+ s->mpeg2 = 1;
+}
+
+static void mpeg_decode_quant_matrix_extension(MpegEncContext *s)
+{
+ int i, v;
+
+ if (get_bits(&s->gb, 1)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ s->intra_matrix[i] = v;
+ s->chroma_intra_matrix[i] = v;
+ }
+ }
+ if (get_bits(&s->gb, 1)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ s->non_intra_matrix[i] = v;
+ s->chroma_non_intra_matrix[i] = v;
+ }
+ }
+ if (get_bits(&s->gb, 1)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ s->chroma_intra_matrix[i] = v;
+ }
+ }
+ if (get_bits(&s->gb, 1)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ s->chroma_non_intra_matrix[i] = v;
+ }
+ }
+}
+
+static void mpeg_decode_picture_coding_extension(MpegEncContext *s)
+{
+ s->full_pel[0] = s->full_pel[1] = 0;
+ s->mpeg_f_code[0][0] = get_bits(&s->gb, 4);
+ s->mpeg_f_code[0][1] = get_bits(&s->gb, 4);
+ s->mpeg_f_code[1][0] = get_bits(&s->gb, 4);
+ s->mpeg_f_code[1][1] = get_bits(&s->gb, 4);
+ s->intra_dc_precision = get_bits(&s->gb, 2);
+ s->picture_structure = get_bits(&s->gb, 2);
+ s->top_field_first = get_bits(&s->gb, 1);
+ s->frame_pred_frame_dct = get_bits(&s->gb, 1);
+ s->concealment_motion_vectors = get_bits(&s->gb, 1);
+ s->q_scale_type = get_bits(&s->gb, 1);
+ s->intra_vlc_format = get_bits(&s->gb, 1);
+ s->alternate_scan = get_bits(&s->gb, 1);
+ s->repeat_first_field = get_bits(&s->gb, 1);
+ s->chroma_420_type = get_bits(&s->gb, 1);
+ s->progressive_frame = get_bits(&s->gb, 1);
+ /* composite display not parsed */
+ dprintf("dc_preci=%d\n", s->intra_dc_precision);
+ dprintf("pict_structure=%d\n", s->picture_structure);
+ dprintf("conceal=%d\n", s->concealment_motion_vectors);
+ dprintf("intrafmt=%d\n", s->intra_vlc_format);
+ dprintf("frame_pred_frame_dct=%d\n", s->frame_pred_frame_dct);
+}
+
+static void mpeg_decode_extension(AVCodecContext *avctx,
+ UINT8 *buf, int buf_size)
+{
+ Mpeg1Context *s1 = avctx->priv_data;
+ MpegEncContext *s = &s1->mpeg_enc_ctx;
+ int ext_type;
+
+ init_get_bits(&s->gb, buf, buf_size);
+
+ ext_type = get_bits(&s->gb, 4);
+ switch(ext_type) {
+ case 0x1:
+ /* sequence ext */
+ mpeg_decode_sequence_extension(s);
+ break;
+ case 0x3:
+ /* quant matrix extension */
+ mpeg_decode_quant_matrix_extension(s);
+ break;
+ case 0x8:
+ /* picture extension */
+ mpeg_decode_picture_coding_extension(s);
+ break;
+ }
+}
+
+/* return 1 if end of frame */
+static int mpeg_decode_slice(AVCodecContext *avctx,
+ AVPicture *pict,
+ int start_code,
+ UINT8 *buf, int buf_size)
+{
+ Mpeg1Context *s1 = avctx->priv_data;
+ MpegEncContext *s = &s1->mpeg_enc_ctx;
+ int ret;
+ DCTELEM block[6][64];
+
+ start_code = (start_code - 1) & 0xff;
+ if (start_code >= s->mb_height)
+ return -1;
+ s->last_dc[0] = 1 << (7 + s->intra_dc_precision);
+ s->last_dc[1] = s->last_dc[0];
+ s->last_dc[2] = s->last_dc[0];
+ memset(s->last_mv, 0, sizeof(s->last_mv));
+ s->mb_x = -1;
+ s->mb_y = start_code;
+ s->mb_incr = 0;
+
+ /* start frame decoding */
+ if (s->first_slice) {
+ s->first_slice = 0;
+ MPV_frame_start(s);
+ }
+
+ init_get_bits(&s->gb, buf, buf_size);
+
+ s->qscale = get_bits(&s->gb, 5);
+ /* extra slice info */
+ while (get_bits(&s->gb, 1) != 0) {
+ get_bits(&s->gb, 8);
+ }
+
+ for(;;) {
+ memset(block, 0, sizeof(block));
+ ret = mpeg_decode_mb(s, block);
+ dprintf("ret=%d\n", ret);
+ if (ret < 0)
+ return -1;
+ if (ret == 1)
+ break;
+ MPV_decode_mb(s, block);
+ }
+
+ /* end of slice reached */
+ if (s->mb_x == (s->mb_width - 1) &&
+ s->mb_y == (s->mb_height - 1)) {
+ /* end of image */
+ UINT8 **picture;
+
+ MPV_frame_end(s);
+
+ /* XXX: incorrect reported qscale for mpeg2 */
+ if (s->pict_type == B_TYPE) {
+ picture = s->current_picture;
+ avctx->quality = s->qscale;
+ } else {
+ /* latency of 1 frame for I and P frames */
+ /* XXX: use another variable than picture_number */
+ if (s->picture_number == 0) {
+ picture = NULL;
+ } else {
+ picture = s->last_picture;
+ avctx->quality = s->last_qscale;
+ }
+ s->last_qscale = s->qscale;
+ s->picture_number++;
+ }
+ if (picture) {
+ pict->data[0] = picture[0];
+ pict->data[1] = picture[1];
+ pict->data[2] = picture[2];
+ pict->linesize[0] = s->linesize;
+ pict->linesize[1] = s->linesize / 2;
+ pict->linesize[2] = s->linesize / 2;
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+}
+
+static int mpeg1_decode_sequence(AVCodecContext *avctx,
+ UINT8 *buf, int buf_size)
+{
+ Mpeg1Context *s1 = avctx->priv_data;
+ MpegEncContext *s = &s1->mpeg_enc_ctx;
+ int width, height, i, v;
+
+ init_get_bits(&s->gb, buf, buf_size);
+
+ width = get_bits(&s->gb, 12);
+ height = get_bits(&s->gb, 12);
+ get_bits(&s->gb, 4);
+ s->frame_rate_index = get_bits(&s->gb, 4);
+ if (s->frame_rate_index == 0)
+ return -1;
+ s->bit_rate = get_bits(&s->gb, 18) * 400;
+ if (get_bits(&s->gb, 1) == 0) /* marker */
+ return -1;
+ if (width <= 0 || height <= 0 ||
+ (width % 2) != 0 || (height % 2) != 0)
+ return -1;
+ if (width != s->width ||
+ height != s->height) {
+ /* start new mpeg1 context decoding */
+ s->out_format = FMT_MPEG1;
+ if (s1->mpeg_enc_ctx_allocated) {
+ MPV_common_end(s);
+ }
+ s->width = width;
+ s->height = height;
+ s->has_b_frames = 1;
+ avctx->width = width;
+ avctx->height = height;
+ avctx->frame_rate = frame_rate_tab[s->frame_rate_index];
+ avctx->bit_rate = s->bit_rate;
+
+ if (MPV_common_init(s) < 0)
+ return -1;
+ mpeg1_init_vlc(s);
+ s1->mpeg_enc_ctx_allocated = 1;
+ }
+
+ get_bits(&s->gb, 10); /* vbv_buffer_size */
+ get_bits(&s->gb, 1);
+
+ /* get matrix */
+ if (get_bits(&s->gb, 1)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ s->intra_matrix[i] = v;
+ s->chroma_intra_matrix[i] = v;
+ }
+ } else {
+ for(i=0;i<64;i++) {
+ v = default_intra_matrix[i];
+ s->intra_matrix[i] = v;
+ s->chroma_intra_matrix[i] = v;
+ }
+ }
+ if (get_bits(&s->gb, 1)) {
+ for(i=0;i<64;i++) {
+ v = get_bits(&s->gb, 8);
+ s->non_intra_matrix[i] = v;
+ s->chroma_non_intra_matrix[i] = v;
+ }
+ } else {
+ for(i=0;i<64;i++) {
+ v = default_non_intra_matrix[i];
+ s->non_intra_matrix[i] = v;
+ s->chroma_non_intra_matrix[i] = v;
+ }
+ }
+
+ /* we set mpeg2 parameters so that it emulates mpeg1 */
+ s->progressive_sequence = 1;
+ s->progressive_frame = 1;
+ s->picture_structure = PICT_FRAME;
+ s->frame_pred_frame_dct = 1;
+ s->mpeg2 = 0;
+ return 0;
+}
+
+/* handle buffering and image synchronisation */
+static int mpeg_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ UINT8 *buf, int buf_size)
+{
+ Mpeg1Context *s = avctx->priv_data;
+ UINT8 *buf_end, *buf_ptr, *buf_start;
+ int len, start_code_found, ret, code, start_code, input_size;
+ AVPicture *picture = data;
+
+ dprintf("fill_buffer\n");
+
+ *data_size = 0;
+ /* special case for last picture */
+ if (buf_size == 0) {
+ MpegEncContext *s2 = &s->mpeg_enc_ctx;
+ if (s2->picture_number > 0) {
+ picture->data[0] = s2->next_picture[0];
+ picture->data[1] = s2->next_picture[1];
+ picture->data[2] = s2->next_picture[2];
+ picture->linesize[0] = s2->linesize;
+ picture->linesize[1] = s2->linesize / 2;
+ picture->linesize[2] = s2->linesize / 2;
+ *data_size = sizeof(AVPicture);
+ }
+ return 0;
+ }
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+ while (buf_ptr < buf_end) {
+ buf_start = buf_ptr;
+ /* find start next code */
+ code = find_start_code(&buf_ptr, buf_end, &s->header_state);
+ if (code >= 0) {
+ start_code_found = 1;
+ } else {
+ start_code_found = 0;
+ }
+ /* copy to buffer */
+ len = buf_ptr - buf_start;
+ if (len + (s->buf_ptr - s->buffer) > s->buffer_size) {
+ /* data too big : flush */
+ s->buf_ptr = s->buffer;
+ if (start_code_found)
+ s->start_code = code;
+ } else {
+ memcpy(s->buf_ptr, buf_start, len);
+ s->buf_ptr += len;
+
+ if (start_code_found) {
+ /* prepare data for next start code */
+ input_size = s->buf_ptr - s->buffer;
+ start_code = s->start_code;
+ s->buf_ptr = s->buffer;
+ s->start_code = code;
+ switch(start_code) {
+ case SEQ_START_CODE:
+ mpeg1_decode_sequence(avctx, s->buffer,
+ input_size);
+ break;
+
+ case PICTURE_START_CODE:
+ /* we have a complete image : we try to decompress it */
+ mpeg1_decode_picture(avctx,
+ s->buffer, input_size);
+ break;
+ case EXT_START_CODE:
+ mpeg_decode_extension(avctx,
+ s->buffer, input_size);
+ break;
+ default:
+ if (start_code >= SLICE_MIN_START_CODE &&
+ start_code <= SLICE_MAX_START_CODE) {
+ ret = mpeg_decode_slice(avctx, picture,
+ start_code, s->buffer, input_size);
+ if (ret == 1) {
+ /* got a picture: exit */
+ *data_size = sizeof(AVPicture);
+ goto the_end;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ the_end:
+ return buf_ptr - buf;
+}
+
+static int mpeg_decode_end(AVCodecContext *avctx)
+{
+ Mpeg1Context *s = avctx->priv_data;
+
+ if (s->mpeg_enc_ctx_allocated)
+ MPV_common_end(&s->mpeg_enc_ctx);
+ return 0;
+}
+
+AVCodec mpeg_decoder = {
+ "mpegvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG1VIDEO,
+ sizeof(Mpeg1Context),
+ mpeg_decode_init,
+ NULL,
+ mpeg_decode_end,
+ mpeg_decode_frame,
+};
diff --git a/libavcodec/mpeg12data.h b/libavcodec/mpeg12data.h
new file mode 100644
index 0000000000..2b5a9c2e22
--- /dev/null
+++ b/libavcodec/mpeg12data.h
@@ -0,0 +1,362 @@
+/*
+ * MPEG1/2 tables
+ */
+
+const UINT8 default_intra_matrix[64] = {
+ 8, 16, 19, 22, 26, 27, 29, 34,
+ 16, 16, 22, 24, 27, 29, 34, 37,
+ 19, 22, 26, 27, 29, 34, 34, 38,
+ 22, 22, 26, 27, 29, 34, 37, 40,
+ 22, 26, 27, 29, 32, 35, 40, 48,
+ 26, 27, 29, 32, 35, 40, 48, 58,
+ 26, 27, 29, 34, 38, 46, 56, 69,
+ 27, 29, 35, 38, 46, 56, 69, 83
+};
+
+const UINT8 default_non_intra_matrix[64] = {
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+};
+
+const unsigned char vlc_dc_table[256] = {
+ 0, 1, 2, 2,
+ 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+
+ 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, 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,
+
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+};
+
+const UINT16 vlc_dc_lum_code[12] = {
+ 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe, 0x1ff,
+};
+const unsigned char vlc_dc_lum_bits[12] = {
+ 3, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 9,
+};
+
+const UINT16 vlc_dc_chroma_code[12] = {
+ 0x0, 0x1, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe, 0x3fe, 0x3ff,
+};
+const unsigned char vlc_dc_chroma_bits[12] = {
+ 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10,
+};
+
+static const UINT16 mpeg1_vlc[113][2] = {
+ { 0x3, 2 }, { 0x4, 4 }, { 0x5, 5 }, { 0x6, 7 },
+ { 0x26, 8 }, { 0x21, 8 }, { 0xa, 10 }, { 0x1d, 12 },
+ { 0x18, 12 }, { 0x13, 12 }, { 0x10, 12 }, { 0x1a, 13 },
+ { 0x19, 13 }, { 0x18, 13 }, { 0x17, 13 }, { 0x1f, 14 },
+ { 0x1e, 14 }, { 0x1d, 14 }, { 0x1c, 14 }, { 0x1b, 14 },
+ { 0x1a, 14 }, { 0x19, 14 }, { 0x18, 14 }, { 0x17, 14 },
+ { 0x16, 14 }, { 0x15, 14 }, { 0x14, 14 }, { 0x13, 14 },
+ { 0x12, 14 }, { 0x11, 14 }, { 0x10, 14 }, { 0x18, 15 },
+ { 0x17, 15 }, { 0x16, 15 }, { 0x15, 15 }, { 0x14, 15 },
+ { 0x13, 15 }, { 0x12, 15 }, { 0x11, 15 }, { 0x10, 15 },
+ { 0x3, 3 }, { 0x6, 6 }, { 0x25, 8 }, { 0xc, 10 },
+ { 0x1b, 12 }, { 0x16, 13 }, { 0x15, 13 }, { 0x1f, 15 },
+ { 0x1e, 15 }, { 0x1d, 15 }, { 0x1c, 15 }, { 0x1b, 15 },
+ { 0x1a, 15 }, { 0x19, 15 }, { 0x13, 16 }, { 0x12, 16 },
+ { 0x11, 16 }, { 0x10, 16 }, { 0x5, 4 }, { 0x4, 7 },
+ { 0xb, 10 }, { 0x14, 12 }, { 0x14, 13 }, { 0x7, 5 },
+ { 0x24, 8 }, { 0x1c, 12 }, { 0x13, 13 }, { 0x6, 5 },
+ { 0xf, 10 }, { 0x12, 12 }, { 0x7, 6 }, { 0x9, 10 },
+ { 0x12, 13 }, { 0x5, 6 }, { 0x1e, 12 }, { 0x14, 16 },
+ { 0x4, 6 }, { 0x15, 12 }, { 0x7, 7 }, { 0x11, 12 },
+ { 0x5, 7 }, { 0x11, 13 }, { 0x27, 8 }, { 0x10, 13 },
+ { 0x23, 8 }, { 0x1a, 16 }, { 0x22, 8 }, { 0x19, 16 },
+ { 0x20, 8 }, { 0x18, 16 }, { 0xe, 10 }, { 0x17, 16 },
+ { 0xd, 10 }, { 0x16, 16 }, { 0x8, 10 }, { 0x15, 16 },
+ { 0x1f, 12 }, { 0x1a, 12 }, { 0x19, 12 }, { 0x17, 12 },
+ { 0x16, 12 }, { 0x1f, 13 }, { 0x1e, 13 }, { 0x1d, 13 },
+ { 0x1c, 13 }, { 0x1b, 13 }, { 0x1f, 16 }, { 0x1e, 16 },
+ { 0x1d, 16 }, { 0x1c, 16 }, { 0x1b, 16 },
+ { 0x1, 6 }, /* escape */
+ { 0x2, 2 }, /* EOB */
+};
+
+static const UINT16 mpeg2_vlc[113][2] = {
+ {0x02, 2}, {0x06, 3}, {0x07, 4}, {0x1c, 5},
+ {0x1d, 5}, {0x05, 6}, {0x04, 6}, {0x7b, 7},
+ {0x7c, 7}, {0x23, 8}, {0x22, 8}, {0xfa, 8},
+ {0xfb, 8}, {0xfe, 8}, {0xff, 8}, {0x1f,14},
+ {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14},
+ {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14},
+ {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14},
+ {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15},
+ {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15},
+ {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15},
+ {0x02, 3}, {0x06, 5}, {0x79, 7}, {0x27, 8},
+ {0x20, 8}, {0x16,13}, {0x15,13}, {0x1f,15},
+ {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15},
+ {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16},
+ {0x11,16}, {0x10,16}, {0x05, 5}, {0x07, 7},
+ {0xfc, 8}, {0x0c,10}, {0x14,13}, {0x07, 5},
+ {0x26, 8}, {0x1c,12}, {0x13,13}, {0x06, 6},
+ {0xfd, 8}, {0x12,12}, {0x07, 6}, {0x04, 9},
+ {0x12,13}, {0x06, 7}, {0x1e,12}, {0x14,16},
+ {0x04, 7}, {0x15,12}, {0x05, 7}, {0x11,12},
+ {0x78, 7}, {0x11,13}, {0x7a, 7}, {0x10,13},
+ {0x21, 8}, {0x1a,16}, {0x25, 8}, {0x19,16},
+ {0x24, 8}, {0x18,16}, {0x05, 9}, {0x17,16},
+ {0x07, 9}, {0x16,16}, {0x0d,10}, {0x15,16},
+ {0x1f,12}, {0x1a,12}, {0x19,12}, {0x17,12},
+ {0x16,12}, {0x1f,13}, {0x1e,13}, {0x1d,13},
+ {0x1c,13}, {0x1b,13}, {0x1f,16}, {0x1e,16},
+ {0x1d,16}, {0x1c,16}, {0x1b,16},
+ {0x01,6}, /* escape */
+ {0x06,4}, /* EOB */
+};
+
+static const UINT8 mpeg1_level[111] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40,
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 1, 2, 3, 4, 5, 1,
+ 2, 3, 4, 1, 2, 3, 1, 2,
+ 3, 1, 2, 3, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1,
+};
+
+static const UINT8 mpeg1_run[111] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 2, 3,
+ 3, 3, 3, 4, 4, 4, 5, 5,
+ 5, 6, 6, 6, 7, 7, 8, 8,
+ 9, 9, 10, 10, 11, 11, 12, 12,
+ 13, 13, 14, 14, 15, 15, 16, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31,
+};
+
+static RLTable rl_mpeg1 = {
+ 111,
+ 111,
+ mpeg1_vlc,
+ mpeg1_run,
+ mpeg1_level,
+};
+
+static RLTable rl_mpeg2 = {
+ 111,
+ 111,
+ mpeg2_vlc,
+ mpeg1_run,
+ mpeg1_level,
+};
+
+static const UINT8 mbAddrIncrTable[35][2] = {
+ {0x1, 1},
+ {0x3, 3},
+ {0x2, 3},
+ {0x3, 4},
+ {0x2, 4},
+ {0x3, 5},
+ {0x2, 5},
+ {0x7, 7},
+ {0x6, 7},
+ {0xb, 8},
+ {0xa, 8},
+ {0x9, 8},
+ {0x8, 8},
+ {0x7, 8},
+ {0x6, 8},
+ {0x17, 10},
+ {0x16, 10},
+ {0x15, 10},
+ {0x14, 10},
+ {0x13, 10},
+ {0x12, 10},
+ {0x23, 11},
+ {0x22, 11},
+ {0x21, 11},
+ {0x20, 11},
+ {0x1f, 11},
+ {0x1e, 11},
+ {0x1d, 11},
+ {0x1c, 11},
+ {0x1b, 11},
+ {0x1a, 11},
+ {0x19, 11},
+ {0x18, 11},
+ {0x8, 11}, /* escape */
+ {0xf, 11}, /* stuffing */
+};
+
+static const UINT8 mbPatTable[63][2] = {
+ {0xb, 5},
+ {0x9, 5},
+ {0xd, 6},
+ {0xd, 4},
+ {0x17, 7},
+ {0x13, 7},
+ {0x1f, 8},
+ {0xc, 4},
+ {0x16, 7},
+ {0x12, 7},
+ {0x1e, 8},
+ {0x13, 5},
+ {0x1b, 8},
+ {0x17, 8},
+ {0x13, 8},
+ {0xb, 4},
+ {0x15, 7},
+ {0x11, 7},
+ {0x1d, 8},
+ {0x11, 5},
+ {0x19, 8},
+ {0x15, 8},
+ {0x11, 8},
+ {0xf, 6},
+ {0xf, 8},
+ {0xd, 8},
+ {0x3, 9},
+ {0xf, 5},
+ {0xb, 8},
+ {0x7, 8},
+ {0x7, 9},
+ {0xa, 4},
+ {0x14, 7},
+ {0x10, 7},
+ {0x1c, 8},
+ {0xe, 6},
+ {0xe, 8},
+ {0xc, 8},
+ {0x2, 9},
+ {0x10, 5},
+ {0x18, 8},
+ {0x14, 8},
+ {0x10, 8},
+ {0xe, 5},
+ {0xa, 8},
+ {0x6, 8},
+ {0x6, 9},
+ {0x12, 5},
+ {0x1a, 8},
+ {0x16, 8},
+ {0x12, 8},
+ {0xd, 5},
+ {0x9, 8},
+ {0x5, 8},
+ {0x5, 9},
+ {0xc, 5},
+ {0x8, 8},
+ {0x4, 8},
+ {0x4, 9},
+ {0x7, 3},
+ {0xa, 5},
+ {0x8, 5},
+ {0xc, 6}
+};
+
+#define MB_INTRA 0x01
+#define MB_PAT 0x02
+#define MB_BACK 0x04
+#define MB_FOR 0x08
+#define MB_QUANT 0x10
+
+static const UINT8 table_mb_ptype[32][2] = {
+ [ MB_FOR|MB_PAT ] { 1, 1 },
+ [ MB_PAT ] { 1, 2 },
+ [ MB_FOR ] { 1, 3 },
+ [ MB_INTRA ] { 3, 5 },
+ [ MB_QUANT|MB_FOR|MB_PAT ] { 2, 5 },
+ [ MB_QUANT|MB_PAT ] { 1, 5 },
+ [ MB_QUANT|MB_INTRA ] { 1, 6 },
+};
+
+static const UINT8 table_mb_btype[32][2] = {
+ [ MB_FOR|MB_BACK ] { 2, 2 },
+ [ MB_FOR|MB_BACK|MB_PAT ] { 3, 2 },
+ [ MB_BACK ] { 2, 3 },
+ [ MB_BACK|MB_PAT ] { 3, 3 },
+ [ MB_FOR ] { 2, 4 },
+ [ MB_FOR|MB_PAT ] { 3, 4 },
+ [ MB_INTRA ] { 3, 5 },
+ [ MB_QUANT|MB_FOR|MB_BACK|MB_PAT ] { 2, 5 },
+ [ MB_QUANT|MB_FOR|MB_PAT ] { 3, 6 },
+ [ MB_QUANT|MB_BACK|MB_PAT ] { 2, 6 },
+ [ MB_QUANT|MB_INTRA ] { 1, 6 },
+};
+
+static const UINT8 mbMotionVectorTable[17][2] = {
+{ 0x1, 1 },
+{ 0x1, 2 },
+{ 0x1, 3 },
+{ 0x1, 4 },
+{ 0x3, 6 },
+{ 0x5, 7 },
+{ 0x4, 7 },
+{ 0x3, 7 },
+{ 0xb, 9 },
+{ 0xa, 9 },
+{ 0x9, 9 },
+{ 0x11, 10 },
+{ 0x10, 10 },
+{ 0xf, 10 },
+{ 0xe, 10 },
+{ 0xd, 10 },
+{ 0xc, 10 },
+};
+
+const UINT8 zigzag_direct[64] = {
+ 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
+};
+
+static const int frame_rate_tab[9] = {
+ 0,
+ (int)(23.976 * FRAME_RATE_BASE),
+ (int)(24 * FRAME_RATE_BASE),
+ (int)(25 * FRAME_RATE_BASE),
+ (int)(29.97 * FRAME_RATE_BASE),
+ (int)(30 * FRAME_RATE_BASE),
+ (int)(50 * FRAME_RATE_BASE),
+ (int)(59.94 * FRAME_RATE_BASE),
+ (int)(60 * FRAME_RATE_BASE),
+};
+
+static const UINT8 non_linear_qscale[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,
+};
diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h
new file mode 100644
index 0000000000..54b93d97ed
--- /dev/null
+++ b/libavcodec/mpeg4data.h
@@ -0,0 +1,106 @@
+
+/* dc encoding for mpeg4 */
+static const UINT8 DCtab_lum[13][2] =
+{
+ {3,3}, {3,2}, {2,2}, {2,3}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7},
+ {1,8}, {1,9}, {1,10}, {1,11},
+};
+
+static const UINT8 DCtab_chrom[13][2] =
+{
+ {3,2}, {2,2}, {1,2}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, {1,8},
+ {1,9}, {1,10}, {1,11}, {1,12},
+};
+
+const UINT16 intra_vlc[103][2] = {
+{ 0x2, 2 },
+{ 0x6, 3 },{ 0xf, 4 },{ 0xd, 5 },{ 0xc, 5 },
+{ 0x15, 6 },{ 0x13, 6 },{ 0x12, 6 },{ 0x17, 7 },
+{ 0x1f, 8 },{ 0x1e, 8 },{ 0x1d, 8 },{ 0x25, 9 },
+{ 0x24, 9 },{ 0x23, 9 },{ 0x21, 9 },{ 0x21, 10 },
+{ 0x20, 10 },{ 0xf, 10 },{ 0xe, 10 },{ 0x7, 11 },
+{ 0x6, 11 },{ 0x20, 11 },{ 0x21, 11 },{ 0x50, 12 },
+{ 0x51, 12 },{ 0x52, 12 },{ 0xe, 4 },{ 0x14, 6 },
+{ 0x16, 7 },{ 0x1c, 8 },{ 0x20, 9 },{ 0x1f, 9 },
+{ 0xd, 10 },{ 0x22, 11 },{ 0x53, 12 },{ 0x55, 12 },
+{ 0xb, 5 },{ 0x15, 7 },{ 0x1e, 9 },{ 0xc, 10 },
+{ 0x56, 12 },{ 0x11, 6 },{ 0x1b, 8 },{ 0x1d, 9 },
+{ 0xb, 10 },{ 0x10, 6 },{ 0x22, 9 },{ 0xa, 10 },
+{ 0xd, 6 },{ 0x1c, 9 },{ 0x8, 10 },{ 0x12, 7 },
+{ 0x1b, 9 },{ 0x54, 12 },{ 0x14, 7 },{ 0x1a, 9 },
+{ 0x57, 12 },{ 0x19, 8 },{ 0x9, 10 },{ 0x18, 8 },
+{ 0x23, 11 },{ 0x17, 8 },{ 0x19, 9 },{ 0x18, 9 },
+{ 0x7, 10 },{ 0x58, 12 },{ 0x7, 4 },{ 0xc, 6 },
+{ 0x16, 8 },{ 0x17, 9 },{ 0x6, 10 },{ 0x5, 11 },
+{ 0x4, 11 },{ 0x59, 12 },{ 0xf, 6 },{ 0x16, 9 },
+{ 0x5, 10 },{ 0xe, 6 },{ 0x4, 10 },{ 0x11, 7 },
+{ 0x24, 11 },{ 0x10, 7 },{ 0x25, 11 },{ 0x13, 7 },
+{ 0x5a, 12 },{ 0x15, 8 },{ 0x5b, 12 },{ 0x14, 8 },
+{ 0x13, 8 },{ 0x1a, 8 },{ 0x15, 9 },{ 0x14, 9 },
+{ 0x13, 9 },{ 0x12, 9 },{ 0x11, 9 },{ 0x26, 11 },
+{ 0x27, 11 },{ 0x5c, 12 },{ 0x5d, 12 },{ 0x5e, 12 },
+{ 0x5f, 12 },{ 0x3, 7 },
+};
+
+const INT8 intra_level[102] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 1, 2, 3,
+ 4, 5, 1, 2, 3, 4, 1, 2,
+ 3, 1, 2, 3, 1, 2, 3, 1,
+ 2, 3, 1, 2, 1, 2, 1, 1,
+ 1, 1, 1, 1, 2, 3, 4, 5,
+ 6, 7, 8, 1, 2, 3, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1,
+};
+
+const INT8 intra_run[102] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 3, 3, 3, 3, 4, 4,
+ 4, 5, 5, 5, 6, 6, 6, 7,
+ 7, 7, 8, 8, 9, 9, 10, 11,
+ 12, 13, 14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 2, 2,
+ 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20,
+};
+
+static RLTable rl_intra = {
+ 102,
+ 67,
+ intra_vlc,
+ intra_run,
+ intra_level,
+};
+
+/* alternate scan orders used when doing AC prediction */
+UINT8 ff_alternate_horizontal_scan[64] = {
+ 0, 1, 2, 3, 8, 9, 16, 17,
+ 10, 11, 4, 5, 6, 7, 15, 14,
+ 13, 12, 19, 18, 24, 25, 32, 33,
+ 26, 27, 20, 21, 22, 23, 28, 29,
+ 30, 31, 34, 35, 40, 41, 48, 49,
+ 42, 43, 36, 37, 38, 39, 44, 45,
+ 46, 47, 50, 51, 56, 57, 58, 59,
+ 52, 53, 54, 55, 60, 61, 62, 63,
+};
+
+UINT8 ff_alternate_vertical_scan[64] = {
+ 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,
+};
diff --git a/libavcodec/mpegaudio.c b/libavcodec/mpegaudio.c
new file mode 100644
index 0000000000..af05e29279
--- /dev/null
+++ b/libavcodec/mpegaudio.c
@@ -0,0 +1,774 @@
+/*
+ * The simplest mpeg audio layer 2 encoder
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "avcodec.h"
+#include "mpegaudio.h"
+
+#define NDEBUG
+#include <assert.h>
+
+/* define it to use floats in quantization (I don't like floats !) */
+//#define USE_FLOATS
+
+#define MPA_STEREO 0
+#define MPA_JSTEREO 1
+#define MPA_DUAL 2
+#define MPA_MONO 3
+
+#include "mpegaudiotab.h"
+
+int MPA_encode_init(AVCodecContext *avctx)
+{
+ MpegAudioContext *s = avctx->priv_data;
+ int freq = avctx->sample_rate;
+ int bitrate = avctx->bit_rate;
+ int channels = avctx->channels;
+ int i, v, table, ch_bitrate;
+ float a;
+
+ if (channels > 2)
+ return -1;
+ bitrate = bitrate / 1000;
+ s->nb_channels = channels;
+ s->freq = freq;
+ s->bit_rate = bitrate * 1000;
+ avctx->frame_size = MPA_FRAME_SIZE;
+ avctx->key_frame = 1; /* always key frame */
+
+ /* encoding freq */
+ s->lsf = 0;
+ for(i=0;i<3;i++) {
+ if (freq_tab[i] == freq)
+ break;
+ if ((freq_tab[i] / 2) == freq) {
+ s->lsf = 1;
+ break;
+ }
+ }
+ if (i == 3)
+ return -1;
+ s->freq_index = i;
+
+ /* encoding bitrate & frequency */
+ for(i=0;i<15;i++) {
+ if (bitrate_tab[1-s->lsf][i] == bitrate)
+ break;
+ }
+ if (i == 15)
+ return -1;
+ s->bitrate_index = i;
+
+ /* compute total header size & pad bit */
+
+ a = (float)(bitrate * 1000 * MPA_FRAME_SIZE) / (freq * 8.0);
+ s->frame_size = ((int)a) * 8;
+
+ /* frame fractional size to compute padding */
+ s->frame_frac = 0;
+ s->frame_frac_incr = (int)((a - floor(a)) * 65536.0);
+
+ /* select the right allocation table */
+ ch_bitrate = bitrate / s->nb_channels;
+ if (!s->lsf) {
+ if ((freq == 48000 && ch_bitrate >= 56) ||
+ (ch_bitrate >= 56 && ch_bitrate <= 80))
+ table = 0;
+ else if (freq != 48000 && ch_bitrate >= 96)
+ table = 1;
+ else if (freq != 32000 && ch_bitrate <= 48)
+ table = 2;
+ else
+ table = 3;
+ } else {
+ table = 4;
+ }
+ /* number of used subbands */
+ s->sblimit = sblimit_table[table];
+ s->alloc_table = alloc_tables[table];
+
+#ifdef DEBUG
+ printf("%d kb/s, %d Hz, frame_size=%d bits, table=%d, padincr=%x\n",
+ bitrate, freq, s->frame_size, table, s->frame_frac_incr);
+#endif
+
+ for(i=0;i<s->nb_channels;i++)
+ s->samples_offset[i] = 0;
+
+ for(i=0;i<512;i++) {
+ float a = enwindow[i] * 32768.0 * 16.0;
+ filter_bank[i] = (int)(a);
+ }
+ for(i=0;i<64;i++) {
+ v = (int)(pow(2.0, (3 - i) / 3.0) * (1 << 20));
+ if (v <= 0)
+ v = 1;
+ scale_factor_table[i] = v;
+#ifdef USE_FLOATS
+ scale_factor_inv_table[i] = pow(2.0, -(3 - i) / 3.0) / (float)(1 << 20);
+#else
+#define P 15
+ scale_factor_shift[i] = 21 - P - (i / 3);
+ scale_factor_mult[i] = (1 << P) * pow(2.0, (i % 3) / 3.0);
+#endif
+ }
+ for(i=0;i<128;i++) {
+ v = i - 64;
+ if (v <= -3)
+ v = 0;
+ else if (v < 0)
+ v = 1;
+ else if (v == 0)
+ v = 2;
+ else if (v < 3)
+ v = 3;
+ else
+ v = 4;
+ scale_diff_table[i] = v;
+ }
+
+ for(i=0;i<17;i++) {
+ v = quant_bits[i];
+ if (v < 0)
+ v = -v;
+ else
+ v = v * 3;
+ total_quant_bits[i] = 12 * v;
+ }
+
+ return 0;
+}
+
+/* 32 point floating point IDCT */
+static void idct32(int *out, int *tab, int sblimit, int left_shift)
+{
+ int i, j;
+ int *t, *t1, xr;
+ const int *xp = costab32;
+
+ for(j=31;j>=3;j-=2) tab[j] += tab[j - 2];
+
+ t = tab + 30;
+ t1 = tab + 2;
+ do {
+ t[0] += t[-4];
+ t[1] += t[1 - 4];
+ t -= 4;
+ } while (t != t1);
+
+ t = tab + 28;
+ t1 = tab + 4;
+ do {
+ t[0] += t[-8];
+ t[1] += t[1-8];
+ t[2] += t[2-8];
+ t[3] += t[3-8];
+ t -= 8;
+ } while (t != t1);
+
+ t = tab;
+ t1 = tab + 32;
+ do {
+ t[ 3] = -t[ 3];
+ t[ 6] = -t[ 6];
+
+ t[11] = -t[11];
+ t[12] = -t[12];
+ t[13] = -t[13];
+ t[15] = -t[15];
+ t += 16;
+ } while (t != t1);
+
+
+ t = tab;
+ t1 = tab + 8;
+ do {
+ int x1, x2, x3, x4;
+
+ x3 = MUL(t[16], FIX(SQRT2*0.5));
+ x4 = t[0] - x3;
+ x3 = t[0] + x3;
+
+ x2 = MUL(-(t[24] + t[8]), FIX(SQRT2*0.5));
+ x1 = MUL((t[8] - x2), xp[0]);
+ x2 = MUL((t[8] + x2), xp[1]);
+
+ t[ 0] = x3 + x1;
+ t[ 8] = x4 - x2;
+ t[16] = x4 + x2;
+ t[24] = x3 - x1;
+ t++;
+ } while (t != t1);
+
+ xp += 2;
+ t = tab;
+ t1 = tab + 4;
+ do {
+ xr = MUL(t[28],xp[0]);
+ t[28] = (t[0] - xr);
+ t[0] = (t[0] + xr);
+
+ xr = MUL(t[4],xp[1]);
+ t[ 4] = (t[24] - xr);
+ t[24] = (t[24] + xr);
+
+ xr = MUL(t[20],xp[2]);
+ t[20] = (t[8] - xr);
+ t[ 8] = (t[8] + xr);
+
+ xr = MUL(t[12],xp[3]);
+ t[12] = (t[16] - xr);
+ t[16] = (t[16] + xr);
+ t++;
+ } while (t != t1);
+ xp += 4;
+
+ for (i = 0; i < 4; i++) {
+ xr = MUL(tab[30-i*4],xp[0]);
+ tab[30-i*4] = (tab[i*4] - xr);
+ tab[ i*4] = (tab[i*4] + xr);
+
+ xr = MUL(tab[ 2+i*4],xp[1]);
+ tab[ 2+i*4] = (tab[28-i*4] - xr);
+ tab[28-i*4] = (tab[28-i*4] + xr);
+
+ xr = MUL(tab[31-i*4],xp[0]);
+ tab[31-i*4] = (tab[1+i*4] - xr);
+ tab[ 1+i*4] = (tab[1+i*4] + xr);
+
+ xr = MUL(tab[ 3+i*4],xp[1]);
+ tab[ 3+i*4] = (tab[29-i*4] - xr);
+ tab[29-i*4] = (tab[29-i*4] + xr);
+
+ xp += 2;
+ }
+
+ t = tab + 30;
+ t1 = tab + 1;
+ do {
+ xr = MUL(t1[0], *xp);
+ t1[0] = (t[0] - xr);
+ t[0] = (t[0] + xr);
+ t -= 2;
+ t1 += 2;
+ xp++;
+ } while (t >= tab);
+
+ for(i=0;i<32;i++) {
+ out[i] = tab[bitinv32[i]] << left_shift;
+ }
+}
+
+static void filter(MpegAudioContext *s, int ch, short *samples, int incr)
+{
+ short *p, *q;
+ int sum, offset, i, j, norm, n;
+ short tmp[64];
+ int tmp1[32];
+ int *out;
+
+ // print_pow1(samples, 1152);
+
+ offset = s->samples_offset[ch];
+ out = &s->sb_samples[ch][0][0][0];
+ for(j=0;j<36;j++) {
+ /* 32 samples at once */
+ for(i=0;i<32;i++) {
+ s->samples_buf[ch][offset + (31 - i)] = samples[0];
+ samples += incr;
+ }
+
+ /* filter */
+ p = s->samples_buf[ch] + offset;
+ q = filter_bank;
+ /* maxsum = 23169 */
+ for(i=0;i<64;i++) {
+ sum = p[0*64] * q[0*64];
+ sum += p[1*64] * q[1*64];
+ sum += p[2*64] * q[2*64];
+ sum += p[3*64] * q[3*64];
+ sum += p[4*64] * q[4*64];
+ sum += p[5*64] * q[5*64];
+ sum += p[6*64] * q[6*64];
+ sum += p[7*64] * q[7*64];
+ tmp[i] = sum >> 14;
+ p++;
+ q++;
+ }
+ tmp1[0] = tmp[16];
+ for( i=1; i<=16; i++ ) tmp1[i] = tmp[i+16]+tmp[16-i];
+ for( i=17; i<=31; i++ ) tmp1[i] = tmp[i+16]-tmp[80-i];
+
+ /* integer IDCT 32 with normalization. XXX: There may be some
+ overflow left */
+ norm = 0;
+ for(i=0;i<32;i++) {
+ norm |= abs(tmp1[i]);
+ }
+ n = log2(norm) - 12;
+ if (n > 0) {
+ for(i=0;i<32;i++)
+ tmp1[i] >>= n;
+ } else {
+ n = 0;
+ }
+
+ idct32(out, tmp1, s->sblimit, n);
+
+ /* advance of 32 samples */
+ offset -= 32;
+ out += 32;
+ /* handle the wrap around */
+ if (offset < 0) {
+ memmove(s->samples_buf[ch] + SAMPLES_BUF_SIZE - (512 - 32),
+ s->samples_buf[ch], (512 - 32) * 2);
+ offset = SAMPLES_BUF_SIZE - 512;
+ }
+ }
+ s->samples_offset[ch] = offset;
+
+ // print_pow(s->sb_samples, 1152);
+}
+
+static void compute_scale_factors(unsigned char scale_code[SBLIMIT],
+ unsigned char scale_factors[SBLIMIT][3],
+ int sb_samples[3][12][SBLIMIT],
+ int sblimit)
+{
+ int *p, vmax, v, n, i, j, k, code;
+ int index, d1, d2;
+ unsigned char *sf = &scale_factors[0][0];
+
+ for(j=0;j<sblimit;j++) {
+ for(i=0;i<3;i++) {
+ /* find the max absolute value */
+ p = &sb_samples[i][0][j];
+ vmax = abs(*p);
+ for(k=1;k<12;k++) {
+ p += SBLIMIT;
+ v = abs(*p);
+ if (v > vmax)
+ vmax = v;
+ }
+ /* compute the scale factor index using log 2 computations */
+ if (vmax > 0) {
+ n = log2(vmax);
+ /* n is the position of the MSB of vmax. now
+ use at most 2 compares to find the index */
+ index = (21 - n) * 3 - 3;
+ if (index >= 0) {
+ while (vmax <= scale_factor_table[index+1])
+ index++;
+ } else {
+ index = 0; /* very unlikely case of overflow */
+ }
+ } else {
+ index = 63;
+ }
+
+#if 0
+ printf("%2d:%d in=%x %x %d\n",
+ j, i, vmax, scale_factor_table[index], index);
+#endif
+ /* store the scale factor */
+ assert(index >=0 && index <= 63);
+ sf[i] = index;
+ }
+
+ /* compute the transmission factor : look if the scale factors
+ are close enough to each other */
+ d1 = scale_diff_table[sf[0] - sf[1] + 64];
+ d2 = scale_diff_table[sf[1] - sf[2] + 64];
+
+ /* handle the 25 cases */
+ switch(d1 * 5 + d2) {
+ case 0*5+0:
+ case 0*5+4:
+ case 3*5+4:
+ case 4*5+0:
+ case 4*5+4:
+ code = 0;
+ break;
+ case 0*5+1:
+ case 0*5+2:
+ case 4*5+1:
+ case 4*5+2:
+ code = 3;
+ sf[2] = sf[1];
+ break;
+ case 0*5+3:
+ case 4*5+3:
+ code = 3;
+ sf[1] = sf[2];
+ break;
+ case 1*5+0:
+ case 1*5+4:
+ case 2*5+4:
+ code = 1;
+ sf[1] = sf[0];
+ break;
+ case 1*5+1:
+ case 1*5+2:
+ case 2*5+0:
+ case 2*5+1:
+ case 2*5+2:
+ code = 2;
+ sf[1] = sf[2] = sf[0];
+ break;
+ case 2*5+3:
+ case 3*5+3:
+ code = 2;
+ sf[0] = sf[1] = sf[2];
+ break;
+ case 3*5+0:
+ case 3*5+1:
+ case 3*5+2:
+ code = 2;
+ sf[0] = sf[2] = sf[1];
+ break;
+ case 1*5+3:
+ code = 2;
+ if (sf[0] > sf[2])
+ sf[0] = sf[2];
+ sf[1] = sf[2] = sf[0];
+ break;
+ default:
+ abort();
+ }
+
+#if 0
+ printf("%d: %2d %2d %2d %d %d -> %d\n", j,
+ sf[0], sf[1], sf[2], d1, d2, code);
+#endif
+ scale_code[j] = code;
+ sf += 3;
+ }
+}
+
+/* The most important function : psycho acoustic module. In this
+ encoder there is basically none, so this is the worst you can do,
+ but also this is the simpler. */
+static void psycho_acoustic_model(MpegAudioContext *s, short smr[SBLIMIT])
+{
+ int i;
+
+ for(i=0;i<s->sblimit;i++) {
+ smr[i] = (int)(fixed_smr[i] * 10);
+ }
+}
+
+
+#define SB_NOTALLOCATED 0
+#define SB_ALLOCATED 1
+#define SB_NOMORE 2
+
+/* Try to maximize the smr while using a number of bits inferior to
+ the frame size. I tried to make the code simpler, faster and
+ smaller than other encoders :-) */
+static void compute_bit_allocation(MpegAudioContext *s,
+ short smr1[MPA_MAX_CHANNELS][SBLIMIT],
+ unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT],
+ int *padding)
+{
+ int i, ch, b, max_smr, max_ch, max_sb, current_frame_size, max_frame_size;
+ int incr;
+ short smr[MPA_MAX_CHANNELS][SBLIMIT];
+ unsigned char subband_status[MPA_MAX_CHANNELS][SBLIMIT];
+ const unsigned char *alloc;
+
+ memcpy(smr, smr1, s->nb_channels * sizeof(short) * SBLIMIT);
+ memset(subband_status, SB_NOTALLOCATED, s->nb_channels * SBLIMIT);
+ memset(bit_alloc, 0, s->nb_channels * SBLIMIT);
+
+ /* compute frame size and padding */
+ max_frame_size = s->frame_size;
+ s->frame_frac += s->frame_frac_incr;
+ if (s->frame_frac >= 65536) {
+ s->frame_frac -= 65536;
+ s->do_padding = 1;
+ max_frame_size += 8;
+ } else {
+ s->do_padding = 0;
+ }
+
+ /* compute the header + bit alloc size */
+ current_frame_size = 32;
+ alloc = s->alloc_table;
+ for(i=0;i<s->sblimit;i++) {
+ incr = alloc[0];
+ current_frame_size += incr * s->nb_channels;
+ alloc += 1 << incr;
+ }
+ for(;;) {
+ /* look for the subband with the largest signal to mask ratio */
+ max_sb = -1;
+ max_ch = -1;
+ max_smr = 0x80000000;
+ for(ch=0;ch<s->nb_channels;ch++) {
+ for(i=0;i<s->sblimit;i++) {
+ if (smr[ch][i] > max_smr && subband_status[ch][i] != SB_NOMORE) {
+ max_smr = smr[ch][i];
+ max_sb = i;
+ max_ch = ch;
+ }
+ }
+ }
+#if 0
+ printf("current=%d max=%d max_sb=%d alloc=%d\n",
+ current_frame_size, max_frame_size, max_sb,
+ bit_alloc[max_sb]);
+#endif
+ if (max_sb < 0)
+ break;
+
+ /* find alloc table entry (XXX: not optimal, should use
+ pointer table) */
+ alloc = s->alloc_table;
+ for(i=0;i<max_sb;i++) {
+ alloc += 1 << alloc[0];
+ }
+
+ if (subband_status[max_ch][max_sb] == SB_NOTALLOCATED) {
+ /* nothing was coded for this band: add the necessary bits */
+ incr = 2 + nb_scale_factors[s->scale_code[max_ch][max_sb]] * 6;
+ incr += total_quant_bits[alloc[1]];
+ } else {
+ /* increments bit allocation */
+ b = bit_alloc[max_ch][max_sb];
+ incr = total_quant_bits[alloc[b + 1]] -
+ total_quant_bits[alloc[b]];
+ }
+
+ if (current_frame_size + incr <= max_frame_size) {
+ /* can increase size */
+ b = ++bit_alloc[max_ch][max_sb];
+ current_frame_size += incr;
+ /* decrease smr by the resolution we added */
+ smr[max_ch][max_sb] = smr1[max_ch][max_sb] - quant_snr[alloc[b]];
+ /* max allocation size reached ? */
+ if (b == ((1 << alloc[0]) - 1))
+ subband_status[max_ch][max_sb] = SB_NOMORE;
+ else
+ subband_status[max_ch][max_sb] = SB_ALLOCATED;
+ } else {
+ /* cannot increase the size of this subband */
+ subband_status[max_ch][max_sb] = SB_NOMORE;
+ }
+ }
+ *padding = max_frame_size - current_frame_size;
+ assert(*padding >= 0);
+
+#if 0
+ for(i=0;i<s->sblimit;i++) {
+ printf("%d ", bit_alloc[i]);
+ }
+ printf("\n");
+#endif
+}
+
+/*
+ * Output the mpeg audio layer 2 frame. Note how the code is small
+ * compared to other encoders :-)
+ */
+static void encode_frame(MpegAudioContext *s,
+ unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT],
+ int padding)
+{
+ int i, j, k, l, bit_alloc_bits, b, ch;
+ unsigned char *sf;
+ int q[3];
+ PutBitContext *p = &s->pb;
+
+ /* header */
+
+ put_bits(p, 12, 0xfff);
+ put_bits(p, 1, 1 - s->lsf); /* 1 = mpeg1 ID, 0 = mpeg2 lsf ID */
+ put_bits(p, 2, 4-2); /* layer 2 */
+ put_bits(p, 1, 1); /* no error protection */
+ put_bits(p, 4, s->bitrate_index);
+ put_bits(p, 2, s->freq_index);
+ put_bits(p, 1, s->do_padding); /* use padding */
+ put_bits(p, 1, 0); /* private_bit */
+ put_bits(p, 2, s->nb_channels == 2 ? MPA_STEREO : MPA_MONO);
+ put_bits(p, 2, 0); /* mode_ext */
+ put_bits(p, 1, 0); /* no copyright */
+ put_bits(p, 1, 1); /* original */
+ put_bits(p, 2, 0); /* no emphasis */
+
+ /* bit allocation */
+ j = 0;
+ for(i=0;i<s->sblimit;i++) {
+ bit_alloc_bits = s->alloc_table[j];
+ for(ch=0;ch<s->nb_channels;ch++) {
+ put_bits(p, bit_alloc_bits, bit_alloc[ch][i]);
+ }
+ j += 1 << bit_alloc_bits;
+ }
+
+ /* scale codes */
+ for(i=0;i<s->sblimit;i++) {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ if (bit_alloc[ch][i])
+ put_bits(p, 2, s->scale_code[ch][i]);
+ }
+ }
+
+ /* scale factors */
+ for(i=0;i<s->sblimit;i++) {
+ for(ch=0;ch<s->nb_channels;ch++) {
+ if (bit_alloc[ch][i]) {
+ sf = &s->scale_factors[ch][i][0];
+ switch(s->scale_code[ch][i]) {
+ case 0:
+ put_bits(p, 6, sf[0]);
+ put_bits(p, 6, sf[1]);
+ put_bits(p, 6, sf[2]);
+ break;
+ case 3:
+ case 1:
+ put_bits(p, 6, sf[0]);
+ put_bits(p, 6, sf[2]);
+ break;
+ case 2:
+ put_bits(p, 6, sf[0]);
+ break;
+ }
+ }
+ }
+ }
+
+ /* quantization & write sub band samples */
+
+ for(k=0;k<3;k++) {
+ for(l=0;l<12;l+=3) {
+ j = 0;
+ for(i=0;i<s->sblimit;i++) {
+ bit_alloc_bits = s->alloc_table[j];
+ for(ch=0;ch<s->nb_channels;ch++) {
+ b = bit_alloc[ch][i];
+ if (b) {
+ int qindex, steps, m, sample, bits;
+ /* we encode 3 sub band samples of the same sub band at a time */
+ qindex = s->alloc_table[j+b];
+ steps = quant_steps[qindex];
+ for(m=0;m<3;m++) {
+ sample = s->sb_samples[ch][k][l + m][i];
+ /* divide by scale factor */
+#ifdef USE_FLOATS
+ {
+ float a;
+ a = (float)sample * scale_factor_inv_table[s->scale_factors[ch][i][k]];
+ q[m] = (int)((a + 1.0) * steps * 0.5);
+ }
+#else
+ {
+ int q1, e, shift, mult;
+ e = s->scale_factors[ch][i][k];
+ shift = scale_factor_shift[e];
+ mult = scale_factor_mult[e];
+
+ /* normalize to P bits */
+ if (shift < 0)
+ q1 = sample << (-shift);
+ else
+ q1 = sample >> shift;
+ q1 = (q1 * mult) >> P;
+ q[m] = ((q1 + (1 << P)) * steps) >> (P + 1);
+ }
+#endif
+ if (q[m] >= steps)
+ q[m] = steps - 1;
+ assert(q[m] >= 0 && q[m] < steps);
+ }
+ bits = quant_bits[qindex];
+ if (bits < 0) {
+ /* group the 3 values to save bits */
+ put_bits(p, -bits,
+ q[0] + steps * (q[1] + steps * q[2]));
+#if 0
+ printf("%d: gr1 %d\n",
+ i, q[0] + steps * (q[1] + steps * q[2]));
+#endif
+ } else {
+#if 0
+ printf("%d: gr3 %d %d %d\n",
+ i, q[0], q[1], q[2]);
+#endif
+ put_bits(p, bits, q[0]);
+ put_bits(p, bits, q[1]);
+ put_bits(p, bits, q[2]);
+ }
+ }
+ }
+ /* next subband in alloc table */
+ j += 1 << bit_alloc_bits;
+ }
+ }
+ }
+
+ /* padding */
+ for(i=0;i<padding;i++)
+ put_bits(p, 1, 0);
+
+ /* flush */
+ flush_put_bits(p);
+}
+
+int MPA_encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ MpegAudioContext *s = avctx->priv_data;
+ short *samples = data;
+ short smr[MPA_MAX_CHANNELS][SBLIMIT];
+ unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT];
+ int padding, i;
+
+ for(i=0;i<s->nb_channels;i++) {
+ filter(s, i, samples + i, s->nb_channels);
+ }
+
+ for(i=0;i<s->nb_channels;i++) {
+ compute_scale_factors(s->scale_code[i], s->scale_factors[i],
+ s->sb_samples[i], s->sblimit);
+ }
+ for(i=0;i<s->nb_channels;i++) {
+ psycho_acoustic_model(s, smr[i]);
+ }
+ compute_bit_allocation(s, smr, bit_alloc, &padding);
+
+ init_put_bits(&s->pb, frame, MPA_MAX_CODED_FRAME_SIZE, NULL, NULL);
+
+ encode_frame(s, bit_alloc, padding);
+
+ s->nb_samples += MPA_FRAME_SIZE;
+ return s->pb.buf_ptr - s->pb.buf;
+}
+
+
+AVCodec mp2_encoder = {
+ "mp2",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP2,
+ sizeof(MpegAudioContext),
+ MPA_encode_init,
+ MPA_encode_frame,
+ NULL,
+};
diff --git a/libavcodec/mpegaudio.h b/libavcodec/mpegaudio.h
new file mode 100644
index 0000000000..006650a99c
--- /dev/null
+++ b/libavcodec/mpegaudio.h
@@ -0,0 +1,34 @@
+
+/* max compressed frame size */
+#define MPA_MAX_CODED_FRAME_SIZE 1200
+
+#define MPA_FRAME_SIZE 1152
+#define MPA_MAX_CHANNELS 2
+
+#define SAMPLES_BUF_SIZE 4096
+#define SBLIMIT 32 /* number of subbands */
+#define DCT_BITS 14 /* number of bits for the DCT */
+#define MUL(a,b) (((a) * (b)) >> DCT_BITS)
+#define FIX(a) ((int)((a) * (1 << DCT_BITS)))
+
+typedef struct MpegAudioContext {
+ PutBitContext pb;
+ int nb_channels;
+ int freq, bit_rate;
+ int lsf; /* 1 if mpeg2 low bitrate selected */
+ int bitrate_index; /* bit rate */
+ int freq_index;
+ int frame_size; /* frame size, in bits, without padding */
+ long long nb_samples; /* total number of samples encoded */
+ /* padding computation */
+ int frame_frac, frame_frac_incr, do_padding;
+ short samples_buf[MPA_MAX_CHANNELS][SAMPLES_BUF_SIZE]; /* buffer for filter */
+ int samples_offset[MPA_MAX_CHANNELS]; /* offset in samples_buf */
+ int sb_samples[MPA_MAX_CHANNELS][3][12][SBLIMIT];
+ unsigned char scale_factors[MPA_MAX_CHANNELS][SBLIMIT][3]; /* scale factors */
+ /* code to group 3 scale factors */
+ unsigned char scale_code[MPA_MAX_CHANNELS][SBLIMIT];
+ int sblimit; /* number of used subbands */
+ const unsigned char *alloc_table;
+} MpegAudioContext;
+
diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c
new file mode 100644
index 0000000000..f3fa90af55
--- /dev/null
+++ b/libavcodec/mpegaudiodec.c
@@ -0,0 +1,293 @@
+/*
+ * MPEG Audio decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "avcodec.h"
+#include "mpglib/mpg123.h"
+
+/*
+ * TODO:
+ * - add free format
+ * - do not rely anymore on mpglib (first step: implement dct64 and decoding filter)
+ */
+
+#define HEADER_SIZE 4
+#define BACKSTEP_SIZE 512
+
+typedef struct MPADecodeContext {
+ struct mpstr mpstr;
+ UINT8 inbuf1[2][MAXFRAMESIZE + BACKSTEP_SIZE]; /* input buffer */
+ int inbuf_index;
+ UINT8 *inbuf_ptr, *inbuf;
+ int frame_size;
+ int error_protection;
+ int layer;
+ int sample_rate;
+ int bit_rate;
+ int old_frame_size;
+ GetBitContext gb;
+} MPADecodeContext;
+
+/* XXX: suppress that mess */
+struct mpstr *gmp;
+GetBitContext *gmp_gb;
+static MPADecodeContext *gmp_s;
+
+/* XXX: merge constants with encoder */
+static const unsigned short mp_bitrate_tab[2][3][15] = {
+ { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
+ {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 },
+ {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } },
+ { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
+ }
+};
+
+static unsigned short mp_freq_tab[3] = { 44100, 48000, 32000 };
+
+static int decode_init(AVCodecContext * avctx)
+{
+ MPADecodeContext *s = avctx->priv_data;
+ struct mpstr *mp = &s->mpstr;
+ static int init;
+
+ mp->fr.single = -1;
+ mp->synth_bo = 1;
+
+ if(!init) {
+ init = 1;
+ make_decode_tables(32767);
+ init_layer2();
+ init_layer3(SBLIMIT);
+ }
+
+ s->inbuf_index = 0;
+ s->inbuf = &s->inbuf1[s->inbuf_index][BACKSTEP_SIZE];
+ s->inbuf_ptr = s->inbuf;
+
+ return 0;
+}
+
+/* fast header check for resync */
+static int check_header(UINT32 header)
+{
+ /* header */
+ if ((header & 0xffe00000) != 0xffe00000)
+ return -1;
+ /* layer check */
+ if (((header >> 17) & 3) == 0)
+ return -1;
+ /* bit rate : currently no free format supported */
+ if (((header >> 12) & 0xf) == 0xf ||
+ ((header >> 12) & 0xf) == 0x0)
+ return -1;
+ /* frequency */
+ if (((header >> 10) & 3) == 3)
+ return -1;
+ return 0;
+}
+
+/* header decoding. MUST check the header before because no
+ consistency check is done there */
+static void decode_header(MPADecodeContext *s, UINT32 header)
+{
+ struct frame *fr = &s->mpstr.fr;
+ int sample_rate, frame_size;
+
+ if (header & (1<<20)) {
+ fr->lsf = (header & (1<<19)) ? 0 : 1;
+ fr->mpeg25 = 0;
+ } else {
+ fr->lsf = 1;
+ fr->mpeg25 = 1;
+ }
+
+ s->layer = 4 - ((header >> 17) & 3);
+ /* extract frequency */
+ fr->sampling_frequency = ((header >> 10) & 3);
+ sample_rate = mp_freq_tab[fr->sampling_frequency] >> (fr->lsf + fr->mpeg25);
+ fr->sampling_frequency += 3 * (fr->lsf + fr->mpeg25);
+
+ s->error_protection = ((header>>16) & 1) ^ 1;
+
+ fr->bitrate_index = ((header>>12)&0xf);
+ fr->padding = ((header>>9)&0x1);
+ fr->extension = ((header>>8)&0x1);
+ fr->mode = ((header>>6)&0x3);
+ fr->mode_ext = ((header>>4)&0x3);
+ fr->copyright = ((header>>3)&0x1);
+ fr->original = ((header>>2)&0x1);
+ fr->emphasis = header & 0x3;
+
+ fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;
+
+
+ frame_size = mp_bitrate_tab[fr->lsf][s->layer - 1][fr->bitrate_index];
+ s->bit_rate = frame_size * 1000;
+ switch(s->layer) {
+ case 1:
+ frame_size = (frame_size * 12000) / sample_rate;
+ frame_size = ((frame_size + fr->padding) << 2);
+ break;
+ case 2:
+ frame_size = (frame_size * 144000) / sample_rate;
+ frame_size += fr->padding;
+ break;
+ case 3:
+ frame_size = (frame_size * 144000) / (sample_rate << fr->lsf);
+ frame_size += fr->padding;
+ break;
+ }
+ s->frame_size = frame_size;
+ s->sample_rate = sample_rate;
+
+#if 0
+ printf("layer%d, %d Hz, %d kbits/s, %s\n",
+ s->layer, s->sample_rate, s->bit_rate, fr->stereo ? "stereo" : "mono");
+#endif
+}
+
+static int mp_decode_frame(MPADecodeContext *s,
+ short *samples)
+{
+ int nb_bytes;
+
+ init_get_bits(&s->gb, s->inbuf + HEADER_SIZE, s->inbuf_ptr - s->inbuf - HEADER_SIZE);
+
+ /* skip error protection field */
+ if (s->error_protection)
+ get_bits(&s->gb, 16);
+
+ /* XXX: horrible: global! */
+ gmp = &s->mpstr;
+ gmp_s = s;
+ gmp_gb = &s->gb;
+
+ nb_bytes = 0;
+ switch(s->layer) {
+ case 1:
+ do_layer1(&s->mpstr.fr,(unsigned char *)samples, &nb_bytes);
+ break;
+ case 2:
+ do_layer2(&s->mpstr.fr,(unsigned char *)samples, &nb_bytes);
+ break;
+ case 3:
+ do_layer3(&s->mpstr.fr,(unsigned char *)samples, &nb_bytes);
+ s->inbuf_index ^= 1;
+ s->inbuf = &s->inbuf1[s->inbuf_index][BACKSTEP_SIZE];
+ s->old_frame_size = s->frame_size;
+ break;
+ default:
+ break;
+ }
+ return nb_bytes;
+}
+
+/*
+ * seek back in the stream for backstep bytes (at most 511 bytes, and
+ * at most in last frame). Note that this is slightly incorrect (data
+ * can span more than one block!)
+ */
+int set_pointer(long backstep)
+{
+ UINT8 *ptr;
+
+ /* compute current position in stream */
+ ptr = gmp_gb->buf_ptr - (gmp_gb->bit_cnt >> 3);
+ /* copy old data before current one */
+ ptr -= backstep;
+ memcpy(ptr, gmp_s->inbuf1[gmp_s->inbuf_index ^ 1] +
+ BACKSTEP_SIZE + gmp_s->old_frame_size - backstep, backstep);
+ /* init get bits again */
+ init_get_bits(gmp_gb, ptr, gmp_s->frame_size + backstep);
+
+ return 0;
+}
+
+static int decode_frame(AVCodecContext * avctx,
+ void *data, int *data_size,
+ UINT8 * buf, int buf_size)
+{
+ MPADecodeContext *s = avctx->priv_data;
+ UINT32 header;
+ UINT8 *buf_ptr;
+ int len, out_size;
+ short *out_samples = data;
+
+ *data_size = 0;
+ buf_ptr = buf;
+ while (buf_size > 0) {
+ len = s->inbuf_ptr - s->inbuf;
+ if (s->frame_size == 0) {
+ /* no header seen : find one. We need at least 7 bytes to parse it */
+ len = HEADER_SIZE - len;
+ if (len > buf_size)
+ len = buf_size;
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ if ((s->inbuf_ptr - s->inbuf) == HEADER_SIZE) {
+ header = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) |
+ (s->inbuf[2] << 8) | s->inbuf[3];
+ if (check_header(header) < 0) {
+ /* no sync found : move by one byte (inefficient, but simple!) */
+ memcpy(s->inbuf, s->inbuf + 1, HEADER_SIZE - 1);
+ s->inbuf_ptr--;
+ } else {
+ decode_header(s, header);
+ /* update codec info */
+ avctx->sample_rate = s->sample_rate;
+ avctx->channels = s->mpstr.fr.stereo ? 2 : 1;
+ avctx->bit_rate = s->bit_rate;
+ }
+ }
+ } else if (len < s->frame_size) {
+ len = s->frame_size - len;
+ if (len > buf_size)
+ len = buf_size;
+
+ memcpy(s->inbuf_ptr, buf_ptr, len);
+ buf_ptr += len;
+ s->inbuf_ptr += len;
+ buf_size -= len;
+ } else {
+ out_size = mp_decode_frame(s, out_samples);
+ s->inbuf_ptr = s->inbuf;
+ s->frame_size = 0;
+ *data_size = out_size;
+ break;
+ }
+ }
+ return buf_ptr - buf;
+}
+
+AVCodec mp3_decoder =
+{
+ "mpegaudio",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_MP2,
+ sizeof(MPADecodeContext),
+ decode_init,
+ NULL,
+ NULL,
+ decode_frame,
+};
diff --git a/libavcodec/mpegaudiotab.h b/libavcodec/mpegaudiotab.h
new file mode 100644
index 0000000000..05bdb9eea1
--- /dev/null
+++ b/libavcodec/mpegaudiotab.h
@@ -0,0 +1,310 @@
+/*
+ * mpeg audio layer 2 tables. Most of them come from the mpeg audio
+ * specification.
+ *
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * The licence of this code is contained in file LICENCE found in the
+ * same archive
+ */
+
+static const unsigned short bitrate_tab[2][15] = {
+ {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}, /* mpeg2 lsf */
+ {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384}, /* mpeg1 */
+};
+
+static const unsigned short freq_tab[3] = { 44100, 48000, 32000 };
+
+#define SQRT2 1.41421356237309514547
+
+static const int costab32[30] = {
+ FIX(0.54119610014619701222),
+ FIX(1.3065629648763763537),
+
+ FIX(0.50979557910415917998),
+ FIX(2.5629154477415054814),
+ FIX(0.89997622313641556513),
+ FIX(0.60134488693504528634),
+
+ FIX(0.5024192861881556782),
+ FIX(5.1011486186891552563),
+ FIX(0.78815462345125020249),
+ FIX(0.64682178335999007679),
+ FIX(0.56694403481635768927),
+ FIX(1.0606776859903470633),
+ FIX(1.7224470982383341955),
+ FIX(0.52249861493968885462),
+
+ FIX(10.19000812354803287),
+ FIX(0.674808341455005678),
+ FIX(1.1694399334328846596),
+ FIX(0.53104259108978413284),
+ FIX(2.0577810099534108446),
+ FIX(0.58293496820613388554),
+ FIX(0.83934964541552681272),
+ FIX(0.50547095989754364798),
+ FIX(3.4076084184687189804),
+ FIX(0.62250412303566482475),
+ FIX(0.97256823786196078263),
+ FIX(0.51544730992262455249),
+ FIX(1.4841646163141661852),
+ FIX(0.5531038960344445421),
+ FIX(0.74453627100229857749),
+ FIX(0.5006029982351962726),
+};
+
+static const int bitinv32[32] = {
+ 0, 16, 8, 24, 4, 20, 12, 28,
+ 2, 18, 10, 26, 6, 22, 14, 30,
+ 1, 17, 9, 25, 5, 21, 13, 29,
+ 3, 19, 11, 27, 7, 23, 15, 31
+};
+
+
+static short filter_bank[512];
+
+static const double enwindow[512] = {0.000000000,
+ -0.000000477, -0.000000477, -0.000000477, -0.000000477, -0.000000477, -0.000000477, -0.000000954, -0.000000954,
+ -0.000000954, -0.000000954, -0.000001431, -0.000001431, -0.000001907, -0.000001907, -0.000002384, -0.000002384,
+ -0.000002861, -0.000003338, -0.000003338, -0.000003815, -0.000004292, -0.000004768, -0.000005245, -0.000006199,
+ -0.000006676, -0.000007629, -0.000008106, -0.000009060, -0.000010014, -0.000011444, -0.000012398, -0.000013828,
+ -0.000014782, -0.000016689, -0.000018120, -0.000019550, -0.000021458, -0.000023365, -0.000025272, -0.000027657,
+ -0.000030041, -0.000032425, -0.000034809, -0.000037670, -0.000040531, -0.000043392, -0.000046253, -0.000049591,
+ -0.000052929, -0.000055790, -0.000059605, -0.000062943, -0.000066280, -0.000070095, -0.000073433, -0.000076771,
+ -0.000080585, -0.000083923, -0.000087261, -0.000090599, -0.000093460, -0.000096321, -0.000099182, 0.000101566,
+ 0.000103951, 0.000105858, 0.000107288, 0.000108242, 0.000108719, 0.000108719, 0.000108242, 0.000106812,
+ 0.000105381, 0.000102520, 0.000099182, 0.000095367, 0.000090122, 0.000084400, 0.000077724, 0.000069618,
+ 0.000060558, 0.000050545, 0.000039577, 0.000027180, 0.000013828, -0.000000954, -0.000017166, -0.000034332,
+ -0.000052929, -0.000072956, -0.000093937, -0.000116348, -0.000140190, -0.000165462, -0.000191212, -0.000218868,
+ -0.000247478, -0.000277042, -0.000307560, -0.000339031, -0.000371456, -0.000404358, -0.000438213, -0.000472546,
+ -0.000507355, -0.000542164, -0.000576973, -0.000611782, -0.000646591, -0.000680923, -0.000714302, -0.000747204,
+ -0.000779152, -0.000809669, -0.000838757, -0.000866413, -0.000891685, -0.000915051, -0.000935555, -0.000954151,
+ -0.000968933, -0.000980854, -0.000989437, -0.000994205, -0.000995159, -0.000991821, -0.000983715, 0.000971317,
+ 0.000953674, 0.000930786, 0.000902653, 0.000868797, 0.000829220, 0.000783920, 0.000731945, 0.000674248,
+ 0.000610352, 0.000539303, 0.000462532, 0.000378609, 0.000288486, 0.000191689, 0.000088215, -0.000021458,
+ -0.000137329, -0.000259876, -0.000388145, -0.000522137, -0.000661850, -0.000806808, -0.000956535, -0.001111031,
+ -0.001269817, -0.001432419, -0.001597881, -0.001766682, -0.001937389, -0.002110004, -0.002283096, -0.002457142,
+ -0.002630711, -0.002803326, -0.002974033, -0.003141880, -0.003306866, -0.003467083, -0.003622532, -0.003771782,
+ -0.003914356, -0.004048824, -0.004174709, -0.004290581, -0.004395962, -0.004489899, -0.004570484, -0.004638195,
+ -0.004691124, -0.004728317, -0.004748821, -0.004752159, -0.004737377, -0.004703045, -0.004649162, -0.004573822,
+ -0.004477024, -0.004357815, -0.004215240, -0.004049301, -0.003858566, -0.003643036, -0.003401756, 0.003134727,
+ 0.002841473, 0.002521515, 0.002174854, 0.001800537, 0.001399517, 0.000971317, 0.000515938, 0.000033379,
+ -0.000475883, -0.001011848, -0.001573563, -0.002161503, -0.002774239, -0.003411293, -0.004072189, -0.004756451,
+ -0.005462170, -0.006189346, -0.006937027, -0.007703304, -0.008487225, -0.009287834, -0.010103703, -0.010933399,
+ -0.011775017, -0.012627602, -0.013489246, -0.014358521, -0.015233517, -0.016112804, -0.016994476, -0.017876148,
+ -0.018756866, -0.019634247, -0.020506859, -0.021372318, -0.022228718, -0.023074150, -0.023907185, -0.024725437,
+ -0.025527000, -0.026310921, -0.027073860, -0.027815342, -0.028532982, -0.029224873, -0.029890060, -0.030526638,
+ -0.031132698, -0.031706810, -0.032248020, -0.032754898, -0.033225536, -0.033659935, -0.034055710, -0.034412861,
+ -0.034730434, -0.035007000, -0.035242081, -0.035435200, -0.035586357, -0.035694122, -0.035758972, 0.035780907,
+ 0.035758972, 0.035694122, 0.035586357, 0.035435200, 0.035242081, 0.035007000, 0.034730434, 0.034412861,
+ 0.034055710, 0.033659935, 0.033225536, 0.032754898, 0.032248020, 0.031706810, 0.031132698, 0.030526638,
+ 0.029890060, 0.029224873, 0.028532982, 0.027815342, 0.027073860, 0.026310921, 0.025527000, 0.024725437,
+ 0.023907185, 0.023074150, 0.022228718, 0.021372318, 0.020506859, 0.019634247, 0.018756866, 0.017876148,
+ 0.016994476, 0.016112804, 0.015233517, 0.014358521, 0.013489246, 0.012627602, 0.011775017, 0.010933399,
+ 0.010103703, 0.009287834, 0.008487225, 0.007703304, 0.006937027, 0.006189346, 0.005462170, 0.004756451,
+ 0.004072189, 0.003411293, 0.002774239, 0.002161503, 0.001573563, 0.001011848, 0.000475883, -0.000033379,
+ -0.000515938, -0.000971317, -0.001399517, -0.001800537, -0.002174854, -0.002521515, -0.002841473, 0.003134727,
+ 0.003401756, 0.003643036, 0.003858566, 0.004049301, 0.004215240, 0.004357815, 0.004477024, 0.004573822,
+ 0.004649162, 0.004703045, 0.004737377, 0.004752159, 0.004748821, 0.004728317, 0.004691124, 0.004638195,
+ 0.004570484, 0.004489899, 0.004395962, 0.004290581, 0.004174709, 0.004048824, 0.003914356, 0.003771782,
+ 0.003622532, 0.003467083, 0.003306866, 0.003141880, 0.002974033, 0.002803326, 0.002630711, 0.002457142,
+ 0.002283096, 0.002110004, 0.001937389, 0.001766682, 0.001597881, 0.001432419, 0.001269817, 0.001111031,
+ 0.000956535, 0.000806808, 0.000661850, 0.000522137, 0.000388145, 0.000259876, 0.000137329, 0.000021458,
+ -0.000088215, -0.000191689, -0.000288486, -0.000378609, -0.000462532, -0.000539303, -0.000610352, -0.000674248,
+ -0.000731945, -0.000783920, -0.000829220, -0.000868797, -0.000902653, -0.000930786, -0.000953674, 0.000971317,
+ 0.000983715, 0.000991821, 0.000995159, 0.000994205, 0.000989437, 0.000980854, 0.000968933, 0.000954151,
+ 0.000935555, 0.000915051, 0.000891685, 0.000866413, 0.000838757, 0.000809669, 0.000779152, 0.000747204,
+ 0.000714302, 0.000680923, 0.000646591, 0.000611782, 0.000576973, 0.000542164, 0.000507355, 0.000472546,
+ 0.000438213, 0.000404358, 0.000371456, 0.000339031, 0.000307560, 0.000277042, 0.000247478, 0.000218868,
+ 0.000191212, 0.000165462, 0.000140190, 0.000116348, 0.000093937, 0.000072956, 0.000052929, 0.000034332,
+ 0.000017166, 0.000000954, -0.000013828, -0.000027180, -0.000039577, -0.000050545, -0.000060558, -0.000069618,
+ -0.000077724, -0.000084400, -0.000090122, -0.000095367, -0.000099182, -0.000102520, -0.000105381, -0.000106812,
+ -0.000108242, -0.000108719, -0.000108719, -0.000108242, -0.000107288, -0.000105858, -0.000103951, 0.000101566,
+ 0.000099182, 0.000096321, 0.000093460, 0.000090599, 0.000087261, 0.000083923, 0.000080585, 0.000076771,
+ 0.000073433, 0.000070095, 0.000066280, 0.000062943, 0.000059605, 0.000055790, 0.000052929, 0.000049591,
+ 0.000046253, 0.000043392, 0.000040531, 0.000037670, 0.000034809, 0.000032425, 0.000030041, 0.000027657,
+ 0.000025272, 0.000023365, 0.000021458, 0.000019550, 0.000018120, 0.000016689, 0.000014782, 0.000013828,
+ 0.000012398, 0.000011444, 0.000010014, 0.000009060, 0.000008106, 0.000007629, 0.000006676, 0.000006199,
+ 0.000005245, 0.000004768, 0.000004292, 0.000003815, 0.000003338, 0.000003338, 0.000002861, 0.000002384,
+ 0.000002384, 0.000001907, 0.000001907, 0.000001431, 0.000001431, 0.000000954, 0.000000954, 0.000000954,
+ 0.000000954, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477
+ };
+
+static int scale_factor_table[64];
+#ifdef USE_FLOATS
+static float scale_factor_inv_table[64];
+#else
+static INT8 scale_factor_shift[64];
+static unsigned short scale_factor_mult[64];
+#endif
+static unsigned char scale_diff_table[128];
+
+static const int sblimit_table[5] = { 27 , 30 , 8, 12 , 30 };
+
+static const int quant_steps[17] = {
+ 3, 5, 7, 9, 15,
+ 31, 63, 127, 255, 511,
+ 1023, 2047, 4095, 8191, 16383,
+ 32767, 65535
+};
+
+/* we use a negative value if grouped */
+static const int quant_bits[17] = {
+ -5, -7, 3, -10, 4,
+ 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14,
+ 15, 16
+};
+
+/* signal to noise ratio of each quantification step (could be
+ computed from quant_steps[]). The values are dB multiplied by 10
+*/
+static unsigned short quant_snr[17] = {
+ 70, 110, 160, 208,
+ 253, 316, 378, 439,
+ 499, 559, 620, 680,
+ 740, 800, 861, 920,
+ 980
+};
+
+
+/* total number of bits per allocation group */
+static unsigned short total_quant_bits[17];
+
+/* encoding tables which give the quantization index. Note how it is
+ possible to store them efficiently ! */
+static const unsigned char alloc_table_0[] = {
+ 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+};
+
+static const unsigned char alloc_table_1[] = {
+ 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 3, 0, 1, 2, 3, 4, 5, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+ 2, 0, 1, 16,
+};
+
+static const unsigned char alloc_table_2[] = {
+ 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+};
+
+static const unsigned char alloc_table_3[] = {
+ 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+};
+
+static const unsigned char alloc_table_4[] = {
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 3, 0, 1, 3, 4, 5, 6, 7,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+ 2, 0, 1, 3,
+};
+
+const unsigned char *alloc_tables[5] =
+{ alloc_table_0, alloc_table_1, alloc_table_2, alloc_table_3, alloc_table_4, };
+
+/* fixed psycho acoustic model. Values of SNR taken from the 'toolame'
+ project */
+const float fixed_smr[SBLIMIT] = {
+ 30, 17, 16, 10, 3, 12, 8, 2.5,
+ 5, 5, 6, 6, 5, 6, 10, 6,
+ -4, -10, -21, -30, -42, -55, -68, -75,
+ -75, -75, -75, -75, -91, -107, -110, -108
+};
+
+const unsigned char nb_scale_factors[4] = { 3, 2, 1, 2 };
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
new file mode 100644
index 0000000000..467062ddf6
--- /dev/null
+++ b/libavcodec/mpegvideo.c
@@ -0,0 +1,1281 @@
+/*
+ * The simplest mpeg encoder (well, it was the simplest!)
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+#define EDGE_WIDTH 16
+
+/* enable all paranoid tests for rounding, overflows, etc... */
+//#define PARANOID
+
+//#define DEBUG
+
+/* for jpeg fast DCT */
+#define CONST_BITS 14
+
+static const unsigned short aanscales[64] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+};
+
+static UINT8 h263_chroma_roundtab[16] = {
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
+};
+
+static void encode_picture(MpegEncContext *s, int picture_number);
+static void rate_control_init(MpegEncContext *s);
+static int rate_estimate_qscale(MpegEncContext *s);
+
+/* default motion estimation */
+int motion_estimation_method = ME_LOG;
+
+/* XXX: should use variable shift ? */
+#define QMAT_SHIFT_MMX 19
+#define QMAT_SHIFT 25
+
+static void convert_matrix(int *qmat, const UINT16 *quant_matrix, int qscale)
+{
+ int i;
+
+ if (av_fdct == jpeg_fdct_ifast) {
+ for(i=0;i<64;i++) {
+ /* 16 <= qscale * quant_matrix[i] <= 7905 */
+ /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */
+
+ qmat[i] = (int)((1ULL << (QMAT_SHIFT + 11)) / (aanscales[i] * qscale * quant_matrix[i]));
+ }
+ } else {
+ for(i=0;i<64;i++) {
+ /* We can safely suppose that 16 <= quant_matrix[i] <= 255
+ So 16 <= qscale * quant_matrix[i] <= 7905
+ so (1 << QMAT_SHIFT) / 16 >= qmat[i] >= (1 << QMAT_SHIFT) / 7905
+ */
+ qmat[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]);
+ }
+ }
+}
+
+/* init common structure for both encoder and decoder */
+int MPV_common_init(MpegEncContext *s)
+{
+ int c_size, i;
+ UINT8 *pict;
+
+ s->mb_width = (s->width + 15) / 16;
+ s->mb_height = (s->height + 15) / 16;
+ s->linesize = s->mb_width * 16 + 2 * EDGE_WIDTH;
+
+ for(i=0;i<3;i++) {
+ int w, h, shift, pict_start;
+
+ w = s->linesize;
+ h = s->mb_height * 16 + 2 * EDGE_WIDTH;
+ shift = (i == 0) ? 0 : 1;
+ c_size = (w >> shift) * (h >> shift);
+ pict_start = (w >> shift) * (EDGE_WIDTH >> shift) + (EDGE_WIDTH >> shift);
+
+ pict = av_mallocz(c_size);
+ if (pict == NULL)
+ goto fail;
+ s->last_picture_base[i] = pict;
+ s->last_picture[i] = pict + pict_start;
+
+ pict = av_mallocz(c_size);
+ if (pict == NULL)
+ goto fail;
+ s->next_picture_base[i] = pict;
+ s->next_picture[i] = pict + pict_start;
+
+ if (s->has_b_frames) {
+ pict = av_mallocz(c_size);
+ if (pict == NULL)
+ goto fail;
+ s->aux_picture_base[i] = pict;
+ s->aux_picture[i] = pict + pict_start;
+ }
+ }
+
+ if (s->out_format == FMT_H263) {
+ int size;
+ /* MV prediction */
+ size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2);
+ s->motion_val = malloc(size * 2 * sizeof(INT16));
+ if (s->motion_val == NULL)
+ goto fail;
+ memset(s->motion_val, 0, size * 2 * sizeof(INT16));
+ }
+
+ if (s->h263_pred) {
+ int y_size, c_size, i, size;
+
+ /* dc values */
+
+ y_size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2);
+ c_size = (s->mb_width + 2) * (s->mb_height + 2);
+ size = y_size + 2 * c_size;
+ s->dc_val[0] = malloc(size * sizeof(INT16));
+ if (s->dc_val[0] == NULL)
+ goto fail;
+ s->dc_val[1] = s->dc_val[0] + y_size;
+ s->dc_val[2] = s->dc_val[1] + c_size;
+ for(i=0;i<size;i++)
+ s->dc_val[0][i] = 1024;
+
+ /* ac values */
+ s->ac_val[0] = av_mallocz(size * sizeof(INT16) * 16);
+ if (s->ac_val[0] == NULL)
+ goto fail;
+ s->ac_val[1] = s->ac_val[0] + y_size;
+ s->ac_val[2] = s->ac_val[1] + c_size;
+
+ /* cbp values */
+ s->coded_block = av_mallocz(y_size);
+ if (!s->coded_block)
+ goto fail;
+ }
+ /* default structure is frame */
+ s->picture_structure = PICT_FRAME;
+
+ /* init default q matrix (only for mpeg and mjpeg) */
+ for(i=0;i<64;i++) {
+ s->intra_matrix[i] = default_intra_matrix[i];
+ s->chroma_intra_matrix[i] = default_intra_matrix[i];
+ s->non_intra_matrix[i] = default_non_intra_matrix[i];
+ s->chroma_non_intra_matrix[i] = default_non_intra_matrix[i];
+ }
+ s->context_initialized = 1;
+ return 0;
+ fail:
+ if (s->motion_val)
+ free(s->motion_val);
+ if (s->dc_val[0])
+ free(s->dc_val[0]);
+ if (s->ac_val[0])
+ free(s->ac_val[0]);
+ if (s->coded_block)
+ free(s->coded_block);
+ for(i=0;i<3;i++) {
+ if (s->last_picture_base[i])
+ free(s->last_picture_base[i]);
+ if (s->next_picture_base[i])
+ free(s->next_picture_base[i]);
+ if (s->aux_picture_base[i])
+ free(s->aux_picture_base[i]);
+ }
+ return -1;
+}
+
+/* init common structure for both encoder and decoder */
+void MPV_common_end(MpegEncContext *s)
+{
+ int i;
+
+ if (s->motion_val)
+ free(s->motion_val);
+ if (s->h263_pred) {
+ free(s->dc_val[0]);
+ free(s->ac_val[0]);
+ free(s->coded_block);
+ }
+ for(i=0;i<3;i++) {
+ free(s->last_picture_base[i]);
+ free(s->next_picture_base[i]);
+ if (s->has_b_frames)
+ free(s->aux_picture_base[i]);
+ }
+ s->context_initialized = 0;
+}
+
+/* init video encoder */
+int MPV_encode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ s->bit_rate = avctx->bit_rate;
+ s->frame_rate = avctx->frame_rate;
+ s->width = avctx->width;
+ s->height = avctx->height;
+ s->gop_size = avctx->gop_size;
+ if (s->gop_size <= 1) {
+ s->intra_only = 1;
+ s->gop_size = 12;
+ } else {
+ s->intra_only = 0;
+ }
+ s->full_search = motion_estimation_method;
+
+ s->fixed_qscale = (avctx->flags & CODEC_FLAG_QSCALE);
+
+ switch(avctx->codec->id) {
+ case CODEC_ID_MPEG1VIDEO:
+ s->out_format = FMT_MPEG1;
+ break;
+ case CODEC_ID_MJPEG:
+ s->out_format = FMT_MJPEG;
+ s->intra_only = 1; /* force intra only for jpeg */
+ if (mjpeg_init(s) < 0)
+ return -1;
+ break;
+ case CODEC_ID_H263:
+ if (h263_get_picture_format(s->width, s->height) == 7)
+ return -1;
+ s->out_format = FMT_H263;
+ break;
+ case CODEC_ID_H263P:
+ s->out_format = FMT_H263;
+ s->h263_plus = 1;
+ /* XXX: not unrectricted mv yet */
+ break;
+ case CODEC_ID_RV10:
+ s->out_format = FMT_H263;
+ s->h263_rv10 = 1;
+ break;
+ case CODEC_ID_OPENDIVX:
+ s->out_format = FMT_H263;
+ s->h263_pred = 1;
+ s->unrestricted_mv = 1;
+ break;
+ case CODEC_ID_MSMPEG4:
+ s->out_format = FMT_H263;
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->unrestricted_mv = 1;
+ break;
+ default:
+ return -1;
+ }
+
+ if (s->out_format == FMT_H263)
+ h263_encode_init_vlc(s);
+
+ /* init */
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ /* rate control init */
+ rate_control_init(s);
+
+ s->picture_number = 0;
+ s->fake_picture_number = 0;
+ /* motion detector init */
+ s->f_code = 1;
+
+ return 0;
+}
+
+int MPV_encode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+#ifdef STATS
+ print_stats();
+#endif
+ MPV_common_end(s);
+ if (s->out_format == FMT_MJPEG)
+ mjpeg_close(s);
+ return 0;
+}
+
+/* draw the edges of width 'w' of an image of size width, height */
+static void draw_edges(UINT8 *buf, int wrap, int width, int height, int w)
+{
+ UINT8 *ptr, *last_line;
+ int i;
+
+ last_line = buf + (height - 1) * wrap;
+ for(i=0;i<w;i++) {
+ /* top and bottom */
+ memcpy(buf - (i + 1) * wrap, buf, width);
+ memcpy(last_line + (i + 1) * wrap, last_line, width);
+ }
+ /* left and right */
+ ptr = buf;
+ for(i=0;i<height;i++) {
+ memset(ptr - w, ptr[0], w);
+ memset(ptr + width, ptr[width-1], w);
+ ptr += wrap;
+ }
+ /* corners */
+ for(i=0;i<w;i++) {
+ memset(buf - (i + 1) * wrap - w, buf[0], w); /* top left */
+ memset(buf - (i + 1) * wrap + width, buf[width-1], w); /* top right */
+ memset(last_line + (i + 1) * wrap - w, last_line[0], w); /* top left */
+ memset(last_line + (i + 1) * wrap + width, last_line[width-1], w); /* top right */
+ }
+}
+
+
+/* generic function for encode/decode called before a frame is coded/decoded */
+void MPV_frame_start(MpegEncContext *s)
+{
+ int i;
+ UINT8 *tmp;
+
+ if (s->pict_type == B_TYPE) {
+ for(i=0;i<3;i++) {
+ s->current_picture[i] = s->aux_picture[i];
+ }
+ } else {
+ for(i=0;i<3;i++) {
+ /* swap next and last */
+ tmp = s->last_picture[i];
+ s->last_picture[i] = s->next_picture[i];
+ s->next_picture[i] = tmp;
+ s->current_picture[i] = tmp;
+ }
+ }
+}
+
+/* generic function for encode/decode called after a frame has been coded/decoded */
+void MPV_frame_end(MpegEncContext *s)
+{
+ /* draw edge for correct motion prediction if outside */
+ if (s->pict_type != B_TYPE) {
+ draw_edges(s->current_picture[0], s->linesize, s->width, s->height, EDGE_WIDTH);
+ draw_edges(s->current_picture[1], s->linesize/2, s->width/2, s->height/2, EDGE_WIDTH/2);
+ draw_edges(s->current_picture[2], s->linesize/2, s->width/2, s->height/2, EDGE_WIDTH/2);
+ }
+}
+
+int MPV_encode_picture(AVCodecContext *avctx,
+ unsigned char *buf, int buf_size, void *data)
+{
+ MpegEncContext *s = avctx->priv_data;
+ AVPicture *pict = data;
+ int i, j;
+
+ if (s->fixed_qscale)
+ s->qscale = avctx->quality;
+
+ init_put_bits(&s->pb, buf, buf_size, NULL, NULL);
+
+ if (!s->intra_only) {
+ /* first picture of GOP is intra */
+ if ((s->picture_number % s->gop_size) == 0)
+ s->pict_type = I_TYPE;
+ else
+ s->pict_type = P_TYPE;
+ } else {
+ s->pict_type = I_TYPE;
+ }
+ avctx->key_frame = (s->pict_type == I_TYPE);
+
+ MPV_frame_start(s);
+
+ for(i=0;i<3;i++) {
+ UINT8 *src = pict->data[i];
+ UINT8 *dest = s->current_picture[i];
+ int src_wrap = pict->linesize[i];
+ int dest_wrap = s->linesize;
+ int w = s->width;
+ int h = s->height;
+
+ if (i >= 1) {
+ dest_wrap >>= 1;
+ w >>= 1;
+ h >>= 1;
+ }
+
+ for(j=0;j<h;j++) {
+ memcpy(dest, src, w);
+ dest += dest_wrap;
+ src += src_wrap;
+ }
+ s->new_picture[i] = s->current_picture[i];
+ }
+
+ encode_picture(s, s->picture_number);
+
+ MPV_frame_end(s);
+ s->picture_number++;
+
+ if (s->out_format == FMT_MJPEG)
+ mjpeg_picture_trailer(s);
+
+ flush_put_bits(&s->pb);
+ s->total_bits += (s->pb.buf_ptr - s->pb.buf) * 8;
+ avctx->quality = s->qscale;
+ return s->pb.buf_ptr - s->pb.buf;
+}
+
+static inline int clip(int a, int amin, int amax)
+{
+ if (a < amin)
+ return amin;
+ else if (a > amax)
+ return amax;
+ else
+ return a;
+}
+
+static int dct_quantize(MpegEncContext *s, DCTELEM *block, int n, int qscale);
+static int dct_quantize_mmx(MpegEncContext *s,
+ DCTELEM *block, int n,
+ int qscale);
+static void dct_unquantize(MpegEncContext *s, DCTELEM *block, int n, int qscale);
+
+/* apply one mpeg motion vector to the three components */
+static inline void mpeg_motion(MpegEncContext *s,
+ UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr,
+ int dest_offset,
+ UINT8 **ref_picture, int src_offset,
+ int field_based, op_pixels_func *pix_op,
+ int motion_x, int motion_y, int h)
+{
+ UINT8 *ptr;
+ int dxy, offset, mx, my, src_x, src_y, height, linesize;
+
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ src_x = s->mb_x * 16 + (motion_x >> 1);
+ src_y = s->mb_y * (16 >> field_based) + (motion_y >> 1);
+
+ /* WARNING: do no forget half pels */
+ height = s->height >> field_based;
+ src_x = clip(src_x, -16, s->width);
+ if (src_x == s->width)
+ dxy &= ~1;
+ src_y = clip(src_y, -16, height);
+ if (src_y == height)
+ dxy &= ~2;
+ linesize = s->linesize << field_based;
+ ptr = ref_picture[0] + (src_y * linesize) + (src_x) + src_offset;
+ dest_y += dest_offset;
+ pix_op[dxy](dest_y, ptr, linesize, h);
+ pix_op[dxy](dest_y + 8, ptr + 8, linesize, h);
+
+ if (s->out_format == FMT_H263) {
+ dxy = 0;
+ if ((motion_x & 3) != 0)
+ dxy |= 1;
+ if ((motion_y & 3) != 0)
+ dxy |= 2;
+ mx = motion_x >> 2;
+ my = motion_y >> 2;
+ } else {
+ mx = motion_x / 2;
+ my = motion_y / 2;
+ dxy = ((my & 1) << 1) | (mx & 1);
+ mx >>= 1;
+ my >>= 1;
+ }
+
+ src_x = s->mb_x * 8 + mx;
+ src_y = s->mb_y * (8 >> field_based) + my;
+ src_x = clip(src_x, -8, s->width >> 1);
+ if (src_x == (s->width >> 1))
+ dxy &= ~1;
+ src_y = clip(src_y, -8, height >> 1);
+ if (src_y == (height >> 1))
+ dxy &= ~2;
+
+ offset = (src_y * (linesize >> 1)) + src_x + (src_offset >> 1);
+ ptr = ref_picture[1] + offset;
+ pix_op[dxy](dest_cb + (dest_offset >> 1), ptr, linesize >> 1, h >> 1);
+ ptr = ref_picture[2] + offset;
+ pix_op[dxy](dest_cr + (dest_offset >> 1), ptr, linesize >> 1, h >> 1);
+}
+
+static inline void MPV_motion(MpegEncContext *s,
+ UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr,
+ int dir, UINT8 **ref_picture,
+ op_pixels_func *pix_op)
+{
+ int dxy, offset, mx, my, src_x, src_y, motion_x, motion_y;
+ int mb_x, mb_y, i;
+ UINT8 *ptr, *dest;
+
+ mb_x = s->mb_x;
+ mb_y = s->mb_y;
+
+ switch(s->mv_type) {
+ case MV_TYPE_16X16:
+ mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
+ ref_picture, 0,
+ 0, pix_op,
+ s->mv[dir][0][0], s->mv[dir][0][1], 16);
+ break;
+ case MV_TYPE_8X8:
+ for(i=0;i<4;i++) {
+ motion_x = s->mv[dir][i][0];
+ motion_y = s->mv[dir][i][1];
+
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ src_x = mb_x * 16 + (motion_x >> 1) + (i & 1) * 8;
+ src_y = mb_y * 16 + (motion_y >> 1) + ((i >> 1) & 1) * 8;
+
+ /* WARNING: do no forget half pels */
+ src_x = clip(src_x, -16, s->width);
+ if (src_x == s->width)
+ dxy &= ~1;
+ src_y = clip(src_y, -16, s->height);
+ if (src_y == s->height)
+ dxy &= ~2;
+
+ ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);
+ dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize;
+ pix_op[dxy](dest, ptr, s->linesize, 8);
+ }
+ /* In case of 8X8, we construct a single chroma motion vector
+ with a special rounding */
+ mx = 0;
+ my = 0;
+ for(i=0;i<4;i++) {
+ mx += s->mv[dir][i][0];
+ my += s->mv[dir][i][1];
+ }
+ if (mx >= 0)
+ mx = (h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1));
+ else {
+ mx = -mx;
+ mx = -(h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1));
+ }
+ if (my >= 0)
+ my = (h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1));
+ else {
+ my = -my;
+ my = -(h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1));
+ }
+ dxy = ((my & 1) << 1) | (mx & 1);
+ mx >>= 1;
+ my >>= 1;
+
+ src_x = mb_x * 8 + mx;
+ src_y = mb_y * 8 + my;
+ src_x = clip(src_x, -8, s->width/2);
+ if (src_x == s->width/2)
+ dxy &= ~1;
+ src_y = clip(src_y, -8, s->height/2);
+ if (src_y == s->height/2)
+ dxy &= ~2;
+
+ offset = (src_y * (s->linesize >> 1)) + src_x;
+ ptr = ref_picture[1] + offset;
+ pix_op[dxy](dest_cb, ptr, s->linesize >> 1, 8);
+ ptr = ref_picture[2] + offset;
+ pix_op[dxy](dest_cr, ptr, s->linesize >> 1, 8);
+ break;
+ case MV_TYPE_FIELD:
+ if (s->picture_structure == PICT_FRAME) {
+ /* top field */
+ mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
+ ref_picture, s->field_select[dir][0] ? s->linesize : 0,
+ 1, pix_op,
+ s->mv[dir][0][0], s->mv[dir][0][1], 8);
+ /* bottom field */
+ mpeg_motion(s, dest_y, dest_cb, dest_cr, s->linesize,
+ ref_picture, s->field_select[dir][1] ? s->linesize : 0,
+ 1, pix_op,
+ s->mv[dir][1][0], s->mv[dir][1][1], 8);
+ } else {
+
+
+ }
+ break;
+ }
+}
+
+
+/* put block[] to dest[] */
+static inline void put_dct(MpegEncContext *s,
+ DCTELEM *block, int i, UINT8 *dest, int line_size)
+{
+ if (!s->mpeg2)
+ dct_unquantize(s, block, i, s->qscale);
+ j_rev_dct (block);
+ put_pixels_clamped(block, dest, line_size);
+}
+
+/* add block[] to dest[] */
+static inline void add_dct(MpegEncContext *s,
+ DCTELEM *block, int i, UINT8 *dest, int line_size)
+{
+ if (s->block_last_index[i] >= 0) {
+ if (!s->mpeg2)
+ dct_unquantize(s, block, i, s->qscale);
+ j_rev_dct (block);
+ add_pixels_clamped(block, dest, line_size);
+ }
+}
+
+/* generic function called after a macroblock has been parsed by the
+ decoder or after it has been encoded by the encoder.
+
+ Important variables used:
+ s->mb_intra : true if intra macroblock
+ s->mv_dir : motion vector direction
+ s->mv_type : motion vector type
+ s->mv : motion vector
+ s->interlaced_dct : true if interlaced dct used (mpeg2)
+ */
+void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
+{
+ int mb_x, mb_y, motion_x, motion_y;
+ int dct_linesize, dct_offset;
+ op_pixels_func *op_pix;
+
+ mb_x = s->mb_x;
+ mb_y = s->mb_y;
+
+ /* update DC predictors for P macroblocks */
+ if (!s->mb_intra) {
+ if (s->h263_pred) {
+ int wrap, x, y, v;
+ wrap = 2 * s->mb_width + 2;
+ v = 1024;
+ x = 2 * mb_x + 1;
+ y = 2 * mb_y + 1;
+ s->dc_val[0][(x) + (y) * wrap] = v;
+ s->dc_val[0][(x + 1) + (y) * wrap] = v;
+ s->dc_val[0][(x) + (y + 1) * wrap] = v;
+ s->dc_val[0][(x + 1) + (y + 1) * wrap] = v;
+ /* ac pred */
+ memset(s->ac_val[0][(x) + (y) * wrap], 0, 16 * sizeof(INT16));
+ memset(s->ac_val[0][(x + 1) + (y) * wrap], 0, 16 * sizeof(INT16));
+ memset(s->ac_val[0][(x) + (y + 1) * wrap], 0, 16 * sizeof(INT16));
+ memset(s->ac_val[0][(x + 1) + (y + 1) * wrap], 0, 16 * sizeof(INT16));
+ if (s->h263_msmpeg4) {
+ s->coded_block[(x) + (y) * wrap] = 0;
+ s->coded_block[(x + 1) + (y) * wrap] = 0;
+ s->coded_block[(x) + (y + 1) * wrap] = 0;
+ s->coded_block[(x + 1) + (y + 1) * wrap] = 0;
+ }
+ /* chroma */
+ wrap = s->mb_width + 2;
+ x = mb_x + 1;
+ y = mb_y + 1;
+ s->dc_val[1][(x) + (y) * wrap] = v;
+ s->dc_val[2][(x) + (y) * wrap] = v;
+ /* ac pred */
+ memset(s->ac_val[1][(x) + (y) * wrap], 0, 16 * sizeof(INT16));
+ memset(s->ac_val[2][(x) + (y) * wrap], 0, 16 * sizeof(INT16));
+ } else {
+ s->last_dc[0] = 128 << s->intra_dc_precision;
+ s->last_dc[1] = 128 << s->intra_dc_precision;
+ s->last_dc[2] = 128 << s->intra_dc_precision;
+ }
+ }
+
+ /* update motion predictor */
+ if (s->out_format == FMT_H263) {
+ int x, y, wrap;
+
+ x = 2 * mb_x + 1;
+ y = 2 * mb_y + 1;
+ wrap = 2 * s->mb_width + 2;
+ if (s->mb_intra) {
+ motion_x = 0;
+ motion_y = 0;
+ goto motion_init;
+ } else if (s->mv_type == MV_TYPE_16X16) {
+ motion_x = s->mv[0][0][0];
+ motion_y = s->mv[0][0][1];
+ motion_init:
+ /* no update if 8X8 because it has been done during parsing */
+ s->motion_val[(x) + (y) * wrap][0] = motion_x;
+ s->motion_val[(x) + (y) * wrap][1] = motion_y;
+ s->motion_val[(x + 1) + (y) * wrap][0] = motion_x;
+ s->motion_val[(x + 1) + (y) * wrap][1] = motion_y;
+ s->motion_val[(x) + (y + 1) * wrap][0] = motion_x;
+ s->motion_val[(x) + (y + 1) * wrap][1] = motion_y;
+ s->motion_val[(x + 1) + (y + 1) * wrap][0] = motion_x;
+ s->motion_val[(x + 1) + (y + 1) * wrap][1] = motion_y;
+ }
+ }
+
+ if (!s->intra_only) {
+ UINT8 *dest_y, *dest_cb, *dest_cr;
+
+ dest_y = s->current_picture[0] + (mb_y * 16 * s->linesize) + mb_x * 16;
+ dest_cb = s->current_picture[1] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8;
+ dest_cr = s->current_picture[2] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8;
+
+ if (s->interlaced_dct) {
+ dct_linesize = s->linesize * 2;
+ dct_offset = s->linesize;
+ } else {
+ dct_linesize = s->linesize;
+ dct_offset = s->linesize * 8;
+ }
+
+ if (!s->mb_intra) {
+ /* motion handling */
+ if (!s->no_rounding)
+ op_pix = put_pixels_tab;
+ else
+ op_pix = put_no_rnd_pixels_tab;
+
+ if (s->mv_dir & MV_DIR_FORWARD) {
+ MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix);
+ if (!s->no_rounding)
+ op_pix = avg_pixels_tab;
+ else
+ op_pix = avg_no_rnd_pixels_tab;
+ }
+ if (s->mv_dir & MV_DIR_BACKWARD) {
+ MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix);
+ }
+
+ /* add dct residue */
+ add_dct(s, block[0], 0, dest_y, dct_linesize);
+ add_dct(s, block[1], 1, dest_y + 8, dct_linesize);
+ add_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize);
+ add_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize);
+
+ add_dct(s, block[4], 4, dest_cb, dct_linesize >> 1);
+ add_dct(s, block[5], 5, dest_cr, dct_linesize >> 1);
+ } else {
+ /* dct only in intra block */
+ put_dct(s, block[0], 0, dest_y, dct_linesize);
+ put_dct(s, block[1], 1, dest_y + 8, dct_linesize);
+ put_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize);
+ put_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize);
+
+ put_dct(s, block[4], 4, dest_cb, dct_linesize >> 1);
+ put_dct(s, block[5], 5, dest_cr, dct_linesize >> 1);
+ }
+ }
+}
+
+static void encode_picture(MpegEncContext *s, int picture_number)
+{
+ int mb_x, mb_y, wrap;
+ UINT8 *ptr;
+ DCTELEM block[6][64];
+ int i, motion_x, motion_y;
+
+ s->picture_number = picture_number;
+ if (!s->fixed_qscale)
+ s->qscale = rate_estimate_qscale(s);
+
+ /* precompute matrix */
+ if (s->out_format == FMT_MJPEG) {
+ /* for mjpeg, we do include qscale in the matrix */
+ s->intra_matrix[0] = default_intra_matrix[0];
+ for(i=1;i<64;i++)
+ s->intra_matrix[i] = (default_intra_matrix[i] * s->qscale) >> 3;
+ convert_matrix(s->q_intra_matrix, s->intra_matrix, 8);
+ } else {
+ convert_matrix(s->q_intra_matrix, s->intra_matrix, s->qscale);
+ convert_matrix(s->q_non_intra_matrix, s->non_intra_matrix, s->qscale);
+ }
+
+ switch(s->out_format) {
+ case FMT_MJPEG:
+ mjpeg_picture_header(s);
+ break;
+ case FMT_H263:
+ if (s->h263_msmpeg4)
+ msmpeg4_encode_picture_header(s, picture_number);
+ else if (s->h263_pred)
+ mpeg4_encode_picture_header(s, picture_number);
+ else if (s->h263_rv10)
+ rv10_encode_picture_header(s, picture_number);
+ else
+ h263_encode_picture_header(s, picture_number);
+ break;
+ case FMT_MPEG1:
+ mpeg1_encode_picture_header(s, picture_number);
+ break;
+ }
+
+ /* init last dc values */
+ /* note: quant matrix value (8) is implied here */
+ s->last_dc[0] = 128;
+ s->last_dc[1] = 128;
+ s->last_dc[2] = 128;
+ s->mb_incr = 1;
+ s->last_mv[0][0][0] = 0;
+ s->last_mv[0][0][1] = 0;
+ s->mv_type = MV_TYPE_16X16;
+ s->mv_dir = MV_DIR_FORWARD;
+
+ for(mb_y=0; mb_y < s->mb_height; mb_y++) {
+ for(mb_x=0; mb_x < s->mb_width; mb_x++) {
+
+ s->mb_x = mb_x;
+ s->mb_y = mb_y;
+
+ /* compute motion vector and macro block type (intra or non intra) */
+ motion_x = 0;
+ motion_y = 0;
+ if (s->pict_type == P_TYPE) {
+ s->mb_intra = estimate_motion(s, mb_x, mb_y,
+ &motion_x,
+ &motion_y);
+ } else {
+ s->mb_intra = 1;
+ }
+
+ /* get the pixels */
+ wrap = s->linesize;
+ ptr = s->new_picture[0] + (mb_y * 16 * wrap) + mb_x * 16;
+ get_pixels(block[0], ptr, wrap);
+ get_pixels(block[1], ptr + 8, wrap);
+ get_pixels(block[2], ptr + 8 * wrap, wrap);
+ get_pixels(block[3], ptr + 8 * wrap + 8, wrap);
+ wrap = s->linesize >> 1;
+ ptr = s->new_picture[1] + (mb_y * 8 * wrap) + mb_x * 8;
+ get_pixels(block[4], ptr, wrap);
+
+ wrap = s->linesize >> 1;
+ ptr = s->new_picture[2] + (mb_y * 8 * wrap) + mb_x * 8;
+ get_pixels(block[5], ptr, wrap);
+
+ /* subtract previous frame if non intra */
+ if (!s->mb_intra) {
+ int dxy, offset, mx, my;
+
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ ptr = s->last_picture[0] +
+ ((mb_y * 16 + (motion_y >> 1)) * s->linesize) +
+ (mb_x * 16 + (motion_x >> 1));
+
+ sub_pixels_2(block[0], ptr, s->linesize, dxy);
+ sub_pixels_2(block[1], ptr + 8, s->linesize, dxy);
+ sub_pixels_2(block[2], ptr + s->linesize * 8, s->linesize, dxy);
+ sub_pixels_2(block[3], ptr + 8 + s->linesize * 8, s->linesize ,dxy);
+
+ if (s->out_format == FMT_H263) {
+ /* special rounding for h263 */
+ dxy = 0;
+ if ((motion_x & 3) != 0)
+ dxy |= 1;
+ if ((motion_y & 3) != 0)
+ dxy |= 2;
+ mx = motion_x >> 2;
+ my = motion_y >> 2;
+ } else {
+ mx = motion_x / 2;
+ my = motion_y / 2;
+ dxy = ((my & 1) << 1) | (mx & 1);
+ mx >>= 1;
+ my >>= 1;
+ }
+ offset = ((mb_y * 8 + my) * (s->linesize >> 1)) + (mb_x * 8 + mx);
+ ptr = s->last_picture[1] + offset;
+ sub_pixels_2(block[4], ptr, s->linesize >> 1, dxy);
+ ptr = s->last_picture[2] + offset;
+ sub_pixels_2(block[5], ptr, s->linesize >> 1, dxy);
+ }
+
+ /* DCT & quantize */
+ if (s->h263_msmpeg4) {
+ msmpeg4_dc_scale(s);
+ } else if (s->h263_pred) {
+ h263_dc_scale(s);
+ } else {
+ /* default quantization values */
+ s->y_dc_scale = 8;
+ s->c_dc_scale = 8;
+ }
+
+ for(i=0;i<6;i++) {
+ int last_index;
+ if (av_fdct == jpeg_fdct_ifast)
+ last_index = dct_quantize(s, block[i], i, s->qscale);
+ else
+ last_index = dct_quantize_mmx(s, block[i], i, s->qscale);
+ s->block_last_index[i] = last_index;
+ }
+
+ /* huffman encode */
+ switch(s->out_format) {
+ case FMT_MPEG1:
+ mpeg1_encode_mb(s, block, motion_x, motion_y);
+ break;
+ case FMT_H263:
+ if (s->h263_msmpeg4)
+ msmpeg4_encode_mb(s, block, motion_x, motion_y);
+ else
+ h263_encode_mb(s, block, motion_x, motion_y);
+ break;
+ case FMT_MJPEG:
+ mjpeg_encode_mb(s, block);
+ break;
+ }
+
+ /* decompress blocks so that we keep the state of the decoder */
+ s->mv[0][0][0] = motion_x;
+ s->mv[0][0][1] = motion_y;
+
+ MPV_decode_mb(s, block);
+ }
+ }
+}
+
+static int dct_quantize(MpegEncContext *s,
+ DCTELEM *block, int n,
+ int qscale)
+{
+ int i, j, level, last_non_zero, q;
+ const int *qmat;
+
+ av_fdct (block);
+
+ if (s->mb_intra) {
+ if (n < 4)
+ q = s->y_dc_scale;
+ else
+ q = s->c_dc_scale;
+ q = q << 3;
+
+ /* note: block[0] is assumed to be positive */
+ block[0] = (block[0] + (q >> 1)) / q;
+ i = 1;
+ last_non_zero = 0;
+ if (s->out_format == FMT_H263) {
+ qmat = s->q_non_intra_matrix;
+ } else {
+ qmat = s->q_intra_matrix;
+ }
+ } else {
+ i = 0;
+ last_non_zero = -1;
+ qmat = s->q_non_intra_matrix;
+ }
+
+ for(;i<64;i++) {
+ j = zigzag_direct[i];
+ level = block[j];
+ level = level * qmat[j];
+#ifdef PARANOID
+ {
+ static int count = 0;
+ int level1, level2, qmat1;
+ double val;
+ if (qmat == s->q_non_intra_matrix) {
+ qmat1 = default_non_intra_matrix[j] * s->qscale;
+ } else {
+ qmat1 = default_intra_matrix[j] * s->qscale;
+ }
+ if (av_fdct != jpeg_fdct_ifast)
+ val = ((double)block[j] * 8.0) / (double)qmat1;
+ else
+ val = ((double)block[j] * 8.0 * 2048.0) /
+ ((double)qmat1 * aanscales[j]);
+ level1 = (int)val;
+ level2 = level / (1 << (QMAT_SHIFT - 3));
+ if (level1 != level2) {
+ fprintf(stderr, "%d: quant error qlevel=%d wanted=%d level=%d qmat1=%d qmat=%d wantedf=%0.6f\n",
+ count, level2, level1, block[j], qmat1, qmat[j],
+ val);
+ count++;
+ }
+
+ }
+#endif
+ /* XXX: slight error for the low range. Test should be equivalent to
+ (level <= -(1 << (QMAT_SHIFT - 3)) || level >= (1 <<
+ (QMAT_SHIFT - 3)))
+ */
+ if (((level << (31 - (QMAT_SHIFT - 3))) >> (31 - (QMAT_SHIFT - 3))) !=
+ level) {
+ level = level / (1 << (QMAT_SHIFT - 3));
+ /* XXX: currently, this code is not optimal. the range should be:
+ mpeg1: -255..255
+ mpeg2: -2048..2047
+ h263: -128..127
+ mpeg4: -2048..2047
+ */
+ if (level > 127)
+ level = 127;
+ else if (level < -128)
+ level = -128;
+ block[j] = level;
+ last_non_zero = i;
+ } else {
+ block[j] = 0;
+ }
+ }
+ return last_non_zero;
+}
+
+static int dct_quantize_mmx(MpegEncContext *s,
+ DCTELEM *block, int n,
+ int qscale)
+{
+ int i, j, level, last_non_zero, q;
+ const int *qmat;
+
+ av_fdct (block);
+
+ if (s->mb_intra) {
+ if (n < 4)
+ q = s->y_dc_scale;
+ else
+ q = s->c_dc_scale;
+
+ /* note: block[0] is assumed to be positive */
+ block[0] = (block[0] + (q >> 1)) / q;
+ i = 1;
+ last_non_zero = 0;
+ if (s->out_format == FMT_H263) {
+ qmat = s->q_non_intra_matrix;
+ } else {
+ qmat = s->q_intra_matrix;
+ }
+ } else {
+ i = 0;
+ last_non_zero = -1;
+ qmat = s->q_non_intra_matrix;
+ }
+
+ for(;i<64;i++) {
+ j = zigzag_direct[i];
+ level = block[j];
+ level = level * qmat[j];
+ /* XXX: slight error for the low range. Test should be equivalent to
+ (level <= -(1 << (QMAT_SHIFT_MMX - 3)) || level >= (1 <<
+ (QMAT_SHIFT_MMX - 3)))
+ */
+ if (((level << (31 - (QMAT_SHIFT_MMX - 3))) >> (31 - (QMAT_SHIFT_MMX - 3))) !=
+ level) {
+ level = level / (1 << (QMAT_SHIFT_MMX - 3));
+ /* XXX: currently, this code is not optimal. the range should be:
+ mpeg1: -255..255
+ mpeg2: -2048..2047
+ h263: -128..127
+ mpeg4: -2048..2047
+ */
+ if (level > 127)
+ level = 127;
+ else if (level < -128)
+ level = -128;
+ block[j] = level;
+ last_non_zero = i;
+ } else {
+ block[j] = 0;
+ }
+ }
+ return last_non_zero;
+}
+
+static void dct_unquantize(MpegEncContext *s,
+ DCTELEM *block, int n, int qscale)
+{
+ int i, level;
+ const UINT16 *quant_matrix;
+
+ if (s->mb_intra) {
+ if (n < 4)
+ block[0] = block[0] * s->y_dc_scale;
+ else
+ block[0] = block[0] * s->c_dc_scale;
+ if (s->out_format == FMT_H263) {
+ i = 1;
+ goto unquant_even;
+ }
+ /* XXX: only mpeg1 */
+ quant_matrix = s->intra_matrix;
+ for(i=1;i<64;i++) {
+ level = block[i];
+ if (level) {
+ if (level < 0) {
+ level = -level;
+ level = (int)(level * qscale * quant_matrix[i]) >> 3;
+ level = (level - 1) | 1;
+ level = -level;
+ } else {
+ level = (int)(level * qscale * quant_matrix[i]) >> 3;
+ level = (level - 1) | 1;
+ }
+#ifdef PARANOID
+ if (level < -2048 || level > 2047)
+ fprintf(stderr, "unquant error %d %d\n", i, level);
+#endif
+ block[i] = level;
+ }
+ }
+ } else {
+ i = 0;
+ unquant_even:
+ quant_matrix = s->non_intra_matrix;
+ for(;i<64;i++) {
+ level = block[i];
+ if (level) {
+ if (level < 0) {
+ level = -level;
+ level = (((level << 1) + 1) * qscale *
+ ((int) (quant_matrix[i]))) >> 4;
+ level = (level - 1) | 1;
+ level = -level;
+ } else {
+ level = (((level << 1) + 1) * qscale *
+ ((int) (quant_matrix[i]))) >> 4;
+ level = (level - 1) | 1;
+ }
+#ifdef PARANOID
+ if (level < -2048 || level > 2047)
+ fprintf(stderr, "unquant error %d %d\n", i, level);
+#endif
+ block[i] = level;
+ }
+ }
+ }
+}
+
+
+/* rate control */
+
+/* an I frame is I_FRAME_SIZE_RATIO bigger than a P frame */
+#define I_FRAME_SIZE_RATIO 3.0
+#define QSCALE_K 20
+
+static void rate_control_init(MpegEncContext *s)
+{
+ s->wanted_bits = 0;
+
+ if (s->intra_only) {
+ s->I_frame_bits = ((INT64)s->bit_rate * FRAME_RATE_BASE) / s->frame_rate;
+ s->P_frame_bits = s->I_frame_bits;
+ } else {
+ s->P_frame_bits = (int) ((float)(s->gop_size * s->bit_rate) /
+ (float)((float)s->frame_rate / FRAME_RATE_BASE * (I_FRAME_SIZE_RATIO + s->gop_size - 1)));
+ s->I_frame_bits = (int)(s->P_frame_bits * I_FRAME_SIZE_RATIO);
+ }
+
+#if defined(DEBUG)
+ printf("I_frame_size=%d P_frame_size=%d\n",
+ s->I_frame_bits, s->P_frame_bits);
+#endif
+}
+
+
+/*
+ * This heuristic is rather poor, but at least we do not have to
+ * change the qscale at every macroblock.
+ */
+static int rate_estimate_qscale(MpegEncContext *s)
+{
+ long long total_bits = s->total_bits;
+ float q;
+ int qscale, diff, qmin;
+
+ if (s->pict_type == I_TYPE) {
+ s->wanted_bits += s->I_frame_bits;
+ } else {
+ s->wanted_bits += s->P_frame_bits;
+ }
+ diff = s->wanted_bits - total_bits;
+ q = 31.0 - (float)diff / (QSCALE_K * s->mb_height * s->mb_width);
+ /* adjust for I frame */
+ if (s->pict_type == I_TYPE && !s->intra_only) {
+ q /= I_FRAME_SIZE_RATIO;
+ }
+
+ /* using a too small Q scale leeds to problems in mpeg1 and h263
+ because AC coefficients are clamped to 255 or 127 */
+ qmin = 3;
+ if (q < qmin)
+ q = qmin;
+ else if (q > 31)
+ q = 31;
+ qscale = (int)(q + 0.5);
+#if defined(DEBUG)
+ printf("%d: total=%Ld br=%0.1f diff=%d qest=%0.1f\n",
+ s->picture_number,
+ total_bits,
+ (float)s->frame_rate / FRAME_RATE_BASE *
+ total_bits / s->picture_number,
+ diff, q);
+#endif
+ return qscale;
+}
+
+AVCodec mpeg1video_encoder = {
+ "mpeg1video",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MPEG1VIDEO,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+};
+
+AVCodec h263_encoder = {
+ "h263",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+};
+
+AVCodec h263p_encoder = {
+ "h263p",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263P,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+};
+
+AVCodec rv10_encoder = {
+ "rv10",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RV10,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+};
+
+AVCodec mjpeg_encoder = {
+ "mjpeg",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MJPEG,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+};
+
+AVCodec opendivx_encoder = {
+ "opendivx",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_OPENDIVX,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+};
+
+AVCodec msmpeg4_encoder = {
+ "msmpeg4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4,
+ sizeof(MpegEncContext),
+ MPV_encode_init,
+ MPV_encode_picture,
+ MPV_encode_end,
+};
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
new file mode 100644
index 0000000000..b04d7b7693
--- /dev/null
+++ b/libavcodec/mpegvideo.h
@@ -0,0 +1,273 @@
+/*
+ * Generic DCT based hybrid video encoder
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Macros for picture code type. */
+#define I_TYPE 1
+#define P_TYPE 2
+#define B_TYPE 3
+
+enum OutputFormat {
+ FMT_MPEG1,
+ FMT_H263,
+ FMT_MJPEG,
+};
+
+#define MPEG_BUF_SIZE (16 * 1024)
+
+typedef struct MpegEncContext {
+ /* the following parameters must be initialized before encoding */
+ int width, height; /* picture size. must be a multiple of 16 */
+ int gop_size;
+ int frame_rate; /* number of frames per second */
+ int intra_only; /* if true, only intra pictures are generated */
+ int bit_rate; /* wanted bit rate */
+ enum OutputFormat out_format; /* output format */
+ int h263_plus; /* h263 plus headers */
+ int h263_rv10; /* use RV10 variation for H263 */
+ int h263_pred; /* use OpenDIVX (aka mpeg4) ac/dc predictions */
+ int h263_msmpeg4; /* generate MSMPEG4 compatible stream */
+ int h263_intel; /* use I263 intel h263 header */
+ int fixed_qscale; /* fixed qscale if non zero */
+ /* the following fields are managed internally by the encoder */
+
+ /* bit output */
+ PutBitContext pb;
+
+ /* sequence parameters */
+ int context_initialized;
+ int picture_number;
+ int fake_picture_number; /* picture number at the bitstream frame rate */
+ int gop_picture_number; /* index of the first picture of a GOP */
+ int mb_width, mb_height;
+ int linesize; /* line size, in bytes, may be different from width */
+ UINT8 *new_picture[3]; /* picture to be compressed */
+ UINT8 *last_picture[3]; /* previous picture */
+ UINT8 *last_picture_base[3]; /* real start of the picture */
+ UINT8 *next_picture[3]; /* previous picture (for bidir pred) */
+ UINT8 *next_picture_base[3]; /* real start of the picture */
+ UINT8 *aux_picture[3]; /* aux picture (for B frames only) */
+ UINT8 *aux_picture_base[3]; /* real start of the picture */
+ UINT8 *current_picture[3]; /* buffer to store the decompressed current picture */
+ int last_dc[3]; /* last DC values for MPEG1 */
+ INT16 *dc_val[3]; /* used for mpeg4 DC prediction */
+ int y_dc_scale, c_dc_scale;
+ UINT8 *coded_block; /* used for coded block pattern prediction */
+ INT16 (*ac_val[3])[16]; /* used for for mpeg4 AC prediction */
+ int ac_pred;
+
+ int qscale;
+ int pict_type;
+ int frame_rate_index;
+ /* motion compensation */
+ int unrestricted_mv;
+ int h263_long_vectors; /* use horrible h263v1 long vector mode */
+
+ int f_code; /* resolution */
+ INT16 (*motion_val)[2]; /* used for MV prediction */
+ int full_search;
+ int mv_dir;
+#define MV_DIR_BACKWARD 1
+#define MV_DIR_FORWARD 2
+ int mv_type;
+#define MV_TYPE_16X16 0 /* 1 vector for the whole mb */
+#define MV_TYPE_8X8 1 /* 4 vectors (h263) */
+#define MV_TYPE_16X8 2 /* 2 vectors, one per 16x8 block */
+#define MV_TYPE_FIELD 3 /* 2 vectors, one per field */
+#define MV_TYPE_DMV 4 /* 2 vectors, special mpeg2 Dual Prime Vectors */
+ /* motion vectors for a macroblock
+ first coordinate : 0 = forward 1 = backward
+ second " : depend on type
+ third " : 0 = x, 1 = y
+ */
+ int mv[2][4][2];
+ int field_select[2][2];
+ int last_mv[2][2][2];
+
+ int has_b_frames;
+ int no_rounding; /* apply no rounding to motion estimation (MPEG4) */
+
+ /* macroblock layer */
+ int mb_x, mb_y;
+ int mb_incr;
+ int mb_intra;
+ /* matrix transmitted in the bitstream */
+ UINT16 intra_matrix[64];
+ UINT16 chroma_intra_matrix[64];
+ UINT16 non_intra_matrix[64];
+ UINT16 chroma_non_intra_matrix[64];
+ /* precomputed matrix (combine qscale and DCT renorm) */
+ int q_intra_matrix[64];
+ int q_non_intra_matrix[64];
+ int block_last_index[6]; /* last non zero coefficient in block */
+
+ void *opaque; /* private data for the user */
+
+ /* bit rate control */
+ int I_frame_bits; /* wanted number of bits per I frame */
+ int P_frame_bits; /* same for P frame */
+ long long wanted_bits;
+ long long total_bits;
+
+ /* mpeg4 specific */
+ int time_increment_bits;
+
+ /* RV10 specific */
+ int rv10_version; /* RV10 version: 0 or 3 */
+ int rv10_first_dc_coded[3];
+
+ /* MJPEG specific */
+ struct MJpegContext *mjpeg_ctx;
+
+ /* MSMPEG4 specific */
+ int mv_table_index;
+ int rl_table_index;
+ int rl_chroma_table_index;
+ int dc_table_index;
+ int use_skip_mb_code;
+ int slice_height; /* in macroblocks */
+ int first_slice_line;
+ /* decompression specific */
+ GetBitContext gb;
+
+ /* MPEG2 specific - I wish I had not to support this mess. */
+ int progressive_sequence;
+ int mpeg_f_code[2][2];
+ int picture_structure;
+/* picture type */
+#define PICT_TOP_FIELD 1
+#define PICT_BOTTOM_FIELD 2
+#define PICT_FRAME 3
+
+ int intra_dc_precision;
+ int frame_pred_frame_dct;
+ int top_field_first;
+ int concealment_motion_vectors;
+ int q_scale_type;
+ int intra_vlc_format;
+ int alternate_scan;
+ int repeat_first_field;
+ int chroma_420_type;
+ int progressive_frame;
+ int mpeg2;
+ int full_pel[2];
+ int interlaced_dct;
+ int last_qscale;
+ int first_slice;
+} MpegEncContext;
+
+extern const UINT8 zigzag_direct[64];
+
+int MPV_common_init(MpegEncContext *s);
+void MPV_common_end(MpegEncContext *s);
+void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
+void MPV_frame_start(MpegEncContext *s);
+void MPV_frame_end(MpegEncContext *s);
+
+/* motion_est.c */
+
+int estimate_motion(MpegEncContext *s,
+ int mb_x, int mb_y,
+ int *mx_ptr, int *my_ptr);
+
+/* mpeg12.c */
+extern const UINT8 default_intra_matrix[64];
+extern const UINT8 default_non_intra_matrix[64];
+
+void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number);
+void mpeg1_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y);
+
+/* h263enc.c */
+
+/* run length table */
+#define MAX_RUN 64
+#define MAX_LEVEL 64
+
+typedef struct RLTable {
+ int n; /* number of entries of table_vlc minus 1 */
+ int last; /* number of values for last = 0 */
+ const UINT16 (*table_vlc)[2];
+ const INT8 *table_run;
+ const INT8 *table_level;
+ UINT8 *index_run[2]; /* encoding only */
+ INT8 *max_level[2]; /* encoding & decoding */
+ INT8 *max_run[2]; /* encoding & decoding */
+ VLC vlc; /* decoding only */
+} RLTable;
+
+void init_rl(RLTable *rl);
+void init_vlc_rl(RLTable *rl);
+
+extern inline int get_rl_index(const RLTable *rl, int last, int run, int level)
+{
+ int index;
+ index = rl->index_run[last][run];
+ if (index >= rl->n)
+ return rl->n;
+ if (level > rl->max_level[last][run])
+ return rl->n;
+ return index + level - 1;
+}
+
+void h263_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y);
+void h263_encode_picture_header(MpegEncContext *s, int picture_number);
+void h263_dc_scale(MpegEncContext *s);
+INT16 *h263_pred_motion(MpegEncContext * s, int block,
+ int *px, int *py);
+void mpeg4_pred_ac(MpegEncContext * s, INT16 *block, int n,
+ int dir);
+void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number);
+void h263_encode_init_vlc(MpegEncContext *s);
+
+void h263_decode_init_vlc(MpegEncContext *s);
+int h263_decode_picture_header(MpegEncContext *s);
+int mpeg4_decode_picture_header(MpegEncContext * s);
+int intel_h263_decode_picture_header(MpegEncContext *s);
+int h263_decode_mb(MpegEncContext *s,
+ DCTELEM block[6][64]);
+int h263_get_picture_format(int width, int height);
+extern UINT8 ff_alternate_horizontal_scan[64];
+extern UINT8 ff_alternate_vertical_scan[64];
+
+/* rv10.c */
+void rv10_encode_picture_header(MpegEncContext *s, int picture_number);
+int rv_decode_dc(MpegEncContext *s, int n);
+
+/* msmpeg4.c */
+void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number);
+void msmpeg4_encode_mb(MpegEncContext * s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y);
+void msmpeg4_dc_scale(MpegEncContext * s);
+int msmpeg4_decode_picture_header(MpegEncContext * s);
+int msmpeg4_decode_mb(MpegEncContext *s,
+ DCTELEM block[6][64]);
+int msmpeg4_decode_init_vlc(MpegEncContext *s);
+
+/* mjpegenc.c */
+
+int mjpeg_init(MpegEncContext *s);
+void mjpeg_close(MpegEncContext *s);
+void mjpeg_encode_mb(MpegEncContext *s,
+ DCTELEM block[6][64]);
+void mjpeg_picture_header(MpegEncContext *s);
+void mjpeg_picture_trailer(MpegEncContext *s);
diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c
new file mode 100644
index 0000000000..044d964ee5
--- /dev/null
+++ b/libavcodec/msmpeg4.c
@@ -0,0 +1,931 @@
+/*
+ * MSMPEG4 backend for ffmpeg encoder and decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "common.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+/*
+ * You can also call this codec : MPEG4 with a twist !
+ *
+ * TODO:
+ * - (encoding) select best mv table (two choices)
+ * - (encoding) select best vlc/dc table
+ * - (decoding) handle slice indication
+ */
+//#define DEBUG
+
+/* motion vector table */
+typedef struct MVTable {
+ int n;
+ const UINT16 *table_mv_code;
+ const UINT8 *table_mv_bits;
+ const UINT8 *table_mvx;
+ const UINT8 *table_mvy;
+ UINT16 *table_mv_index; /* encoding: convert mv to index in table_mv */
+ VLC vlc; /* decoding: vlc */
+} MVTable;
+
+static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n);
+static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded);
+static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr);
+static int msmpeg4_decode_motion(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr);
+
+#ifdef DEBUG
+int intra_count = 0;
+int frame_count = 0;
+#endif
+/* XXX: move it to mpegvideo.h */
+
+static int init_done = 0;
+
+#include "msmpeg4data.h"
+
+#ifdef STATS
+
+const char *st_names[ST_NB] = {
+ "unknown",
+ "dc",
+ "intra_ac",
+ "inter_ac",
+ "intra_mb",
+ "inter_mb",
+ "mv",
+};
+
+int st_current_index = 0;
+unsigned int st_bit_counts[ST_NB];
+unsigned int st_out_bit_counts[ST_NB];
+
+#define set_stat(var) st_current_index = var;
+
+void print_stats(void)
+{
+ unsigned int total;
+ int i;
+
+ printf("Input:\n");
+ total = 0;
+ for(i=0;i<ST_NB;i++)
+ total += st_bit_counts[i];
+ if (total == 0)
+ total = 1;
+ for(i=0;i<ST_NB;i++) {
+ printf("%-10s : %10.1f %5.1f%%\n",
+ st_names[i],
+ (double)st_bit_counts[i] / 8.0,
+ (double)st_bit_counts[i] * 100.0 / total);
+ }
+ printf("%-10s : %10.1f %5.1f%%\n",
+ "total",
+ (double)total / 8.0,
+ 100.0);
+
+ printf("Output:\n");
+ total = 0;
+ for(i=0;i<ST_NB;i++)
+ total += st_out_bit_counts[i];
+ if (total == 0)
+ total = 1;
+ for(i=0;i<ST_NB;i++) {
+ printf("%-10s : %10.1f %5.1f%%\n",
+ st_names[i],
+ (double)st_out_bit_counts[i] / 8.0,
+ (double)st_out_bit_counts[i] * 100.0 / total);
+ }
+ printf("%-10s : %10.1f %5.1f%%\n",
+ "total",
+ (double)total / 8.0,
+ 100.0);
+}
+
+#else
+
+#define set_stat(var)
+
+#endif
+
+/* build the table which associate a (x,y) motion vector to a vlc */
+static void init_mv_table(MVTable *tab)
+{
+ int i, x, y;
+
+ tab->table_mv_index = malloc(sizeof(UINT16) * 4096);
+ /* mark all entries as not used */
+ for(i=0;i<4096;i++)
+ tab->table_mv_index[i] = tab->n;
+
+ for(i=0;i<tab->n;i++) {
+ x = tab->table_mvx[i];
+ y = tab->table_mvy[i];
+ tab->table_mv_index[(x << 6) | y] = i;
+ }
+}
+
+static void code012(PutBitContext *pb, int n)
+{
+ if (n == 0) {
+ put_bits(pb, 1, 0);
+ } else {
+ put_bits(pb, 1, 1);
+ put_bits(pb, 1, (n >= 2));
+ }
+}
+
+/* write MSMPEG4 V3 compatible frame header */
+void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
+{
+ int i;
+
+ align_put_bits(&s->pb);
+
+ put_bits(&s->pb, 2, s->pict_type - 1);
+
+ put_bits(&s->pb, 5, s->qscale);
+
+ s->rl_table_index = 2;
+ s->rl_chroma_table_index = 1; /* only for I frame */
+ s->dc_table_index = 1;
+ s->mv_table_index = 1; /* only if P frame */
+ s->use_skip_mb_code = 1; /* only if P frame */
+
+ if (s->pict_type == I_TYPE) {
+ put_bits(&s->pb, 5, 0x17); /* indicate only one "slice" */
+
+ code012(&s->pb, s->rl_chroma_table_index);
+ code012(&s->pb, s->rl_table_index);
+
+ put_bits(&s->pb, 1, s->dc_table_index);
+ s->no_rounding = 1;
+ } else {
+ put_bits(&s->pb, 1, s->use_skip_mb_code);
+
+ s->rl_chroma_table_index = s->rl_table_index;
+ code012(&s->pb, s->rl_table_index);
+
+ put_bits(&s->pb, 1, s->dc_table_index);
+
+ put_bits(&s->pb, 1, s->mv_table_index);
+ s->no_rounding ^= 1;
+ }
+
+ if (!init_done) {
+ /* init various encoding tables */
+ init_done = 1;
+ init_mv_table(&mv_tables[0]);
+ init_mv_table(&mv_tables[1]);
+ for(i=0;i<NB_RL_TABLES;i++)
+ init_rl(&rl_table[i]);
+ }
+
+#ifdef DEBUG
+ intra_count = 0;
+ printf("*****frame %d:\n", frame_count++);
+#endif
+}
+
+/* predict coded block */
+static inline int coded_block_pred(MpegEncContext * s, int n, UINT8 **coded_block_ptr)
+{
+ int x, y, wrap, pred, a, b, c;
+
+ x = 2 * s->mb_x + 1 + (n & 1);
+ y = 2 * s->mb_y + 1 + ((n & 2) >> 1);
+ wrap = s->mb_width * 2 + 2;
+
+ /* B C
+ * A X
+ */
+ a = s->coded_block[(x - 1) + (y) * wrap];
+ b = s->coded_block[(x - 1) + (y - 1) * wrap];
+ c = s->coded_block[(x) + (y - 1) * wrap];
+
+ if (b == c) {
+ pred = a;
+ } else {
+ pred = c;
+ }
+
+ /* store value */
+ *coded_block_ptr = &s->coded_block[(x) + (y) * wrap];
+
+ return pred;
+}
+
+static void msmpeg4_encode_motion(MpegEncContext * s,
+ int mx, int my)
+{
+ int code;
+ MVTable *mv;
+
+ /* modulo encoding */
+ /* WARNING : you cannot reach all the MVs even with the modulo
+ encoding. This is a somewhat strange compromise they took !!! */
+ if (mx <= -64)
+ mx += 64;
+ else if (mx >= 64)
+ mx -= 64;
+ if (my <= -64)
+ my += 64;
+ else if (my >= 64)
+ my -= 64;
+
+ mx += 32;
+ my += 32;
+#if 0
+ if ((unsigned)mx >= 64 ||
+ (unsigned)my >= 64)
+ fprintf(stderr, "error mx=%d my=%d\n", mx, my);
+#endif
+ mv = &mv_tables[s->mv_table_index];
+
+ code = mv->table_mv_index[(mx << 6) | my];
+ set_stat(ST_MV);
+ put_bits(&s->pb,
+ mv->table_mv_bits[code],
+ mv->table_mv_code[code]);
+ if (code == mv->n) {
+ /* escape : code litterally */
+ put_bits(&s->pb, 6, mx);
+ put_bits(&s->pb, 6, my);
+ }
+}
+
+void msmpeg4_encode_mb(MpegEncContext * s,
+ DCTELEM block[6][64],
+ int motion_x, int motion_y)
+{
+ int cbp, coded_cbp, i;
+ int pred_x, pred_y;
+ UINT8 *coded_block;
+
+ if (!s->mb_intra) {
+ /* compute cbp */
+ set_stat(ST_INTER_MB);
+ cbp = 0;
+ for (i = 0; i < 6; i++) {
+ if (s->block_last_index[i] >= 0)
+ cbp |= 1 << (5 - i);
+ }
+ if (s->use_skip_mb_code && (cbp | motion_x | motion_y) == 0) {
+ /* skip macroblock */
+ put_bits(&s->pb, 1, 1);
+ return;
+ }
+ if (s->use_skip_mb_code)
+ put_bits(&s->pb, 1, 0); /* mb coded */
+
+ put_bits(&s->pb,
+ table_mb_non_intra[cbp + 64][1],
+ table_mb_non_intra[cbp + 64][0]);
+
+ /* motion vector */
+ h263_pred_motion(s, 0, &pred_x, &pred_y);
+ msmpeg4_encode_motion(s, motion_x - pred_x,
+ motion_y - pred_y);
+ } else {
+ /* compute cbp */
+ cbp = 0;
+ coded_cbp = 0;
+ for (i = 0; i < 6; i++) {
+ int val, pred;
+ val = (s->block_last_index[i] >= 1);
+ cbp |= val << (5 - i);
+ if (i < 4) {
+ /* predict value for close blocks only for luma */
+ pred = coded_block_pred(s, i, &coded_block);
+ *coded_block = val;
+ val = val ^ pred;
+ }
+ coded_cbp |= val << (5 - i);
+ }
+#if 0
+ if (coded_cbp)
+ printf("cbp=%x %x\n", cbp, coded_cbp);
+#endif
+
+ if (s->pict_type == I_TYPE) {
+ set_stat(ST_INTRA_MB);
+ put_bits(&s->pb,
+ table_mb_intra[coded_cbp][1], table_mb_intra[coded_cbp][0]);
+ } else {
+ if (s->use_skip_mb_code)
+ put_bits(&s->pb, 1, 0); /* mb coded */
+ put_bits(&s->pb,
+ table_mb_non_intra[cbp][1],
+ table_mb_non_intra[cbp][0]);
+ }
+ set_stat(ST_INTRA_MB);
+ put_bits(&s->pb, 1, 0); /* no AC prediction yet */
+ }
+
+ for (i = 0; i < 6; i++) {
+ msmpeg4_encode_block(s, block[i], i);
+ }
+}
+
+
+/* strongly inspirated from MPEG4, but not exactly the same ! */
+void msmpeg4_dc_scale(MpegEncContext * s)
+{
+ int scale;
+
+ if (s->qscale < 5)
+ scale = 8;
+ else if (s->qscale < 9)
+ scale = 2 * s->qscale;
+ else
+ scale = s->qscale + 8;
+ s->y_dc_scale = scale;
+ s->c_dc_scale = (s->qscale + 13) / 2;
+}
+
+/* dir = 0: left, dir = 1: top prediction */
+static int msmpeg4_pred_dc(MpegEncContext * s, int n,
+ UINT16 **dc_val_ptr, int *dir_ptr)
+{
+ int a, b, c, x, y, wrap, pred, scale;
+ UINT16 *dc_val;
+
+ /* find prediction */
+ if (n < 4) {
+ x = 2 * s->mb_x + 1 + (n & 1);
+ y = 2 * s->mb_y + 1 + ((n & 2) >> 1);
+ wrap = s->mb_width * 2 + 2;
+ dc_val = s->dc_val[0];
+ scale = s->y_dc_scale;
+ } else {
+ x = s->mb_x + 1;
+ y = s->mb_y + 1;
+ wrap = s->mb_width + 2;
+ dc_val = s->dc_val[n - 4 + 1];
+ scale = s->c_dc_scale;
+ }
+
+ /* B C
+ * A X
+ */
+ a = dc_val[(x - 1) + (y) * wrap];
+ b = dc_val[(x - 1) + (y - 1) * wrap];
+ c = dc_val[(x) + (y - 1) * wrap];
+
+ /* XXX: the following solution consumes divisions, but it does not
+ necessitate to modify mpegvideo.c. The problem comes from the
+ fact they decided to store the quantized DC (which would lead
+ to problems if Q could vary !) */
+ a = (a + (scale >> 1)) / scale;
+ b = (b + (scale >> 1)) / scale;
+ c = (c + (scale >> 1)) / scale;
+
+ /* XXX: WARNING: they did not choose the same test as MPEG4. This
+ is very important ! */
+ if (abs(a - b) <= abs(b - c)) {
+ pred = c;
+ *dir_ptr = 1;
+ } else {
+ pred = a;
+ *dir_ptr = 0;
+ }
+
+ /* update predictor */
+ *dc_val_ptr = &dc_val[(x) + (y) * wrap];
+ return pred;
+}
+
+#define DC_MAX 119
+
+static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr)
+{
+ int sign, code;
+ int pred;
+ UINT16 *dc_val;
+
+ pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+
+ /* update predictor */
+ if (n < 4) {
+ *dc_val = level * s->y_dc_scale;
+ } else {
+ *dc_val = level * s->c_dc_scale;
+ }
+
+ /* do the prediction */
+ level -= pred;
+
+ sign = 0;
+ if (level < 0) {
+ level = -level;
+ sign = 1;
+ }
+
+ code = level;
+ if (code > DC_MAX)
+ code = DC_MAX;
+
+ if (s->dc_table_index == 0) {
+ if (n < 4) {
+ put_bits(&s->pb, table0_dc_lum[code][1], table0_dc_lum[code][0]);
+ } else {
+ put_bits(&s->pb, table0_dc_chroma[code][1], table0_dc_chroma[code][0]);
+ }
+ } else {
+ if (n < 4) {
+ put_bits(&s->pb, table1_dc_lum[code][1], table1_dc_lum[code][0]);
+ } else {
+ put_bits(&s->pb, table1_dc_chroma[code][1], table1_dc_chroma[code][0]);
+ }
+ }
+
+ if (code == DC_MAX)
+ put_bits(&s->pb, 8, level);
+
+ if (level != 0) {
+ put_bits(&s->pb, 1, sign);
+ }
+}
+
+/* Encoding of a block. Very similar to MPEG4 except for a different
+ escape coding (same as H263) and more vlc tables.
+ */
+static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
+{
+ int level, run, last, i, j, last_index;
+ int last_non_zero, sign, slevel;
+ int code, run_diff, dc_pred_dir;
+ const RLTable *rl;
+
+ if (s->mb_intra) {
+ set_stat(ST_DC);
+ msmpeg4_encode_dc(s, block[0], n, &dc_pred_dir);
+ i = 1;
+ if (n < 4) {
+ rl = &rl_table[s->rl_table_index];
+ } else {
+ rl = &rl_table[3 + s->rl_chroma_table_index];
+ }
+ run_diff = 0;
+ set_stat(ST_INTRA_AC);
+ } else {
+ i = 0;
+ rl = &rl_table[3 + s->rl_table_index];
+ run_diff = 1;
+ set_stat(ST_INTER_AC);
+ }
+
+ /* AC coefs */
+ last_index = s->block_last_index[n];
+ last_non_zero = i - 1;
+ for (; i <= last_index; i++) {
+ j = zigzag_direct[i];
+ level = block[j];
+ if (level) {
+ run = i - last_non_zero - 1;
+ last = (i == last_index);
+ sign = 0;
+ slevel = level;
+ if (level < 0) {
+ sign = 1;
+ level = -level;
+ }
+ code = get_rl_index(rl, last, run, level);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ if (code == rl->n) {
+ int level1, run1;
+
+ level1 = level - rl->max_level[last][run];
+ if (level1 < 1)
+ goto esc2;
+ code = get_rl_index(rl, last, run, level1);
+ if (code == rl->n) {
+ esc2:
+ put_bits(&s->pb, 1, 0);
+ if (level > MAX_LEVEL)
+ goto esc3;
+ run1 = run - rl->max_run[last][level] - run_diff;
+ if (run1 < 0)
+ goto esc3;
+ code = get_rl_index(rl, last, run1, level);
+ if (code == rl->n) {
+ esc3:
+ /* third escape */
+ put_bits(&s->pb, 1, 0);
+ put_bits(&s->pb, 1, last);
+ put_bits(&s->pb, 6, run);
+ put_bits(&s->pb, 8, slevel & 0xff);
+ } else {
+ /* second escape */
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ put_bits(&s->pb, 1, sign);
+ }
+ } else {
+ /* first escape */
+ put_bits(&s->pb, 1, 1);
+ put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
+ put_bits(&s->pb, 1, sign);
+ }
+ } else {
+ put_bits(&s->pb, 1, sign);
+ }
+ last_non_zero = i;
+ }
+ }
+}
+
+/****************************************/
+/* decoding stuff */
+
+static VLC mb_non_intra_vlc;
+static VLC mb_intra_vlc;
+static VLC dc_lum_vlc[2];
+static VLC dc_chroma_vlc[2];
+
+/* init all vlc decoding tables */
+int msmpeg4_decode_init_vlc(MpegEncContext *s)
+{
+ int i;
+ MVTable *mv;
+
+ for(i=0;i<NB_RL_TABLES;i++) {
+ init_rl(&rl_table[i]);
+ init_vlc_rl(&rl_table[i]);
+ }
+ for(i=0;i<2;i++) {
+ mv = &mv_tables[i];
+ init_vlc(&mv->vlc, 9, mv->n + 1,
+ mv->table_mv_bits, 1, 1,
+ mv->table_mv_code, 2, 2);
+ }
+
+ init_vlc(&dc_lum_vlc[0], 9, 120,
+ &table0_dc_lum[0][1], 8, 4,
+ &table0_dc_lum[0][0], 8, 4);
+ init_vlc(&dc_chroma_vlc[0], 9, 120,
+ &table0_dc_chroma[0][1], 8, 4,
+ &table0_dc_chroma[0][0], 8, 4);
+ init_vlc(&dc_lum_vlc[1], 9, 120,
+ &table1_dc_lum[0][1], 8, 4,
+ &table1_dc_lum[0][0], 8, 4);
+ init_vlc(&dc_chroma_vlc[1], 9, 120,
+ &table1_dc_chroma[0][1], 8, 4,
+ &table1_dc_chroma[0][0], 8, 4);
+
+ init_vlc(&mb_non_intra_vlc, 9, 128,
+ &table_mb_non_intra[0][1], 8, 4,
+ &table_mb_non_intra[0][0], 8, 4);
+ init_vlc(&mb_intra_vlc, 9, 128,
+ &table_mb_intra[0][1], 4, 2,
+ &table_mb_intra[0][0], 4, 2);
+ return 0;
+}
+
+static int decode012(GetBitContext *gb)
+{
+ int n;
+ n = get_bits(gb, 1);
+ if (n == 0)
+ return 0;
+ else
+ return get_bits(gb, 1) + 1;
+}
+
+int msmpeg4_decode_picture_header(MpegEncContext * s)
+{
+ int code;
+
+ s->pict_type = get_bits(&s->gb, 2) + 1;
+ if (s->pict_type != I_TYPE &&
+ s->pict_type != P_TYPE)
+ return -1;
+
+ s->qscale = get_bits(&s->gb, 5);
+
+ if (s->pict_type == I_TYPE) {
+ code = get_bits(&s->gb, 5);
+ /* 0x17: one slice, 0x18: three slices */
+ /* XXX: implement it */
+ if (code < 0x17)
+ return -1;
+ s->slice_height = s->mb_height / (code - 0x16);
+ s->rl_chroma_table_index = decode012(&s->gb);
+ s->rl_table_index = decode012(&s->gb);
+
+ s->dc_table_index = get_bits(&s->gb, 1);
+ s->no_rounding = 1;
+ } else {
+ s->use_skip_mb_code = get_bits(&s->gb, 1);
+
+ s->rl_table_index = decode012(&s->gb);
+ s->rl_chroma_table_index = s->rl_table_index;
+
+ s->dc_table_index = get_bits(&s->gb, 1);
+
+ s->mv_table_index = get_bits(&s->gb, 1);
+ s->no_rounding ^= 1;
+ }
+#ifdef DEBUG
+ printf("*****frame %d:\n", frame_count++);
+#endif
+ return 0;
+}
+
+void memsetw(short *tab, int val, int n)
+{
+ int i;
+ for(i=0;i<n;i++)
+ tab[i] = val;
+}
+
+int msmpeg4_decode_mb(MpegEncContext *s,
+ DCTELEM block[6][64])
+{
+ int cbp, code, i;
+ int pred, val;
+ UINT8 *coded_val;
+
+ /* special slice handling */
+ if (s->mb_x == 0) {
+ if ((s->mb_y % s->slice_height) == 0) {
+ int wrap;
+ /* reset DC pred (set previous line to 1024) */
+ wrap = 2 * s->mb_width + 2;
+ memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap],
+ 1024, 2 * s->mb_width);
+ wrap = s->mb_width + 2;
+ memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap],
+ 1024, s->mb_width);
+ memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap],
+ 1024, s->mb_width);
+
+ s->first_slice_line = 1;
+ } else {
+ s->first_slice_line = 0;
+ }
+ }
+
+ if (s->pict_type == P_TYPE) {
+ set_stat(ST_INTER_MB);
+ if (s->use_skip_mb_code) {
+ if (get_bits(&s->gb, 1)) {
+ /* skip mb */
+ s->mb_intra = 0;
+ for(i=0;i<6;i++)
+ s->block_last_index[i] = -1;
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ s->mv[0][0][0] = 0;
+ s->mv[0][0][1] = 0;
+ return 0;
+ }
+ }
+
+ code = get_vlc(&s->gb, &mb_non_intra_vlc);
+ if (code < 0)
+ return -1;
+ if (code & 0x40)
+ s->mb_intra = 0;
+ else
+ s->mb_intra = 1;
+
+ cbp = code & 0x3f;
+ } else {
+ set_stat(ST_INTRA_MB);
+ s->mb_intra = 1;
+ code = get_vlc(&s->gb, &mb_intra_vlc);
+ if (code < 0)
+ return -1;
+ /* predict coded block pattern */
+ cbp = 0;
+ for(i=0;i<6;i++) {
+ val = ((code >> (5 - i)) & 1);
+ if (i < 4) {
+ pred = coded_block_pred(s, i, &coded_val);
+ val = val ^ pred;
+ *coded_val = val;
+ }
+ cbp |= val << (5 - i);
+ }
+ }
+
+ if (!s->mb_intra) {
+ int mx, my;
+ set_stat(ST_MV);
+ h263_pred_motion(s, 0, &mx, &my);
+ if (msmpeg4_decode_motion(s, &mx, &my) < 0)
+ return -1;
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ s->mv[0][0][0] = mx;
+ s->mv[0][0][1] = my;
+ } else {
+ set_stat(ST_INTRA_MB);
+ s->ac_pred = get_bits(&s->gb, 1);
+ }
+
+ for (i = 0; i < 6; i++) {
+ if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+ int n, int coded)
+{
+ int code, level, i, j, last, run, run_diff;
+ int dc_pred_dir;
+ RLTable *rl;
+ const UINT8 *scan_table;
+
+ if (s->mb_intra) {
+ /* DC coef */
+ set_stat(ST_DC);
+ level = msmpeg4_decode_dc(s, n, &dc_pred_dir);
+ if (level < 0)
+ return -1;
+ block[0] = level;
+ if (n < 4) {
+ rl = &rl_table[s->rl_table_index];
+ } else {
+ rl = &rl_table[3 + s->rl_chroma_table_index];
+ }
+ run_diff = 0;
+ i = 1;
+ if (!coded) {
+ goto not_coded;
+ }
+ if (s->ac_pred) {
+ if (dc_pred_dir == 0)
+ scan_table = ff_alternate_vertical_scan; /* left */
+ else
+ scan_table = ff_alternate_horizontal_scan; /* top */
+ } else {
+ scan_table = zigzag_direct;
+ }
+ set_stat(ST_INTRA_AC);
+ } else {
+ i = 0;
+ rl = &rl_table[3 + s->rl_table_index];
+ run_diff = 1;
+ if (!coded) {
+ s->block_last_index[n] = i - 1;
+ return 0;
+ }
+ scan_table = zigzag_direct;
+ set_stat(ST_INTER_AC);
+ }
+
+ for(;;) {
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0)
+ return -1;
+ if (code == rl->n) {
+ /* escape */
+ if (get_bits(&s->gb, 1) == 0) {
+ if (get_bits(&s->gb, 1) == 0) {
+ /* third escape */
+ last = get_bits(&s->gb, 1);
+ run = get_bits(&s->gb, 6);
+ level = get_bits(&s->gb, 8);
+ level = (level << 24) >> 24; /* sign extend */
+ } else {
+ /* second escape */
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0 || code >= rl->n)
+ return -1;
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ last = code >= rl->last;
+ run += rl->max_run[last][level] + run_diff;
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ } else {
+ /* first escape */
+ code = get_vlc(&s->gb, &rl->vlc);
+ if (code < 0 || code >= rl->n)
+ return -1;
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ last = code >= rl->last;
+ level += rl->max_level[last][run];
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ } else {
+ run = rl->table_run[code];
+ level = rl->table_level[code];
+ last = code >= rl->last;
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+ i += run;
+ if (i >= 64)
+ return -1;
+ j = scan_table[i];
+ block[j] = level;
+ i++;
+ if (last)
+ break;
+ }
+ not_coded:
+ if (s->mb_intra) {
+ mpeg4_pred_ac(s, block, n, dc_pred_dir);
+ if (s->ac_pred) {
+ i = 64; /* XXX: not optimal */
+ }
+ }
+ s->block_last_index[n] = i - 1;
+
+ return 0;
+}
+
+static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
+{
+ int level, pred;
+ UINT16 *dc_val;
+
+ if (n < 4) {
+ level = get_vlc(&s->gb, &dc_lum_vlc[s->dc_table_index]);
+ } else {
+ level = get_vlc(&s->gb, &dc_chroma_vlc[s->dc_table_index]);
+ }
+ if (level < 0)
+ return -1;
+
+ if (level == DC_MAX) {
+ level = get_bits(&s->gb, 8);
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ } else if (level != 0) {
+ if (get_bits(&s->gb, 1))
+ level = -level;
+ }
+
+ pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+ level += pred;
+
+ /* update predictor */
+ if (n < 4) {
+ *dc_val = level * s->y_dc_scale;
+ } else {
+ *dc_val = level * s->c_dc_scale;
+ }
+
+ return level;
+}
+
+static int msmpeg4_decode_motion(MpegEncContext * s,
+ int *mx_ptr, int *my_ptr)
+{
+ MVTable *mv;
+ int code, mx, my;
+
+ mv = &mv_tables[s->mv_table_index];
+
+ code = get_vlc(&s->gb, &mv->vlc);
+ if (code < 0)
+ return -1;
+ if (code == mv->n) {
+ mx = get_bits(&s->gb, 6);
+ my = get_bits(&s->gb, 6);
+ } else {
+ mx = mv->table_mvx[code];
+ my = mv->table_mvy[code];
+ }
+
+ mx += *mx_ptr - 32;
+ my += *my_ptr - 32;
+ /* WARNING : they do not do exactly modulo encoding */
+ if (mx <= -64)
+ mx += 64;
+ else if (mx >= 64)
+ mx -= 64;
+
+ if (my <= -64)
+ my += 64;
+ else if (my >= 64)
+ my -= 64;
+ *mx_ptr = mx;
+ *my_ptr = my;
+ return 0;
+}
diff --git a/libavcodec/msmpeg4data.h b/libavcodec/msmpeg4data.h
new file mode 100644
index 0000000000..03a2612114
--- /dev/null
+++ b/libavcodec/msmpeg4data.h
@@ -0,0 +1,1767 @@
+/*
+ * MSMPEG4 data tables.
+ */
+
+/* intra picture macro block coded block pattern */
+const UINT16 table_mb_intra[64][2] = {
+{ 0x1, 1 },{ 0x17, 6 },{ 0x9, 5 },{ 0x5, 5 },
+{ 0x6, 5 },{ 0x47, 9 },{ 0x20, 7 },{ 0x10, 7 },
+{ 0x2, 5 },{ 0x7c, 9 },{ 0x3a, 7 },{ 0x1d, 7 },
+{ 0x2, 6 },{ 0xec, 9 },{ 0x77, 8 },{ 0x0, 8 },
+{ 0x3, 5 },{ 0xb7, 9 },{ 0x2c, 7 },{ 0x13, 7 },
+{ 0x1, 6 },{ 0x168, 10 },{ 0x46, 8 },{ 0x3f, 8 },
+{ 0x1e, 6 },{ 0x712, 13 },{ 0xb5, 9 },{ 0x42, 8 },
+{ 0x22, 7 },{ 0x1c5, 11 },{ 0x11e, 10 },{ 0x87, 9 },
+{ 0x6, 4 },{ 0x3, 9 },{ 0x1e, 7 },{ 0x1c, 6 },
+{ 0x12, 7 },{ 0x388, 12 },{ 0x44, 9 },{ 0x70, 9 },
+{ 0x1f, 6 },{ 0x23e, 11 },{ 0x39, 8 },{ 0x8e, 9 },
+{ 0x1, 7 },{ 0x1c6, 11 },{ 0xb6, 9 },{ 0x45, 9 },
+{ 0x14, 6 },{ 0x23f, 11 },{ 0x7d, 9 },{ 0x18, 9 },
+{ 0x7, 7 },{ 0x1c7, 11 },{ 0x86, 9 },{ 0x19, 9 },
+{ 0x15, 6 },{ 0x1db, 10 },{ 0x2, 9 },{ 0x46, 9 },
+{ 0xd, 8 },{ 0x713, 13 },{ 0x1da, 10 },{ 0x169, 10 },
+};
+
+/* non intra picture macro block coded block pattern + mb type */
+const UINT32 table_mb_non_intra[128][2] = {
+{ 0x40, 7 },{ 0x13c9, 13 },{ 0x9fd, 12 },{ 0x1fc, 15 },
+{ 0x9fc, 12 },{ 0xa83, 18 },{ 0x12d34, 17 },{ 0x83bc, 16 },
+{ 0x83a, 12 },{ 0x7f8, 17 },{ 0x3fd, 16 },{ 0x3ff, 16 },
+{ 0x79, 13 },{ 0xa82, 18 },{ 0x969d, 16 },{ 0x2a4, 16 },
+{ 0x978, 12 },{ 0x543, 17 },{ 0x41df, 15 },{ 0x7f9, 17 },
+{ 0x12f3, 13 },{ 0x25a6b, 18 },{ 0x25ef9, 18 },{ 0x3fa, 16 },
+{ 0x20ee, 14 },{ 0x969ab, 20 },{ 0x969c, 16 },{ 0x25ef8, 18 },
+{ 0x12d2, 13 },{ 0xa85, 18 },{ 0x969e, 16 },{ 0x4bc8, 15 },
+{ 0x3d, 12 },{ 0x12f7f, 17 },{ 0x2a2, 16 },{ 0x969f, 16 },
+{ 0x25ee, 14 },{ 0x12d355, 21 },{ 0x12f7d, 17 },{ 0x12f7e, 17 },
+{ 0x9e5, 12 },{ 0xa81, 18 },{ 0x4b4d4, 19 },{ 0x83bd, 16 },
+{ 0x78, 13 },{ 0x969b, 16 },{ 0x3fe, 16 },{ 0x2a5, 16 },
+{ 0x7e, 13 },{ 0xa80, 18 },{ 0x2a3, 16 },{ 0x3fb, 16 },
+{ 0x1076, 13 },{ 0xa84, 18 },{ 0x153, 15 },{ 0x4bc9, 15 },
+{ 0x55, 13 },{ 0x12d354, 21 },{ 0x4bde, 15 },{ 0x25e5, 14 },
+{ 0x25b, 10 },{ 0x4b4c, 15 },{ 0x96b, 12 },{ 0x96a, 12 },
+{ 0x1, 2 },{ 0x0, 7 },{ 0x26, 6 },{ 0x12b, 9 },
+{ 0x7, 3 },{ 0x20f, 10 },{ 0x4, 9 },{ 0x28, 12 },
+{ 0x6, 3 },{ 0x20a, 10 },{ 0x128, 9 },{ 0x2b, 12 },
+{ 0x11, 5 },{ 0x1b, 11 },{ 0x13a, 9 },{ 0x4ff, 11 },
+{ 0x3, 4 },{ 0x277, 10 },{ 0x106, 9 },{ 0x839, 12 },
+{ 0xb, 4 },{ 0x27b, 10 },{ 0x12c, 9 },{ 0x4bf, 11 },
+{ 0x9, 6 },{ 0x35, 12 },{ 0x27e, 10 },{ 0x13c8, 13 },
+{ 0x1, 6 },{ 0x4aa, 11 },{ 0x208, 10 },{ 0x29, 12 },
+{ 0x1, 4 },{ 0x254, 10 },{ 0x12e, 9 },{ 0x838, 12 },
+{ 0x24, 6 },{ 0x4f3, 11 },{ 0x276, 10 },{ 0x12f6, 13 },
+{ 0x1, 5 },{ 0x27a, 10 },{ 0x13e, 9 },{ 0x3e, 12 },
+{ 0x8, 6 },{ 0x413, 11 },{ 0xc, 10 },{ 0x4be, 11 },
+{ 0x14, 5 },{ 0x412, 11 },{ 0x253, 10 },{ 0x97a, 12 },
+{ 0x21, 6 },{ 0x4ab, 11 },{ 0x20b, 10 },{ 0x34, 12 },
+{ 0x15, 5 },{ 0x278, 10 },{ 0x252, 10 },{ 0x968, 12 },
+{ 0x5, 5 },{ 0xb, 10 },{ 0x9c, 8 },{ 0xe, 10 },
+};
+
+/* dc table 0 */
+
+static const UINT32 table0_dc_lum[120][2] = {
+{ 0x1, 1 },{ 0x1, 2 },{ 0x1, 4 },{ 0x1, 5 },
+{ 0x5, 5 },{ 0x7, 5 },{ 0x8, 6 },{ 0xc, 6 },
+{ 0x0, 7 },{ 0x2, 7 },{ 0x12, 7 },{ 0x1a, 7 },
+{ 0x3, 8 },{ 0x7, 8 },{ 0x27, 8 },{ 0x37, 8 },
+{ 0x5, 9 },{ 0x4c, 9 },{ 0x6c, 9 },{ 0x6d, 9 },
+{ 0x8, 10 },{ 0x19, 10 },{ 0x9b, 10 },{ 0x1b, 10 },
+{ 0x9a, 10 },{ 0x13, 11 },{ 0x34, 11 },{ 0x35, 11 },
+{ 0x61, 12 },{ 0x48, 13 },{ 0xc4, 13 },{ 0x4a, 13 },
+{ 0xc6, 13 },{ 0xc7, 13 },{ 0x92, 14 },{ 0x18b, 14 },
+{ 0x93, 14 },{ 0x183, 14 },{ 0x182, 14 },{ 0x96, 14 },
+{ 0x97, 14 },{ 0x180, 14 },{ 0x314, 15 },{ 0x315, 15 },
+{ 0x605, 16 },{ 0x604, 16 },{ 0x606, 16 },{ 0xc0e, 17 },
+{ 0x303cd, 23 },{ 0x303c9, 23 },{ 0x303c8, 23 },{ 0x303ca, 23 },
+{ 0x303cb, 23 },{ 0x303cc, 23 },{ 0x303ce, 23 },{ 0x303cf, 23 },
+{ 0x303d0, 23 },{ 0x303d1, 23 },{ 0x303d2, 23 },{ 0x303d3, 23 },
+{ 0x303d4, 23 },{ 0x303d5, 23 },{ 0x303d6, 23 },{ 0x303d7, 23 },
+{ 0x303d8, 23 },{ 0x303d9, 23 },{ 0x303da, 23 },{ 0x303db, 23 },
+{ 0x303dc, 23 },{ 0x303dd, 23 },{ 0x303de, 23 },{ 0x303df, 23 },
+{ 0x303e0, 23 },{ 0x303e1, 23 },{ 0x303e2, 23 },{ 0x303e3, 23 },
+{ 0x303e4, 23 },{ 0x303e5, 23 },{ 0x303e6, 23 },{ 0x303e7, 23 },
+{ 0x303e8, 23 },{ 0x303e9, 23 },{ 0x303ea, 23 },{ 0x303eb, 23 },
+{ 0x303ec, 23 },{ 0x303ed, 23 },{ 0x303ee, 23 },{ 0x303ef, 23 },
+{ 0x303f0, 23 },{ 0x303f1, 23 },{ 0x303f2, 23 },{ 0x303f3, 23 },
+{ 0x303f4, 23 },{ 0x303f5, 23 },{ 0x303f6, 23 },{ 0x303f7, 23 },
+{ 0x303f8, 23 },{ 0x303f9, 23 },{ 0x303fa, 23 },{ 0x303fb, 23 },
+{ 0x303fc, 23 },{ 0x303fd, 23 },{ 0x303fe, 23 },{ 0x303ff, 23 },
+{ 0x60780, 24 },{ 0x60781, 24 },{ 0x60782, 24 },{ 0x60783, 24 },
+{ 0x60784, 24 },{ 0x60785, 24 },{ 0x60786, 24 },{ 0x60787, 24 },
+{ 0x60788, 24 },{ 0x60789, 24 },{ 0x6078a, 24 },{ 0x6078b, 24 },
+{ 0x6078c, 24 },{ 0x6078d, 24 },{ 0x6078e, 24 },{ 0x6078f, 24 },
+};
+
+static const UINT32 table0_dc_chroma[120][2] = {
+{ 0x0, 2 },{ 0x1, 2 },{ 0x5, 3 },{ 0x9, 4 },
+{ 0xd, 4 },{ 0x11, 5 },{ 0x1d, 5 },{ 0x1f, 5 },
+{ 0x21, 6 },{ 0x31, 6 },{ 0x38, 6 },{ 0x33, 6 },
+{ 0x39, 6 },{ 0x3d, 6 },{ 0x61, 7 },{ 0x79, 7 },
+{ 0x80, 8 },{ 0xc8, 8 },{ 0xca, 8 },{ 0xf0, 8 },
+{ 0x81, 8 },{ 0xc0, 8 },{ 0xc9, 8 },{ 0x107, 9 },
+{ 0x106, 9 },{ 0x196, 9 },{ 0x183, 9 },{ 0x1e3, 9 },
+{ 0x1e2, 9 },{ 0x20a, 10 },{ 0x20b, 10 },{ 0x609, 11 },
+{ 0x412, 11 },{ 0x413, 11 },{ 0x60b, 11 },{ 0x411, 11 },
+{ 0x60a, 11 },{ 0x65f, 11 },{ 0x410, 11 },{ 0x65d, 11 },
+{ 0x65e, 11 },{ 0xcb8, 12 },{ 0xc10, 12 },{ 0xcb9, 12 },
+{ 0x1823, 13 },{ 0x3045, 14 },{ 0x6089, 15 },{ 0xc110, 16 },
+{ 0x304448, 22 },{ 0x304449, 22 },{ 0x30444a, 22 },{ 0x30444b, 22 },
+{ 0x30444c, 22 },{ 0x30444d, 22 },{ 0x30444e, 22 },{ 0x30444f, 22 },
+{ 0x304450, 22 },{ 0x304451, 22 },{ 0x304452, 22 },{ 0x304453, 22 },
+{ 0x304454, 22 },{ 0x304455, 22 },{ 0x304456, 22 },{ 0x304457, 22 },
+{ 0x304458, 22 },{ 0x304459, 22 },{ 0x30445a, 22 },{ 0x30445b, 22 },
+{ 0x30445c, 22 },{ 0x30445d, 22 },{ 0x30445e, 22 },{ 0x30445f, 22 },
+{ 0x304460, 22 },{ 0x304461, 22 },{ 0x304462, 22 },{ 0x304463, 22 },
+{ 0x304464, 22 },{ 0x304465, 22 },{ 0x304466, 22 },{ 0x304467, 22 },
+{ 0x304468, 22 },{ 0x304469, 22 },{ 0x30446a, 22 },{ 0x30446b, 22 },
+{ 0x30446c, 22 },{ 0x30446d, 22 },{ 0x30446e, 22 },{ 0x30446f, 22 },
+{ 0x304470, 22 },{ 0x304471, 22 },{ 0x304472, 22 },{ 0x304473, 22 },
+{ 0x304474, 22 },{ 0x304475, 22 },{ 0x304476, 22 },{ 0x304477, 22 },
+{ 0x304478, 22 },{ 0x304479, 22 },{ 0x30447a, 22 },{ 0x30447b, 22 },
+{ 0x30447c, 22 },{ 0x30447d, 22 },{ 0x30447e, 22 },{ 0x30447f, 22 },
+{ 0x608880, 23 },{ 0x608881, 23 },{ 0x608882, 23 },{ 0x608883, 23 },
+{ 0x608884, 23 },{ 0x608885, 23 },{ 0x608886, 23 },{ 0x608887, 23 },
+{ 0x608888, 23 },{ 0x608889, 23 },{ 0x60888a, 23 },{ 0x60888b, 23 },
+{ 0x60888c, 23 },{ 0x60888d, 23 },{ 0x60888e, 23 },{ 0x60888f, 23 },
+};
+
+/* dc table 1 */
+
+const UINT32 table1_dc_lum[120][2] = {
+{ 0x2, 2 },{ 0x3, 2 },{ 0x3, 3 },{ 0x2, 4 },
+{ 0x5, 4 },{ 0x1, 5 },{ 0x3, 5 },{ 0x8, 5 },
+{ 0x0, 6 },{ 0x5, 6 },{ 0xd, 6 },{ 0xf, 6 },
+{ 0x13, 6 },{ 0x8, 7 },{ 0x18, 7 },{ 0x1c, 7 },
+{ 0x24, 7 },{ 0x4, 8 },{ 0x6, 8 },{ 0x12, 8 },
+{ 0x32, 8 },{ 0x3b, 8 },{ 0x4a, 8 },{ 0x4b, 8 },
+{ 0xb, 9 },{ 0x26, 9 },{ 0x27, 9 },{ 0x66, 9 },
+{ 0x74, 9 },{ 0x75, 9 },{ 0x14, 10 },{ 0x1c, 10 },
+{ 0x1f, 10 },{ 0x1d, 10 },{ 0x2b, 11 },{ 0x3d, 11 },
+{ 0x19d, 11 },{ 0x19f, 11 },{ 0x54, 12 },{ 0x339, 12 },
+{ 0x338, 12 },{ 0x33d, 12 },{ 0xab, 13 },{ 0xf1, 13 },
+{ 0x678, 13 },{ 0xf2, 13 },{ 0x1e0, 14 },{ 0x1e1, 14 },
+{ 0x154, 14 },{ 0xcf2, 14 },{ 0x3cc, 15 },{ 0x2ab, 15 },
+{ 0x19e7, 15 },{ 0x3ce, 15 },{ 0x19e6, 15 },{ 0x554, 16 },
+{ 0x79f, 16 },{ 0x555, 16 },{ 0xf3d, 17 },{ 0xf37, 17 },
+{ 0xf3c, 17 },{ 0xf35, 17 },{ 0x1e6d, 18 },{ 0x1e68, 18 },
+{ 0x3cd8, 19 },{ 0x3cd3, 19 },{ 0x3cd9, 19 },{ 0x79a4, 20 },
+{ 0xf34ba, 25 },{ 0xf34b4, 25 },{ 0xf34b5, 25 },{ 0xf34b6, 25 },
+{ 0xf34b7, 25 },{ 0xf34b8, 25 },{ 0xf34b9, 25 },{ 0xf34bb, 25 },
+{ 0xf34bc, 25 },{ 0xf34bd, 25 },{ 0xf34be, 25 },{ 0xf34bf, 25 },
+{ 0x1e6940, 26 },{ 0x1e6941, 26 },{ 0x1e6942, 26 },{ 0x1e6943, 26 },
+{ 0x1e6944, 26 },{ 0x1e6945, 26 },{ 0x1e6946, 26 },{ 0x1e6947, 26 },
+{ 0x1e6948, 26 },{ 0x1e6949, 26 },{ 0x1e694a, 26 },{ 0x1e694b, 26 },
+{ 0x1e694c, 26 },{ 0x1e694d, 26 },{ 0x1e694e, 26 },{ 0x1e694f, 26 },
+{ 0x1e6950, 26 },{ 0x1e6951, 26 },{ 0x1e6952, 26 },{ 0x1e6953, 26 },
+{ 0x1e6954, 26 },{ 0x1e6955, 26 },{ 0x1e6956, 26 },{ 0x1e6957, 26 },
+{ 0x1e6958, 26 },{ 0x1e6959, 26 },{ 0x1e695a, 26 },{ 0x1e695b, 26 },
+{ 0x1e695c, 26 },{ 0x1e695d, 26 },{ 0x1e695e, 26 },{ 0x1e695f, 26 },
+{ 0x1e6960, 26 },{ 0x1e6961, 26 },{ 0x1e6962, 26 },{ 0x1e6963, 26 },
+{ 0x1e6964, 26 },{ 0x1e6965, 26 },{ 0x1e6966, 26 },{ 0x1e6967, 26 },
+};
+
+const UINT32 table1_dc_chroma[120][2] = {
+{ 0x0, 2 },{ 0x1, 2 },{ 0x4, 3 },{ 0x7, 3 },
+{ 0xb, 4 },{ 0xd, 4 },{ 0x15, 5 },{ 0x28, 6 },
+{ 0x30, 6 },{ 0x32, 6 },{ 0x52, 7 },{ 0x62, 7 },
+{ 0x66, 7 },{ 0xa6, 8 },{ 0xc6, 8 },{ 0xcf, 8 },
+{ 0x14f, 9 },{ 0x18e, 9 },{ 0x19c, 9 },{ 0x29d, 10 },
+{ 0x33a, 10 },{ 0x538, 11 },{ 0x63c, 11 },{ 0x63e, 11 },
+{ 0x63f, 11 },{ 0x676, 11 },{ 0xa73, 12 },{ 0xc7a, 12 },
+{ 0xcef, 12 },{ 0x14e5, 13 },{ 0x19dd, 13 },{ 0x29c8, 14 },
+{ 0x29c9, 14 },{ 0x63dd, 15 },{ 0x33b8, 14 },{ 0x33b9, 14 },
+{ 0xc7b6, 16 },{ 0x63d8, 15 },{ 0x63df, 15 },{ 0xc7b3, 16 },
+{ 0xc7b4, 16 },{ 0xc7b5, 16 },{ 0x63de, 15 },{ 0xc7b7, 16 },
+{ 0xc7b8, 16 },{ 0xc7b9, 16 },{ 0x18f65, 17 },{ 0x31ec8, 18 },
+{ 0xc7b248, 24 },{ 0xc7b249, 24 },{ 0xc7b24a, 24 },{ 0xc7b24b, 24 },
+{ 0xc7b24c, 24 },{ 0xc7b24d, 24 },{ 0xc7b24e, 24 },{ 0xc7b24f, 24 },
+{ 0xc7b250, 24 },{ 0xc7b251, 24 },{ 0xc7b252, 24 },{ 0xc7b253, 24 },
+{ 0xc7b254, 24 },{ 0xc7b255, 24 },{ 0xc7b256, 24 },{ 0xc7b257, 24 },
+{ 0xc7b258, 24 },{ 0xc7b259, 24 },{ 0xc7b25a, 24 },{ 0xc7b25b, 24 },
+{ 0xc7b25c, 24 },{ 0xc7b25d, 24 },{ 0xc7b25e, 24 },{ 0xc7b25f, 24 },
+{ 0xc7b260, 24 },{ 0xc7b261, 24 },{ 0xc7b262, 24 },{ 0xc7b263, 24 },
+{ 0xc7b264, 24 },{ 0xc7b265, 24 },{ 0xc7b266, 24 },{ 0xc7b267, 24 },
+{ 0xc7b268, 24 },{ 0xc7b269, 24 },{ 0xc7b26a, 24 },{ 0xc7b26b, 24 },
+{ 0xc7b26c, 24 },{ 0xc7b26d, 24 },{ 0xc7b26e, 24 },{ 0xc7b26f, 24 },
+{ 0xc7b270, 24 },{ 0xc7b271, 24 },{ 0xc7b272, 24 },{ 0xc7b273, 24 },
+{ 0xc7b274, 24 },{ 0xc7b275, 24 },{ 0xc7b276, 24 },{ 0xc7b277, 24 },
+{ 0xc7b278, 24 },{ 0xc7b279, 24 },{ 0xc7b27a, 24 },{ 0xc7b27b, 24 },
+{ 0xc7b27c, 24 },{ 0xc7b27d, 24 },{ 0xc7b27e, 24 },{ 0xc7b27f, 24 },
+{ 0x18f6480, 25 },{ 0x18f6481, 25 },{ 0x18f6482, 25 },{ 0x18f6483, 25 },
+{ 0x18f6484, 25 },{ 0x18f6485, 25 },{ 0x18f6486, 25 },{ 0x18f6487, 25 },
+{ 0x18f6488, 25 },{ 0x18f6489, 25 },{ 0x18f648a, 25 },{ 0x18f648b, 25 },
+{ 0x18f648c, 25 },{ 0x18f648d, 25 },{ 0x18f648e, 25 },{ 0x18f648f, 25 },
+};
+
+/* vlc table 0, for intra luma */
+
+static const UINT16 table0_vlc[133][2] = {
+{ 0x1, 2 },{ 0x6, 3 },{ 0xf, 4 },{ 0x16, 5 },
+{ 0x20, 6 },{ 0x18, 7 },{ 0x8, 8 },{ 0x9a, 8 },
+{ 0x56, 9 },{ 0x13e, 9 },{ 0xf0, 10 },{ 0x3a5, 10 },
+{ 0x77, 11 },{ 0x1ef, 11 },{ 0x9a, 12 },{ 0x5d, 13 },
+{ 0x1, 4 },{ 0x11, 5 },{ 0x2, 7 },{ 0xb, 8 },
+{ 0x12, 9 },{ 0x1d6, 9 },{ 0x27e, 10 },{ 0x191, 11 },
+{ 0xea, 12 },{ 0x3dc, 12 },{ 0x13b, 13 },{ 0x4, 5 },
+{ 0x14, 7 },{ 0x9e, 8 },{ 0x9, 10 },{ 0x1ac, 11 },
+{ 0x1e2, 11 },{ 0x3ca, 12 },{ 0x5f, 13 },{ 0x17, 5 },
+{ 0x4e, 7 },{ 0x5e, 9 },{ 0xf3, 10 },{ 0x1ad, 11 },
+{ 0xec, 12 },{ 0x5f0, 13 },{ 0xe, 6 },{ 0xe1, 8 },
+{ 0x3a4, 10 },{ 0x9c, 12 },{ 0x13d, 13 },{ 0x3b, 6 },
+{ 0x1c, 9 },{ 0x14, 11 },{ 0x9be, 12 },{ 0x6, 7 },
+{ 0x7a, 9 },{ 0x190, 11 },{ 0x137, 13 },{ 0x1b, 7 },
+{ 0x8, 10 },{ 0x75c, 11 },{ 0x71, 7 },{ 0xd7, 10 },
+{ 0x9bf, 12 },{ 0x7, 8 },{ 0xaf, 10 },{ 0x4cc, 11 },
+{ 0x34, 8 },{ 0x265, 10 },{ 0x9f, 12 },{ 0xe0, 8 },
+{ 0x16, 11 },{ 0x327, 12 },{ 0x15, 9 },{ 0x17d, 11 },
+{ 0xebb, 12 },{ 0x14, 9 },{ 0xf6, 10 },{ 0x1e4, 11 },
+{ 0xcb, 10 },{ 0x99d, 12 },{ 0xca, 10 },{ 0x2fc, 12 },
+{ 0x17f, 11 },{ 0x4cd, 11 },{ 0x2fd, 12 },{ 0x4fe, 11 },
+{ 0x13a, 13 },{ 0xa, 4 },{ 0x42, 7 },{ 0x1d3, 9 },
+{ 0x4dd, 11 },{ 0x12, 5 },{ 0xe8, 8 },{ 0x4c, 11 },
+{ 0x136, 13 },{ 0x39, 6 },{ 0x264, 10 },{ 0xeba, 12 },
+{ 0x0, 7 },{ 0xae, 10 },{ 0x99c, 12 },{ 0x1f, 7 },
+{ 0x4de, 11 },{ 0x43, 7 },{ 0x4dc, 11 },{ 0x3, 8 },
+{ 0x3cb, 12 },{ 0x6, 8 },{ 0x99e, 12 },{ 0x2a, 8 },
+{ 0x5f1, 13 },{ 0xf, 8 },{ 0x9fe, 12 },{ 0x33, 8 },
+{ 0x9ff, 12 },{ 0x98, 8 },{ 0x99f, 12 },{ 0xea, 8 },
+{ 0x13c, 13 },{ 0x2e, 8 },{ 0x192, 11 },{ 0x136, 9 },
+{ 0x6a, 9 },{ 0x15, 11 },{ 0x3af, 10 },{ 0x1e3, 11 },
+{ 0x74, 11 },{ 0xeb, 12 },{ 0x2f9, 12 },{ 0x5c, 13 },
+{ 0xed, 12 },{ 0x3dd, 12 },{ 0x326, 12 },{ 0x5e, 13 },
+{ 0x16, 7 },
+};
+
+const INT8 table0_level[132] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 1, 2, 3, 4, 5,
+ 6, 7, 8, 1, 2, 3, 4, 5,
+ 6, 7, 1, 2, 3, 4, 5, 1,
+ 2, 3, 4, 1, 2, 3, 4, 1,
+ 2, 3, 1, 2, 3, 1, 2, 3,
+ 1, 2, 3, 1, 2, 3, 1, 2,
+ 3, 1, 2, 3, 1, 2, 1, 2,
+ 1, 1, 1, 1, 1, 1, 2, 3,
+ 4, 1, 2, 3, 4, 1, 2, 3,
+ 1, 2, 3, 1, 2, 1, 2, 1,
+ 2, 1, 2, 1, 2, 1, 2, 1,
+ 2, 1, 2, 1, 2, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1,
+};
+
+const INT8 table0_run[132] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 2, 2, 2,
+ 2, 2, 2, 3, 3, 3, 3, 3,
+ 3, 3, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 6, 6, 6, 6, 7,
+ 7, 7, 8, 8, 8, 9, 9, 9,
+ 10, 10, 10, 11, 11, 11, 12, 12,
+ 12, 13, 13, 13, 14, 14, 15, 15,
+ 16, 17, 18, 19, 20, 0, 0, 0,
+ 0, 1, 1, 1, 1, 2, 2, 2,
+ 3, 3, 3, 4, 4, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10,
+ 10, 11, 11, 12, 12, 13, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26,
+};
+
+/* vlc table 1, for intra chroma and P macro blocks */
+
+const UINT16 table1_vlc[149][2] = {
+{ 0x4, 3 },{ 0x14, 5 },{ 0x17, 7 },{ 0x7f, 8 },
+{ 0x154, 9 },{ 0x1f2, 10 },{ 0xbf, 11 },{ 0x65, 12 },
+{ 0xaaa, 12 },{ 0x630, 13 },{ 0x1597, 13 },{ 0x3b7, 14 },
+{ 0x2b22, 14 },{ 0xbe6, 15 },{ 0xb, 4 },{ 0x37, 7 },
+{ 0x62, 9 },{ 0x7, 11 },{ 0x166, 12 },{ 0xce, 13 },
+{ 0x1590, 13 },{ 0x5f6, 14 },{ 0xbe7, 15 },{ 0x7, 5 },
+{ 0x6d, 8 },{ 0x3, 11 },{ 0x31f, 12 },{ 0x5f2, 14 },
+{ 0x2, 6 },{ 0x61, 9 },{ 0x55, 12 },{ 0x1df, 14 },
+{ 0x1a, 6 },{ 0x1e, 10 },{ 0xac9, 12 },{ 0x2b23, 14 },
+{ 0x1e, 6 },{ 0x1f, 10 },{ 0xac3, 12 },{ 0x2b2b, 14 },
+{ 0x6, 7 },{ 0x4, 11 },{ 0x2f8, 13 },{ 0x19, 7 },
+{ 0x6, 11 },{ 0x63d, 13 },{ 0x57, 7 },{ 0x182, 11 },
+{ 0x2aa2, 14 },{ 0x4, 8 },{ 0x180, 11 },{ 0x59c, 14 },
+{ 0x7d, 8 },{ 0x164, 12 },{ 0x76d, 15 },{ 0x2, 9 },
+{ 0x18d, 11 },{ 0x1581, 13 },{ 0xad, 8 },{ 0x60, 12 },
+{ 0xc67, 14 },{ 0x1c, 9 },{ 0xee, 13 },{ 0x3, 9 },
+{ 0x2cf, 13 },{ 0xd9, 9 },{ 0x1580, 13 },{ 0x2, 11 },
+{ 0x183, 11 },{ 0x57, 12 },{ 0x61, 12 },{ 0x31, 11 },
+{ 0x66, 12 },{ 0x631, 13 },{ 0x632, 13 },{ 0xac, 13 },
+{ 0x31d, 12 },{ 0x76, 12 },{ 0x3a, 11 },{ 0x165, 12 },
+{ 0xc66, 14 },{ 0x3, 2 },{ 0x54, 7 },{ 0x2ab, 10 },
+{ 0x16, 13 },{ 0x5f7, 14 },{ 0x5, 4 },{ 0xf8, 9 },
+{ 0xaa9, 12 },{ 0x5f, 15 },{ 0x4, 4 },{ 0x1c, 10 },
+{ 0x1550, 13 },{ 0x4, 5 },{ 0x77, 11 },{ 0x76c, 15 },
+{ 0xe, 5 },{ 0xa, 12 },{ 0xc, 5 },{ 0x562, 11 },
+{ 0x4, 6 },{ 0x31c, 12 },{ 0x6, 6 },{ 0xc8, 13 },
+{ 0xd, 6 },{ 0x1da, 13 },{ 0x7, 6 },{ 0xc9, 13 },
+{ 0x1, 7 },{ 0x2e, 14 },{ 0x14, 7 },{ 0x1596, 13 },
+{ 0xa, 7 },{ 0xac2, 12 },{ 0x16, 7 },{ 0x15b, 14 },
+{ 0x15, 7 },{ 0x15a, 14 },{ 0xf, 8 },{ 0x5e, 15 },
+{ 0x7e, 8 },{ 0xab, 8 },{ 0x2d, 9 },{ 0xd8, 9 },
+{ 0xb, 9 },{ 0x14, 10 },{ 0x2b3, 10 },{ 0x1f3, 10 },
+{ 0x3a, 10 },{ 0x0, 10 },{ 0x58, 10 },{ 0x2e, 9 },
+{ 0x5e, 10 },{ 0x563, 11 },{ 0xec, 12 },{ 0x54, 12 },
+{ 0xac1, 12 },{ 0x1556, 13 },{ 0x2fa, 13 },{ 0x181, 11 },
+{ 0x1557, 13 },{ 0x59d, 14 },{ 0x2aa3, 14 },{ 0x2b2a, 14 },
+{ 0x1de, 14 },{ 0x63c, 13 },{ 0xcf, 13 },{ 0x1594, 13 },
+{ 0xd, 9 },
+};
+
+const INT8 table1_level[148] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 1,
+ 2, 3, 4, 5, 1, 2, 3, 4,
+ 1, 2, 3, 4, 1, 2, 3, 4,
+ 1, 2, 3, 1, 2, 3, 1, 2,
+ 3, 1, 2, 3, 1, 2, 3, 1,
+ 2, 3, 1, 2, 3, 1, 2, 1,
+ 2, 1, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 3, 4, 5, 1, 2,
+ 3, 4, 1, 2, 3, 1, 2, 3,
+ 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2,
+ 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,
+};
+
+const INT8 table1_run[148] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5,
+ 6, 6, 6, 7, 7, 7, 8, 8,
+ 8, 9, 9, 9, 10, 10, 10, 11,
+ 11, 11, 12, 12, 12, 13, 13, 14,
+ 14, 15, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 2, 2, 2, 3, 3, 3,
+ 4, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13, 14, 14, 15, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43,
+};
+
+/* third vlc table */
+
+const UINT16 table2_vlc[186][2] = {
+{ 0x1, 2 },{ 0x5, 3 },{ 0xd, 4 },{ 0x12, 5 },
+{ 0xe, 6 },{ 0x15, 7 },{ 0x13, 8 },{ 0x3f, 8 },
+{ 0x4b, 9 },{ 0x11f, 9 },{ 0xb8, 10 },{ 0x3e3, 10 },
+{ 0x172, 11 },{ 0x24d, 12 },{ 0x3da, 12 },{ 0x2dd, 13 },
+{ 0x1f55, 13 },{ 0x5b9, 14 },{ 0x3eae, 14 },{ 0x0, 4 },
+{ 0x10, 5 },{ 0x8, 7 },{ 0x20, 8 },{ 0x29, 9 },
+{ 0x1f4, 9 },{ 0x233, 10 },{ 0x1e0, 11 },{ 0x12a, 12 },
+{ 0x3dd, 12 },{ 0x50a, 13 },{ 0x1f29, 13 },{ 0xa42, 14 },
+{ 0x1272, 15 },{ 0x1737, 15 },{ 0x3, 5 },{ 0x11, 7 },
+{ 0xc4, 8 },{ 0x4b, 10 },{ 0xb4, 11 },{ 0x7d4, 11 },
+{ 0x345, 12 },{ 0x2d7, 13 },{ 0x7bf, 13 },{ 0x938, 14 },
+{ 0xbbb, 14 },{ 0x95e, 15 },{ 0x13, 5 },{ 0x78, 7 },
+{ 0x69, 9 },{ 0x232, 10 },{ 0x461, 11 },{ 0x3ec, 12 },
+{ 0x520, 13 },{ 0x1f2a, 13 },{ 0x3e50, 14 },{ 0x3e51, 14 },
+{ 0x1486, 15 },{ 0xc, 6 },{ 0x24, 9 },{ 0x94, 11 },
+{ 0x8c0, 12 },{ 0xf09, 14 },{ 0x1ef0, 15 },{ 0x3d, 6 },
+{ 0x53, 9 },{ 0x1a0, 11 },{ 0x2d6, 13 },{ 0xf08, 14 },
+{ 0x13, 7 },{ 0x7c, 9 },{ 0x7c1, 11 },{ 0x4ac, 14 },
+{ 0x1b, 7 },{ 0xa0, 10 },{ 0x344, 12 },{ 0xf79, 14 },
+{ 0x79, 7 },{ 0x3e1, 10 },{ 0x2d4, 13 },{ 0x2306, 14 },
+{ 0x21, 8 },{ 0x23c, 10 },{ 0xfae, 12 },{ 0x23de, 14 },
+{ 0x35, 8 },{ 0x175, 11 },{ 0x7b3, 13 },{ 0xc5, 8 },
+{ 0x174, 11 },{ 0x785, 13 },{ 0x48, 9 },{ 0x1a3, 11 },
+{ 0x49e, 13 },{ 0x2c, 9 },{ 0xfa, 10 },{ 0x7d6, 11 },
+{ 0x92, 10 },{ 0x5cc, 13 },{ 0x1ef1, 15 },{ 0xa3, 10 },
+{ 0x3ed, 12 },{ 0x93e, 14 },{ 0x1e2, 11 },{ 0x1273, 15 },
+{ 0x7c4, 11 },{ 0x1487, 15 },{ 0x291, 12 },{ 0x293, 12 },
+{ 0xf8a, 12 },{ 0x509, 13 },{ 0x508, 13 },{ 0x78d, 13 },
+{ 0x7be, 13 },{ 0x78c, 13 },{ 0x4ae, 14 },{ 0xbba, 14 },
+{ 0x2307, 14 },{ 0xb9a, 14 },{ 0x1736, 15 },{ 0xe, 4 },
+{ 0x45, 7 },{ 0x1f3, 9 },{ 0x47a, 11 },{ 0x5dc, 13 },
+{ 0x23df, 14 },{ 0x19, 5 },{ 0x28, 9 },{ 0x176, 11 },
+{ 0x49d, 13 },{ 0x23dd, 14 },{ 0x30, 6 },{ 0xa2, 10 },
+{ 0x2ef, 12 },{ 0x5b8, 14 },{ 0x3f, 6 },{ 0xa5, 10 },
+{ 0x3db, 12 },{ 0x93f, 14 },{ 0x44, 7 },{ 0x7cb, 11 },
+{ 0x95f, 15 },{ 0x63, 7 },{ 0x3c3, 12 },{ 0x15, 8 },
+{ 0x8f6, 12 },{ 0x17, 8 },{ 0x498, 13 },{ 0x2c, 8 },
+{ 0x7b2, 13 },{ 0x2f, 8 },{ 0x1f54, 13 },{ 0x8d, 8 },
+{ 0x7bd, 13 },{ 0x8e, 8 },{ 0x1182, 13 },{ 0xfb, 8 },
+{ 0x50b, 13 },{ 0x2d, 8 },{ 0x7c0, 11 },{ 0x79, 9 },
+{ 0x1f5f, 13 },{ 0x7a, 9 },{ 0x1f56, 13 },{ 0x231, 10 },
+{ 0x3e4, 10 },{ 0x1a1, 11 },{ 0x143, 11 },{ 0x1f7, 11 },
+{ 0x16f, 12 },{ 0x292, 12 },{ 0x2e7, 12 },{ 0x16c, 12 },
+{ 0x16d, 12 },{ 0x3dc, 12 },{ 0xf8b, 12 },{ 0x499, 13 },
+{ 0x3d8, 12 },{ 0x78e, 13 },{ 0x2d5, 13 },{ 0x1f5e, 13 },
+{ 0x1f2b, 13 },{ 0x78f, 13 },{ 0x4ad, 14 },{ 0x3eaf, 14 },
+{ 0x23dc, 14 },{ 0x4a, 9 },
+};
+
+const INT8 table2_level[185] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 1, 2, 3, 4, 5, 6, 1,
+ 2, 3, 4, 5, 1, 2, 3, 4,
+ 1, 2, 3, 4, 1, 2, 3, 4,
+ 1, 2, 3, 4, 1, 2, 3, 1,
+ 2, 3, 1, 2, 3, 1, 2, 3,
+ 1, 2, 3, 1, 2, 3, 1, 2,
+ 1, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 3, 4, 5, 6, 1, 2, 3,
+ 4, 5, 1, 2, 3, 4, 1, 2,
+ 3, 4, 1, 2, 3, 1, 2, 1,
+ 2, 1, 2, 1, 2, 1, 2, 1,
+ 2, 1, 2, 1, 2, 1, 2, 1,
+ 2, 1, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1,
+};
+
+const INT8 table2_run[185] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 6, 6, 6, 6,
+ 7, 7, 7, 7, 8, 8, 8, 8,
+ 9, 9, 9, 9, 10, 10, 10, 11,
+ 11, 11, 12, 12, 12, 13, 13, 13,
+ 14, 14, 14, 15, 15, 15, 16, 16,
+ 17, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 3, 3,
+ 3, 3, 4, 4, 4, 5, 5, 6,
+ 6, 7, 7, 8, 8, 9, 9, 10,
+ 10, 11, 11, 12, 12, 13, 13, 14,
+ 14, 15, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+ 37,
+};
+
+/* second non intra vlc table */
+const UINT16 table4_vlc[169][2] = {
+{ 0x0, 3 },{ 0x3, 4 },{ 0xb, 5 },{ 0x14, 6 },
+{ 0x3f, 6 },{ 0x5d, 7 },{ 0xa2, 8 },{ 0xac, 9 },
+{ 0x16e, 9 },{ 0x20a, 10 },{ 0x2e2, 10 },{ 0x432, 11 },
+{ 0x5c9, 11 },{ 0x827, 12 },{ 0xb54, 12 },{ 0x4e6, 13 },
+{ 0x105f, 13 },{ 0x172a, 13 },{ 0x20b2, 14 },{ 0x2d4e, 14 },
+{ 0x39f0, 14 },{ 0x4175, 15 },{ 0x5a9e, 15 },{ 0x4, 4 },
+{ 0x1e, 5 },{ 0x42, 7 },{ 0xb6, 8 },{ 0x173, 9 },
+{ 0x395, 10 },{ 0x72e, 11 },{ 0xb94, 12 },{ 0x16a4, 13 },
+{ 0x20b3, 14 },{ 0x2e45, 14 },{ 0x5, 5 },{ 0x40, 7 },
+{ 0x49, 9 },{ 0x28f, 10 },{ 0x5cb, 11 },{ 0x48a, 13 },
+{ 0x9dd, 14 },{ 0x73e2, 15 },{ 0x18, 5 },{ 0x25, 8 },
+{ 0x8a, 10 },{ 0x51b, 11 },{ 0xe5f, 12 },{ 0x9c9, 14 },
+{ 0x139c, 15 },{ 0x29, 6 },{ 0x4f, 9 },{ 0x412, 11 },
+{ 0x48d, 13 },{ 0x2e41, 14 },{ 0x38, 6 },{ 0x10e, 9 },
+{ 0x5a8, 11 },{ 0x105c, 13 },{ 0x39f2, 14 },{ 0x58, 7 },
+{ 0x21f, 10 },{ 0xe7e, 12 },{ 0x39ff, 14 },{ 0x23, 8 },
+{ 0x2e3, 10 },{ 0x4e5, 13 },{ 0x2e40, 14 },{ 0xa1, 8 },
+{ 0x5be, 11 },{ 0x9c8, 14 },{ 0x83, 8 },{ 0x13a, 11 },
+{ 0x1721, 13 },{ 0x44, 9 },{ 0x276, 12 },{ 0x39f6, 14 },
+{ 0x8b, 10 },{ 0x4ef, 13 },{ 0x5a9b, 15 },{ 0x208, 10 },
+{ 0x1cfe, 13 },{ 0x399, 10 },{ 0x1cb4, 13 },{ 0x39e, 10 },
+{ 0x39f3, 14 },{ 0x5ab, 11 },{ 0x73e3, 15 },{ 0x737, 11 },
+{ 0x5a9f, 15 },{ 0x82d, 12 },{ 0xe69, 12 },{ 0xe68, 12 },
+{ 0x433, 11 },{ 0xb7b, 12 },{ 0x2df8, 14 },{ 0x2e56, 14 },
+{ 0x2e57, 14 },{ 0x39f7, 14 },{ 0x51a5, 15 },{ 0x3, 3 },
+{ 0x2a, 6 },{ 0xe4, 8 },{ 0x28e, 10 },{ 0x735, 11 },
+{ 0x1058, 13 },{ 0x1cfa, 13 },{ 0x2df9, 14 },{ 0x4174, 15 },
+{ 0x9, 4 },{ 0x54, 8 },{ 0x398, 10 },{ 0x48b, 13 },
+{ 0x139d, 15 },{ 0xd, 4 },{ 0xad, 9 },{ 0x826, 12 },
+{ 0x2d4c, 14 },{ 0x11, 5 },{ 0x16b, 9 },{ 0xb7f, 12 },
+{ 0x51a4, 15 },{ 0x19, 5 },{ 0x21b, 10 },{ 0x16fd, 13 },
+{ 0x1d, 5 },{ 0x394, 10 },{ 0x28d3, 14 },{ 0x2b, 6 },
+{ 0x5bc, 11 },{ 0x5a9a, 15 },{ 0x2f, 6 },{ 0x247, 12 },
+{ 0x10, 7 },{ 0xa35, 12 },{ 0x3e, 6 },{ 0xb7a, 12 },
+{ 0x59, 7 },{ 0x105e, 13 },{ 0x26, 8 },{ 0x9cf, 14 },
+{ 0x55, 8 },{ 0x1cb5, 13 },{ 0x57, 8 },{ 0xe5b, 12 },
+{ 0xa0, 8 },{ 0x1468, 13 },{ 0x170, 9 },{ 0x90, 10 },
+{ 0x1ce, 9 },{ 0x21a, 10 },{ 0x218, 10 },{ 0x168, 9 },
+{ 0x21e, 10 },{ 0x244, 12 },{ 0x736, 11 },{ 0x138, 11 },
+{ 0x519, 11 },{ 0xe5e, 12 },{ 0x72c, 11 },{ 0xb55, 12 },
+{ 0x9dc, 14 },{ 0x20bb, 14 },{ 0x48c, 13 },{ 0x1723, 13 },
+{ 0x2e44, 14 },{ 0x16a5, 13 },{ 0x518, 11 },{ 0x39fe, 14 },
+{ 0x169, 9 },
+};
+
+const INT8 table4_level[168] = {
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 1, 2, 3, 4, 5, 6,
+ 7, 8, 1, 2, 3, 4, 5, 6,
+ 7, 1, 2, 3, 4, 5, 1, 2,
+ 3, 4, 5, 1, 2, 3, 4, 1,
+ 2, 3, 4, 1, 2, 3, 1, 2,
+ 3, 1, 2, 3, 1, 2, 3, 1,
+ 2, 1, 2, 1, 2, 1, 2, 1,
+ 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 1, 2, 3, 4,
+ 5, 1, 2, 3, 4, 1, 2, 3,
+ 4, 1, 2, 3, 1, 2, 3, 1,
+ 2, 3, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 2, 1, 2, 1, 2,
+ 1, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+const INT8 table4_run[168] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 3, 3, 3, 3, 3, 3,
+ 3, 4, 4, 4, 4, 4, 5, 5,
+ 5, 5, 5, 6, 6, 6, 6, 7,
+ 7, 7, 7, 8, 8, 8, 9, 9,
+ 9, 10, 10, 10, 11, 11, 11, 12,
+ 12, 13, 13, 14, 14, 15, 15, 16,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 3, 3, 3,
+ 3, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 8, 8, 9, 9,
+ 10, 10, 11, 11, 12, 12, 13, 13,
+ 14, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+};
+
+extern const UINT16 inter_vlc[103][2];
+extern const INT8 inter_level[102];
+extern const INT8 inter_run[102];
+
+extern const UINT16 intra_vlc[103][2];
+extern const INT8 intra_level[102];
+extern const INT8 intra_run[102];
+
+#define NB_RL_TABLES 6
+
+static RLTable rl_table[NB_RL_TABLES] = {
+ /* intra luminance tables */
+ {
+ 132,
+ 85,
+ table0_vlc,
+ table0_run,
+ table0_level,
+ },
+ {
+ 185,
+ 119,
+ table2_vlc,
+ table2_run,
+ table2_level,
+ },
+ {
+ 102,
+ 67,
+ intra_vlc,
+ intra_run,
+ intra_level,
+ },
+ /* intra chrominance / non intra tables */
+ {
+ 148,
+ 81,
+ table1_vlc,
+ table1_run,
+ table1_level,
+ },
+ {
+ 168,
+ 99,
+ table4_vlc,
+ table4_run,
+ table4_level,
+ },
+ {
+ 102,
+ 58,
+ inter_vlc,
+ inter_run,
+ inter_level,
+ },
+};
+
+/* motion vector table 0 */
+
+const UINT16 table0_mv_code[1100] = {
+ 0x0001, 0x0003, 0x0005, 0x0007, 0x0003, 0x0008, 0x000c, 0x0001,
+ 0x0002, 0x001b, 0x0006, 0x000b, 0x0015, 0x0002, 0x000e, 0x000f,
+ 0x0014, 0x0020, 0x0022, 0x0025, 0x0027, 0x0029, 0x002d, 0x004b,
+ 0x004d, 0x0003, 0x0022, 0x0023, 0x0025, 0x0027, 0x0042, 0x0048,
+ 0x0049, 0x0050, 0x005c, 0x0091, 0x009f, 0x000e, 0x0043, 0x004c,
+ 0x0054, 0x0056, 0x008c, 0x0098, 0x009a, 0x009b, 0x00b1, 0x00b2,
+ 0x0120, 0x0121, 0x0126, 0x0133, 0x0139, 0x01a1, 0x01a4, 0x01a5,
+ 0x01a6, 0x01a7, 0x01ae, 0x01af, 0x000b, 0x0019, 0x0085, 0x0090,
+ 0x009b, 0x00aa, 0x00af, 0x010c, 0x010e, 0x011c, 0x011e, 0x0133,
+ 0x0144, 0x0160, 0x0174, 0x0175, 0x0177, 0x0178, 0x0249, 0x024b,
+ 0x0252, 0x0261, 0x0265, 0x0270, 0x0352, 0x0353, 0x0355, 0x0359,
+ 0x0010, 0x0011, 0x0013, 0x0034, 0x0035, 0x0036, 0x0037, 0x003d,
+ 0x003e, 0x0109, 0x0126, 0x0156, 0x021a, 0x021e, 0x023a, 0x023e,
+ 0x028e, 0x028f, 0x02cf, 0x0491, 0x0494, 0x049f, 0x04a0, 0x04a3,
+ 0x04a6, 0x04a7, 0x04ad, 0x04ae, 0x04c0, 0x04c4, 0x04c6, 0x04c8,
+ 0x04c9, 0x04f5, 0x04f6, 0x04f7, 0x0680, 0x0682, 0x0683, 0x0688,
+ 0x0689, 0x068d, 0x068e, 0x068f, 0x06a2, 0x06a3, 0x06a9, 0x06b0,
+ 0x06b1, 0x06b4, 0x06b5, 0x0024, 0x0060, 0x0063, 0x0078, 0x0079,
+ 0x0211, 0x0244, 0x0245, 0x0247, 0x0248, 0x0249, 0x024a, 0x024b,
+ 0x026b, 0x02af, 0x02b8, 0x02bb, 0x0436, 0x0476, 0x0477, 0x047e,
+ 0x04c8, 0x04c9, 0x04ca, 0x0514, 0x0586, 0x0587, 0x0598, 0x059d,
+ 0x05d9, 0x05da, 0x0920, 0x0921, 0x093b, 0x093c, 0x093d, 0x0942,
+ 0x0943, 0x0944, 0x0945, 0x0959, 0x095e, 0x095f, 0x0982, 0x0983,
+ 0x098e, 0x098f, 0x09c4, 0x09e7, 0x09e8, 0x09e9, 0x0d02, 0x0d17,
+ 0x0d18, 0x0d19, 0x0d41, 0x0d42, 0x0d43, 0x0d50, 0x0d5f, 0x0d6d,
+ 0x0d6e, 0x0d6f, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x041e, 0x041f, 0x0420, 0x0421,
+ 0x048c, 0x048d, 0x04d3, 0x04d4, 0x04d5, 0x055c, 0x055d, 0x0572,
+ 0x0573, 0x0574, 0x0575, 0x08de, 0x08df, 0x08fe, 0x08ff, 0x0996,
+ 0x0a36, 0x0a37, 0x0b08, 0x0b09, 0x0b0a, 0x0b0b, 0x0b32, 0x0b33,
+ 0x0b34, 0x0b35, 0x0b36, 0x0b37, 0x0b38, 0x0b39, 0x0bb0, 0x0bf7,
+ 0x0bf8, 0x0bf9, 0x0bfa, 0x0bfb, 0x0bfc, 0x0bfd, 0x0bfe, 0x0bff,
+ 0x1254, 0x1255, 0x1256, 0x1257, 0x1270, 0x1271, 0x1272, 0x1273,
+ 0x1274, 0x1275, 0x12ab, 0x12ac, 0x12ad, 0x12ae, 0x12af, 0x12b0,
+ 0x12b1, 0x1315, 0x1316, 0x1317, 0x13bf, 0x13c0, 0x13c1, 0x13c2,
+ 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9, 0x13ca,
+ 0x13cb, 0x13cc, 0x13cd, 0x1a06, 0x1a07, 0x1a28, 0x1a29, 0x1a2a,
+ 0x1a2b, 0x1a2c, 0x1a2d, 0x1a80, 0x1abb, 0x1abc, 0x1abd, 0x1ad8,
+ 0x1ad9, 0x0094, 0x0095, 0x0096, 0x0097, 0x00a0, 0x00a1, 0x00a2,
+ 0x00a3, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837,
+ 0x0838, 0x0839, 0x083a, 0x083b, 0x0939, 0x093a, 0x093b, 0x093c,
+ 0x093d, 0x093e, 0x093f, 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x09a4,
+ 0x09a5, 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2,
+ 0x11b3, 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba,
+ 0x11bb, 0x132f, 0x1454, 0x1455, 0x1456, 0x1457, 0x1458, 0x1459,
+ 0x145a, 0x145b, 0x145c, 0x145d, 0x145e, 0x145f, 0x1460, 0x1461,
+ 0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469,
+ 0x146a, 0x146b, 0x17de, 0x17df, 0x17e0, 0x17e1, 0x17e2, 0x17e3,
+ 0x17e4, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9, 0x17ea, 0x17eb,
+ 0x17ec, 0x17ed, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545,
+ 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d,
+ 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555,
+ 0x2628, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c,
+ 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774,
+ 0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c,
+ 0x277d, 0x3503, 0x3544, 0x3545, 0x3546, 0x3547, 0x3560, 0x3561,
+ 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569,
+ 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571,
+ 0x3572, 0x3573, 0x3574, 0x3575, 0x03f0, 0x103d, 0x103e, 0x103f,
+ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
+ 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f,
+ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
+ 0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f,
+ 0x1060, 0x1061, 0x1270, 0x1271, 0x21b8, 0x21b9, 0x21ba, 0x21bb,
+ 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x21f0, 0x21f1, 0x21f2, 0x21f3,
+ 0x21f4, 0x21f5, 0x21f6, 0x21f7, 0x21f8, 0x21f9, 0x21fa, 0x21fb,
+ 0x21fc, 0x21fd, 0x21fe, 0x21ff, 0x2340, 0x2341, 0x2342, 0x2343,
+ 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b,
+ 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353,
+ 0x2354, 0x2355, 0x2356, 0x2357, 0x265c, 0x2f88, 0x2f89, 0x2f8a,
+ 0x2f8b, 0x2f8c, 0x2f8d, 0x2f8e, 0x2f8f, 0x2f90, 0x2f91, 0x2f92,
+ 0x2f93, 0x2f94, 0x2f95, 0x2f96, 0x2f97, 0x2f98, 0x2f99, 0x2f9a,
+ 0x2f9b, 0x2f9c, 0x2f9d, 0x2f9e, 0x2f9f, 0x2fa0, 0x2fa1, 0x2fa2,
+ 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9, 0x2faa,
+ 0x2fab, 0x2fac, 0x2fad, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb2,
+ 0x2fb3, 0x2fb4, 0x2fb5, 0x2fb6, 0x2fb7, 0x2fb8, 0x2fb9, 0x2fba,
+ 0x2fbb, 0x4c52, 0x4c53, 0x4e28, 0x4e29, 0x4e2a, 0x4e2b, 0x4e2c,
+ 0x4e2d, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e32, 0x4e33, 0x4e34,
+ 0x4e35, 0x4e36, 0x4e37, 0x4e38, 0x4e39, 0x4e3a, 0x4e3b, 0x4e3c,
+ 0x4e3d, 0x4e3e, 0x4e3f, 0x4e80, 0x4e81, 0x4e82, 0x4e83, 0x4e84,
+ 0x4e85, 0x4e86, 0x4e87, 0x4e88, 0x4e89, 0x4e8a, 0x4e8b, 0x4e8c,
+ 0x4e8d, 0x4e8e, 0x4e8f, 0x4e90, 0x4e91, 0x4e92, 0x4e93, 0x4e94,
+ 0x4e95, 0x4e96, 0x4e97, 0x4e98, 0x4e99, 0x4e9a, 0x4e9b, 0x4e9c,
+ 0x4e9d, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea1, 0x4ea2, 0x4ea3, 0x4ea4,
+ 0x4ea5, 0x4ea6, 0x4ea7, 0x4ea8, 0x4ea9, 0x4eaa, 0x4eab, 0x4eac,
+ 0x4ead, 0x4eae, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb2, 0x4eb3, 0x4eb4,
+ 0x4eb5, 0x4eb6, 0x4eb7, 0x4eb8, 0x4eb9, 0x4eba, 0x4ebb, 0x4ebc,
+ 0x4ebd, 0x4ebe, 0x4ebf, 0x4ec0, 0x4ec1, 0x4ec2, 0x4ec3, 0x4ec4,
+ 0x4ec5, 0x4ec6, 0x4ec7, 0x4ec8, 0x4ec9, 0x4eca, 0x4ecb, 0x6a04,
+ 0x6a05, 0x07e2, 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8,
+ 0x07e9, 0x07ea, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0,
+ 0x07f1, 0x07f2, 0x07f3, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8,
+ 0x07f9, 0x07fa, 0x07fb, 0x07fc, 0x07fd, 0x07fe, 0x07ff, 0x2000,
+ 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
+ 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x200e, 0x200f, 0x2010,
+ 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018,
+ 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020,
+ 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028,
+ 0x2029, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x202f, 0x2030,
+ 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038,
+ 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040,
+ 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048,
+ 0x2049, 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050,
+ 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058,
+ 0x2059, 0x205a, 0x205b, 0x205c, 0x205d, 0x205e, 0x205f, 0x2060,
+ 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068,
+ 0x2069, 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0x2070,
+ 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078,
+ 0x2079, 0x4cba, 0x4cbb, 0x5d88, 0x5d89, 0x5d8a, 0x5d8b, 0x5d8c,
+ 0x5d8d, 0x5d8e, 0x5d8f, 0x5db0, 0x5db1, 0x5db2, 0x5db3, 0x5db4,
+ 0x5db5, 0x5db6, 0x5db7, 0x5db8, 0x5db9, 0x5dba, 0x5dbb, 0x5dbc,
+ 0x5dbd, 0x5dbe, 0x5dbf, 0x5e40, 0x5e41, 0x5e42, 0x5e43, 0x5e44,
+ 0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4a, 0x5e4b, 0x5e4c,
+ 0x5e4d, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e54,
+ 0x5e55, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5b, 0x5e5c,
+ 0x5e5d, 0x5e5e, 0x5e5f, 0x5e60, 0x5e61, 0x5e62, 0x5e63, 0x5e64,
+ 0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c,
+ 0x5e6d, 0x5e6e, 0x5e6f, 0x5e70, 0x5e71, 0x5e72, 0x5e73, 0x5e74,
+ 0x5e75, 0x5e76, 0x5e77, 0x5e78, 0x5e79, 0x5e7a, 0x5e7b, 0x5e7c,
+ 0x5e7d, 0x5e7e, 0x5e7f, 0x5e80, 0x5e81, 0x5e82, 0x5e83, 0x5e84,
+ 0x5e85, 0x5e86, 0x5e87, 0x5e88, 0x5e89, 0x5e8a, 0x5e8b, 0x5e8c,
+ 0x5e8d, 0x5e8e, 0x5e8f, 0x5e90, 0x5e91, 0x5e92, 0x5e93, 0x5e94,
+ 0x5e95, 0x5e96, 0x5e97, 0x5e98, 0x5e99, 0x5e9a, 0x5e9b, 0x5e9c,
+ 0x5e9d, 0x5e9e, 0x5e9f, 0x5ea0, 0x5ea1, 0x5ea2, 0x5ea3, 0x5ea4,
+ 0x5ea5, 0x5ea6, 0x5ea7, 0x5ea8, 0x5ea9, 0x5eaa, 0x5eab, 0x5eac,
+ 0x5ead, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb2, 0x5eb3, 0x5eb4,
+ 0x5eb5, 0x5eb6, 0x5eb7, 0x5eb8, 0x5eb9, 0x5eba, 0x5ebb, 0x5ebc,
+ 0x5ebd, 0x5ebe, 0x5ebf, 0x5ec0, 0x5ec1, 0x5ec2, 0x5ec3, 0x5ec4,
+ 0x5ec5, 0x5ec6, 0x5ec7, 0x5ec8, 0x5ec9, 0x5eca, 0x5ecb, 0x5ecc,
+ 0x5ecd, 0x5ece, 0x5ecf, 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4,
+ 0x5ed5, 0x5ed6, 0x5ed7, 0x5ed8, 0x5ed9, 0x5eda, 0x5edb, 0x5edc,
+ 0x5edd, 0x5ede, 0x5edf, 0x5ee0, 0x5ee1, 0x5ee2, 0x5ee3, 0x5ee4,
+ 0x5ee5, 0x5ee6, 0x5ee7, 0x5ee8, 0x5ee9, 0x5eea, 0x5eeb, 0x5eec,
+ 0x5eed, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef2, 0x5ef3, 0x5ef4,
+ 0x5ef5, 0x5ef6, 0x5ef7, 0x5ef8, 0x5ef9, 0x5efa, 0x5efb, 0x5efc,
+ 0x5efd, 0x5efe, 0x5eff, 0x5f00, 0x5f01, 0x5f02, 0x5f03, 0x5f04,
+ 0x5f05, 0x5f06, 0x5f07, 0x5f08, 0x5f09, 0x5f0a, 0x5f0b, 0x5f0c,
+ 0x5f0d, 0x5f0e, 0x5f0f, 0x0000,
+};
+
+const UINT8 table0_mv_bits[1100] = {
+ 1, 4, 4, 4, 5, 5, 5, 6,
+ 6, 6, 7, 7, 7, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 8,
+};
+
+const UINT8 table0_mvx[1099] = {
+ 32, 32, 31, 32, 33, 31, 33, 31,
+ 33, 32, 34, 32, 30, 32, 31, 34,
+ 35, 32, 34, 33, 29, 33, 30, 30,
+ 31, 31, 35, 29, 33, 35, 33, 34,
+ 31, 29, 30, 34, 30, 36, 28, 32,
+ 34, 37, 30, 27, 32, 25, 39, 32,
+ 34, 32, 35, 35, 35, 31, 35, 29,
+ 32, 29, 30, 29, 37, 27, 36, 38,
+ 37, 33, 32, 31, 29, 31, 28, 36,
+ 33, 30, 34, 33, 33, 28, 27, 25,
+ 31, 26, 39, 32, 32, 31, 33, 39,
+ 31, 38, 28, 36, 21, 23, 43, 36,
+ 34, 41, 30, 25, 28, 31, 30, 34,
+ 38, 35, 61, 34, 28, 30, 37, 37,
+ 35, 27, 36, 3, 59, 38, 37, 32,
+ 31, 29, 26, 33, 37, 33, 27, 27,
+ 35, 34, 34, 40, 42, 33, 32, 29,
+ 4, 5, 28, 24, 25, 35, 39, 38,
+ 32, 23, 27, 32, 30, 35, 26, 34,
+ 60, 36, 29, 22, 26, 41, 7, 30,
+ 38, 30, 36, 29, 30, 41, 26, 25,
+ 32, 34, 24, 39, 1, 25, 39, 32,
+ 28, 29, 32, 38, 26, 36, 28, 63,
+ 28, 39, 23, 21, 26, 35, 31, 35,
+ 57, 31, 29, 29, 28, 30, 27, 35,
+ 2, 38, 40, 34, 37, 29, 38, 43,
+ 26, 32, 33, 42, 24, 40, 28, 32,
+ 32, 32, 36, 32, 43, 25, 21, 31,
+ 30, 31, 41, 29, 33, 37, 26, 37,
+ 27, 59, 23, 33, 35, 31, 31, 37,
+ 38, 39, 32, 23, 32, 27, 37, 36,
+ 31, 40, 25, 27, 38, 31, 36, 28,
+ 31, 36, 25, 45, 3, 34, 38, 39,
+ 40, 38, 30, 32, 19, 24, 25, 26,
+ 45, 20, 24, 33, 33, 31, 41, 34,
+ 39, 47, 40, 58, 59, 41, 33, 3,
+ 17, 61, 42, 30, 26, 29, 36, 61,
+ 33, 37, 62, 28, 25, 38, 25, 38,
+ 17, 23, 34, 33, 21, 33, 49, 27,
+ 32, 23, 27, 22, 24, 22, 39, 43,
+ 27, 37, 6, 42, 47, 26, 30, 31,
+ 41, 39, 33, 22, 45, 36, 32, 45,
+ 19, 22, 30, 5, 5, 17, 29, 22,
+ 31, 31, 43, 37, 27, 32, 32, 32,
+ 33, 34, 43, 35, 29, 26, 22, 32,
+ 19, 32, 25, 31, 41, 49, 28, 34,
+ 28, 39, 34, 19, 37, 38, 29, 21,
+ 36, 42, 24, 48, 16, 28, 49, 22,
+ 34, 31, 38, 39, 44, 11, 35, 30,
+ 33, 33, 23, 28, 33, 46, 15, 13,
+ 24, 41, 24, 34, 34, 30, 26, 24,
+ 14, 60, 21, 29, 39, 23, 35, 37,
+ 63, 45, 33, 34, 47, 41, 22, 42,
+ 35, 35, 23, 32, 35, 43, 32, 7,
+ 31, 41, 20, 31, 16, 13, 63, 25,
+ 30, 32, 35, 30, 30, 31, 42, 47,
+ 39, 38, 40, 40, 51, 55, 56, 18,
+ 21, 39, 39, 33, 17, 41, 23, 24,
+ 43, 25, 31, 20, 19, 45, 1, 34,
+ 31, 22, 35, 15, 46, 46, 35, 31,
+ 28, 29, 29, 23, 41, 27, 14, 53,
+ 53, 27, 24, 32, 57, 32, 17, 42,
+ 37, 29, 33, 1, 25, 32, 32, 63,
+ 26, 40, 44, 36, 31, 39, 20, 20,
+ 44, 23, 33, 34, 35, 33, 33, 28,
+ 41, 23, 41, 41, 29, 25, 26, 49,
+ 29, 24, 37, 49, 50, 51, 51, 26,
+ 39, 25, 26, 15, 39, 18, 42, 17,
+ 4, 31, 32, 32, 60, 1, 42, 32,
+ 0, 12, 19, 35, 21, 41, 17, 26,
+ 20, 45, 46, 32, 37, 22, 47, 29,
+ 31, 27, 29, 30, 21, 33, 35, 18,
+ 25, 33, 50, 51, 42, 2, 15, 51,
+ 53, 33, 25, 29, 55, 37, 38, 33,
+ 38, 59, 38, 33, 39, 13, 32, 40,
+ 61, 61, 32, 9, 44, 3, 31, 29,
+ 25, 31, 27, 23, 9, 25, 9, 29,
+ 20, 30, 30, 42, 18, 28, 25, 28,
+ 28, 21, 29, 43, 29, 43, 26, 44,
+ 44, 21, 38, 21, 24, 45, 45, 35,
+ 39, 22, 35, 36, 34, 34, 45, 34,
+ 29, 31, 46, 25, 46, 16, 17, 31,
+ 20, 32, 47, 47, 47, 32, 49, 49,
+ 49, 31, 1, 27, 28, 39, 39, 21,
+ 36, 23, 51, 2, 40, 51, 32, 53,
+ 24, 30, 24, 30, 21, 40, 57, 57,
+ 31, 41, 58, 32, 12, 4, 32, 34,
+ 59, 31, 32, 13, 9, 35, 26, 35,
+ 37, 61, 37, 63, 26, 29, 41, 38,
+ 23, 20, 41, 26, 41, 42, 42, 42,
+ 26, 26, 26, 26, 1, 26, 37, 37,
+ 37, 23, 34, 42, 27, 43, 34, 27,
+ 31, 24, 33, 16, 3, 31, 24, 33,
+ 24, 4, 44, 44, 11, 44, 31, 13,
+ 13, 44, 45, 13, 25, 22, 38, 26,
+ 38, 38, 39, 32, 30, 39, 30, 22,
+ 32, 26, 30, 47, 47, 47, 19, 47,
+ 30, 31, 35, 8, 23, 47, 47, 27,
+ 35, 47, 31, 48, 35, 19, 36, 49,
+ 49, 33, 31, 39, 27, 39, 49, 49,
+ 50, 50, 50, 39, 31, 51, 51, 39,
+ 28, 33, 33, 21, 40, 31, 52, 53,
+ 40, 53, 9, 33, 31, 53, 54, 54,
+ 54, 55, 55, 34, 15, 56, 25, 56,
+ 21, 21, 40, 40, 25, 40, 58, 36,
+ 5, 41, 41, 12, 60, 41, 41, 37,
+ 22, 61, 18, 29, 29, 30, 61, 30,
+ 61, 62, 62, 30, 30, 63, 18, 13,
+ 30, 23, 19, 20, 20, 41, 13, 2,
+ 5, 5, 1, 5, 32, 6, 32, 35,
+ 20, 35, 27, 35, 35, 36, 36, 13,
+ 36, 41, 41, 41, 3, 30, 42, 27,
+ 20, 30, 27, 28, 30, 21, 33, 33,
+ 14, 24, 30, 42, 24, 33, 25, 42,
+ 43, 14, 43, 43, 14, 43, 7, 36,
+ 37, 37, 37, 37, 7, 14, 25, 43,
+ 43, 44, 15, 37, 7, 7, 3, 1,
+ 8, 15, 15, 8, 44, 44, 44, 45,
+ 45, 45, 45, 8, 8, 45, 21, 45,
+ 28, 28, 28, 21, 28, 28, 22, 37,
+ 46, 46, 37, 8, 29, 37, 29, 22,
+ 46, 37, 22, 29, 47, 47, 38, 38,
+ 16, 38, 38, 33, 38, 22, 47, 47,
+ 29, 25, 16, 0, 48, 1, 34, 48,
+ 48, 34, 25, 26, 26, 49, 49, 26,
+ 1, 49, 4, 26, 4, 49, 1, 9,
+ 49, 49, 49, 10, 49, 17, 38, 17,
+ 17, 50, 38, 50, 50, 22, 38, 51,
+ 38, 38, 51, 39, 39, 18, 22, 39,
+ 51, 22, 52, 52, 52, 39, 53, 53,
+ 10, 23, 18, 29, 10, 53, 29, 54,
+ 11, 54, 11, 11, 55, 1, 18, 55,
+ 55, 55, 55, 55, 55, 29, 34, 18,
+ 29, 56, 56, 34, 57, 34, 34, 29,
+ 29, 57, 57, 35, 35, 35, 35, 35,
+ 39, 35, 59, 59, 18, 59, 39, 30,
+ 18, 40, 60, 60, 61, 30, 18, 61,
+ 61, 19, 19,
+};
+
+const UINT8 table0_mvy[1099] = {
+ 32, 31, 32, 33, 32, 31, 31, 33,
+ 33, 34, 32, 30, 32, 35, 34, 31,
+ 32, 29, 33, 30, 32, 34, 33, 31,
+ 30, 35, 31, 31, 29, 33, 35, 30,
+ 29, 33, 34, 34, 30, 32, 32, 36,
+ 29, 32, 35, 32, 28, 32, 32, 27,
+ 35, 37, 34, 29, 30, 36, 35, 34,
+ 25, 30, 29, 35, 33, 31, 31, 32,
+ 31, 28, 39, 28, 29, 37, 31, 33,
+ 27, 36, 28, 36, 37, 33, 33, 31,
+ 27, 32, 31, 38, 26, 25, 25, 33,
+ 39, 31, 34, 30, 32, 32, 32, 34,
+ 36, 32, 28, 33, 30, 38, 37, 27,
+ 33, 28, 32, 37, 35, 38, 29, 34,
+ 27, 29, 29, 32, 32, 34, 35, 3,
+ 26, 36, 31, 38, 30, 26, 35, 34,
+ 37, 26, 25, 32, 32, 39, 23, 37,
+ 32, 32, 29, 32, 29, 36, 29, 30,
+ 41, 31, 30, 21, 39, 25, 34, 38,
+ 32, 35, 39, 32, 33, 33, 32, 27,
+ 29, 25, 28, 27, 26, 31, 30, 35,
+ 24, 24, 31, 34, 32, 30, 35, 40,
+ 28, 38, 5, 35, 29, 36, 36, 32,
+ 38, 30, 33, 31, 35, 26, 23, 38,
+ 32, 41, 28, 25, 37, 40, 37, 39,
+ 32, 36, 33, 39, 25, 26, 28, 31,
+ 28, 42, 23, 31, 33, 31, 39, 1,
+ 59, 22, 27, 4, 33, 34, 33, 24,
+ 41, 3, 35, 41, 41, 28, 36, 36,
+ 28, 33, 35, 21, 23, 21, 22, 37,
+ 27, 27, 43, 29, 60, 39, 27, 25,
+ 59, 34, 27, 27, 26, 40, 37, 27,
+ 61, 26, 39, 33, 31, 22, 37, 25,
+ 30, 25, 24, 61, 31, 34, 25, 38,
+ 32, 32, 30, 3, 61, 43, 29, 23,
+ 28, 32, 28, 32, 31, 34, 5, 33,
+ 32, 33, 33, 42, 37, 23, 38, 31,
+ 40, 26, 32, 26, 37, 38, 36, 24,
+ 29, 30, 20, 22, 29, 24, 32, 41,
+ 2, 34, 25, 33, 29, 31, 39, 35,
+ 36, 24, 32, 30, 33, 27, 44, 60,
+ 30, 36, 19, 34, 31, 24, 16, 35,
+ 32, 38, 21, 33, 31, 31, 21, 35,
+ 5, 17, 29, 38, 38, 18, 58, 19,
+ 43, 41, 30, 41, 43, 39, 29, 7,
+ 29, 17, 28, 19, 28, 31, 25, 19,
+ 40, 26, 21, 33, 39, 23, 40, 30,
+ 39, 34, 35, 32, 32, 24, 33, 30,
+ 40, 47, 39, 37, 32, 33, 24, 23,
+ 45, 47, 27, 23, 42, 32, 32, 33,
+ 36, 37, 37, 17, 18, 22, 40, 38,
+ 32, 31, 35, 24, 17, 25, 17, 23,
+ 33, 34, 51, 42, 31, 36, 36, 29,
+ 21, 22, 37, 44, 43, 25, 47, 33,
+ 45, 27, 31, 58, 31, 32, 31, 38,
+ 43, 20, 47, 45, 54, 1, 26, 34,
+ 38, 14, 22, 24, 33, 34, 32, 32,
+ 37, 21, 23, 49, 35, 23, 28, 39,
+ 39, 23, 55, 33, 30, 30, 63, 16,
+ 42, 28, 13, 33, 33, 35, 19, 46,
+ 43, 17, 19, 36, 39, 24, 31, 32,
+ 33, 26, 28, 62, 33, 63, 33, 39,
+ 19, 49, 17, 31, 43, 13, 15, 29,
+ 25, 35, 33, 23, 49, 41, 28, 29,
+ 34, 38, 7, 61, 11, 50, 13, 41,
+ 19, 47, 25, 26, 15, 42, 41, 29,
+ 45, 27, 17, 35, 32, 29, 32, 24,
+ 13, 26, 26, 31, 24, 33, 28, 30,
+ 31, 11, 45, 46, 33, 33, 35, 57,
+ 32, 32, 35, 45, 34, 11, 37, 42,
+ 39, 37, 31, 49, 21, 27, 29, 47,
+ 53, 40, 51, 16, 26, 1, 40, 30,
+ 41, 44, 34, 25, 27, 31, 35, 35,
+ 31, 15, 49, 1, 35, 40, 5, 58,
+ 21, 29, 22, 59, 45, 31, 9, 26,
+ 9, 29, 11, 32, 30, 3, 13, 20,
+ 18, 20, 11, 3, 29, 40, 31, 53,
+ 30, 17, 20, 37, 31, 42, 47, 47,
+ 54, 38, 9, 34, 13, 37, 21, 25,
+ 27, 43, 42, 45, 40, 25, 27, 46,
+ 22, 25, 53, 20, 2, 14, 39, 15,
+ 22, 44, 34, 21, 38, 33, 27, 48,
+ 34, 52, 35, 47, 49, 54, 2, 13,
+ 23, 52, 29, 45, 22, 49, 54, 21,
+ 40, 42, 31, 30, 29, 34, 0, 25,
+ 23, 51, 24, 59, 28, 38, 29, 31,
+ 2, 13, 31, 8, 31, 33, 12, 45,
+ 41, 7, 14, 30, 25, 18, 43, 20,
+ 43, 35, 44, 1, 49, 42, 42, 18,
+ 41, 38, 41, 44, 53, 11, 20, 25,
+ 45, 46, 47, 48, 39, 52, 46, 49,
+ 63, 55, 44, 38, 13, 13, 57, 22,
+ 51, 16, 12, 28, 35, 57, 25, 20,
+ 26, 28, 28, 29, 32, 31, 62, 34,
+ 35, 35, 19, 49, 48, 39, 40, 18,
+ 43, 46, 11, 6, 48, 19, 49, 41,
+ 10, 23, 58, 17, 21, 23, 34, 30,
+ 60, 0, 44, 34, 26, 37, 46, 43,
+ 49, 59, 4, 34, 59, 37, 22, 25,
+ 28, 46, 6, 40, 59, 42, 36, 61,
+ 28, 30, 31, 43, 10, 22, 23, 47,
+ 20, 52, 55, 36, 25, 16, 1, 11,
+ 27, 29, 5, 63, 18, 41, 31, 34,
+ 38, 1, 5, 13, 28, 31, 17, 38,
+ 39, 41, 36, 37, 22, 39, 33, 43,
+ 43, 15, 17, 49, 30, 21, 22, 20,
+ 10, 17, 25, 54, 57, 3, 34, 8,
+ 36, 25, 31, 14, 15, 19, 29, 25,
+ 18, 39, 53, 22, 27, 20, 29, 33,
+ 41, 42, 35, 62, 50, 29, 53, 50,
+ 35, 55, 42, 61, 63, 4, 7, 42,
+ 21, 46, 47, 49, 27, 46, 17, 55,
+ 41, 50, 63, 4, 56, 18, 8, 10,
+ 18, 51, 63, 36, 55, 18, 5, 55,
+ 9, 29, 17, 21, 30, 27, 1, 59,
+ 7, 11, 12, 15, 5, 42, 24, 41,
+ 43, 7, 27, 22, 25, 31, 30, 37,
+ 22, 39, 53, 29, 36, 37, 48, 0,
+ 5, 13, 17, 31, 32, 26, 46, 28,
+ 44, 45, 46, 53, 49, 51, 3, 41,
+ 3, 22, 42, 33, 5, 45, 7, 22,
+ 40, 53, 24, 14, 25, 27, 10, 12,
+ 34, 16, 17, 53, 20, 26, 39, 45,
+ 18, 45, 35, 33, 31, 49, 4, 39,
+ 42, 11, 51, 5, 13, 26, 27, 17,
+ 52, 30, 0, 22, 12, 34, 62, 36,
+ 38, 41, 47, 30, 63, 38, 41, 43,
+ 59, 33, 45, 37, 38, 40, 47, 24,
+ 48, 49, 30, 1, 10, 22, 49, 15,
+ 39, 59, 31, 32, 33, 18, 13, 15,
+ 31, 21, 27, 44, 42, 39, 46, 17,
+ 26, 32, 30, 31, 0, 30, 34, 9,
+ 12, 13, 25, 31, 32, 55, 43, 35,
+ 61, 33, 35, 46, 25, 47, 48, 62,
+ 63, 38, 61, 1, 2, 5, 7, 9,
+ 46, 10, 34, 35, 36, 55, 51, 7,
+ 40, 23, 34, 37, 5, 13, 42, 18,
+ 25, 27, 28,
+};
+
+/* motion vector table 1 */
+const UINT16 table1_mv_code[1100] = {
+ 0x0000, 0x0007, 0x0009, 0x000f, 0x000a, 0x0011, 0x001a, 0x001c,
+ 0x0011, 0x0031, 0x0025, 0x002d, 0x002f, 0x006f, 0x0075, 0x0041,
+ 0x004c, 0x004e, 0x005c, 0x0060, 0x0062, 0x0066, 0x0068, 0x0069,
+ 0x006b, 0x00a6, 0x00c1, 0x00cb, 0x00cc, 0x00ce, 0x00da, 0x00e8,
+ 0x00ee, 0x0087, 0x0090, 0x009e, 0x009f, 0x00ba, 0x00ca, 0x00d8,
+ 0x00db, 0x00df, 0x0104, 0x0109, 0x010c, 0x0143, 0x0145, 0x014a,
+ 0x0156, 0x015c, 0x01b3, 0x01d3, 0x01da, 0x0103, 0x0109, 0x010b,
+ 0x0122, 0x0127, 0x0134, 0x0161, 0x0164, 0x0176, 0x0184, 0x018d,
+ 0x018e, 0x018f, 0x0190, 0x0193, 0x0196, 0x019d, 0x019e, 0x019f,
+ 0x01a9, 0x01b2, 0x01b4, 0x01ba, 0x01bb, 0x01bc, 0x0201, 0x0202,
+ 0x0205, 0x0207, 0x020d, 0x0210, 0x0211, 0x0215, 0x021b, 0x021f,
+ 0x0281, 0x0285, 0x0290, 0x029c, 0x029d, 0x02a2, 0x02a7, 0x02a8,
+ 0x02aa, 0x02b0, 0x02b1, 0x02b4, 0x02bc, 0x02bf, 0x0320, 0x0326,
+ 0x0327, 0x0329, 0x032a, 0x0336, 0x0360, 0x0362, 0x0363, 0x0372,
+ 0x03b2, 0x03bc, 0x03bd, 0x0203, 0x0205, 0x021a, 0x0249, 0x024a,
+ 0x024c, 0x02c7, 0x02ca, 0x02ce, 0x02ef, 0x030d, 0x0322, 0x0325,
+ 0x0338, 0x0373, 0x037a, 0x0409, 0x0415, 0x0416, 0x0418, 0x0428,
+ 0x042d, 0x042f, 0x0434, 0x0508, 0x0509, 0x0510, 0x0511, 0x051c,
+ 0x051e, 0x0524, 0x0541, 0x0543, 0x0546, 0x0547, 0x054d, 0x0557,
+ 0x055f, 0x056a, 0x056c, 0x056d, 0x056f, 0x0576, 0x0577, 0x057a,
+ 0x057b, 0x057c, 0x057d, 0x0600, 0x0601, 0x0603, 0x0614, 0x0616,
+ 0x0617, 0x061c, 0x061f, 0x0642, 0x0648, 0x0649, 0x064a, 0x064b,
+ 0x0657, 0x0668, 0x0669, 0x066b, 0x066e, 0x067f, 0x06c2, 0x06c8,
+ 0x06cb, 0x06de, 0x06df, 0x06e2, 0x06e3, 0x06ef, 0x0748, 0x074b,
+ 0x076e, 0x076f, 0x077c, 0x0409, 0x0423, 0x0428, 0x0429, 0x042a,
+ 0x042b, 0x0432, 0x0433, 0x0496, 0x049a, 0x04d5, 0x04db, 0x0581,
+ 0x0582, 0x058b, 0x058c, 0x058d, 0x0598, 0x0599, 0x059a, 0x059e,
+ 0x05dd, 0x0619, 0x0632, 0x0633, 0x0648, 0x0672, 0x06a1, 0x06a2,
+ 0x06a3, 0x06af, 0x06e2, 0x06e3, 0x06e4, 0x0800, 0x0801, 0x0802,
+ 0x0803, 0x081a, 0x081b, 0x0829, 0x082f, 0x0832, 0x083e, 0x083f,
+ 0x0852, 0x0853, 0x0858, 0x086b, 0x0877, 0x0878, 0x0879, 0x087a,
+ 0x087b, 0x0a00, 0x0a01, 0x0a0d, 0x0a0e, 0x0a0f, 0x0a24, 0x0a37,
+ 0x0a3a, 0x0a3b, 0x0a3e, 0x0a46, 0x0a47, 0x0a4a, 0x0a4b, 0x0a5f,
+ 0x0a79, 0x0a7a, 0x0a7b, 0x0a80, 0x0a81, 0x0a84, 0x0a85, 0x0a99,
+ 0x0aa5, 0x0aa6, 0x0ab8, 0x0aba, 0x0abb, 0x0abc, 0x0abd, 0x0ac8,
+ 0x0ace, 0x0acf, 0x0ad7, 0x0adc, 0x0aeb, 0x0c04, 0x0c25, 0x0c26,
+ 0x0c27, 0x0c2a, 0x0c2b, 0x0c3a, 0x0c3b, 0x0c3c, 0x0c3d, 0x0ca0,
+ 0x0cad, 0x0cd4, 0x0cd5, 0x0cfc, 0x0cfd, 0x0d86, 0x0d92, 0x0d93,
+ 0x0d94, 0x0d95, 0x0db0, 0x0db8, 0x0db9, 0x0dba, 0x0dbb, 0x0dc0,
+ 0x0dc2, 0x0dc3, 0x0dda, 0x0ddb, 0x0ddc, 0x0ddd, 0x0e92, 0x0e93,
+ 0x0e94, 0x0e95, 0x0ec7, 0x0ecc, 0x0ece, 0x0ecf, 0x0ed8, 0x0ed9,
+ 0x0eda, 0x0edb, 0x0808, 0x0809, 0x080a, 0x0810, 0x0811, 0x0844,
+ 0x0845, 0x0861, 0x0862, 0x0863, 0x086c, 0x0922, 0x0923, 0x092e,
+ 0x092f, 0x0936, 0x0937, 0x09b1, 0x09b2, 0x09b3, 0x09b4, 0x09b5,
+ 0x09b8, 0x09b9, 0x09ba, 0x09bb, 0x09bc, 0x09bd, 0x09be, 0x09bf,
+ 0x0b00, 0x0b15, 0x0b2c, 0x0b2d, 0x0b2e, 0x0b2f, 0x0b36, 0x0bb9,
+ 0x0c28, 0x0c2a, 0x0c2b, 0x0c2c, 0x0c2d, 0x0c2e, 0x0c2f, 0x0c30,
+ 0x0c31, 0x0c38, 0x0c60, 0x0c61, 0x0c62, 0x0c63, 0x0c8d, 0x0c8e,
+ 0x0c8f, 0x0c92, 0x0cbe, 0x0cbf, 0x0ce6, 0x0ce7, 0x0d40, 0x0d41,
+ 0x0d57, 0x0d58, 0x0d59, 0x0d5a, 0x0d5b, 0x0d5c, 0x0d5d, 0x0d98,
+ 0x0d99, 0x0d9a, 0x0d9b, 0x0d9c, 0x0d9d, 0x0dad, 0x0dae, 0x0daf,
+ 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3, 0x0dca, 0x0dcb, 0x0dec, 0x0ded,
+ 0x0dee, 0x0def, 0x1018, 0x1022, 0x1023, 0x1030, 0x1031, 0x1032,
+ 0x1033, 0x1050, 0x1051, 0x105c, 0x1074, 0x1075, 0x1076, 0x1077,
+ 0x1078, 0x1079, 0x107a, 0x107b, 0x10b2, 0x10b3, 0x10b8, 0x10b9,
+ 0x10ba, 0x10bb, 0x10d4, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x1404,
+ 0x1405, 0x1406, 0x1407, 0x1410, 0x1411, 0x1412, 0x1413, 0x1414,
+ 0x1415, 0x1416, 0x1417, 0x1418, 0x1419, 0x1466, 0x1467, 0x1468,
+ 0x1469, 0x146a, 0x146b, 0x146c, 0x146d, 0x147e, 0x147f, 0x1488,
+ 0x1489, 0x148a, 0x148b, 0x14b6, 0x14b7, 0x14b8, 0x14b9, 0x14ba,
+ 0x14bb, 0x14bc, 0x14bd, 0x14f0, 0x14f1, 0x14f8, 0x14f9, 0x14fa,
+ 0x14fb, 0x14fc, 0x14fd, 0x14fe, 0x14ff, 0x152a, 0x152b, 0x152c,
+ 0x152d, 0x152e, 0x152f, 0x1530, 0x1531, 0x1548, 0x1549, 0x154e,
+ 0x154f, 0x1558, 0x1559, 0x155a, 0x155b, 0x1572, 0x159a, 0x159b,
+ 0x15ac, 0x15ba, 0x15bb, 0x15d0, 0x15d1, 0x15d2, 0x15d3, 0x15d4,
+ 0x15d5, 0x181d, 0x181e, 0x181f, 0x1840, 0x1841, 0x1842, 0x1843,
+ 0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x1861, 0x1862,
+ 0x1863, 0x1864, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869, 0x186a,
+ 0x186b, 0x186c, 0x186d, 0x186e, 0x191b, 0x191c, 0x191d, 0x191e,
+ 0x191f, 0x1942, 0x1943, 0x1944, 0x1945, 0x1946, 0x1947, 0x1958,
+ 0x1959, 0x19ed, 0x19ee, 0x19ef, 0x19f0, 0x19f1, 0x19f2, 0x19f3,
+ 0x19f4, 0x19f5, 0x19f6, 0x19f7, 0x1b0e, 0x1b0f, 0x1b62, 0x1b63,
+ 0x1b64, 0x1b65, 0x1b66, 0x1b67, 0x1b68, 0x1b69, 0x1b6a, 0x1b6b,
+ 0x1b6c, 0x1b6d, 0x1b6e, 0x1b6f, 0x1b82, 0x1ba8, 0x1ba9, 0x1baa,
+ 0x1bab, 0x1bac, 0x1bad, 0x1bae, 0x1baf, 0x1bb0, 0x1bb1, 0x1bb2,
+ 0x1bb3, 0x1d80, 0x1d81, 0x1d82, 0x1d83, 0x1d84, 0x1d85, 0x1d86,
+ 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, 0x1d8c, 0x1d8d, 0x1007,
+ 0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f,
+ 0x1016, 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086,
+ 0x1087, 0x10c0, 0x123a, 0x123b, 0x123c, 0x123d, 0x123e, 0x123f,
+ 0x1240, 0x1241, 0x1242, 0x1243, 0x1350, 0x1352, 0x1353, 0x1358,
+ 0x1359, 0x135a, 0x135b, 0x135c, 0x135d, 0x135e, 0x135f, 0x1360,
+ 0x1361, 0x1602, 0x1603, 0x160c, 0x160d, 0x160e, 0x160f, 0x1620,
+ 0x1621, 0x1622, 0x1623, 0x1624, 0x1625, 0x1626, 0x1627, 0x1628,
+ 0x1629, 0x166e, 0x166f, 0x167c, 0x167d, 0x167e, 0x167f, 0x1770,
+ 0x1771, 0x1852, 0x1853, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876,
+ 0x1877, 0x1878, 0x1879, 0x187a, 0x187b, 0x187c, 0x187d, 0x187e,
+ 0x187f, 0x1918, 0x1919, 0x1926, 0x1927, 0x1970, 0x1971, 0x1972,
+ 0x1973, 0x1974, 0x1975, 0x1976, 0x1977, 0x1978, 0x1979, 0x197a,
+ 0x197b, 0x1aa0, 0x1aa1, 0x1aa2, 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa6,
+ 0x1aa7, 0x1aa8, 0x1aa9, 0x1aaa, 0x1aab, 0x1aac, 0x1aad, 0x1b3c,
+ 0x1b3d, 0x1b3e, 0x1b3f, 0x1b50, 0x1b51, 0x1b52, 0x1b53, 0x1b54,
+ 0x1b55, 0x1b56, 0x1b57, 0x1b58, 0x1b59, 0x2032, 0x2033, 0x2034,
+ 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b, 0x203c,
+ 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, 0x20ba,
+ 0x20bb, 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20e0, 0x20e1, 0x20e2,
+ 0x20e3, 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x21aa, 0x21ab, 0x21c0,
+ 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, 0x21c8,
+ 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, 0x21d0,
+ 0x21d1, 0x21d2, 0x21d3, 0x2894, 0x2895, 0x2896, 0x2897, 0x2898,
+ 0x2899, 0x289a, 0x289b, 0x289c, 0x289d, 0x289e, 0x289f, 0x28c0,
+ 0x28c1, 0x28c2, 0x28c3, 0x28c4, 0x28c5, 0x28c6, 0x28c7, 0x28c8,
+ 0x28c9, 0x28ca, 0x28cb, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934,
+ 0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b, 0x293c,
+ 0x293d, 0x293e, 0x293f, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964,
+ 0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b, 0x2a40,
+ 0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47, 0x2a48,
+ 0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f, 0x2a50,
+ 0x2a51, 0x2a52, 0x2a53, 0x2ae6, 0x2ae7, 0x2b24, 0x2b25, 0x2b26,
+ 0x2b27, 0x2b28, 0x2b29, 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2d, 0x2b2e,
+ 0x2b2f, 0x2b30, 0x2b31, 0x2b32, 0x2b33, 0x2b5a, 0x2b5b, 0x3014,
+ 0x3015, 0x3016, 0x3017, 0x3020, 0x3021, 0x3022, 0x3023, 0x3024,
+ 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302a, 0x302b, 0x302c,
+ 0x302d, 0x302e, 0x302f, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034,
+ 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x30c0, 0x30c1, 0x30de,
+ 0x30df, 0x3218, 0x3219, 0x321a, 0x321b, 0x321c, 0x321d, 0x321e,
+ 0x321f, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226,
+ 0x3227, 0x3228, 0x3229, 0x322a, 0x322b, 0x322c, 0x322d, 0x322e,
+ 0x322f, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3378,
+ 0x3379, 0x337a, 0x337b, 0x337c, 0x337d, 0x337e, 0x337f, 0x33c0,
+ 0x33c1, 0x33c2, 0x33c3, 0x33c4, 0x33c5, 0x33c6, 0x33c7, 0x33c8,
+ 0x33c9, 0x33ca, 0x33cb, 0x33cc, 0x33cd, 0x33ce, 0x33cf, 0x33d0,
+ 0x33d1, 0x33d2, 0x33d3, 0x33d4, 0x33d5, 0x33d6, 0x33d7, 0x33d8,
+ 0x33d9, 0x3706, 0x3707, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734,
+ 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373a, 0x373b, 0x373c,
+ 0x373d, 0x373e, 0x373f, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744,
+ 0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374a, 0x374b, 0x374c,
+ 0x374d, 0x374e, 0x374f, 0x3b34, 0x3b35, 0x3b36, 0x3b37, 0x3be8,
+ 0x3be9, 0x3bea, 0x3beb, 0x3bec, 0x3bed, 0x3bee, 0x3bef, 0x3bf0,
+ 0x3bf1, 0x3bf2, 0x3bf3, 0x3bf4, 0x3bf5, 0x3bf6, 0x3bf7, 0x3bf8,
+ 0x3bf9, 0x3bfa, 0x3bfb, 0x3bfc, 0x3bfd, 0x3bfe, 0x3bff, 0x2000,
+ 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
+ 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x202e, 0x202f, 0x2182,
+ 0x2183, 0x21b4, 0x21b5, 0x21b6, 0x21b7, 0x21b8, 0x21b9, 0x21ba,
+ 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x2460, 0x2461, 0x2462,
+ 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a,
+ 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472,
+ 0x2473, 0x26a2, 0x26a3, 0x000b,
+};
+
+const UINT8 table1_mv_bits[1100] = {
+ 2, 4, 4, 4, 5, 5, 5, 5,
+ 6, 6, 7, 7, 7, 7, 7, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 4,
+};
+
+const UINT8 table1_mvx[1099] = {
+ 32, 31, 32, 31, 33, 32, 33, 33,
+ 31, 34, 30, 32, 32, 34, 35, 32,
+ 34, 33, 29, 30, 30, 32, 31, 31,
+ 33, 35, 35, 33, 31, 29, 29, 33,
+ 34, 30, 31, 28, 36, 30, 34, 32,
+ 32, 37, 32, 32, 25, 27, 39, 32,
+ 32, 32, 38, 35, 36, 32, 37, 61,
+ 26, 32, 34, 35, 3, 35, 27, 28,
+ 29, 34, 28, 37, 31, 36, 32, 27,
+ 31, 30, 29, 39, 33, 29, 33, 35,
+ 25, 25, 29, 33, 31, 31, 31, 33,
+ 32, 30, 32, 32, 41, 39, 33, 36,
+ 32, 28, 34, 36, 38, 24, 60, 31,
+ 23, 28, 32, 33, 59, 32, 40, 30,
+ 5, 34, 32, 38, 32, 30, 43, 4,
+ 32, 32, 42, 31, 31, 32, 26, 38,
+ 26, 22, 21, 37, 61, 63, 37, 31,
+ 32, 33, 2, 1, 23, 33, 41, 27,
+ 35, 30, 38, 23, 33, 3, 28, 34,
+ 34, 27, 41, 29, 39, 35, 36, 29,
+ 32, 27, 30, 32, 24, 61, 37, 26,
+ 59, 25, 35, 27, 36, 37, 30, 31,
+ 34, 40, 3, 28, 34, 39, 32, 31,
+ 32, 30, 24, 28, 35, 36, 26, 32,
+ 31, 33, 29, 33, 39, 25, 30, 24,
+ 35, 59, 29, 34, 25, 30, 21, 35,
+ 43, 40, 32, 29, 5, 28, 31, 62,
+ 33, 33, 25, 31, 21, 31, 43, 31,
+ 34, 33, 20, 40, 39, 31, 31, 57,
+ 38, 32, 42, 33, 32, 31, 32, 29,
+ 30, 44, 5, 31, 22, 34, 36, 17,
+ 38, 58, 38, 35, 32, 60, 35, 24,
+ 32, 38, 16, 45, 42, 32, 31, 29,
+ 4, 30, 17, 40, 46, 48, 63, 32,
+ 42, 19, 41, 22, 28, 36, 45, 33,
+ 33, 32, 29, 7, 41, 42, 18, 33,
+ 33, 32, 22, 37, 1, 26, 22, 23,
+ 49, 28, 26, 27, 32, 33, 27, 23,
+ 28, 36, 15, 6, 34, 27, 31, 26,
+ 23, 2, 33, 32, 34, 41, 28, 32,
+ 41, 0, 36, 38, 34, 31, 47, 32,
+ 17, 31, 39, 33, 37, 51, 30, 47,
+ 32, 50, 32, 19, 63, 30, 25, 27,
+ 33, 62, 24, 31, 27, 30, 37, 31,
+ 45, 32, 39, 20, 46, 47, 35, 19,
+ 34, 1, 49, 21, 21, 14, 51, 26,
+ 23, 31, 36, 35, 58, 29, 29, 21,
+ 20, 42, 13, 28, 12, 40, 31, 33,
+ 39, 60, 32, 44, 33, 31, 28, 37,
+ 29, 32, 30, 49, 43, 28, 39, 25,
+ 32, 48, 2, 15, 20, 25, 31, 28,
+ 21, 24, 25, 15, 31, 17, 37, 43,
+ 18, 32, 33, 24, 33, 36, 13, 33,
+ 31, 39, 11, 31, 33, 32, 39, 37,
+ 32, 32, 29, 17, 44, 46, 36, 35,
+ 26, 37, 58, 32, 34, 38, 8, 38,
+ 38, 22, 29, 25, 16, 35, 32, 35,
+ 33, 43, 18, 46, 38, 50, 33, 18,
+ 53, 60, 13, 32, 36, 33, 51, 36,
+ 43, 45, 27, 42, 29, 24, 30, 25,
+ 31, 52, 31, 35, 38, 9, 22, 34,
+ 4, 17, 28, 55, 42, 25, 17, 20,
+ 47, 34, 33, 16, 40, 25, 16, 30,
+ 53, 29, 10, 11, 14, 26, 33, 4,
+ 35, 44, 26, 16, 31, 26, 34, 38,
+ 29, 31, 30, 24, 22, 61, 32, 9,
+ 45, 34, 31, 19, 9, 31, 46, 31,
+ 35, 54, 29, 57, 30, 50, 3, 31,
+ 63, 34, 47, 41, 51, 18, 31, 14,
+ 37, 38, 31, 24, 32, 31, 50, 33,
+ 31, 54, 27, 9, 33, 23, 19, 32,
+ 29, 29, 33, 28, 47, 49, 30, 47,
+ 33, 27, 25, 54, 44, 45, 50, 58,
+ 51, 48, 33, 59, 33, 34, 57, 13,
+ 26, 33, 13, 48, 30, 11, 7, 56,
+ 34, 55, 26, 0, 26, 35, 1, 51,
+ 33, 53, 31, 45, 12, 29, 29, 51,
+ 31, 48, 2, 6, 34, 30, 28, 33,
+ 60, 40, 27, 46, 31, 9, 35, 29,
+ 31, 39, 55, 46, 19, 37, 62, 34,
+ 30, 16, 19, 49, 41, 41, 39, 37,
+ 14, 5, 13, 35, 55, 30, 40, 40,
+ 42, 8, 20, 25, 45, 35, 33, 36,
+ 54, 38, 27, 37, 62, 40, 15, 59,
+ 49, 31, 29, 34, 34, 39, 24, 29,
+ 25, 29, 21, 29, 10, 61, 33, 49,
+ 35, 34, 3, 38, 39, 29, 7, 41,
+ 1, 35, 4, 23, 15, 23, 11, 37,
+ 28, 35, 30, 30, 24, 1, 43, 56,
+ 8, 34, 42, 24, 45, 30, 20, 23,
+ 8, 38, 22, 33, 17, 52, 34, 22,
+ 53, 43, 44, 1, 27, 31, 41, 43,
+ 41, 30, 31, 36, 30, 5, 55, 31,
+ 33, 30, 40, 23, 15, 29, 34, 34,
+ 59, 34, 30, 11, 13, 38, 5, 0,
+ 30, 42, 5, 30, 29, 34, 10, 44,
+ 30, 63, 35, 12, 3, 26, 15, 17,
+ 25, 34, 43, 39, 34, 56, 29, 23,
+ 30, 12, 30, 10, 35, 9, 24, 58,
+ 10, 12, 54, 33, 37, 20, 41, 35,
+ 29, 18, 61, 30, 40, 24, 39, 53,
+ 62, 26, 29, 33, 34, 53, 49, 21,
+ 27, 11, 63, 20, 26, 23, 7, 13,
+ 6, 47, 29, 30, 9, 51, 22, 34,
+ 21, 25, 33, 56, 57, 30, 38, 51,
+ 51, 38, 63, 28, 40, 35, 33, 18,
+ 33, 33, 24, 58, 58, 34, 49, 29,
+ 43, 4, 1, 4, 42, 35, 35, 30,
+ 17, 5, 56, 61, 25, 37, 36, 55,
+ 28, 35, 29, 50, 48, 52, 2, 42,
+ 34, 40, 46, 46, 43, 35, 29, 48,
+ 20, 29, 31, 41, 7, 30, 35, 19,
+ 14, 21, 8, 39, 39, 40, 46, 55,
+ 34, 6, 30, 34, 37, 25, 37, 33,
+ 22, 44, 52, 17, 35, 29, 36, 35,
+ 40, 37, 28, 30, 50, 14, 28, 55,
+ 6, 23, 19, 14, 30, 3, 30, 28,
+ 28, 61, 61, 47, 45, 48, 40, 40,
+ 34, 34, 25, 30, 29, 35, 4, 26,
+ 53, 50, 26, 41, 27, 59, 27, 38,
+ 39, 3, 50, 43, 47, 23, 33, 55,
+ 35, 21, 23, 35, 61, 33, 46, 52,
+ 35, 34, 24, 30, 43, 16, 37, 21,
+ 2, 24, 45, 34, 30, 55, 55, 1,
+ 29, 29, 26, 28, 25, 31, 36, 22,
+ 17, 30, 52, 2, 44, 44, 57, 26,
+ 62, 41, 39, 57, 26, 46, 49, 11,
+ 16, 19, 5, 59, 38, 39, 58, 38,
+ 25, 49, 50, 22, 28, 59, 9, 59,
+ 7, 28, 55, 17, 4, 35, 50, 21,
+ 29, 44, 47, 18, 24, 19, 25, 42,
+ 35, 3, 51, 35, 16, 35, 30, 63,
+ 57, 39, 39, 25, 35, 38, 9, 16,
+ 36, 45, 31, 60, 14, 34, 42, 24,
+ 0, 37, 18, 61, 57, 37, 28, 53,
+ 20, 46, 14, 47, 38, 38, 38, 9,
+ 34, 39, 43, 17, 39, 59, 5, 27,
+ 0, 12, 27,
+};
+
+const UINT8 table1_mvy[1099] = {
+ 32, 32, 31, 31, 32, 33, 31, 33,
+ 33, 32, 32, 30, 34, 31, 32, 29,
+ 33, 30, 32, 33, 31, 35, 34, 30,
+ 34, 31, 33, 29, 29, 31, 33, 35,
+ 30, 30, 35, 32, 32, 34, 34, 28,
+ 25, 32, 36, 27, 32, 32, 32, 37,
+ 39, 3, 32, 30, 31, 26, 31, 32,
+ 32, 38, 29, 29, 32, 34, 31, 31,
+ 34, 35, 33, 33, 28, 33, 1, 33,
+ 27, 29, 30, 31, 28, 29, 37, 35,
+ 31, 33, 35, 27, 36, 37, 25, 25,
+ 61, 35, 4, 5, 32, 33, 36, 30,
+ 23, 30, 28, 34, 31, 32, 32, 39,
+ 32, 34, 21, 39, 32, 59, 32, 28,
+ 32, 36, 60, 33, 24, 36, 32, 32,
+ 41, 2, 32, 38, 26, 22, 33, 30,
+ 31, 32, 32, 30, 31, 32, 29, 3,
+ 40, 38, 32, 32, 33, 26, 31, 34,
+ 28, 38, 34, 31, 3, 31, 35, 38,
+ 27, 35, 33, 28, 29, 27, 29, 27,
+ 43, 29, 37, 63, 31, 33, 34, 30,
+ 31, 30, 37, 30, 35, 35, 26, 41,
+ 37, 31, 33, 28, 26, 30, 42, 24,
+ 7, 27, 33, 29, 36, 28, 34, 57,
+ 23, 41, 36, 23, 35, 34, 25, 30,
+ 25, 33, 25, 25, 29, 24, 33, 39,
+ 33, 33, 0, 37, 31, 36, 21, 32,
+ 61, 24, 35, 61, 31, 5, 31, 59,
+ 39, 21, 32, 30, 34, 22, 40, 32,
+ 29, 16, 31, 5, 62, 2, 20, 39,
+ 39, 32, 33, 1, 31, 24, 36, 32,
+ 36, 32, 28, 26, 6, 31, 38, 34,
+ 58, 35, 32, 33, 33, 17, 43, 26,
+ 31, 40, 31, 34, 32, 32, 31, 19,
+ 30, 32, 29, 33, 38, 38, 32, 59,
+ 40, 18, 38, 32, 35, 34, 32, 17,
+ 1, 15, 30, 28, 31, 28, 34, 29,
+ 32, 27, 35, 27, 49, 22, 37, 34,
+ 37, 26, 32, 32, 22, 28, 45, 29,
+ 30, 31, 43, 46, 41, 30, 26, 13,
+ 34, 32, 27, 38, 42, 42, 33, 47,
+ 33, 60, 27, 42, 25, 32, 22, 32,
+ 48, 32, 45, 33, 33, 41, 27, 25,
+ 19, 31, 35, 19, 36, 42, 27, 17,
+ 31, 44, 28, 33, 33, 31, 23, 31,
+ 40, 33, 31, 34, 30, 32, 33, 36,
+ 35, 47, 37, 41, 31, 23, 41, 29,
+ 30, 35, 32, 25, 32, 28, 58, 2,
+ 37, 33, 14, 33, 49, 20, 39, 36,
+ 21, 9, 23, 33, 35, 24, 39, 37,
+ 11, 33, 30, 31, 31, 28, 51, 40,
+ 35, 29, 25, 33, 46, 35, 37, 30,
+ 30, 8, 63, 28, 15, 40, 33, 45,
+ 49, 25, 32, 4, 47, 51, 36, 39,
+ 53, 10, 24, 29, 30, 31, 25, 40,
+ 38, 38, 33, 56, 23, 27, 32, 37,
+ 26, 29, 43, 36, 33, 24, 55, 43,
+ 9, 29, 34, 34, 24, 33, 18, 33,
+ 33, 30, 31, 50, 24, 60, 30, 39,
+ 34, 30, 39, 28, 22, 38, 2, 26,
+ 63, 32, 57, 21, 39, 33, 28, 18,
+ 30, 34, 22, 33, 29, 41, 30, 34,
+ 35, 21, 13, 34, 35, 39, 30, 46,
+ 32, 42, 32, 31, 33, 26, 11, 33,
+ 22, 31, 25, 31, 53, 27, 43, 25,
+ 40, 50, 21, 36, 38, 30, 12, 31,
+ 34, 20, 15, 29, 32, 62, 30, 13,
+ 17, 32, 19, 31, 20, 31, 30, 7,
+ 1, 17, 34, 37, 31, 31, 44, 34,
+ 26, 40, 16, 37, 52, 48, 30, 20,
+ 18, 33, 38, 29, 7, 25, 30, 54,
+ 45, 47, 46, 41, 29, 29, 16, 30,
+ 14, 26, 38, 34, 34, 29, 34, 30,
+ 29, 30, 57, 30, 4, 46, 33, 29,
+ 39, 44, 30, 31, 50, 33, 31, 32,
+ 19, 32, 40, 31, 37, 47, 1, 35,
+ 16, 31, 0, 35, 33, 1, 17, 34,
+ 9, 34, 33, 31, 49, 43, 42, 51,
+ 34, 29, 23, 29, 14, 30, 45, 49,
+ 11, 24, 31, 28, 35, 41, 30, 44,
+ 18, 29, 34, 35, 36, 25, 26, 21,
+ 31, 30, 34, 19, 34, 44, 36, 38,
+ 25, 31, 28, 23, 37, 3, 55, 41,
+ 30, 22, 41, 24, 33, 26, 35, 35,
+ 30, 55, 51, 47, 48, 38, 24, 15,
+ 21, 50, 25, 46, 30, 29, 10, 34,
+ 42, 45, 29, 42, 22, 3, 33, 27,
+ 34, 1, 34, 28, 34, 36, 35, 23,
+ 23, 13, 58, 3, 26, 63, 25, 31,
+ 34, 61, 38, 39, 25, 61, 29, 37,
+ 30, 41, 26, 48, 28, 33, 50, 35,
+ 30, 37, 29, 29, 40, 6, 39, 28,
+ 28, 19, 8, 22, 45, 34, 35, 10,
+ 58, 17, 37, 39, 30, 18, 54, 14,
+ 29, 16, 59, 30, 35, 23, 35, 30,
+ 47, 36, 29, 55, 20, 12, 31, 35,
+ 14, 29, 18, 34, 34, 24, 29, 26,
+ 22, 2, 27, 23, 8, 30, 55, 38,
+ 60, 31, 4, 34, 49, 34, 27, 34,
+ 33, 30, 31, 54, 42, 35, 38, 46,
+ 44, 26, 27, 9, 39, 25, 21, 29,
+ 28, 42, 13, 0, 5, 34, 37, 28,
+ 24, 29, 63, 26, 22, 27, 29, 25,
+ 33, 25, 61, 0, 35, 25, 36, 15,
+ 27, 40, 53, 33, 3, 10, 16, 37,
+ 38, 18, 30, 46, 27, 9, 6, 29,
+ 62, 8, 42, 28, 29, 3, 25, 16,
+ 26, 29, 35, 28, 27, 51, 61, 48,
+ 37, 9, 34, 7, 49, 45, 20, 29,
+ 21, 5, 5, 29, 28, 34, 29, 24,
+ 10, 24, 35, 36, 38, 55, 11, 36,
+ 38, 53, 54, 26, 30, 49, 20, 27,
+ 30, 39, 33, 41, 49, 22, 38, 38,
+ 4, 30, 8, 9, 3, 24, 22, 50,
+ 37, 36, 31, 27, 2, 9, 42, 63,
+ 25, 19, 44, 1, 28, 28, 48, 30,
+ 34, 41, 41, 38, 12, 27, 15, 0,
+ 16, 34, 35, 38, 28, 29, 40, 42,
+ 51, 52, 45, 54, 59, 59, 42, 44,
+ 37, 26, 46, 24, 15, 39, 22, 46,
+ 19, 35, 38, 17, 37, 23, 52, 55,
+ 50, 37, 26, 11, 37, 12, 24, 30,
+ 16, 13, 22, 13, 36, 35, 40, 41,
+ 34, 41, 26, 53, 51, 5, 21, 30,
+ 2, 63, 41, 20, 1, 56, 21, 24,
+ 25, 5, 28, 35, 26, 28, 30, 18,
+ 29, 23, 40, 34, 20, 42, 39, 34,
+ 28, 61, 38, 27, 62, 9, 36, 17,
+ 9, 49, 24, 25, 54, 34, 39, 37,
+ 3, 1, 25, 38, 38, 44, 35, 36,
+ 12, 60, 36, 38, 40, 25, 43, 39,
+ 53, 28, 39, 57, 46, 10, 52, 27,
+ 35, 42, 45, 59, 15, 60, 38, 24,
+ 23, 39, 12, 29, 24, 0, 20, 16,
+ 28, 43, 35, 28, 1, 49, 4, 21,
+ 42, 39, 29, 3, 44, 21, 53, 55,
+ 11, 5, 3, 39, 53, 28, 25, 19,
+ 34, 28, 21,
+};
+
+static MVTable mv_tables[2] = {
+ {
+ 1099,
+ table0_mv_code,
+ table0_mv_bits,
+ table0_mvx,
+ table0_mvy,
+ },
+ {
+ 1099,
+ table1_mv_code,
+ table1_mv_bits,
+ table1_mvx,
+ table1_mvy,
+ }
+};
diff --git a/libavcodec/resample.c b/libavcodec/resample.c
new file mode 100644
index 0000000000..29445964f6
--- /dev/null
+++ b/libavcodec/resample.c
@@ -0,0 +1,301 @@
+/*
+ * Sample rate convertion for both audio and video
+ * Copyright (c) 2000 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "avcodec.h"
+
+#define NDEBUG
+#include <assert.h>
+
+typedef struct {
+ /* fractional resampling */
+ UINT32 incr; /* fractional increment */
+ UINT32 frac;
+ int last_sample;
+ /* integer down sample */
+ int iratio; /* integer divison ratio */
+ int icount, isum;
+ int inv;
+} ReSampleChannelContext;
+
+struct ReSampleContext {
+ ReSampleChannelContext channel_ctx[2];
+ float ratio;
+ /* channel convert */
+ int input_channels, output_channels, filter_channels;
+};
+
+
+#define FRAC_BITS 16
+#define FRAC (1 << FRAC_BITS)
+
+static void init_mono_resample(ReSampleChannelContext *s, float ratio)
+{
+ ratio = 1.0 / ratio;
+ s->iratio = (int)floor(ratio);
+ if (s->iratio == 0)
+ s->iratio = 1;
+ s->incr = (int)((ratio / s->iratio) * FRAC);
+ s->frac = 0;
+ s->last_sample = 0;
+ s->icount = s->iratio;
+ s->isum = 0;
+ s->inv = (FRAC / s->iratio);
+}
+
+/* fractional audio resampling */
+static int fractional_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
+{
+ unsigned int frac, incr;
+ int l0, l1;
+ short *q, *p, *pend;
+
+ l0 = s->last_sample;
+ incr = s->incr;
+ frac = s->frac;
+
+ p = input;
+ pend = input + nb_samples;
+ q = output;
+
+ l1 = *p++;
+ for(;;) {
+ /* interpolate */
+ *q++ = (l0 * (FRAC - frac) + l1 * frac) >> FRAC_BITS;
+ frac = frac + s->incr;
+ while (frac >= FRAC) {
+ if (p >= pend)
+ goto the_end;
+ frac -= FRAC;
+ l0 = l1;
+ l1 = *p++;
+ }
+ }
+ the_end:
+ s->last_sample = l1;
+ s->frac = frac;
+ return q - output;
+}
+
+static int integer_downsample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
+{
+ short *q, *p, *pend;
+ int c, sum;
+
+ p = input;
+ pend = input + nb_samples;
+ q = output;
+
+ c = s->icount;
+ sum = s->isum;
+
+ for(;;) {
+ sum += *p++;
+ if (--c == 0) {
+ *q++ = (sum * s->inv) >> FRAC_BITS;
+ c = s->iratio;
+ sum = 0;
+ }
+ if (p >= pend)
+ break;
+ }
+ s->isum = sum;
+ s->icount = c;
+ return q - output;
+}
+
+/* n1: number of samples */
+static void stereo_to_mono(short *output, short *input, int n1)
+{
+ short *p, *q;
+ int n = n1;
+
+ p = input;
+ q = output;
+ while (n >= 4) {
+ q[0] = (p[0] + p[1]) >> 1;
+ q[1] = (p[2] + p[3]) >> 1;
+ q[2] = (p[4] + p[5]) >> 1;
+ q[3] = (p[6] + p[7]) >> 1;
+ q += 4;
+ p += 8;
+ n -= 4;
+ }
+ while (n > 0) {
+ q[0] = (p[0] + p[1]) >> 1;
+ q++;
+ p += 2;
+ n--;
+ }
+}
+
+/* n1: number of samples */
+static void mono_to_stereo(short *output, short *input, int n1)
+{
+ short *p, *q;
+ int n = n1;
+ int v;
+
+ p = input;
+ q = output;
+ while (n >= 4) {
+ v = p[0]; q[0] = v; q[1] = v;
+ v = p[1]; q[2] = v; q[3] = v;
+ v = p[2]; q[4] = v; q[5] = v;
+ v = p[3]; q[6] = v; q[7] = v;
+ q += 8;
+ p += 4;
+ n -= 4;
+ }
+ while (n > 0) {
+ v = p[0]; q[0] = v; q[1] = v;
+ q += 2;
+ p += 1;
+ n--;
+ }
+}
+
+/* XXX: should use more abstract 'N' channels system */
+static void stereo_split(short *output1, short *output2, short *input, int n)
+{
+ int i;
+
+ for(i=0;i<n;i++) {
+ *output1++ = *input++;
+ *output2++ = *input++;
+ }
+}
+
+static void stereo_mux(short *output, short *input1, short *input2, int n)
+{
+ int i;
+
+ for(i=0;i<n;i++) {
+ *output++ = *input1++;
+ *output++ = *input2++;
+ }
+}
+
+static int mono_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples)
+{
+ short buf1[nb_samples];
+ short *buftmp;
+
+ /* first downsample by an integer factor with averaging filter */
+ if (s->iratio > 1) {
+ buftmp = buf1;
+ nb_samples = integer_downsample(s, buftmp, input, nb_samples);
+ } else {
+ buftmp = input;
+ }
+
+ /* then do a fractional resampling with linear interpolation */
+ if (s->incr != FRAC) {
+ nb_samples = fractional_resample(s, output, buftmp, nb_samples);
+ } else {
+ memcpy(output, buftmp, nb_samples * sizeof(short));
+ }
+ return nb_samples;
+}
+
+ReSampleContext *audio_resample_init(int output_channels, int input_channels,
+ int output_rate, int input_rate)
+{
+ ReSampleContext *s;
+ int i;
+
+ if (output_channels > 2 || input_channels > 2)
+ return NULL;
+
+ s = av_mallocz(sizeof(ReSampleContext));
+ if (!s)
+ return NULL;
+
+ s->ratio = (float)output_rate / (float)input_rate;
+
+ s->input_channels = input_channels;
+ s->output_channels = output_channels;
+
+ s->filter_channels = s->input_channels;
+ if (s->output_channels < s->filter_channels)
+ s->filter_channels = s->output_channels;
+
+ for(i=0;i<s->filter_channels;i++) {
+ init_mono_resample(&s->channel_ctx[i], s->ratio);
+ }
+ return s;
+}
+
+/* resample audio. 'nb_samples' is the number of input samples */
+/* XXX: optimize it ! */
+/* XXX: do it with polyphase filters, since the quality here is
+ HORRIBLE. Return the number of samples available in output */
+int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples)
+{
+ int i, nb_samples1;
+ short bufin[2][nb_samples];
+ short bufout[2][(int)(nb_samples * s->ratio) + 16]; /* make some zoom to avoid round pb */
+ short *buftmp2[2], *buftmp3[2];
+
+ if (s->input_channels == s->output_channels && s->ratio == 1.0) {
+ /* nothing to do */
+ memcpy(output, input, nb_samples * s->input_channels * sizeof(short));
+ return nb_samples;
+ }
+
+ if (s->input_channels == 2 &&
+ s->output_channels == 1) {
+ buftmp2[0] = bufin[0];
+ buftmp3[0] = output;
+ stereo_to_mono(buftmp2[0], input, nb_samples);
+ } else if (s->output_channels == 2 && s->input_channels == 1) {
+ buftmp2[0] = input;
+ buftmp3[0] = bufout[0];
+ } else if (s->output_channels == 2) {
+ buftmp2[0] = bufin[0];
+ buftmp2[1] = bufin[1];
+ buftmp3[0] = bufout[0];
+ buftmp3[1] = bufout[1];
+ stereo_split(buftmp2[0], buftmp2[1], input, nb_samples);
+ } else {
+ buftmp2[0] = input;
+ buftmp3[0] = output;
+ }
+
+ /* resample each channel */
+ nb_samples1 = 0; /* avoid warning */
+ for(i=0;i<s->filter_channels;i++) {
+ nb_samples1 = mono_resample(&s->channel_ctx[i], buftmp3[i], buftmp2[i], nb_samples);
+ }
+
+ if (s->output_channels == 2 && s->input_channels == 1) {
+ mono_to_stereo(output, buftmp3[0], nb_samples1);
+ } else if (s->output_channels == 2) {
+ stereo_mux(output, buftmp3[0], buftmp3[1], nb_samples1);
+ }
+
+ return nb_samples1;
+}
+
+void audio_resample_close(ReSampleContext *s)
+{
+ free(s);
+}
diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c
new file mode 100644
index 0000000000..b03cd02937
--- /dev/null
+++ b/libavcodec/rv10.c
@@ -0,0 +1,487 @@
+/*
+ * RV10 codec
+ * Copyright (c) 2000,2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+//#define DEBUG
+
+static const UINT16 rv_lum_code[256] =
+{
+ 0x3e7f, 0x0f00, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05, 0x0f06,
+ 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e,
+ 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16,
+ 0x0f17, 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e,
+ 0x0f1f, 0x0f20, 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26,
+ 0x0f27, 0x0f28, 0x0f29, 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e,
+ 0x0f2f, 0x0f30, 0x0f31, 0x0f32, 0x0f33, 0x0f34, 0x0f35, 0x0f36,
+ 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b, 0x0f3c, 0x0f3d, 0x0f3e,
+ 0x0f3f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386,
+ 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038d, 0x038e,
+ 0x038f, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396,
+ 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e,
+ 0x039f, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6,
+ 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce,
+ 0x00cf, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056,
+ 0x0057, 0x0020, 0x0021, 0x0022, 0x0023, 0x000c, 0x000d, 0x0004,
+ 0x0000, 0x0005, 0x000e, 0x000f, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
+ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
+ 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
+ 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44, 0x0f45, 0x0f46, 0x0f47,
+ 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d, 0x0f4e, 0x0f4f,
+ 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56, 0x0f57,
+ 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
+ 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67,
+ 0x0f68, 0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f,
+ 0x0f70, 0x0f71, 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77,
+ 0x0f78, 0x0f79, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f,
+};
+
+static const UINT8 rv_lum_bits[256] =
+{
+ 14, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 7, 7, 7, 7, 7, 7, 7,
+ 7, 6, 6, 6, 6, 5, 5, 4,
+ 2, 4, 5, 5, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+};
+
+static const UINT16 rv_chrom_code[256] =
+{
+ 0xfe7f, 0x3f00, 0x3f01, 0x3f02, 0x3f03, 0x3f04, 0x3f05, 0x3f06,
+ 0x3f07, 0x3f08, 0x3f09, 0x3f0a, 0x3f0b, 0x3f0c, 0x3f0d, 0x3f0e,
+ 0x3f0f, 0x3f10, 0x3f11, 0x3f12, 0x3f13, 0x3f14, 0x3f15, 0x3f16,
+ 0x3f17, 0x3f18, 0x3f19, 0x3f1a, 0x3f1b, 0x3f1c, 0x3f1d, 0x3f1e,
+ 0x3f1f, 0x3f20, 0x3f21, 0x3f22, 0x3f23, 0x3f24, 0x3f25, 0x3f26,
+ 0x3f27, 0x3f28, 0x3f29, 0x3f2a, 0x3f2b, 0x3f2c, 0x3f2d, 0x3f2e,
+ 0x3f2f, 0x3f30, 0x3f31, 0x3f32, 0x3f33, 0x3f34, 0x3f35, 0x3f36,
+ 0x3f37, 0x3f38, 0x3f39, 0x3f3a, 0x3f3b, 0x3f3c, 0x3f3d, 0x3f3e,
+ 0x3f3f, 0x0f80, 0x0f81, 0x0f82, 0x0f83, 0x0f84, 0x0f85, 0x0f86,
+ 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c, 0x0f8d, 0x0f8e,
+ 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95, 0x0f96,
+ 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e,
+ 0x0f9f, 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6,
+ 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce,
+ 0x03cf, 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6,
+ 0x00e7, 0x0030, 0x0031, 0x0032, 0x0033, 0x0008, 0x0009, 0x0002,
+ 0x0000, 0x0003, 0x000a, 0x000b, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7,
+ 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df,
+ 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
+ 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf,
+ 0x0fb0, 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7,
+ 0x0fb8, 0x0fb9, 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf,
+ 0x3f40, 0x3f41, 0x3f42, 0x3f43, 0x3f44, 0x3f45, 0x3f46, 0x3f47,
+ 0x3f48, 0x3f49, 0x3f4a, 0x3f4b, 0x3f4c, 0x3f4d, 0x3f4e, 0x3f4f,
+ 0x3f50, 0x3f51, 0x3f52, 0x3f53, 0x3f54, 0x3f55, 0x3f56, 0x3f57,
+ 0x3f58, 0x3f59, 0x3f5a, 0x3f5b, 0x3f5c, 0x3f5d, 0x3f5e, 0x3f5f,
+ 0x3f60, 0x3f61, 0x3f62, 0x3f63, 0x3f64, 0x3f65, 0x3f66, 0x3f67,
+ 0x3f68, 0x3f69, 0x3f6a, 0x3f6b, 0x3f6c, 0x3f6d, 0x3f6e, 0x3f6f,
+ 0x3f70, 0x3f71, 0x3f72, 0x3f73, 0x3f74, 0x3f75, 0x3f76, 0x3f77,
+ 0x3f78, 0x3f79, 0x3f7a, 0x3f7b, 0x3f7c, 0x3f7d, 0x3f7e, 0x3f7f,
+};
+
+static const UINT8 rv_chrom_bits[256] =
+{
+ 16, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 8, 8, 8, 8, 8, 8, 8,
+ 8, 6, 6, 6, 6, 4, 4, 3,
+ 2, 3, 4, 4, 6, 6, 6, 6,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+};
+
+static VLC rv_dc_lum, rv_dc_chrom;
+
+int rv_decode_dc(MpegEncContext *s, int n)
+{
+ int code;
+
+ if (n < 4) {
+ code = get_vlc(&s->gb, &rv_dc_lum);
+ if (code < 0) {
+ /* XXX: I don't understand why they use LONGER codes than
+ necessary. The following code would be completely useless
+ if they had thought about it !!! */
+ code = get_bits(&s->gb, 7);
+ if (code == 0x7c) {
+ code = (INT8)(get_bits(&s->gb, 7) + 1);
+ } else if (code == 0x7d) {
+ code = -128 + get_bits(&s->gb, 7);
+ } else if (code == 0x7e) {
+ if (get_bits(&s->gb, 1) == 0)
+ code = (INT8)(get_bits(&s->gb, 8) + 1);
+ else
+ code = (INT8)(get_bits(&s->gb, 8));
+ } else if (code == 0x7f) {
+ get_bits(&s->gb, 11);
+ code = 1;
+ }
+ } else {
+ code -= 128;
+ }
+ } else {
+ code = get_vlc(&s->gb, &rv_dc_chrom);
+ /* same remark */
+ if (code < 0) {
+ code = get_bits(&s->gb, 9);
+ if (code == 0x1fc) {
+ code = (INT8)(get_bits(&s->gb, 7) + 1);
+ } else if (code == 0x1fd) {
+ code = -128 + get_bits(&s->gb, 7);
+ } else if (code == 0x1fe) {
+ get_bits(&s->gb, 9);
+ code = 1;
+ } else {
+ return 0xffff;
+ }
+ } else {
+ code -= 128;
+ }
+ }
+ return -code;
+}
+
+/* write RV 1.0 compatible frame header */
+void rv10_encode_picture_header(MpegEncContext *s, int picture_number)
+{
+ align_put_bits(&s->pb);
+
+ put_bits(&s->pb, 1, 1); /* marker */
+
+ put_bits(&s->pb, 1, (s->pict_type == P_TYPE));
+
+ put_bits(&s->pb, 1, 0); /* not PB frame */
+
+ put_bits(&s->pb, 5, s->qscale);
+
+ if (s->pict_type == I_TYPE) {
+ /* specific MPEG like DC coding not used */
+ }
+ /* if multiple packets per frame are sent, the position at which
+ to display the macro blocks is coded here */
+ put_bits(&s->pb, 6, 0); /* mb_x */
+ put_bits(&s->pb, 6, 0); /* mb_y */
+ put_bits(&s->pb, 12, s->mb_width * s->mb_height);
+
+ put_bits(&s->pb, 3, 0); /* ignored */
+}
+
+static int get_num(GetBitContext *gb)
+{
+ int n, n1;
+
+ n = get_bits(gb, 16);
+ if (n >= 0x4000) {
+ return n - 0x4000;
+ } else {
+ n1 = get_bits(gb, 16);
+ return (n << 16) | n1;
+ }
+}
+
+/* read RV 1.0 compatible frame header */
+static int rv10_decode_picture_header(MpegEncContext *s)
+{
+ int mb_count, pb_frame, marker, h, full_frame;
+
+ /* skip packet header */
+ h = get_bits(&s->gb, 8);
+ if ((h & 0xc0) == 0xc0) {
+ int len, pos;
+ full_frame = 1;
+ len = get_num(&s->gb);
+ pos = get_num(&s->gb);
+ } else {
+ int seq, frame_size, pos;
+ full_frame = 0;
+ seq = get_bits(&s->gb, 8);
+ frame_size = get_num(&s->gb);
+ pos = get_num(&s->gb);
+ }
+ /* picture number */
+ get_bits(&s->gb, 8);
+
+ marker = get_bits(&s->gb, 1);
+
+ if (get_bits(&s->gb, 1))
+ s->pict_type = P_TYPE;
+ else
+ s->pict_type = I_TYPE;
+
+ pb_frame = get_bits(&s->gb, 1);
+
+#ifdef DEBUG
+ printf("pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame);
+#endif
+
+ if (pb_frame)
+ return -1;
+
+ s->qscale = get_bits(&s->gb, 5);
+
+ if (s->pict_type == I_TYPE) {
+ if (s->rv10_version == 3) {
+ /* specific MPEG like DC coding not used */
+ s->last_dc[0] = get_bits(&s->gb, 8);
+ s->last_dc[1] = get_bits(&s->gb, 8);
+ s->last_dc[2] = get_bits(&s->gb, 8);
+#ifdef DEBUG
+ printf("DC:%d %d %d\n",
+ s->last_dc[0],
+ s->last_dc[1],
+ s->last_dc[2]);
+#endif
+ }
+ }
+ /* if multiple packets per frame are sent, the position at which
+ to display the macro blocks is coded here */
+ if (!full_frame) {
+ s->mb_x = get_bits(&s->gb, 6); /* mb_x */
+ s->mb_y = get_bits(&s->gb, 6); /* mb_y */
+ mb_count = get_bits(&s->gb, 12);
+ } else {
+ s->mb_x = 0;
+ s->mb_y = 0;
+ mb_count = s->mb_width * s->mb_height;
+ }
+
+ get_bits(&s->gb, 3); /* ignored */
+ s->f_code = 1;
+ s->unrestricted_mv = 1;
+#if 0
+ s->h263_long_vectors = 1;
+#endif
+ return mb_count;
+}
+
+static int rv10_decode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+ static int done;
+
+ s->out_format = FMT_H263;
+
+ s->width = avctx->width;
+ s->height = avctx->height;
+
+ s->h263_rv10 = 1;
+ s->rv10_version = avctx->sub_id;
+
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ h263_decode_init_vlc(s);
+
+ /* init rv vlc */
+ if (!done) {
+ init_vlc(&rv_dc_lum, 9, 256,
+ rv_lum_bits, 1, 1,
+ rv_lum_code, 2, 2);
+ init_vlc(&rv_dc_chrom, 9, 256,
+ rv_chrom_bits, 1, 1,
+ rv_chrom_code, 2, 2);
+ done = 1;
+ }
+
+ return 0;
+}
+
+static int rv10_decode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ MPV_common_end(s);
+ return 0;
+}
+
+static int rv10_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ UINT8 *buf, int buf_size)
+{
+ MpegEncContext *s = avctx->priv_data;
+ int i, mb_count, mb_pos, left;
+ DCTELEM block[6][64];
+ AVPicture *pict = data;
+
+#ifdef DEBUG
+ printf("*****frame %d size=%d\n", avctx->frame_number, buf_size);
+#endif
+
+ /* no supplementary picture */
+ if (buf_size == 0) {
+ *data_size = 0;
+ return 0;
+ }
+
+ init_get_bits(&s->gb, buf, buf_size);
+
+ mb_count = rv10_decode_picture_header(s);
+ if (mb_count < 0) {
+#ifdef DEBUG
+ printf("HEADER ERROR\n");
+#endif
+ return -1;
+ }
+
+ if (s->mb_x >= s->mb_width ||
+ s->mb_y >= s->mb_height) {
+#ifdef DEBUG
+ printf("POS ERROR %d %d\n", s->mb_x, s->mb_y);
+#endif
+ return -1;
+ }
+ mb_pos = s->mb_y * s->mb_width + s->mb_x;
+ left = s->mb_width * s->mb_height - mb_pos;
+ if (mb_count > left) {
+#ifdef DEBUG
+ printf("COUNT ERROR\n");
+#endif
+ return -1;
+ }
+
+ if (s->mb_x == 0 && s->mb_y == 0) {
+ MPV_frame_start(s);
+ }
+
+#ifdef DEBUG
+ printf("qscale=%d\n", s->qscale);
+#endif
+
+ /* default quantization values */
+ s->y_dc_scale = 8;
+ s->c_dc_scale = 8;
+ s->rv10_first_dc_coded[0] = 0;
+ s->rv10_first_dc_coded[1] = 0;
+ s->rv10_first_dc_coded[2] = 0;
+
+ /* decode each macroblock */
+ for(i=0;i<mb_count;i++) {
+#ifdef DEBUG
+ printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
+#endif
+
+ memset(block, 0, sizeof(block));
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ if (h263_decode_mb(s, block) < 0) {
+#ifdef DEBUG
+ printf("ERROR\n");
+#endif
+ return -1;
+ }
+ MPV_decode_mb(s, block);
+ if (++s->mb_x == s->mb_width) {
+ s->mb_x = 0;
+ s->mb_y++;
+ }
+ }
+
+ if (s->mb_x == 0 &&
+ s->mb_y == s->mb_height) {
+ MPV_frame_end(s);
+
+ pict->data[0] = s->current_picture[0];
+ pict->data[1] = s->current_picture[1];
+ pict->data[2] = s->current_picture[2];
+ pict->linesize[0] = s->linesize;
+ pict->linesize[1] = s->linesize / 2;
+ pict->linesize[2] = s->linesize / 2;
+
+ avctx->quality = s->qscale;
+ *data_size = sizeof(AVPicture);
+ } else {
+ *data_size = 0;
+ }
+ return buf_size;
+}
+
+AVCodec rv10_decoder = {
+ "rv10",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RV10,
+ sizeof(MpegEncContext),
+ rv10_decode_init,
+ NULL,
+ rv10_decode_end,
+ rv10_decode_frame,
+};
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
new file mode 100644
index 0000000000..9497f90117
--- /dev/null
+++ b/libavcodec/utils.c
@@ -0,0 +1,306 @@
+/*
+ * utils for libavcodec
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "common.h"
+#include "dsputil.h"
+#include "avcodec.h"
+
+/* memory alloc */
+void *av_mallocz(int size)
+{
+ void *ptr;
+ ptr = malloc(size);
+ if (!ptr)
+ return NULL;
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+/* encoder management */
+AVCodec *first_avcodec;
+
+void register_avcodec(AVCodec *format)
+{
+ AVCodec **p;
+ p = &first_avcodec;
+ while (*p != NULL) p = &(*p)->next;
+ *p = format;
+ format->next = NULL;
+}
+
+int avcodec_open(AVCodecContext *avctx, AVCodec *codec)
+{
+ int ret;
+
+ avctx->codec = codec;
+ avctx->frame_number = 0;
+ avctx->priv_data = av_mallocz(codec->priv_data_size);
+ if (!avctx->priv_data)
+ return -ENOMEM;
+ ret = avctx->codec->init(avctx);
+ if (ret < 0) {
+ free(avctx->priv_data);
+ avctx->priv_data = NULL;
+ return ret;
+ }
+ return 0;
+}
+
+int avcodec_encode_audio(AVCodecContext *avctx, UINT8 *buf, int buf_size,
+ const short *samples)
+{
+ int ret;
+
+ ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples);
+ avctx->frame_number++;
+ return ret;
+}
+
+int avcodec_encode_video(AVCodecContext *avctx, UINT8 *buf, int buf_size,
+ const AVPicture *pict)
+{
+ int ret;
+
+ ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict);
+ avctx->frame_number++;
+ return ret;
+}
+
+/* decode a frame. return -1 if error, otherwise return the number of
+ bytes used. If no frame could be decompressed, *got_picture_ptr is
+ zero. Otherwise, it is non zero */
+int avcodec_decode_video(AVCodecContext *avctx, AVPicture *picture,
+ int *got_picture_ptr,
+ UINT8 *buf, int buf_size)
+{
+ int ret;
+
+ ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
+ buf, buf_size);
+ avctx->frame_number++;
+ return ret;
+}
+
+/* decode an audio frame. return -1 if error, otherwise return the
+ *number of bytes used. If no frame could be decompressed,
+ *frame_size_ptr is zero. Otherwise, it is the decompressed frame
+ *size in BYTES. */
+int avcodec_decode_audio(AVCodecContext *avctx, INT16 *samples,
+ int *frame_size_ptr,
+ UINT8 *buf, int buf_size)
+{
+ int ret;
+
+ ret = avctx->codec->decode(avctx, samples, frame_size_ptr,
+ buf, buf_size);
+ avctx->frame_number++;
+ return ret;
+}
+
+int avcodec_close(AVCodecContext *avctx)
+{
+ if (avctx->codec->close)
+ avctx->codec->close(avctx);
+ free(avctx->priv_data);
+ avctx->priv_data = NULL;
+ avctx->codec = NULL;
+ return 0;
+}
+
+AVCodec *avcodec_find_encoder(enum CodecID id)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->encode != NULL && p->id == id)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+AVCodec *avcodec_find_decoder(enum CodecID id)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->decode != NULL && p->id == id)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+AVCodec *avcodec_find_decoder_by_name(const char *name)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->decode != NULL && strcmp(name,p->name) == 0)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+AVCodec *avcodec_find(enum CodecID id)
+{
+ AVCodec *p;
+ p = first_avcodec;
+ while (p) {
+ if (p->id == id)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
+{
+ const char *codec_name;
+ AVCodec *p;
+ char buf1[32];
+
+ if (encode)
+ p = avcodec_find_encoder(enc->codec_id);
+ else
+ p = avcodec_find_decoder(enc->codec_id);
+
+ if (p) {
+ codec_name = p->name;
+ } else if (enc->codec_name[0] != '\0') {
+ codec_name = enc->codec_name;
+ } else {
+ /* output avi tags */
+ if (enc->codec_type == CODEC_TYPE_VIDEO) {
+ snprintf(buf1, sizeof(buf1), "%c%c%c%c",
+ enc->codec_tag & 0xff,
+ (enc->codec_tag >> 8) & 0xff,
+ (enc->codec_tag >> 16) & 0xff,
+ (enc->codec_tag >> 24) & 0xff);
+ } else {
+ snprintf(buf1, sizeof(buf1), "0x%04x", enc->codec_tag);
+ }
+ codec_name = buf1;
+ }
+
+ switch(enc->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ snprintf(buf, buf_size,
+ "Video: %s%s",
+ codec_name, enc->flags & CODEC_FLAG_HQ ? " (hq)" : "");
+ if (enc->width) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %dx%d, %0.2f fps",
+ enc->width, enc->height,
+ (float)enc->frame_rate / FRAME_RATE_BASE);
+ }
+ break;
+ case CODEC_TYPE_AUDIO:
+ snprintf(buf, buf_size,
+ "Audio: %s",
+ codec_name);
+ if (enc->sample_rate) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %d Hz, %s",
+ enc->sample_rate,
+ enc->channels == 2 ? "stereo" : "mono");
+ }
+ break;
+ default:
+ abort();
+ }
+ if (enc->bit_rate != 0) {
+ snprintf(buf + strlen(buf), buf_size - strlen(buf),
+ ", %d kb/s", enc->bit_rate / 1000);
+ }
+}
+
+/* must be called before any other functions */
+void avcodec_init(void)
+{
+ dsputil_init();
+}
+
+/* simple call to use all the codecs */
+void avcodec_register_all(void)
+{
+ register_avcodec(&ac3_encoder);
+ register_avcodec(&mp2_encoder);
+ register_avcodec(&mpeg1video_encoder);
+ register_avcodec(&h263_encoder);
+ register_avcodec(&h263p_encoder);
+ register_avcodec(&rv10_encoder);
+ register_avcodec(&mjpeg_encoder);
+ register_avcodec(&opendivx_encoder);
+ register_avcodec(&msmpeg4_encoder);
+ register_avcodec(&pcm_codec);
+ register_avcodec(&rawvideo_codec);
+ /* decoders */
+ register_avcodec(&h263_decoder);
+ register_avcodec(&opendivx_decoder);
+ register_avcodec(&msmpeg4_decoder);
+ register_avcodec(&mpeg_decoder);
+ register_avcodec(&h263i_decoder);
+ register_avcodec(&rv10_decoder);
+}
+
+static int encode_init(AVCodecContext *s)
+{
+ return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ UINT8 *buf, int buf_size)
+{
+ return -1;
+}
+
+static int encode_frame(AVCodecContext *avctx,
+ unsigned char *frame, int buf_size, void *data)
+{
+ return -1;
+}
+
+/* dummy pcm codec */
+AVCodec pcm_codec = {
+ "pcm",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_PCM,
+ 0,
+ encode_init,
+ encode_frame,
+ NULL,
+ decode_frame,
+};
+
+AVCodec rawvideo_codec = {
+ "rawvideo",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_RAWVIDEO,
+ 0,
+ encode_init,
+ encode_frame,
+ NULL,
+ decode_frame,
+};