From 7925b0a98d936c4b8ad0a5fee9ef08b3b2dafd5e Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Tue, 7 Aug 2001 12:41:46 +0000 Subject: introducing the ffmpeg video decoder plugin for ms mpeg 4, opendivx and motion jpeg decoding CVS patchset: 395 CVS date: 2001/08/07 12:41:46 --- configure.in | 7 + src/Makefile.am | 2 +- src/libffmpeg/Makefile.am | 35 + src/libffmpeg/bswap.h | 91 ++ src/libffmpeg/config.h | 6 + src/libffmpeg/libavcodec/Makefile.am | 38 + src/libffmpeg/libavcodec/avcodec.h | 179 +++ src/libffmpeg/libavcodec/common.c | 495 ++++++++ src/libffmpeg/libavcodec/common.h | 228 ++++ src/libffmpeg/libavcodec/dsputil.c | 381 ++++++ src/libffmpeg/libavcodec/dsputil.h | 100 ++ src/libffmpeg/libavcodec/dsputil_mmx.c | 1073 +++++++++++++++++ src/libffmpeg/libavcodec/dsputil_mmx_avg.h | 344 ++++++ src/libffmpeg/libavcodec/fdctref.c | 118 ++ src/libffmpeg/libavcodec/h263.c | 1292 ++++++++++++++++++++ src/libffmpeg/libavcodec/h263data.h | 115 ++ src/libffmpeg/libavcodec/h263dec.c | 204 ++++ src/libffmpeg/libavcodec/jfdctfst.c | 224 ++++ src/libffmpeg/libavcodec/jrevdct.c | 1167 ++++++++++++++++++ src/libffmpeg/libavcodec/mjpeg.c | 943 +++++++++++++++ src/libffmpeg/libavcodec/motion_est.c | 514 ++++++++ src/libffmpeg/libavcodec/mpeg12.c | 1534 ++++++++++++++++++++++++ src/libffmpeg/libavcodec/mpeg12data.h | 363 ++++++ src/libffmpeg/libavcodec/mpeg4data.h | 106 ++ src/libffmpeg/libavcodec/mpegvideo.c | 1357 +++++++++++++++++++++ src/libffmpeg/libavcodec/mpegvideo.h | 285 +++++ src/libffmpeg/libavcodec/mpegvideo_mmx.c | 232 ++++ src/libffmpeg/libavcodec/msmpeg4.c | 932 +++++++++++++++ src/libffmpeg/libavcodec/msmpeg4data.h | 1767 ++++++++++++++++++++++++++++ src/libffmpeg/libavcodec/rv10.c | 487 ++++++++ src/libffmpeg/libavcodec/sad_mmx.s | 799 +++++++++++++ src/libffmpeg/libavcodec/utils.c | 319 +++++ src/libffmpeg/xine_decoder.c | 319 +++++ src/xine-engine/cpu_accel.c | 5 + src/xine-engine/cpu_accel.h | 6 + 35 files changed, 16066 insertions(+), 1 deletion(-) create mode 100644 src/libffmpeg/Makefile.am create mode 100644 src/libffmpeg/bswap.h create mode 100644 src/libffmpeg/config.h create mode 100644 src/libffmpeg/libavcodec/Makefile.am create mode 100644 src/libffmpeg/libavcodec/avcodec.h create mode 100644 src/libffmpeg/libavcodec/common.c create mode 100644 src/libffmpeg/libavcodec/common.h create mode 100644 src/libffmpeg/libavcodec/dsputil.c create mode 100644 src/libffmpeg/libavcodec/dsputil.h create mode 100644 src/libffmpeg/libavcodec/dsputil_mmx.c create mode 100644 src/libffmpeg/libavcodec/dsputil_mmx_avg.h create mode 100644 src/libffmpeg/libavcodec/fdctref.c create mode 100644 src/libffmpeg/libavcodec/h263.c create mode 100644 src/libffmpeg/libavcodec/h263data.h create mode 100644 src/libffmpeg/libavcodec/h263dec.c create mode 100644 src/libffmpeg/libavcodec/jfdctfst.c create mode 100644 src/libffmpeg/libavcodec/jrevdct.c create mode 100644 src/libffmpeg/libavcodec/mjpeg.c create mode 100644 src/libffmpeg/libavcodec/motion_est.c create mode 100644 src/libffmpeg/libavcodec/mpeg12.c create mode 100644 src/libffmpeg/libavcodec/mpeg12data.h create mode 100644 src/libffmpeg/libavcodec/mpeg4data.h create mode 100644 src/libffmpeg/libavcodec/mpegvideo.c create mode 100644 src/libffmpeg/libavcodec/mpegvideo.h create mode 100644 src/libffmpeg/libavcodec/mpegvideo_mmx.c create mode 100644 src/libffmpeg/libavcodec/msmpeg4.c create mode 100644 src/libffmpeg/libavcodec/msmpeg4data.h create mode 100644 src/libffmpeg/libavcodec/rv10.c create mode 100644 src/libffmpeg/libavcodec/sad_mmx.s create mode 100644 src/libffmpeg/libavcodec/utils.c create mode 100644 src/libffmpeg/xine_decoder.c diff --git a/configure.in b/configure.in index ff54d065d..d1e9d4a4a 100644 --- a/configure.in +++ b/configure.in @@ -342,6 +342,7 @@ dnl Common cflags for all platforms COMMON_CFLAGS="$wall -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DXINE_COMPILE" enable_w32dll="no" +enable_ffmmx="no" case $host in i386-*-freebsd*) @@ -352,6 +353,7 @@ case $host in AC_DEFINE([ARCH_X86],,[x86 architecture]) enable_w32dll="yes" + enable_ffmmx="yes" ;; *) dnl Set the appropriate architecture define @@ -378,6 +380,7 @@ case $host in dnl enable x86 specific parts of the code enable_w32dll="yes" + enable_ffmmx="yes" if test x"$sarchopt" != "xno"; then [case "$host_alias" in @@ -463,6 +466,8 @@ else fi AC_SUBST(W32DLL_DEP) +AM_CONDITIONAL(HAVE_FFMMX, test x"$enable_ffmmx" = "xyes") + dnl dnl gcc __attribute__ ((aligned ())) @@ -571,6 +576,8 @@ src/demuxers/Makefile src/dxr3/Makefile src/libmpeg2/Makefile src/libac3/Makefile +src/libffmpeg/Makefile +src/libffmpeg/libavcodec/Makefile src/liblpcm/Makefile src/libmpg123/Makefile src/libw32dll/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index c452cb82c..f3317e936 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = audio_out video_out dxr3 input libmpeg2 libspudec demuxers \ - libac3 libmpg123 liblpcm libw32dll xine-engine + libac3 libffmpeg libmpg123 liblpcm libw32dll xine-engine debug: @list='$(SUBDIRS)'; for subdir in $$list; do \ diff --git a/src/libffmpeg/Makefile.am b/src/libffmpeg/Makefile.am new file mode 100644 index 000000000..28086e79f --- /dev/null +++ b/src/libffmpeg/Makefile.am @@ -0,0 +1,35 @@ +## +## Process this file with automake to produce Makefile.in +## + +SUBDIRS = libavcodec + +CFLAGS = @GLOBAL_CFLAGS@ + +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic + +libdir = $(XINE_PLUGINDIR) + +lib_LTLIBRARIES = xineplug_decode_ff.la + +xineplug_decode_ff_la_SOURCES = xine_decoder.c + +xineplug_decode_ff_la_LDFLAGS = \ + $(top_builddir)/src/libffmpeg/libavcodec/libavcodec.la \ + -avoid-version -module + +noinst_HEADERS = config.h + +debug: + $(MAKE) CFLAGS="-Wall -DDEBUG -g -DXINE_COMPILE" + +install-debug: debug + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in diff --git a/src/libffmpeg/bswap.h b/src/libffmpeg/bswap.h new file mode 100644 index 000000000..21ef3a74e --- /dev/null +++ b/src/libffmpeg/bswap.h @@ -0,0 +1,91 @@ +#ifndef __BSWAP_H__ +#define __BSWAP_H__ + +/* It's need for ffmpeg. Else where will be defined ARCH_X86?*/ +#include "config.h" + +#ifdef HAVE_BYTESWAP_H +#include +#else + +#include + +#ifdef ARCH_X86 +inline static unsigned short ByteSwap16(unsigned short x) +{ + __asm("xchgb %b0,%h0" : + "=q" (x) : + "0" (x)); + return x; +} +#define bswap_16(x) ByteSwap16(x) + +inline static unsigned int ByteSwap32(unsigned int x) +{ +#if __CPU__ > 386 + __asm("bswap %0": + "=r" (x) : +#else + __asm("xchgb %b0,%h0\n" + " rorl $16,%0\n" + " xchgb %b0,%h0": + "=q" (x) : +#endif + "0" (x)); + return x; +} +#define bswap_32(x) ByteSwap32(x) + +inline static unsigned long long int ByteSwap64(unsigned long long int x) +{ + register union { __extension__ unsigned long long int __ll; + unsigned long int __l[2]; } __x; + asm("xchgl %0,%1": + "=r"(__x.__l[0]),"=r"(__x.__l[1]): + "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32)))); + return __x.__ll; +} +#define bswap_64(x) ByteSwap64(x) + +#else + +#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8) + + +// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc. +#define bswap_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned long int __l[2]; } __w, __r; \ + __w.__ll = (x); \ + __r.__l[0] = bswap_32 (__w.__l[1]); \ + __r.__l[1] = bswap_32 (__w.__l[0]); \ + __r.__ll; })) +#endif /* !ARCH_X86 */ + +#endif /* !HAVE_BYTESWAP_H */ + +// be2me ... BigEndian to MachineEndian +// le2me ... LittleEndian to MachineEndian + +#ifdef WORDS_BIGENDIAN +#define be2me_16(x) (x) +#define be2me_32(x) (x) +#define be2me_64(x) (x) +#define le2me_16(x) bswap_16(x) +#define le2me_32(x) bswap_32(x) +#define le2me_64(x) bswap_64(x) +#else +#define be2me_16(x) bswap_16(x) +#define be2me_32(x) bswap_32(x) +#define be2me_64(x) bswap_64(x) +#define le2me_16(x) (x) +#define le2me_32(x) (x) +#define le2me_64(x) (x) +#endif + +#endif diff --git a/src/libffmpeg/config.h b/src/libffmpeg/config.h new file mode 100644 index 000000000..e560cbebb --- /dev/null +++ b/src/libffmpeg/config.h @@ -0,0 +1,6 @@ +/* + * this is just a fake config.h for libavcodec + */ + +#include "../../config.h" + diff --git a/src/libffmpeg/libavcodec/Makefile.am b/src/libffmpeg/libavcodec/Makefile.am new file mode 100644 index 000000000..2f5ddff1e --- /dev/null +++ b/src/libffmpeg/libavcodec/Makefile.am @@ -0,0 +1,38 @@ +## +## Process this file with automake to produce Makefile.in +## + +CFLAGS = @GLOBAL_CFLAGS@ -DCONFIG_DECODERS -DHAVE_AV_CONFIG_H + +LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic + +noinst_LTLIBRARIES = libavcodec.la + +if HAVE_FFMMX +mmx_modules = mpegvideo_mmx.c sad_mmx.s dsputil_mmx.c +endif + +libavcodec_la_SOURCES = dsputil.c fdctref.c jfdctfst.c mpeg12.c \ + utils.c rv10.c h263.c jrevdct.c \ + common.c h263dec.c msmpeg4.c \ + mpegvideo.c mjpeg.c motion_est.c \ + $(mmx_modules) + + +noinst_HEADERS = avcodec.h dsputil.h mpegvideo.h dsputil_mmx_avg.h\ + common.h h263data.h mpeg4data.h msmpeg4data.h \ + mpeg12data.h + +debug: + $(MAKE) CFLAGS="-Wall -DDEBUG -g -DXINE_COMPILE" + +install-debug: debug + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +mostlyclean-generic: + -rm -f *~ \#* .*~ .\#* + +maintainer-clean-generic: + -@echo "This command is intended for maintainers to use;" + -@echo "it deletes files that may require special tools to rebuild." + -rm -f Makefile.in diff --git a/src/libffmpeg/libavcodec/avcodec.h b/src/libffmpeg/libavcodec/avcodec.h new file mode 100644 index 000000000..fe7855740 --- /dev/null +++ b/src/libffmpeg/libavcodec/avcodec.h @@ -0,0 +1,179 @@ +#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, + PIX_FMT_YUV422P, + PIX_FMT_YUV444P, +}; + +/* 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; +extern AVCodec mjpeg_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); diff --git a/src/libffmpeg/libavcodec/common.c b/src/libffmpeg/libavcodec/common.c new file mode 100644 index 000000000..24a9a1656 --- /dev/null +++ b/src/libffmpeg/libavcodec/common.c @@ -0,0 +1,495 @@ +/* + * 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 +#include +#include +#ifdef __FreeBSD__ +#include +#endif +#include +#include +#include "common.h" + +#define NDEBUG +#include + +#include "../bswap.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 : escape 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 */ +/* also true: n > s->bit_cnt */ +unsigned int get_bits_long(GetBitContext *s, int n) +{ + unsigned int val; + int bit_cnt; + unsigned int bit_buf; + +#ifdef STATS + st_bit_counts[st_current_index] += n; +#endif + + bit_buf = s->bit_buf; + bit_cnt = s->bit_cnt - n; + +// if (bit_cnt >= 0) { +// val = bit_buf >> (32 - n); +// bit_buf <<= n; +// } else + { + UINT8 *buf_ptr; + 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) { +#ifdef ARCH_X86 + bit_buf = bswap_32(*((unsigned long*)(&buf_ptr[-4]))); +#else + bit_buf = (buf_ptr[-4] << 24) | + (buf_ptr[-3] << 16) | + (buf_ptr[-2] << 8) | + (buf_ptr[-1]); +#endif + } 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 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> 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_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; +} + + +/* Build VLC decoding tables suitable for use with get_vlc(). + + 'nb_bits' set thee decoding table size (2^nb_bits) entries. The + bigger it is, the faster is the decoding. But it should not be too + big to save memory and L1 cache. '9' is a good compromise. + + 'nb_codes' : number of vlcs codes + + 'bits' : table which gives the size (in bits) of each vlc code. + + 'codes' : table which gives the bit pattern of of each vlc code. + + 'xxx_wrap' : give the number of bytes between each entry of the + 'bits' or 'codes' tables. + + 'xxx_size' : gives the number of bytes of each entry of the 'bits' + or 'codes' tables. + + 'wrap' and 'size' allows to use any memory configuration and types + (byte/word/long) to store the 'bits' and 'codes' tables. +*/ +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/src/libffmpeg/libavcodec/common.h b/src/libffmpeg/libavcodec/common.h new file mode 100644 index 000000000..75908245c --- /dev/null +++ b/src/libffmpeg/libavcodec/common.h @@ -0,0 +1,228 @@ +#ifndef COMMON_H +#define COMMON_H + +#ifdef HAVE_AV_CONFIG_H +#include "../config.h" +#endif + +#ifndef __WINE_WINDEF16_H +/* workaround for typedef conflict in MPlayer (wine typedefs) */ +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 { + UINT32 bit_buf; + int bit_cnt; + UINT8 *buf, *buf_ptr, *buf_end; + 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 { + UINT32 bit_buf; + int bit_cnt; + UINT8 *buf, *buf_ptr, *buf_end; +} 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_long(GetBitContext *s, int n); + +static inline unsigned int get_bits(GetBitContext *s, int n){ + if(s->bit_cnt>=n){ + /* most common case here */ + unsigned int val = s->bit_buf >> (32 - n); + s->bit_buf <<= n; + s->bit_cnt -= n; +#ifdef STATS + st_bit_counts[st_current_index] += n; +#endif + return val; + } + return get_bits_long(s,n); +} + +static inline unsigned int get_bits1(GetBitContext *s){ + if(s->bit_cnt>0){ + /* most common case here */ + unsigned int val = s->bit_buf >> 31; + s->bit_buf <<= 1; + s->bit_cnt--; +#ifdef STATS + st_bit_counts[st_current_index]++; +#endif + return val; + } + return get_bits_long(s,1); +} + +static inline void skip_bits(GetBitContext *s, int n){ + if(s->bit_cnt>=n){ + /* most common case here */ + s->bit_buf <<= n; + s->bit_cnt -= n; +#ifdef STATS + st_bit_counts[st_current_index] += n; +#endif + } else { + get_bits_long(s,n); + } +} + +static inline void skip_bits1(GetBitContext *s){ + if(s->bit_cnt>0){ + /* most common case here */ + s->bit_buf <<= 1; + s->bit_cnt--; +#ifdef STATS + st_bit_counts[st_current_index]++; +#endif + } else { + get_bits_long(s,1); + } +} + + +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/src/libffmpeg/libavcodec/dsputil.c b/src/libffmpeg/libavcodec/dsputil.c new file mode 100644 index 000000000..a41f1bef6 --- /dev/null +++ b/src/libffmpeg/libavcodec/dsputil.c @@ -0,0 +1,381 @@ +/* + * 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 +#include +#include "avcodec.h" +#include "dsputil.h" + +void (*ff_idct)(DCTELEM *block); +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 + +/* 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 (*ff_idct)(DCTELEM *block); +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 HAVE_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;":::"memory"); +} + +#define emms_c() \ +{\ + if (mm_flags & MM_MMX)\ + emms();\ +} + +#define __align8 __attribute__ ((aligned (8))) + +void dsputil_init_mmx(void); + +#else + +#define emms_c() + +#define __align8 + +#endif + +#endif diff --git a/src/libffmpeg/libavcodec/dsputil_mmx.c b/src/libffmpeg/libavcodec/dsputil_mmx.c new file mode 100644 index 000000000..ddb91f54c --- /dev/null +++ b/src/libffmpeg/libavcodec/dsputil_mmx.c @@ -0,0 +1,1073 @@ +/* + * 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 + */ + +#include "dsputil.h" +#include "cpu_accel.h" + +int mm_flags; /* multimedia extension flags */ + +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); + +#ifdef USE_MMX_IDCT +/* external functions, defined in libmpeg2 */ +void mmx_idct(DCTELEM *block); +void mmxext_idct(DCTELEM *block); +/* this should be in dsputil.h? -- A'rpi */ +extern UINT8 ff_alternate_horizontal_scan[64]; +extern UINT8 ff_alternate_vertical_scan[64]; +extern UINT8 zigzag_direct[64]; +#endif + +/* pixel operations */ +static const unsigned long long int mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001; +static const unsigned long long int mm_wtwo __attribute__ ((aligned(8))) = 0x0002000200020002; +//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; + } +} + +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; + } +} + +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; + } +} + +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; + } +} + +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):"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); +} + +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):"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); +} + +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):"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); +} + +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); +} + +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); +} + +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):"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); +} + +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):"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); +} + +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):"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); +} + +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):"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); +} + +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):"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) + :"memory"); + pix += line_size; + p += line_size ; + } while(--h); +} + +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); +} + +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); +} + +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); +} + +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):"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); +} + +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); +} + +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):"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); +} + +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):"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); +} + +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):"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); +} + +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; + av_fdct = 0; + + 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; + } + +#ifdef USE_MMX_IDCT + /* use MMX / MMXEXT iDCT code from libmpeg2 */ + //printf("LIBAVCODEC: Using MMX%s iDCT code\n",(mm_flags & MM_MMXEXT)?"EXT":""); + ff_idct = (mm_flags & MM_MMXEXT) ? mmxext_idct : mmx_idct; + /* the mmx/mmxext idct uses a reordered input, so we patch scan tables */ + { int i,j; + for (i = 0; i < 64; i++) { + j = zigzag_direct[i]; + zigzag_direct[i] = (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2); + j = ff_alternate_horizontal_scan[i]; + ff_alternate_horizontal_scan[i] = (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2); + j = ff_alternate_vertical_scan[i]; + ff_alternate_vertical_scan[i] = (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2); + } + } +#endif + + } +} diff --git a/src/libffmpeg/libavcodec/dsputil_mmx_avg.h b/src/libffmpeg/libavcodec/dsputil_mmx_avg.h new file mode 100644 index 000000000..5cd640f71 --- /dev/null +++ b/src/libffmpeg/libavcodec/dsputil_mmx_avg.h @@ -0,0 +1,344 @@ +/* + * 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 + */ + +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; + } +} + +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"); + } +} + +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; + } +} + +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"); + } +} + +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"); + } +} + +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):"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); +} + +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); +} + +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); +} + diff --git a/src/libffmpeg/libavcodec/fdctref.c b/src/libffmpeg/libavcodec/fdctref.c new file mode 100644 index 000000000..b90a2e52e --- /dev/null +++ b/src/libffmpeg/libavcodec/fdctref.c @@ -0,0 +1,118 @@ +/* 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 + +#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/src/libffmpeg/libavcodec/h263.c b/src/libffmpeg/libavcodec/h263.c new file mode 100644 index 000000000..73355a6ed --- /dev/null +++ b/src/libffmpeg/libavcodec/h263.c @@ -0,0 +1,1292 @@ +/* + * 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 +#include +#include +#include "common.h" +#include "dsputil.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h263data.h" +#include "mpeg4data.h" + +#define NDEBUG +#include + +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;itable_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_bits1(&s->gb)) { + /* 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; + s->mb_skiped = 1; + 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_bits1(&s->gb); + } + 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_bits1(&s->gb); + 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_bits1(&s->gb); + 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_bits1(&s->gb)) + 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) + skip_bits1(&s->gb); /* 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_bits1(&s->gb) != 0) { + if (get_bits1(&s->gb) != 0) { + /* third escape */ + last = get_bits1(&s->gb); + run = get_bits(&s->gb, 6); + get_bits1(&s->gb); /* marker */ + level = get_bits(&s->gb, 12); + level = (level << 20) >> 20; /* sign extend */ + skip_bits1(&s->gb); /* 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_bits1(&s->gb)) + 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_bits1(&s->gb)) + level = -level; + } + } else { + run = rl->table_run[code]; + level = rl->table_level[code]; + last = code >= rl->last; + if (get_bits1(&s->gb)) + 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; + skip_bits(&s->gb, 8); /* picture timestamp */ + + if (get_bits1(&s->gb) != 1) + return -1; /* marker */ + if (get_bits1(&s->gb) != 0) + return -1; /* h263 id */ + skip_bits1(&s->gb); /* split screen off */ + skip_bits1(&s->gb); /* camera off */ + skip_bits1(&s->gb); /* 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_bits1(&s->gb); + + s->unrestricted_mv = get_bits1(&s->gb); + s->h263_long_vectors = s->unrestricted_mv; + + if (get_bits1(&s->gb) != 0) + return -1; /* SAC: off */ + if (get_bits1(&s->gb) != 0) + return -1; /* advanced prediction mode: off */ + if (get_bits1(&s->gb) != 0) + return -1; /* not PB frame */ + + s->qscale = get_bits(&s->gb, 5); + skip_bits1(&s->gb); /* 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; + skip_bits(&s->gb, 12); + skip_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; + skip_bits(&s->gb, 7); + skip_bits(&s->gb, 4); /* aspect ratio */ + width = (get_bits(&s->gb, 9) + 1) * 4; + skip_bits1(&s->gb); + height = get_bits(&s->gb, 9) * 4; + if (height == 0) + return -1; + s->qscale = get_bits(&s->gb, 5); + } + /* PEI */ + while (get_bits1(&s->gb) != 0) { + skip_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 */ + skip_bits(&s->gb, 1); /* random access */ + skip_bits(&s->gb, 8); /* vo_type */ + skip_bits(&s->gb, 1); /* is_ol_id */ + skip_bits(&s->gb, 4); /* vo_ver_id */ + skip_bits(&s->gb, 3); /* vo_priority */ + + skip_bits(&s->gb, 4); /* aspect_ratio_info */ + skip_bits(&s->gb, 1); /* vol control parameter */ + skip_bits(&s->gb, 2); /* vol shape */ + skip_bits1(&s->gb); /* marker */ + + time_increment_resolution = get_bits(&s->gb, 16); + s->time_increment_bits = log2(time_increment_resolution - 1) + 1; + skip_bits1(&s->gb); /* marker */ + + skip_bits1(&s->gb); /* vop rate */ + skip_bits(&s->gb, s->time_increment_bits); + skip_bits1(&s->gb); /* marker */ + + width = get_bits(&s->gb, 13); + skip_bits1(&s->gb); /* marker */ + height = get_bits(&s->gb, 13); + skip_bits1(&s->gb); /* marker */ + + skip_bits1(&s->gb); /* interfaced */ + skip_bits1(&s->gb); /* OBMC */ + skip_bits(&s->gb, 2); /* vol_sprite_usage */ + skip_bits1(&s->gb); /* not_8_bit */ + + skip_bits1(&s->gb); /* vol_quant_type */ + skip_bits1(&s->gb); /* vol_quarter_pixel */ + skip_bits1(&s->gb); /* complexity_estimation_disabled */ + skip_bits1(&s->gb); /* resync_marker_disabled */ + skip_bits1(&s->gb); /* 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_bits1(&s->gb) != 0) + time_incr++; + + skip_bits1(&s->gb); /* marker */ + skip_bits(&s->gb, s->time_increment_bits); + skip_bits1(&s->gb); /* marker */ + /* vop coded */ + if (get_bits1(&s->gb) != 1) + return -1; + + if (s->pict_type == P_TYPE) { + /* rounding type for motion estimation */ + s->no_rounding = get_bits1(&s->gb); + } + + 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; + skip_bits(&s->gb, 8); /* picture timestamp */ + + if (get_bits1(&s->gb) != 1) + return -1; /* marker */ + if (get_bits1(&s->gb) != 0) + return -1; /* h263 id */ + skip_bits1(&s->gb); /* split screen off */ + skip_bits1(&s->gb); /* camera off */ + skip_bits1(&s->gb); /* 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_bits1(&s->gb); + + s->unrestricted_mv = get_bits1(&s->gb); + s->h263_long_vectors = s->unrestricted_mv; + + if (get_bits1(&s->gb) != 0) + return -1; /* SAC: off */ + if (get_bits1(&s->gb) != 0) + return -1; /* advanced prediction mode: off */ + if (get_bits1(&s->gb) != 0) + return -1; /* not PB frame */ + + /* skip unknown header garbage */ + skip_bits(&s->gb, 41); + + s->qscale = get_bits(&s->gb, 5); + skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */ + + /* PEI */ + while (get_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + s->f_code = 1; + return 0; +} diff --git a/src/libffmpeg/libavcodec/h263data.h b/src/libffmpeg/libavcodec/h263data.h new file mode 100644 index 000000000..4fd9d3629 --- /dev/null +++ b/src/libffmpeg/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/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c new file mode 100644 index 000000000..8bbd3a758 --- /dev/null +++ b/src/libffmpeg/libavcodec/h263dec.c @@ -0,0 +1,204 @@ +/* + * 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 +#include +#include +#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; + 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(s->block, 0, sizeof(s->block)); + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + if (s->h263_msmpeg4) { + if (msmpeg4_decode_mb(s, s->block) < 0) + return -1; + } else { + if (h263_decode_mb(s, s->block) < 0) + return -1; + } + MPV_decode_mb(s, 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/src/libffmpeg/libavcodec/jfdctfst.c b/src/libffmpeg/libavcodec/jfdctfst.c new file mode 100644 index 000000000..cdc3b47f9 --- /dev/null +++ b/src/libffmpeg/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 +#include +#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/src/libffmpeg/libavcodec/jrevdct.c b/src/libffmpeg/libavcodec/jrevdct.c new file mode 100644 index 000000000..2ef40f38e --- /dev/null +++ b/src/libffmpeg/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/src/libffmpeg/libavcodec/mjpeg.c b/src/libffmpeg/libavcodec/mjpeg.c new file mode 100644 index 000000000..e119df66f --- /dev/null +++ b/src/libffmpeg/libavcodec/mjpeg.c @@ -0,0 +1,943 @@ +/* + * MJPEG 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 +#include +#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;jhuff_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;ipb; + 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); + } +} + +/******************************************/ +/* decoding */ + +//#define DEBUG + +#ifdef DEBUG +#define dprintf(fmt,args...) printf(fmt, ## args) +#else +#define dprintf(fmt,args...) +#endif + +/* compressed picture size */ +#define PICTURE_BUFFER_SIZE 100000 + +#define MAX_COMPONENTS 4 + +typedef struct MJpegDecodeContext { + GetBitContext gb; + UINT32 header_state; + int start_code; /* current start code */ + UINT8 *buf_ptr; + int buffer_size; + int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ + INT16 quant_matrixes[4][64]; + VLC vlcs[2][4]; + int width, height; + int nb_components; + int component_id[MAX_COMPONENTS]; + int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */ + int v_count[MAX_COMPONENTS]; + int h_max, v_max; /* maximum h and v counts */ + int quant_index[4]; /* quant table index for each component */ + int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */ + UINT8 *current_picture[MAX_COMPONENTS]; /* picture structure */ + int linesize[MAX_COMPONENTS]; + DCTELEM block[64] __align8; + UINT8 buffer[PICTURE_BUFFER_SIZE]; +} MJpegDecodeContext; + +static void build_vlc(VLC *vlc, const UINT8 *bits_table, const UINT8 *val_table, + int nb_codes) +{ + UINT8 huff_size[256]; + UINT16 huff_code[256]; + + memset(huff_size, 0, sizeof(huff_size)); + build_huffman_codes(huff_size, huff_code, bits_table, val_table); + + init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2); +} + +static int mjpeg_decode_init(AVCodecContext *avctx) +{ + MJpegDecodeContext *s = avctx->priv_data; + + s->header_state = 0; + s->mpeg_enc_ctx_allocated = 0; + s->buffer_size = PICTURE_BUFFER_SIZE - 1; /* minus 1 to take into + account FF 00 case */ + s->start_code = -1; + s->buf_ptr = s->buffer; + + build_vlc(&s->vlcs[0][0], bits_dc_luminance, val_dc_luminance, 12); + build_vlc(&s->vlcs[0][1], bits_dc_chrominance, val_dc_chrominance, 12); + build_vlc(&s->vlcs[1][0], bits_ac_luminance, val_ac_luminance, 251); + build_vlc(&s->vlcs[1][1], bits_ac_chrominance, val_ac_chrominance, 251); + return 0; +} + +/* quantize tables */ +static int mjpeg_decode_dqt(MJpegDecodeContext *s, + UINT8 *buf, int buf_size) +{ + int len, index, i; + init_get_bits(&s->gb, buf, buf_size); + + len = get_bits(&s->gb, 16); + len -= 2; + + while (len >= 65) { + /* only 8 bit precision handled */ + if (get_bits(&s->gb, 4) != 0) + return -1; + index = get_bits(&s->gb, 4); + if (index >= 4) + return -1; + dprintf("index=%d\n", index); + /* read quant table */ + for(i=0;i<64;i++) + s->quant_matrixes[index][i] = get_bits(&s->gb, 8); + len -= 65; + } + return 0; +} + +/* decode huffman tables and build VLC decoders */ +static int mjpeg_decode_dht(MJpegDecodeContext *s, + UINT8 *buf, int buf_size) +{ + int len, index, i, class, n, v, code_max; + UINT8 bits_table[17]; + UINT8 val_table[256]; + + init_get_bits(&s->gb, buf, buf_size); + + len = get_bits(&s->gb, 16); + len -= 2; + + while (len > 0) { + if (len < 17) + return -1; + class = get_bits(&s->gb, 4); + if (class >= 2) + return -1; + index = get_bits(&s->gb, 4); + if (index >= 4) + return -1; + n = 0; + for(i=1;i<=16;i++) { + bits_table[i] = get_bits(&s->gb, 8); + n += bits_table[i]; + } + len -= 17; + if (len < n || n > 256) + return -1; + + code_max = 0; + for(i=0;igb, 8); + if (v > code_max) + code_max = v; + val_table[i] = v; + } + len -= n; + + /* build VLC and flush previous vlc if present */ + free_vlc(&s->vlcs[class][index]); + dprintf("class=%d index=%d nb_codes=%d\n", + class, index, code_max + 1); + build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1); + } + return 0; +} + +static int mjpeg_decode_sof0(MJpegDecodeContext *s, + UINT8 *buf, int buf_size) +{ + int len, nb_components, i, width, height; + + init_get_bits(&s->gb, buf, buf_size); + + /* XXX: verify len field validity */ + len = get_bits(&s->gb, 16); + /* only 8 bits/component accepted */ + if (get_bits(&s->gb, 8) != 8) + return -1; + height = get_bits(&s->gb, 16); + width = get_bits(&s->gb, 16); + + nb_components = get_bits(&s->gb, 8); + if (nb_components <= 0 || + nb_components > MAX_COMPONENTS) + return -1; + s->nb_components = nb_components; + s->h_max = 1; + s->v_max = 1; + for(i=0;icomponent_id[i] = get_bits(&s->gb, 8) - 1; + s->h_count[i] = get_bits(&s->gb, 4); + s->v_count[i] = get_bits(&s->gb, 4); + /* compute hmax and vmax (only used in interleaved case) */ + if (s->h_count[i] > s->h_max) + s->h_max = s->h_count[i]; + if (s->v_count[i] > s->v_max) + s->v_max = s->v_count[i]; + s->quant_index[i] = get_bits(&s->gb, 8); + if (s->quant_index[i] >= 4) + return -1; + dprintf("component %d %d:%d\n", i, s->h_count[i], s->v_count[i]); + } + + /* if different size, realloc/alloc picture */ + /* XXX: also check h_count and v_count */ + if (width != s->width || height != s->height) { + for(i=0;icurrent_picture[i]); + s->current_picture[i] = NULL; + } + s->width = width; + s->height = height; + for(i=0;ih_max / s->h_count[i]; + vv = s->v_max / s->v_count[i]; + w = (s->width + 8 * hh - 1) / (8 * hh); + h = (s->height + 8 * vv - 1) / (8 * vv); + w = w * 8; + h = h * 8; + s->linesize[i] = w; + /* memory test is done in mjpeg_decode_sos() */ + s->current_picture[i] = av_mallocz(w * h); + } + } + + return 0; +} + +static inline int decode_dc(MJpegDecodeContext *s, int dc_index) +{ + VLC *dc_vlc; + int code, diff; + + dc_vlc = &s->vlcs[0][dc_index]; + code = get_vlc(&s->gb, dc_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; +} + +/* decode block and dequantize */ +static int decode_block(MJpegDecodeContext *s, DCTELEM *block, + int component, int dc_index, int ac_index, int quant_index) +{ + int nbits, code, i, j, level; + int run, val; + VLC *ac_vlc; + INT16 *quant_matrix; + + quant_matrix = s->quant_matrixes[quant_index]; + /* DC coef */ + val = decode_dc(s, dc_index); + if (val == 0xffff) { + dprintf("error dc\n"); + return -1; + } + val = val * quant_matrix[0] + s->last_dc[component]; + s->last_dc[component] = val; + block[0] = val; + /* AC coefs */ + ac_vlc = &s->vlcs[1][ac_index]; + i = 1; + for(;;) { + code = get_vlc(&s->gb, ac_vlc); + if (code < 0) { + dprintf("error ac\n"); + return -1; + } + /* EOB */ + if (code == 0) + break; + if (code == 0xf0) { + i += 16; + } else { + run = code >> 4; + nbits = code & 0xf; + level = get_bits(&s->gb, nbits); + if ((level & (1 << (nbits - 1))) == 0) + level = (-1 << nbits) | (level + 1); + i += run; + if (i >= 64) { + dprintf("error count: %d\n", i); + return -1; + } + j = zigzag_direct[i]; + block[j] = level * quant_matrix[j]; + i++; + if (i >= 64) + break; + } + } + return 0; +} + +static int mjpeg_decode_sos(MJpegDecodeContext *s, + UINT8 *buf, int buf_size) +{ + int len, nb_components, i, j, n, h, v; + int mb_width, mb_height, mb_x, mb_y, vmax, hmax, index, id; + int comp_index[4]; + int dc_index[4]; + int ac_index[4]; + int nb_blocks[4]; + int h_count[4]; + int v_count[4]; + + init_get_bits(&s->gb, buf, buf_size); + /* XXX: verify len field validity */ + len = get_bits(&s->gb, 16); + nb_components = get_bits(&s->gb, 8); + /* XXX: only interleaved scan accepted */ + if (nb_components != 3) + return -1; + vmax = 0; + hmax = 0; + for(i=0;igb, 8) - 1; + /* find component index */ + for(index=0;indexnb_components;index++) + if (id == s->component_id[index]) + break; + if (index == s->nb_components) + return -1; + + comp_index[i] = index; + nb_blocks[i] = s->h_count[index] * s->v_count[index]; + h_count[i] = s->h_count[index]; + v_count[i] = s->v_count[index]; + + dc_index[i] = get_bits(&s->gb, 4); + if (dc_index[i] >= 4) + return -1; + ac_index[i] = get_bits(&s->gb, 4); + if (ac_index[i] >= 4) + return -1; + } + get_bits(&s->gb, 8); /* Ss */ + get_bits(&s->gb, 8); /* Se */ + get_bits(&s->gb, 8); /* not used */ + + for(i=0;ilast_dc[i] = 1024; + + if (nb_components > 1) { + /* interleaved stream */ + mb_width = (s->width + s->h_max * 8 - 1) / (s->h_max * 8); + mb_height = (s->height + s->v_max * 8 - 1) / (s->v_max * 8); + } else { + h = s->h_max / s->h_count[comp_index[0]]; + v = s->v_max / s->v_count[comp_index[0]]; + mb_width = (s->width + h * 8 - 1) / (h * 8); + mb_height = (s->height + v * 8 - 1) / (v * 8); + nb_blocks[0] = 1; + h_count[0] = 1; + v_count[0] = 1; + } + + for(mb_y = 0; mb_y < mb_height; mb_y++) { + for(mb_x = 0; mb_x < mb_width; mb_x++) { + for(i=0;iblock, 0, sizeof(s->block)); + if (decode_block(s, s->block, i, + dc_index[i], ac_index[i], + s->quant_index[c]) < 0) { + dprintf("error %d %d\n", mb_y, mb_x); + return -1; + } + ff_idct (s->block); + ptr = s->current_picture[c] + + (s->linesize[c] * (v * mb_y + y) * 8) + + (h * mb_x + x) * 8; + put_pixels_clamped(s->block, ptr, s->linesize[c]); + if (++x == h) { + x = 0; + y++; + } + } + } + } + } + return 0; +} + +/* return the 8 bit start code value and update the search + state. Return -1 if no start code found */ +static int find_marker(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; + if (state) { + /* get marker */ + found: + if (buf_ptr < buf_end) { + val = *buf_ptr++; + state = 0; + } else { + val = -1; + } + } else { + while (buf_ptr < buf_end) { + v = *buf_ptr++; + if (v == 0xff) { + state = 1; + goto found; + } + } + val = -1; + } + *pbuf_ptr = buf_ptr; + *header_state = state; + return val; +} + +static int mjpeg_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + UINT8 *buf, int buf_size) +{ + MJpegDecodeContext *s = avctx->priv_data; + UINT8 *buf_end, *buf_ptr, *buf_start; + int len, code, start_code, input_size, i; + AVPicture *picture = data; + + /* no supplementary picture */ + if (buf_size == 0) { + *data_size = 0; + return 0; + } + + buf_ptr = buf; + buf_end = buf + buf_size; + while (buf_ptr < buf_end) { + buf_start = buf_ptr; + /* find start next marker */ + code = find_marker(&buf_ptr, buf_end, &s->header_state); + /* 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 (code > 0) + s->start_code = code; + } else { + memcpy(s->buf_ptr, buf_start, len); + s->buf_ptr += len; + /* if we got FF 00, we copy FF to the stream to unescape FF 00 */ + if (code == 0) { + s->buf_ptr--; + } else if (code > 0) { + /* 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 SOI: + /* nothing to do on SOI */ + break; + case DQT: + mjpeg_decode_dqt(s, s->buffer, input_size); + break; + case DHT: + mjpeg_decode_dht(s, s->buffer, input_size); + break; + case SOF0: + mjpeg_decode_sof0(s, s->buffer, input_size); + break; + case SOS: + mjpeg_decode_sos(s, s->buffer, input_size); + if (s->start_code == EOI) { + for(i=0;i<3;i++) { + picture->data[i] = s->current_picture[i]; + picture->linesize[i] = s->linesize[i]; + } + *data_size = sizeof(AVPicture); + avctx->height = s->height; + avctx->width = s->width; + /* XXX: not complete test ! */ + switch((s->h_count[0] << 4) | s->v_count[0]) { + case 0x11: + avctx->pix_fmt = PIX_FMT_YUV444P; + break; + case 0x21: + avctx->pix_fmt = PIX_FMT_YUV422P; + break; + default: + case 0x22: + avctx->pix_fmt = PIX_FMT_YUV420P; + break; + } + goto the_end; + } + break; + } + } + } + } + the_end: + return buf_ptr - buf; +} + +static int mjpeg_decode_end(AVCodecContext *avctx) +{ + MJpegDecodeContext *s = avctx->priv_data; + int i, j; + + for(i=0;icurrent_picture[i]); + for(i=0;i<2;i++) { + for(j=0;j<4;j++) + free_vlc(&s->vlcs[i][j]); + } + return 0; +} + +AVCodec mjpeg_decoder = { + "mjpeg", + CODEC_TYPE_VIDEO, + CODEC_ID_MJPEG, + sizeof(MJpegDecodeContext), + mjpeg_decode_init, + NULL, + mjpeg_decode_end, + mjpeg_decode_frame, +}; diff --git a/src/libffmpeg/libavcodec/motion_est.c b/src/libffmpeg/libavcodec/motion_est.c new file mode 100644 index 000000000..d3e31fc42 --- /dev/null +++ b/src/libffmpeg/libavcodec/motion_est.c @@ -0,0 +1,514 @@ +/* + * 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 +#include +#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; + } + emms_c(); + + /* 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/src/libffmpeg/libavcodec/mpeg12.c b/src/libffmpeg/libavcodec/mpeg12.c new file mode 100644 index 000000000..182c341e4 --- /dev/null +++ b/src/libffmpeg/libavcodec/mpeg12.c @@ -0,0 +1,1534 @@ +/* + * 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 +#include +#include +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" + +#include "mpeg12data.h" + +#ifdef USE_FASTMEMCPY +#include "fastmemcpy.h" +#endif +//#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, v; + int n; + 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_bits1(&s->gb)) + return 1 - (get_bits1(&s->gb) << 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]; + } + s->mb_skiped = 1; + return 0; + } + + switch(s->pict_type) { + default: + case I_TYPE: + if (get_bits1(&s->gb) == 0) { + if (get_bits1(&s->gb) == 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_bits1(&s->gb); +#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) + skip_bits1(&s->gb); /* 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_bits1(&s->gb); + 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_bits1(&s->gb); + 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_bits1(&s->gb); + 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) { + skip_bits1(&s->gb); /* 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_bits1(&s->gb); + 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_bits1(&s->gb)) + 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_bits1(&s->gb)) + 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_bits1(&s->gb)) + 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); + skip_bits(&s->gb, 16); + if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) { + s->full_pel[0] = get_bits1(&s->gb); + 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_bits1(&s->gb); + 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; + + skip_bits(&s->gb, 8); /* profil and level */ + skip_bits(&s->gb, 1); /* progressive_sequence */ + skip_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; + skip_bits1(&s->gb); /* marker */ + vbv_buf_ext = get_bits(&s->gb, 8); + low_delay = get_bits1(&s->gb); + 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_bits1(&s->gb)) { + 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_bits1(&s->gb)) { + 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_bits1(&s->gb)) { + for(i=0;i<64;i++) { + v = get_bits(&s->gb, 8); + s->chroma_intra_matrix[i] = v; + } + } + if (get_bits1(&s->gb)) { + 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_bits1(&s->gb); + s->frame_pred_frame_dct = get_bits1(&s->gb); + s->concealment_motion_vectors = get_bits1(&s->gb); + s->q_scale_type = get_bits1(&s->gb); + s->intra_vlc_format = get_bits1(&s->gb); + s->alternate_scan = get_bits1(&s->gb); + s->repeat_first_field = get_bits1(&s->gb); + s->chroma_420_type = get_bits1(&s->gb); + s->progressive_frame = get_bits1(&s->gb); + /* 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; + + 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_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + + for(;;) { + memset(s->block, 0, sizeof(s->block)); + ret = mpeg_decode_mb(s, s->block); + dprintf("ret=%d\n", ret); + if (ret < 0) + return -1; + if (ret == 1) + break; + MPV_decode_mb(s, 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); + skip_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_bits1(&s->gb) == 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; + } + + skip_bits(&s->gb, 10); /* vbv_buffer_size */ + skip_bits(&s->gb, 1); + + /* get matrix */ + if (get_bits1(&s->gb)) { + 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_bits1(&s->gb)) { + 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/src/libffmpeg/libavcodec/mpeg12data.h b/src/libffmpeg/libavcodec/mpeg12data.h new file mode 100644 index 000000000..f397c4a17 --- /dev/null +++ b/src/libffmpeg/libavcodec/mpeg12data.h @@ -0,0 +1,363 @@ +/* + * 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 INT8 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 INT8 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/src/libffmpeg/libavcodec/mpeg4data.h b/src/libffmpeg/libavcodec/mpeg4data.h new file mode 100644 index 000000000..54b93d97e --- /dev/null +++ b/src/libffmpeg/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/src/libffmpeg/libavcodec/mpegvideo.c b/src/libffmpeg/libavcodec/mpegvideo.c new file mode 100644 index 000000000..8a5745a8f --- /dev/null +++ b/src/libffmpeg/libavcodec/mpegvideo.c @@ -0,0 +1,1357 @@ +/* + * 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 +#include +#include +#include +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" + +#ifdef USE_FASTMEMCPY +#include "fastmemcpy.h" +#endif + +/* FIXME */ +#ifdef ARCH_X86 +#define HAVE_MMX +#endif + +static void encode_picture(MpegEncContext *s, int picture_number); +static void rate_control_init(MpegEncContext *s); +static int rate_estimate_qscale(MpegEncContext *s); +static void dct_unquantize_mpeg1_c(MpegEncContext *s, + DCTELEM *block, int n, int qscale); +static void dct_unquantize_h263_c(MpegEncContext *s, + DCTELEM *block, int n, int qscale); +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); +#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, +}; + +/* 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; + + if (s->out_format == FMT_H263) + s->dct_unquantize = dct_unquantize_h263_c; + else + s->dct_unquantize = dct_unquantize_mpeg1_c; + +#ifdef HAVE_MMX + MPV_common_init_mmx(s); +#endif + 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;idc_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]; + } + /* init macroblock skip table */ + if (!s->encoding) { + s->mbskip_table = av_mallocz(s->mb_width * s->mb_height); + if (!s->mbskip_table) + goto fail; + } + + 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); + if (s->mbskip_table) + free(s->mbskip_table); + 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); + } + if (s->mbskip_table) + free(s->mbskip_table); + 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); + + s->encoding = 1; + + /* 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;ipict_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;jnew_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; +} + +/* 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) + s->dct_unquantize(s, block, i, s->qscale); + ff_idct (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) + s->dct_unquantize(s, block, i, s->qscale); + ff_idct (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; + UINT8 *mbskip_ptr; + + /* avoid copy if macroblock skipped in last frame too */ + if (!s->encoding && s->pict_type != B_TYPE) { + mbskip_ptr = &s->mbskip_table[s->mb_y * s->mb_width + s->mb_x]; + if (s->mb_skiped) { + s->mb_skiped = 0; + /* if previous was skipped too, then nothing to do ! */ + if (*mbskip_ptr != 0) + goto the_end; + *mbskip_ptr = 1; /* indicate that this time we skiped it */ + } else { + *mbskip_ptr = 0; /* not skipped */ + } + } + + 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); + } + } + the_end: + emms_c(); +} + +static void encode_picture(MpegEncContext *s, int picture_number) +{ + int mb_x, mb_y, wrap; + UINT8 *ptr; + 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(s->block[0], ptr, wrap); + get_pixels(s->block[1], ptr + 8, wrap); + get_pixels(s->block[2], ptr + 8 * wrap, wrap); + get_pixels(s->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(s->block[4], ptr, wrap); + + wrap = s->linesize >> 1; + ptr = s->new_picture[2] + (mb_y * 8 * wrap) + mb_x * 8; + get_pixels(s->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(s->block[0], ptr, s->linesize, dxy); + sub_pixels_2(s->block[1], ptr + 8, s->linesize, dxy); + sub_pixels_2(s->block[2], ptr + s->linesize * 8, s->linesize, dxy); + sub_pixels_2(s->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(s->block[4], ptr, s->linesize >> 1, dxy); + ptr = s->last_picture[2] + offset; + sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy); + } + emms_c(); + + /* 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, s->block[i], i, s->qscale); + else + last_index = dct_quantize_mmx(s, 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, s->block, motion_x, motion_y); + break; + case FMT_H263: + if (s->h263_msmpeg4) + msmpeg4_encode_mb(s, s->block, motion_x, motion_y); + else + h263_encode_mb(s, s->block, motion_x, motion_y); + break; + case FMT_MJPEG: + mjpeg_encode_mb(s, 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, 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_mpeg1_c(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; + /* 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; + 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; + } + } + } +} + +static void dct_unquantize_h263_c(MpegEncContext *s, + DCTELEM *block, int n, int qscale) +{ + int i, level, qmul, qadd; + + if (s->mb_intra) { + if (n < 4) + block[0] = block[0] * s->y_dc_scale; + else + block[0] = block[0] * s->c_dc_scale; + i = 1; + } else { + i = 0; + } + + qmul = s->qscale << 1; + qadd = (s->qscale - 1) | 1; + + for(;i<64;i++) { + level = block[i]; + if (level) { + if (level < 0) { + level = level * qmul - qadd; + } else { + level = level * qmul + qadd; + } +#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/src/libffmpeg/libavcodec/mpegvideo.h b/src/libffmpeg/libavcodec/mpegvideo.h new file mode 100644 index 000000000..9f9307393 --- /dev/null +++ b/src/libffmpeg/libavcodec/mpegvideo.h @@ -0,0 +1,285 @@ +/* + * 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 */ + int encoding; /* true if we are encoding (vs decoding) */ + /* 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 mb_skiped; /* MUST BE SET only during DECODING */ + UINT8 *mbskip_table; /* used to avoid copy if macroblock + skipped (for black regions for example) */ + + 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; + + DCTELEM block[6][64] __align8; + void (*dct_unquantize)(struct MpegEncContext *s, + DCTELEM *block, int n, int qscale); +} MpegEncContext; + +//const +extern 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); +#ifdef HAVE_MMX +void MPV_common_init_mmx(MpegEncContext *s); +#endif + +/* 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/src/libffmpeg/libavcodec/mpegvideo_mmx.c b/src/libffmpeg/libavcodec/mpegvideo_mmx.c new file mode 100644 index 000000000..279e5ec22 --- /dev/null +++ b/src/libffmpeg/libavcodec/mpegvideo_mmx.c @@ -0,0 +1,232 @@ +/* + * 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. + * + * Optimized for ia32 cpus by Nick Kurshev + */ + +#include "dsputil.h" +#include "mpegvideo.h" +#include "cpu_accel.h" + +#if 0 + +/* XXX: GL: I don't understand why this function needs optimization + (it is called only once per frame!), so I disabled it */ + +void MPV_frame_start(MpegEncContext *s) +{ + if (s->pict_type == B_TYPE) { + __asm __volatile( + "movl (%1), %%eax\n\t" + "movl 4(%1), %%edx\n\t" + "movl 8(%1), %%ecx\n\t" + "movl %%eax, (%0)\n\t" + "movl %%edx, 4(%0)\n\t" + "movl %%ecx, 8(%0)\n\t" + : + :"r"(s->current_picture), "r"(s->aux_picture) + :"eax","edx","ecx","memory"); + } else { + /* swap next and last */ + __asm __volatile( + "movl (%1), %%eax\n\t" + "movl 4(%1), %%edx\n\t" + "movl 8(%1), %%ecx\n\t" + "xchgl (%0), %%eax\n\t" + "xchgl 4(%0), %%edx\n\t" + "xchgl 8(%0), %%ecx\n\t" + "movl %%eax, (%1)\n\t" + "movl %%edx, 4(%1)\n\t" + "movl %%ecx, 8(%1)\n\t" + "movl %%eax, (%2)\n\t" + "movl %%edx, 4(%2)\n\t" + "movl %%ecx, 8(%2)\n\t" + : + :"r"(s->last_picture), "r"(s->next_picture), "r"(s->current_picture) + :"eax","edx","ecx","memory"); + } +} +#endif + +static const unsigned long long int mm_wabs __attribute__ ((aligned(8))) = 0xffffffffffffffffULL; +static const unsigned long long int mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001ULL; + +/* + NK: + Note: looking at PARANOID: + "enable all paranoid tests for rounding, overflows, etc..." + +#ifdef PARANOID + if (level < -2048 || level > 2047) + fprintf(stderr, "unquant error %d %d\n", i, level); +#endif + We can suppose that result of two multiplications can't be greate of 0xFFFF + i.e. is 16-bit, so we use here only PMULLW instruction and can avoid + a complex multiplication. +===================================================== + Full formula for multiplication of 2 integer numbers + which are represent as high:low words: + input: value1 = high1:low1 + value2 = high2:low2 + output: value3 = value1*value2 + value3=high3:low3 (on overflow: modulus 2^32 wrap-around) + this mean that for 0x123456 * 0x123456 correct result is 0x766cb0ce4 + but this algorithm will compute only 0x66cb0ce4 + this limited by 16-bit size of operands + --------------------------------- + tlow1 = high1*low2 + tlow2 = high2*low1 + tlow1 = tlow1 + tlow2 + high3:low3 = low1*low2 + high3 += tlow1 +*/ +static void dct_unquantize_mpeg1_mmx(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; + i=1; + /* Align on 4 elements boundary */ + while(i&3) + { + level = block[i]; + if (level) { + if (level < 0) level = -level; + level = (int)(level * qscale * quant_matrix[i]) >> 3; + level = (level - 1) | 1; + if (block[i] < 0) level = -level; + block[i] = level; + } + i++; + } + __asm __volatile( + "movd %0, %%mm6\n\t" /* mm6 = qscale | 0 */ + "punpckldq %%mm6, %%mm6\n\t" /* mm6 = qscale | qscale */ + "movq %2, %%mm4\n\t" + "movq %%mm6, %%mm7\n\t" + "movq %1, %%mm5\n\t" + "packssdw %%mm6, %%mm7\n\t" /* mm7 = qscale | qscale | qscale | qscale */ + "pxor %%mm6, %%mm6\n\t" + ::"g"(qscale),"m"(mm_wone),"m"(mm_wabs):"memory"); + for(;i<64;i+=4) { + __asm __volatile( + "movq %1, %%mm0\n\t" + "movq %%mm7, %%mm1\n\t" + "movq %%mm0, %%mm2\n\t" + "movq %%mm0, %%mm3\n\t" + "pcmpgtw %%mm6, %%mm2\n\t" + "pmullw %2, %%mm1\n\t" + "pandn %%mm4, %%mm2\n\t" + "por %%mm5, %%mm2\n\t" + "pmullw %%mm2, %%mm0\n\t" /* mm0 = abs(block[i]). */ + + "pcmpeqw %%mm6, %%mm3\n\t" + "pmullw %%mm0, %%mm1\n\t" + "psraw $3, %%mm1\n\t" + "psubw %%mm5, %%mm1\n\t" /* block[i] --; */ + "pandn %%mm4, %%mm3\n\t" /* fake of pcmpneqw : mm0 != 0 then mm1 = -1 */ + "por %%mm5, %%mm1\n\t" /* block[i] |= 1 */ + "pmullw %%mm2, %%mm1\n\t" /* change signs again */ + + "pand %%mm3, %%mm1\n\t" /* nullify if was zero */ + "movq %%mm1, %0" + :"=m"(block[i]) + :"m"(block[i]), "m"(quant_matrix[i]) + :"memory"); + } + } else { + i = 0; + unquant_even: + quant_matrix = s->non_intra_matrix; + /* Align on 4 elements boundary */ + while(i&3) + { + level = block[i]; + if (level) { + if (level < 0) level = -level; + level = (((level << 1) + 1) * qscale * + ((int) quant_matrix[i])) >> 4; + level = (level - 1) | 1; + if(block[i] < 0) level = -level; + block[i] = level; + } + i++; + } + __asm __volatile( + "movd %0, %%mm6\n\t" /* mm6 = qscale | 0 */ + "punpckldq %%mm6, %%mm6\n\t" /* mm6 = qscale | qscale */ + "movq %2, %%mm4\n\t" + "movq %%mm6, %%mm7\n\t" + "movq %1, %%mm5\n\t" + "packssdw %%mm6, %%mm7\n\t" /* mm7 = qscale | qscale | qscale | qscale */ + "pxor %%mm6, %%mm6\n\t" + ::"g"(qscale),"m"(mm_wone),"m"(mm_wabs):"memory"); + for(;i<64;i+=4) { + __asm __volatile( + "movq %1, %%mm0\n\t" + "movq %%mm7, %%mm1\n\t" + "movq %%mm0, %%mm2\n\t" + "movq %%mm0, %%mm3\n\t" + "pcmpgtw %%mm6, %%mm2\n\t" + "pmullw %2, %%mm1\n\t" + "pandn %%mm4, %%mm2\n\t" + "por %%mm5, %%mm2\n\t" + "pmullw %%mm2, %%mm0\n\t" /* mm0 = abs(block[i]). */ + "psllw $1, %%mm0\n\t" /* block[i] <<= 1 */ + "paddw %%mm5, %%mm0\n\t" /* block[i] ++ */ + + "pmullw %%mm0, %%mm1\n\t" + "psraw $4, %%mm1\n\t" + "pcmpeqw %%mm6, %%mm3\n\t" + "psubw %%mm5, %%mm1\n\t" /* block[i] --; */ + "pandn %%mm4, %%mm3\n\t" /* fake of pcmpneqw : mm0 != 0 then mm1 = -1 */ + "por %%mm5, %%mm1\n\t" /* block[i] |= 1 */ + "pmullw %%mm2, %%mm1\n\t" /* change signs again */ + + "pand %%mm3, %%mm1\n\t" /* nullify if was zero */ + "movq %%mm1, %0" + :"=m"(block[i]) + :"m"(block[i]), "m"(quant_matrix[i]) + :"memory"); + } + } +} + +void MPV_common_init_mmx(MpegEncContext *s) +{ + int mm_flags; + + mm_flags = mm_accel(); + + if (mm_flags & MM_ACCEL_X86_MMX) { + /* XXX: should include h263 optimization too. It would go even + faster! */ + s->dct_unquantize = dct_unquantize_mpeg1_mmx; + } +} diff --git a/src/libffmpeg/libavcodec/msmpeg4.c b/src/libffmpeg/libavcodec/msmpeg4.c new file mode 100644 index 000000000..885abc117 --- /dev/null +++ b/src/libffmpeg/libavcodec/msmpeg4.c @@ -0,0 +1,932 @@ +/* + * 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 +#include +#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;itable_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;in;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;imb_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, + INT16 **dc_val_ptr, int *dir_ptr) +{ + int a, b, c, x, y, wrap, pred, scale; + INT16 *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; + INT16 *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;ivlc, 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_bits1(gb); + if (n == 0) + return 0; + else + return get_bits1(gb) + 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_bits1(&s->gb); + s->no_rounding = 1; + } else { + s->use_skip_mb_code = get_bits1(&s->gb); + + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + + s->dc_table_index = get_bits1(&s->gb); + + s->mv_table_index = get_bits1(&s->gb); + 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;imb_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_bits1(&s->gb)) { + /* 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; + s->mb_skiped = 1; + 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_bits1(&s->gb); + } + + 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_bits1(&s->gb) == 0) { + if (get_bits1(&s->gb) == 0) { + /* third escape */ + last = get_bits1(&s->gb); + 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_bits1(&s->gb)) + 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_bits1(&s->gb)) + level = -level; + } + } else { + run = rl->table_run[code]; + level = rl->table_level[code]; + last = code >= rl->last; + if (get_bits1(&s->gb)) + 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; + INT16 *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_bits1(&s->gb)) + level = -level; + } else if (level != 0) { + if (get_bits1(&s->gb)) + 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/src/libffmpeg/libavcodec/msmpeg4data.h b/src/libffmpeg/libavcodec/msmpeg4data.h new file mode 100644 index 000000000..03a261211 --- /dev/null +++ b/src/libffmpeg/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/src/libffmpeg/libavcodec/rv10.c b/src/libffmpeg/libavcodec/rv10.c new file mode 100644 index 000000000..b03cd0293 --- /dev/null +++ b/src/libffmpeg/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 +#include +#include +#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;imb_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/src/libffmpeg/libavcodec/sad_mmx.s b/src/libffmpeg/libavcodec/sad_mmx.s new file mode 100644 index 000000000..42c7ade59 --- /dev/null +++ b/src/libffmpeg/libavcodec/sad_mmx.s @@ -0,0 +1,799 @@ +# MMX/SSE optimized routines for SAD of 16*16 macroblocks +# Copyright (C) Juan J. Sierralta P. +# +# dist1_* Original Copyright (C) 2000 Chris Atenasio +# Enhancements and rest Copyright (C) 2000 Andrew Stevens + +# +# 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: + pushl %ebp # save frame pointer + movl %esp,%ebp + + pushl %ebx # Saves registers (called saves convention in + pushl %ecx # x86 GCC it seems) + pushl %edx # + pushl %esi + pushl %edi + + pxor %mm0,%mm0 # zero acculumators + pxor %mm1,%mm1 + pxor %mm6,%mm6 + movl 8(%ebp),%esi # get pix1 + movl 12(%ebp),%edi # get pix2 + movl 16(%ebp),%edx # get lx + movl 20(%ebp),%ecx # get rowsleft + jmp pix_abs16x16_mmx.nextrow +.align 32 + +pix_abs16x16_mmx.nextrow: + # First 8 bytes of the row + + movq (%edi),%mm4 # load first 8 bytes of pix2 row + movq (%esi),%mm5 # load first 8 bytes of pix1 row + movq %mm4,%mm3 # mm4 := abs(mm4-mm5) + movq 8(%esi),%mm2 # load last 8 bytes of pix1 row + psubusb %mm5,%mm4 + movq 8(%edi),%mm7 # load last 8 bytes of pix2 row + psubusb %mm3,%mm5 + por %mm5,%mm4 + + # Last 8 bytes of the row + + movq %mm7,%mm3 # mm7 := abs(mm7-mm2) + psubusb %mm2,%mm7 + psubusb %mm3,%mm2 + por %mm2,%mm7 + + # Now mm4 and mm7 have 16 absdiffs to add + + # First 8 bytes of the row2 + + + addl %edx,%edi + movq (%edi),%mm2 # load first 8 bytes of pix2 row + addl %edx,%esi + movq (%esi),%mm5 # load first 8 bytes of pix1 row + + + + movq %mm2,%mm3 # mm2 := abs(mm2-mm5) + psubusb %mm5,%mm2 + movq 8(%esi),%mm6 # load last 8 bytes of pix1 row + psubusb %mm3,%mm5 + por %mm5,%mm2 + + # Last 8 bytes of the row2 + + movq 8(%edi),%mm5 # load last 8 bytes of pix2 row + + + movq %mm5,%mm3 # mm5 := abs(mm5-mm6) + psubusb %mm6,%mm5 + psubusb %mm3,%mm6 + por %mm6,%mm5 + + # Now mm2, mm4, mm5, mm7 have 32 absdiffs + + movq %mm7,%mm3 + + pxor %mm6,%mm6 # Zero mm6 + + punpcklbw %mm6,%mm3 # Unpack to words and add + punpckhbw %mm6,%mm7 + paddusw %mm3,%mm7 + + movq %mm5,%mm3 + + punpcklbw %mm6,%mm3 # Unpack to words and add + punpckhbw %mm6,%mm5 + paddusw %mm3,%mm5 + + paddusw %mm7,%mm0 # Add to the acumulator (mm0) + paddusw %mm5,%mm1 # Add to the acumulator (mm1) + + movq %mm4,%mm3 + + punpcklbw %mm6,%mm3 # Unpack to words and add + punpckhbw %mm6,%mm4 + movq %mm2,%mm5 + paddusw %mm3,%mm4 + + + + punpcklbw %mm6,%mm5 # Unpack to words and add + punpckhbw %mm6,%mm2 + paddusw %mm5,%mm2 + + # Loop termination + + addl %edx,%esi # update pointers to next row + paddusw %mm4,%mm0 # Add to the acumulator (mm0) + addl %edx,%edi + subl $2,%ecx + paddusw %mm2,%mm1 # Add to the acumulator (mm1) + testl %ecx,%ecx # check rowsleft + jnz pix_abs16x16_mmx.nextrow + + paddusw %mm1,%mm0 + movq %mm0,%mm2 # Copy mm0 to mm2 + psrlq $32,%mm2 + paddusw %mm2,%mm0 # Add + movq %mm0,%mm3 + psrlq $16,%mm3 + paddusw %mm3,%mm0 + movd %mm0,%eax # Store return value + andl $0xffff,%eax + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + + popl %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: + pushl %ebp # save frame pointer + movl %esp,%ebp + + pushl %ebx # Saves registers (called saves convention in + pushl %ecx # x86 GCC it seems) + pushl %edx # + pushl %esi + pushl %edi + + pxor %mm0,%mm0 # zero acculumators + pxor %mm1,%mm1 + movl 8(%ebp),%esi # get pix1 + movl 12(%ebp),%edi # get pix2 + movl 16(%ebp),%edx # get lx + movl 20(%ebp),%ecx # get rowsleft + jmp pix_abs16x16_sse.next4row +.align 32 + +pix_abs16x16_sse.next4row: + # First row + + movq (%edi),%mm4 # load first 8 bytes of pix2 row + movq 8(%edi),%mm5 # load last 8 bytes of pix2 row + psadbw (%esi),%mm4 # SAD of first 8 bytes + psadbw 8(%esi),%mm5 # SAD of last 8 bytes + paddw %mm4,%mm0 # Add to acumulators + paddw %mm5,%mm1 + + # Second row + + addl %edx,%edi # + addl %edx,%esi # + + movq (%edi),%mm6 # load first 8 bytes of pix2 row + movq 8(%edi),%mm7 # load last 8 bytes of pix2 row + psadbw (%esi),%mm6 # SAD of first 8 bytes + psadbw 8(%esi),%mm7 # SAD of last 8 bytes + paddw %mm6,%mm0 # Add to acumulators + paddw %mm7,%mm1 + + # Third row + + addl %edx,%edi # + addl %edx,%esi # + + movq (%edi),%mm4 # load first 8 bytes of pix2 row + movq 8(%edi),%mm5 # load last 8 bytes of pix2 row + psadbw (%esi),%mm4 # SAD of first 8 bytes + psadbw 8(%esi),%mm5 # SAD of last 8 bytes + paddw %mm4,%mm0 # Add to acumulators + paddw %mm5,%mm1 + + # Fourth row + + addl %edx,%edi # + addl %edx,%esi # + + movq (%edi),%mm6 # load first 8 bytes of pix2 row + movq 8(%edi),%mm7 # load last 8 bytes of pix2 row + psadbw (%esi),%mm6 # SAD of first 8 bytes + psadbw 8(%esi),%mm7 # SAD of last 8 bytes + paddw %mm6,%mm0 # Add to acumulators + paddw %mm7,%mm1 + + # Loop termination + + addl %edx,%esi # update pointers to next row + addl %edx,%edi + subl $4,%ecx + testl %ecx,%ecx # check rowsleft + jnz pix_abs16x16_sse.next4row + + paddd %mm1,%mm0 # Sum acumulators + movd %mm0,%eax # Store return value + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + + popl %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: + pushl %ebp # save frame pointer + movl %esp,%ebp + + pushl %ebx # Saves registers (called saves convention in + pushl %ecx # x86 GCC it seems) + pushl %edx # + pushl %esi + pushl %edi + + pxor %mm0,%mm0 # zero acculumators + pxor %mm1,%mm1 + pxor %mm6,%mm6 + movl 8(%ebp),%esi # get pix1 + movl 12(%ebp),%edi # get pix2 + movl 16(%ebp),%edx # get lx + movl 20(%ebp),%ecx # get rowsleft + jmp pix_abs16x16_x2_mmx.nextrow_x2 +.align 32 + +pix_abs16x16_x2_mmx.nextrow_x2: + # First 8 bytes of the row + + movq (%edi),%mm4 # load first 8 bytes of pix2 row + movq 1(%edi),%mm5 # load bytes 1-8 of pix2 row + + movq %mm4,%mm2 # copy mm4 on mm2 + movq %mm5,%mm3 # copy mm5 on mm3 + punpcklbw %mm6,%mm4 # first 4 bytes of [edi] on mm4 + punpcklbw %mm6,%mm5 # first 4 bytes of [edi+1] on mm5 + paddusw %mm5,%mm4 # mm4 := first 4 bytes interpolated in words + psrlw $1,%mm4 + + punpckhbw %mm6,%mm2 # last 4 bytes of [edi] on mm2 + punpckhbw %mm6,%mm3 # last 4 bytes of [edi+1] on mm3 + paddusw %mm3,%mm2 # mm2 := last 4 bytes interpolated in words + psrlw $1,%mm2 + + packuswb %mm2,%mm4 # pack 8 bytes interpolated on mm4 + movq (%esi),%mm5 # load first 8 bytes of pix1 row + + movq %mm4,%mm3 # mm4 := abs(mm4-mm5) + psubusb %mm5,%mm4 + psubusb %mm3,%mm5 + por %mm5,%mm4 + + # Last 8 bytes of the row + + movq 8(%edi),%mm7 # load last 8 bytes of pix2 row + movq 9(%edi),%mm5 # load bytes 10-17 of pix2 row + + movq %mm7,%mm2 # copy mm7 on mm2 + movq %mm5,%mm3 # copy mm5 on mm3 + punpcklbw %mm6,%mm7 # first 4 bytes of [edi+8] on mm7 + punpcklbw %mm6,%mm5 # first 4 bytes of [edi+9] on mm5 + paddusw %mm5,%mm7 # mm1 := first 4 bytes interpolated in words + psrlw $1,%mm7 + + punpckhbw %mm6,%mm2 # last 4 bytes of [edi] on mm2 + punpckhbw %mm6,%mm3 # last 4 bytes of [edi+1] on mm3 + paddusw %mm3,%mm2 # mm2 := last 4 bytes interpolated in words + psrlw $1,%mm2 + + packuswb %mm2,%mm7 # pack 8 bytes interpolated on mm1 + movq 8(%esi),%mm5 # load last 8 bytes of pix1 row + + movq %mm7,%mm3 # mm7 := abs(mm1-mm5) + psubusb %mm5,%mm7 + psubusb %mm3,%mm5 + por %mm5,%mm7 + + # Now mm4 and mm7 have 16 absdiffs to add + + movq %mm4,%mm3 # Make copies of these bytes + movq %mm7,%mm2 + + punpcklbw %mm6,%mm4 # Unpack to words and add + punpcklbw %mm6,%mm7 + paddusw %mm7,%mm4 + paddusw %mm4,%mm0 # Add to the acumulator (mm0) + + punpckhbw %mm6,%mm3 # Unpack to words and add + punpckhbw %mm6,%mm2 + paddusw %mm2,%mm3 + paddusw %mm3,%mm1 # Add to the acumulator (mm1) + + # Loop termination + + addl %edx,%esi # update pointers to next row + addl %edx,%edi + + subl $1,%ecx + testl %ecx,%ecx # check rowsleft + jnz pix_abs16x16_x2_mmx.nextrow_x2 + + paddusw %mm1,%mm0 + + movq %mm0,%mm1 # Copy mm0 to mm1 + psrlq $32,%mm1 + paddusw %mm1,%mm0 # Add + movq %mm0,%mm2 + psrlq $16,%mm2 + paddusw %mm2,%mm0 + movd %mm0,%eax # Store return value + andl $0xffff,%eax + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + + popl %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: + pushl %ebp # save frame pointer + movl %esp,%ebp + + pushl %ebx # Saves registers (called saves convention in + pushl %ecx # x86 GCC it seems) + pushl %edx # + pushl %esi + pushl %edi + + pxor %mm0,%mm0 # zero acculumators + pxor %mm1,%mm1 + pxor %mm6,%mm6 + movl 8(%ebp),%esi # get pix1 + movl 12(%ebp),%edi # get pix2 + movl 16(%ebp),%edx # get lx + movl 20(%ebp),%ecx # get rowsleft + movl %edi,%ebx + addl %edx,%ebx + jmp pix_abs16x16_y2_mmx.nextrow_y2 +.align 32 + +pix_abs16x16_y2_mmx.nextrow_y2: + # First 8 bytes of the row + + movq (%edi),%mm4 # load first 8 bytes of pix2 row + movq (%ebx),%mm5 # load bytes 1-8 of pix2 row + + movq %mm4,%mm2 # copy mm4 on mm2 + movq %mm5,%mm3 # copy mm5 on mm3 + punpcklbw %mm6,%mm4 # first 4 bytes of [edi] on mm4 + punpcklbw %mm6,%mm5 # first 4 bytes of [ebx] on mm5 + paddusw %mm5,%mm4 # mm4 := first 4 bytes interpolated in words + psrlw $1,%mm4 + + punpckhbw %mm6,%mm2 # last 4 bytes of [edi] on mm2 + punpckhbw %mm6,%mm3 # last 4 bytes of [edi+1] on mm3 + paddusw %mm3,%mm2 # mm2 := last 4 bytes interpolated in words + psrlw $1,%mm2 + + packuswb %mm2,%mm4 # pack 8 bytes interpolated on mm4 + movq (%esi),%mm5 # load first 8 bytes of pix1 row + + movq %mm4,%mm3 # mm4 := abs(mm4-mm5) + psubusb %mm5,%mm4 + psubusb %mm3,%mm5 + por %mm5,%mm4 + + # Last 8 bytes of the row + + movq 8(%edi),%mm7 # load last 8 bytes of pix2 row + movq 8(%ebx),%mm5 # load bytes 10-17 of pix2 row + + movq %mm7,%mm2 # copy mm7 on mm2 + movq %mm5,%mm3 # copy mm5 on mm3 + punpcklbw %mm6,%mm7 # first 4 bytes of [edi+8] on mm7 + punpcklbw %mm6,%mm5 # first 4 bytes of [ebx+8] on mm5 + paddusw %mm5,%mm7 # mm1 := first 4 bytes interpolated in words + psrlw $1,%mm7 + + punpckhbw %mm6,%mm2 # last 4 bytes of [edi+8] on mm2 + punpckhbw %mm6,%mm3 # last 4 bytes of [ebx+8] on mm3 + paddusw %mm3,%mm2 # mm2 := last 4 bytes interpolated in words + psrlw $1,%mm2 + + packuswb %mm2,%mm7 # pack 8 bytes interpolated on mm1 + movq 8(%esi),%mm5 # load last 8 bytes of pix1 row + + movq %mm7,%mm3 # mm7 := abs(mm1-mm5) + psubusb %mm5,%mm7 + psubusb %mm3,%mm5 + por %mm5,%mm7 + + # Now mm4 and mm7 have 16 absdiffs to add + + movq %mm4,%mm3 # Make copies of these bytes + movq %mm7,%mm2 + + punpcklbw %mm6,%mm4 # Unpack to words and add + punpcklbw %mm6,%mm7 + paddusw %mm7,%mm4 + paddusw %mm4,%mm0 # Add to the acumulator (mm0) + + punpckhbw %mm6,%mm3 # Unpack to words and add + punpckhbw %mm6,%mm2 + paddusw %mm2,%mm3 + paddusw %mm3,%mm1 # Add to the acumulator (mm1) + + # Loop termination + + addl %edx,%esi # update pointers to next row + addl %edx,%edi + addl %edx,%ebx + subl $1,%ecx + testl %ecx,%ecx # check rowsleft + jnz pix_abs16x16_y2_mmx.nextrow_y2 + + paddusw %mm1,%mm0 + + movq %mm0,%mm1 # Copy mm0 to mm1 + psrlq $32,%mm1 + paddusw %mm1,%mm0 # Add + movq %mm0,%mm2 + psrlq $16,%mm2 + paddusw %mm2,%mm0 + movd %mm0,%eax # Store return value + andl $0xffff,%eax + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + + popl %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: + pushl %ebp # save stack pointer + movl %esp,%ebp # so that we can do this + + pushl %ebx # Saves registers (called saves convention in + pushl %ecx # x86 GCC it seems) + pushl %edx # + pushl %esi + pushl %edi + + pxor %mm0,%mm0 # zero acculumators + + movl 12(%ebp),%esi # get p1 + movl 8(%ebp),%edi # get p2 + movl 16(%ebp),%edx # get lx + movl 20(%ebp),%ecx # rowsleft := h + movl %esi,%ebx + addl %edx,%ebx + jmp pix_abs16x16_xy2_mmx.nextrowmm11 # snap to it +.align 32 +pix_abs16x16_xy2_mmx.nextrowmm11: + + ## + ## First 8 bytes of row + ## + + ## First 4 bytes of 8 + + movq (%esi),%mm4 # mm4 := first 4 bytes p1 + pxor %mm7,%mm7 + movq %mm4,%mm2 # mm2 records all 8 bytes + punpcklbw %mm7,%mm4 # First 4 bytes p1 in Words... + + movq (%ebx),%mm6 # mm6 := first 4 bytes p1+lx + movq %mm6,%mm3 # mm3 records all 8 bytes + punpcklbw %mm7,%mm6 + paddw %mm6,%mm4 + + + movq 1(%esi),%mm5 # mm5 := first 4 bytes p1+1 + punpcklbw %mm7,%mm5 # First 4 bytes p1 in Words... + paddw %mm5,%mm4 + movq 1(%ebx),%mm6 # mm6 := first 4 bytes p1+lx+1 + punpcklbw %mm7,%mm6 + paddw %mm6,%mm4 + + psrlw $2,%mm4 # mm4 := First 4 bytes interpolated in words + + movq (%edi),%mm5 # mm5:=first 4 bytes of p2 in words + movq %mm5,%mm1 + punpcklbw %mm7,%mm5 + + movq %mm4,%mm7 + pcmpgtw %mm5,%mm7 # mm7 := [i : W0..3,mm4>mm5] + + movq %mm4,%mm6 # mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] + psubw %mm5,%mm6 + pand %mm7,%mm6 + + paddw %mm6,%mm0 # Add to accumulator + + movq %mm5,%mm6 # mm6 := [i : W0..3,mm5>mm4] + pcmpgtw %mm4,%mm6 + psubw %mm4,%mm5 # mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] + pand %mm6,%mm5 + + paddw %mm5,%mm0 # Add to accumulator + + ## Second 4 bytes of 8 + + movq %mm2,%mm4 # mm4 := Second 4 bytes p1 in words + pxor %mm7,%mm7 + punpckhbw %mm7,%mm4 + movq %mm3,%mm6 # mm6 := Second 4 bytes p1+1 in words + punpckhbw %mm7,%mm6 + paddw %mm6,%mm4 + + movq 1(%esi),%mm5 # mm5 := first 4 bytes p1+1 + punpckhbw %mm7,%mm5 # First 4 bytes p1 in Words... + paddw %mm5,%mm4 + movq 1(%ebx),%mm6 # mm6 := first 4 bytes p1+lx+1 + punpckhbw %mm7,%mm6 + paddw %mm6,%mm4 + + psrlw $2,%mm4 # mm4 := First 4 bytes interpolated in words + + movq %mm1,%mm5 # mm5:= second 4 bytes of p2 in words + punpckhbw %mm7,%mm5 + + movq %mm4,%mm7 + pcmpgtw %mm5,%mm7 # mm7 := [i : W0..3,mm4>mm5] + + movq %mm4,%mm6 # mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] + psubw %mm5,%mm6 + pand %mm7,%mm6 + + paddw %mm6,%mm0 # Add to accumulator + + movq %mm5,%mm6 # mm6 := [i : W0..3,mm5>mm4] + pcmpgtw %mm4,%mm6 + psubw %mm4,%mm5 # mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] + pand %mm6,%mm5 + + paddw %mm5,%mm0 # Add to accumulator + + + ## + ## Second 8 bytes of row + ## + ## First 4 bytes of 8 + + movq 8(%esi),%mm4 # mm4 := first 4 bytes p1+8 + pxor %mm7,%mm7 + movq %mm4,%mm2 # mm2 records all 8 bytes + punpcklbw %mm7,%mm4 # First 4 bytes p1 in Words... + + movq 8(%ebx),%mm6 # mm6 := first 4 bytes p1+lx+8 + movq %mm6,%mm3 # mm3 records all 8 bytes + punpcklbw %mm7,%mm6 + paddw %mm6,%mm4 + + + movq 9(%esi),%mm5 # mm5 := first 4 bytes p1+9 + punpcklbw %mm7,%mm5 # First 4 bytes p1 in Words... + paddw %mm5,%mm4 + movq 9(%ebx),%mm6 # mm6 := first 4 bytes p1+lx+9 + punpcklbw %mm7,%mm6 + paddw %mm6,%mm4 + + psrlw $2,%mm4 # mm4 := First 4 bytes interpolated in words + + movq 8(%edi),%mm5 # mm5:=first 4 bytes of p2+8 in words + movq %mm5,%mm1 + punpcklbw %mm7,%mm5 + + movq %mm4,%mm7 + pcmpgtw %mm5,%mm7 # mm7 := [i : W0..3,mm4>mm5] + + movq %mm4,%mm6 # mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] + psubw %mm5,%mm6 + pand %mm7,%mm6 + + paddw %mm6,%mm0 # Add to accumulator + + movq %mm5,%mm6 # mm6 := [i : W0..3,mm5>mm4] + pcmpgtw %mm4,%mm6 + psubw %mm4,%mm5 # mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] + pand %mm6,%mm5 + + paddw %mm5,%mm0 # Add to accumulator + + ## Second 4 bytes of 8 + + movq %mm2,%mm4 # mm4 := Second 4 bytes p1 in words + pxor %mm7,%mm7 + punpckhbw %mm7,%mm4 + movq %mm3,%mm6 # mm6 := Second 4 bytes p1+1 in words + punpckhbw %mm7,%mm6 + paddw %mm6,%mm4 + + movq 9(%esi),%mm5 # mm5 := first 4 bytes p1+1 + punpckhbw %mm7,%mm5 # First 4 bytes p1 in Words... + paddw %mm5,%mm4 + movq 9(%ebx),%mm6 # mm6 := first 4 bytes p1+lx+1 + punpckhbw %mm7,%mm6 + paddw %mm6,%mm4 + + psrlw $2,%mm4 # mm4 := First 4 bytes interpolated in words + + movq %mm1,%mm5 # mm5:= second 4 bytes of p2 in words + punpckhbw %mm7,%mm5 + + movq %mm4,%mm7 + pcmpgtw %mm5,%mm7 # mm7 := [i : W0..3,mm4>mm5] + + movq %mm4,%mm6 # mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)] + psubw %mm5,%mm6 + pand %mm7,%mm6 + + paddw %mm6,%mm0 # Add to accumulator + + movq %mm5,%mm6 # mm6 := [i : W0..3,mm5>mm4] + pcmpgtw %mm4,%mm6 + psubw %mm4,%mm5 # mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)] + pand %mm6,%mm5 + + paddw %mm5,%mm0 # Add to accumulator + + + ## + ## Loop termination condition... and stepping + ## + + addl %edx,%esi # update pointer to next row + addl %edx,%edi # ditto + addl %edx,%ebx + + subl $1,%ecx + testl %ecx,%ecx # check rowsleft + jnz pix_abs16x16_xy2_mmx.nextrowmm11 + + ## Sum the Accumulators + movq %mm0,%mm4 + psrlq $32,%mm4 + paddw %mm4,%mm0 + movq %mm0,%mm6 + psrlq $16,%mm6 + paddw %mm6,%mm0 + movd %mm0,%eax # store return value + andl $0xffff,%eax + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + + popl %ebp # restore stack pointer + + emms # clear mmx registers + ret # we now return you to your regular programming + + + diff --git a/src/libffmpeg/libavcodec/utils.c b/src/libffmpeg/libavcodec/utils.c new file mode 100644 index 000000000..958f6d32d --- /dev/null +++ b/src/libffmpeg/libavcodec/utils.c @@ -0,0 +1,319 @@ +/* + * 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 +#include +#include +#include +#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) +{ + /* encoders */ +#ifdef CONFIG_ENCODERS + 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); +#endif /* CONFIG_ENCODERS */ + register_avcodec(&pcm_codec); + register_avcodec(&rawvideo_codec); + + /* decoders */ +#ifdef CONFIG_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); + register_avcodec(&mjpeg_decoder); +#ifdef CONFIG_MPGLIB + register_avcodec(&mp3_decoder); +#endif +#ifdef CONFIG_AC3 + register_avcodec(&ac3_decoder); +#endif +#endif /* CONFIG_DECODERS */ +} + +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, +}; diff --git a/src/libffmpeg/xine_decoder.c b/src/libffmpeg/xine_decoder.c new file mode 100644 index 000000000..8a6166a7c --- /dev/null +++ b/src/libffmpeg/xine_decoder.c @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: xine_decoder.c,v 1.1 2001/08/07 12:41:46 guenter Exp $ + * + * xine decoder plugin using ffmpeg + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "libavcodec/avcodec.h" + +/* this def is taken from xine_internal.h */ +typedef struct video_decoder_s video_decoder_t; +struct video_decoder_s { + int interface_version; + int (*can_handle) (video_decoder_t *this, int buf_type); + void (*init) (video_decoder_t *this, vo_instance_t *video_out); + void (*decode_data) (video_decoder_t *this, buf_element_t *buf); + void (*close) (video_decoder_t *this); + char* (*get_identifier) (void); + int priority; + metronom_t *metronom; +}; + +/* now this is ripped of wine's vfw.h */ +typedef struct { + long biSize; + long biWidth; + long biHeight; + short biPlanes; + short biBitCount; + long biCompression; + long biSizeImage; + long biXPelsPerMeter; + long biYPelsPerMeter; + long biClrUsed; + long biClrImportant; +} BITMAPINFOHEADER; +#ifndef mmioFOURCC +#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \ + ( (long)(unsigned char)(ch0) | ( (long)(unsigned char)(ch1) << 8 ) | \ + ( (long)(unsigned char)(ch2) << 16 ) | ( (long)(unsigned char)(ch3) << 24 ) ) +#endif + +typedef struct ff_decoder_s { + video_decoder_t video_decoder; + + vo_instance_t *video_out; + int video_step; + int decoder_ok; + + BITMAPINFOHEADER bih; + unsigned char buf[128*1024]; + int size; + + AVPicture av_picture; + AVCodecContext context; +} ff_decoder_t; + + +#define IMGFMT_YUY2 mmioFOURCC('Y','U','Y','2') +#define IMGFMT_YV12 mmioFOURCC('Y','V','1','2') + +static int ff_can_handle (video_decoder_t *this_gen, int buf_type) { + return ((buf_type & 0xFFFF0000) == BUF_VIDEO_AVI) ; +} + +static void ff_init (video_decoder_t *this_gen, vo_instance_t *video_out) { + + ff_decoder_t *this = (ff_decoder_t *) this_gen; + + this->video_out = video_out; + this->decoder_ok = 0; +} + +static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { + ff_decoder_t *this = (ff_decoder_t *) this_gen; + + /* + printf ("ffmpeg: processing packet type = %08x, buf : %d, buf->decoder_info[0]=%d\n", + buf->type, buf, buf->decoder_info[0]); + */ + + if (buf->decoder_info[0] == 0) { + + AVCodec *codec = NULL; + + /* init package containing bih */ + + memcpy ( &this->bih, buf->content, sizeof (BITMAPINFOHEADER)); + this->video_step = buf->decoder_info[1]; + + /* init codec */ + + /* + if (this->bih.biCompression == mmioFOURCC('D', 'I', 'V', 'X')) { + printf ("ffmpeg: mpeg4 (opendivx) format detected\n"); + + codec = avcodec_find_decoder (CODEC_ID_OPENDIVX); + } else { + printf ("ffmpeg: ms mpeg4 format detected\n"); + codec = avcodec_find_decoder (CODEC_ID_MSMPEG4); + } + */ + + switch (this->bih.biCompression) { + case mmioFOURCC('M', 'P', 'G', '4'): + case mmioFOURCC('m', 'p', 'g', '4'): + case mmioFOURCC('M', 'P', '4', '2'): + case mmioFOURCC('m', 'p', '4', '2'): + case mmioFOURCC('M', 'P', '4', '3'): + case mmioFOURCC('m', 'p', '4', '3'): + case mmioFOURCC('D', 'I', 'V', '3'): + case mmioFOURCC('d', 'i', 'v', '3'): + case mmioFOURCC('D', 'I', 'V', '4'): + case mmioFOURCC('d', 'i', 'v', '4'): + case mmioFOURCC('M', 'P', '4', '1'): + case mmioFOURCC('m', 'p', '4', '1'): + printf ("ffmpeg: ms mpeg4 format detected\n"); + codec = avcodec_find_decoder (CODEC_ID_MSMPEG4); + break; + case mmioFOURCC('D', 'I', 'V', 'X'): + case mmioFOURCC('d', 'i', 'v', 'x'): + case mmioFOURCC('D', 'i', 'v', 'x'): + case mmioFOURCC('D', 'i', 'v', 'X'): + printf ("ffmpeg: mpeg4 (opendivx) format detected\n"); + codec = avcodec_find_decoder (CODEC_ID_OPENDIVX); + break; + case mmioFOURCC('d', 'm', 'b', '1'): + printf ("ffmpeg: motion jpeg format detected\n"); + codec = avcodec_find_decoder (CODEC_ID_MJPEG); + break; + default: + printf ("ffmpeg: unknown video format 0x%08X\n", + this->bih.biCompression); + } + + if (!codec) { + printf ("ffmpeg: couldn't find decoder\n"); + return; + } + + memset(&this->context, 0, sizeof(this->context)); + this->context.width = this->bih.biWidth; + this->context.height = this->bih.biHeight; + + if (avcodec_open (&this->context, codec) < 0) { + printf ("ffmpeg: couldn't open decoder\n"); + return; + } + + this->decoder_ok = 1; + this->video_out->open (this->video_out); + + } else if (this->decoder_ok) { + + memcpy (&this->buf[this->size], buf->content, buf->size); + + this->size += buf->size; + + if (buf->decoder_info[0] == 2) { + + vo_frame_t *img; + int got_picture, len, y; + uint8_t *dy, *du, *dv, *sy, *su, *sv; + + /* decoder video frame */ + + /* this->bih.biSizeImage = this->size; */ + + len = avcodec_decode_video (&this->context, &this->av_picture, + &got_picture, this->buf, + this->size); + + img = this->video_out->get_frame (this->video_out, + /* this->av_picture.linesize[0], */ + this->bih.biWidth, + this->bih.biHeight, + 42, + IMGFMT_YV12, + this->video_step, + VO_BOTH_FIELDS); + + img->PTS = buf->PTS; + if (len<0) { + printf ("ffmpeg: error decompressing frame\n"); + img->bFrameBad = 1; + } else + img->bFrameBad = 0; + + dy = img->base[0]; + du = img->base[1]; + dv = img->base[2]; + sy = this->av_picture.data[0]; + su = this->av_picture.data[1]; + sv = this->av_picture.data[2]; + + for (y=0; ybih.biHeight; y++) { + + memcpy (dy, sy, this->bih.biWidth); + + dy += this->bih.biWidth; + + sy += this->av_picture.linesize[0]; + } + + for (y=0; y<(this->bih.biHeight/2); y++) { + + memcpy (du, su, this->bih.biWidth/2); + memcpy (dv, sv, this->bih.biWidth/2); + + du += this->bih.biWidth/2; + dv += this->bih.biWidth/2; + + su += this->av_picture.linesize[1]; + sv += this->av_picture.linesize[2]; + } + /* + memcpy (img->base[0], this->av_picture.data[0], + this->context.height * this->av_picture.linesize[0]); + memcpy (img->base[1], this->av_picture.data[1], + this->context.height * this->av_picture.linesize[1]/2); + memcpy (img->base[2], this->av_picture.data[2], + this->context.height * this->av_picture.linesize[2]/2); + */ + + if (img->copy) { + + int height = abs(this->bih.biHeight); + int stride = this->bih.biWidth; + uint8_t* src[3]; + + src[0] = img->base[0]; + src[2] = src[0] + height * this->bih.biWidth; + src[1] = src[2] + height * this->bih.biWidth / 4; + while ((height -= 16) >= 0) { + img->copy(img, src); + src[0] += 16 * stride; + src[1] += 4 * stride; + src[2] += 4 * stride; + } + } + + img->draw(img); + img->free(img); + + this->size = 0; + } + } +} + +static void ff_close (video_decoder_t *this_gen) { + + ff_decoder_t *this = (ff_decoder_t *) this_gen; + + avcodec_close (&this->context); + this->video_out->close(this->video_out); +} + +static char *ff_get_id(void) { + return "ffmpeg video decoder"; +} + + +video_decoder_t *init_video_decoder_plugin (int iface_version, config_values_t *cfg) { + + ff_decoder_t *this ; + + if (iface_version != 2) { + printf( "ffmpeg: plugin doesn't support plugin API version %d.\n" + "ffmpeg: this means there's a version mismatch between xine and this " + "ffmpeg: decoder plugin.\nInstalling current plugins should help.\n", + iface_version); + + return NULL; + } + + this = (ff_decoder_t *) malloc (sizeof (ff_decoder_t)); + + this->video_decoder.interface_version = 2; + this->video_decoder.can_handle = ff_can_handle; + this->video_decoder.init = ff_init; + this->video_decoder.decode_data = ff_decode_data; + this->video_decoder.close = ff_close; + this->video_decoder.get_identifier = ff_get_id; + this->video_decoder.priority = cfg->lookup_int (cfg, "ff_priority", 0); + + avcodec_init(); + avcodec_register_all(); + + return (video_decoder_t *) this; +} + + diff --git a/src/xine-engine/cpu_accel.c b/src/xine-engine/cpu_accel.c index 81adb7a12..d2254084e 100644 --- a/src/xine-engine/cpu_accel.c +++ b/src/xine-engine/cpu_accel.c @@ -111,3 +111,8 @@ uint32_t mm_accel (void) #endif #endif } + +uint32_t mm_support (void) +{ + return mm_accel(); +} diff --git a/src/xine-engine/cpu_accel.h b/src/xine-engine/cpu_accel.h index d563787eb..ca2713ff4 100644 --- a/src/xine-engine/cpu_accel.h +++ b/src/xine-engine/cpu_accel.h @@ -44,8 +44,14 @@ extern "C" { #define MM_ACCEL_X86_MMX 0x80000000 #define MM_ACCEL_X86_3DNOW 0x40000000 #define MM_ACCEL_X86_MMXEXT 0x20000000 +#define MM_MMX 0x80000000 +#define MM_3DNOW 0x40000000 +#define MM_MMXEXT 0x20000000 +#define MM_SSE 0x00000000 +#define MM_SSE2 0x00000000 uint32_t mm_accel (void) ; +uint32_t mm_support (void) ; #ifdef ARCH_X86 -- cgit v1.2.3