diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-03-12 00:40:52 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2002-03-12 00:40:52 +0000 |
commit | 0bf7e08a076a9d88acaebcf6bbed63e090ff6857 (patch) | |
tree | 17001793feff338449d34ef8e8ff89d8dcb0ebad /src | |
parent | 0e27a3976b6b5eaab4983b3e63a7009fe77451cf (diff) | |
download | xine-lib-0bf7e08a076a9d88acaebcf6bbed63e090ff6857.tar.gz xine-lib-0bf7e08a076a9d88acaebcf6bbed63e090ff6857.tar.bz2 |
updated ffmpeg to the latest ffmpeg-cvs, hopefully this will handle divx5 files
CVS patchset: 1558
CVS date: 2002/03/12 00:40:52
Diffstat (limited to 'src')
21 files changed, 3070 insertions, 843 deletions
diff --git a/src/libffmpeg/libavcodec/avcodec.h b/src/libffmpeg/libavcodec/avcodec.h index 864ebb3ba..3c27d99ea 100644 --- a/src/libffmpeg/libavcodec/avcodec.h +++ b/src/libffmpeg/libavcodec/avcodec.h @@ -9,6 +9,7 @@ enum CodecID { CODEC_ID_H263, CODEC_ID_RV10, CODEC_ID_MP2, + CODEC_ID_MP3LAME, CODEC_ID_AC3, CODEC_ID_MJPEG, CODEC_ID_MPEG4, @@ -17,15 +18,6 @@ enum CodecID { CODEC_ID_H263P, CODEC_ID_H263I, - /* various pcm "codecs" */ - CODEC_ID_PCM_S16LE, - CODEC_ID_PCM_S16BE, - CODEC_ID_PCM_U16LE, - CODEC_ID_PCM_U16BE, - CODEC_ID_PCM_S8, - CODEC_ID_PCM_U8, - CODEC_ID_PCM_MULAW, - CODEC_ID_PCM_ALAW, }; enum CodecType { @@ -115,6 +107,20 @@ typedef struct AVCodecContext { /* with a start code on some codecs like H.263 */ /* This doesn't take account of any particular */ /* headers inside the transmited RTP payload */ + + + /* The RTP callcack: This function is called */ + /* every time the encoder as a packet to send */ + /* Depends on the encoder if the data starts */ + /* with a Start Code (it should) H.263 does */ + void (*rtp_callback)(void *data, int size, int packet_number); + + /* These are for PSNR calculation, if you set get_psnr to 1 */ + /* after encoding you will have the PSNR on psnr_y/cb/cr */ + int get_psnr; + float psnr_y; + float psnr_cb; + float psnr_cr; /* the following fields are ignored */ void *opaque; /* can be used to carry app specific stuff */ @@ -144,16 +150,6 @@ typedef struct AVPicture { 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 mpeg4_encoder; -extern AVCodec msmpeg4_encoder; - extern AVCodec h263_decoder; extern AVCodec mpeg4_decoder; extern AVCodec msmpeg4_decoder; @@ -161,25 +157,6 @@ extern AVCodec mpeg_decoder; extern AVCodec h263i_decoder; extern AVCodec rv10_decoder; extern AVCodec mjpeg_decoder; -#ifdef FF_AUDIO_CODECS -extern AVCodec mp3_decoder; - -/* pcm codecs */ -#define PCM_CODEC(id, name) \ -extern AVCodec name ## _decoder; \ -extern AVCodec name ## _encoder; - -PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le); -PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be); -PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le); -PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be); -PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8); -PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8); -PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw); -PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw); - -#undef PCM_CODEC -#endif /* dummy raw video codec */ extern AVCodec rawvideo_codec; diff --git a/src/libffmpeg/libavcodec/common.c b/src/libffmpeg/libavcodec/common.c index 8f0fdc1bb..77f94689e 100644 --- a/src/libffmpeg/libavcodec/common.c +++ b/src/libffmpeg/libavcodec/common.c @@ -15,6 +15,8 @@ * 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. + * + * alternative bitstream reader & writer by Michael Niedermayer <michaelni@gmx.at> */ #include "common.h" #include <math.h> @@ -25,155 +27,96 @@ void init_put_bits(PutBitContext *s, 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; + if(write_data!=NULL) + { + fprintf(stderr, "write Data callback is not supported\n"); } -} - -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; +#ifdef ALT_BITSTREAM_WRITER + s->index=0; + ((uint32_t*)(s->buf))[0]=0; +// memset(buffer, 0, buffer_size); +#else + s->buf_ptr = s->buf; + s->bit_left=32; + s->bit_buf=0; #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 = be2me_32(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 */ INT64 get_bit_count(PutBitContext *s) { - return (s->buf_ptr - s->buf + s->data_out_size) * 8 + (INT64)s->bit_cnt; +#ifdef ALT_BITSTREAM_WRITER + return s->data_out_size * 8 + s->index; +#else + return (s->buf_ptr - s->buf + s->data_out_size) * 8 + 32 - (INT64)s->bit_left; +#endif } void align_put_bits(PutBitContext *s) { - put_bits(s,(8 - s->bit_cnt) & 7,0); +#ifdef ALT_BITSTREAM_WRITER + put_bits(s,( - s->index) & 7,0); +#else + put_bits(s,s->bit_left & 7,0); +#endif } /* pad the end of the output stream with zeros */ void flush_put_bits(PutBitContext *s) { - while (s->bit_cnt > 0) { +#ifdef ALT_BITSTREAM_WRITER + align_put_bits(s); +#else + s->bit_buf<<= s->bit_left; + while (s->bit_left < 32) { /* XXX: should test end of buffer */ *s->buf_ptr++=s->bit_buf >> 24; s->bit_buf<<=8; - s->bit_cnt-=8; + s->bit_left+=8; } - flush_buffer(s); - s->bit_cnt=0; + s->bit_left=32; 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; +#endif } /* pad the end of the output stream with zeros */ +#ifndef ALT_BITSTREAM_WRITER void jflush_put_bits(PutBitContext *s) { unsigned int b; + s->bit_buf<<= s->bit_left; + s->bit_buf |= ~1U >> (32 - s->bit_left); /* set all the unused bits to one */ - while (s->bit_cnt > 0) { + while (s->bit_left < 32) { b = s->bit_buf >> 24; *s->buf_ptr++ = b; if (b == 0xff) *s->buf_ptr++ = 0; s->bit_buf<<=8; - s->bit_cnt-=8; + s->bit_left+=8; } - flush_buffer(s); - s->bit_cnt=0; + s->bit_left=32; s->bit_buf=0; } +#else +void jflush_put_bits(PutBitContext *s) +{ + int num= ( - s->index) & 7; + jput_bits(s, num,0xFF>>(8-num)); +} +#endif /* bit input functions */ void init_get_bits(GetBitContext *s, UINT8 *buffer, int buffer_size) { +#ifdef ALT_BITSTREAM_READER + s->index=0; + s->buffer= buffer; +#else s->buf = buffer; s->buf_ptr = buffer; s->buf_end = buffer + buffer_size; @@ -184,8 +127,10 @@ void init_get_bits(GetBitContext *s, s->bit_buf |= (*s->buf_ptr++ << (24 - s->bit_cnt)); s->bit_cnt += 8; } +#endif } +#ifndef ALT_BITSTREAM_READER /* n must be >= 1 and <= 32 */ /* also true: n > s->bit_cnt */ unsigned int get_bits_long(GetBitContext *s, int n) @@ -241,15 +186,22 @@ unsigned int get_bits_long(GetBitContext *s, int n) s->bit_cnt = bit_cnt; return val; } +#endif void align_get_bits(GetBitContext *s) { +#ifdef ALT_BITSTREAM_READER + s->index= (s->index + 7) & (~7); +#else int n; n = s->bit_cnt & 7; if (n > 0) { get_bits(s, n); } +#endif } + +#ifndef ALT_BITSTREAM_READER /* This function is identical to get_bits_long(), the */ /* only diference is that it doesn't touch the buffer */ /* it is usefull to see the buffer. */ @@ -296,6 +248,7 @@ unsigned int show_bits_long(GetBitContext *s, int n) return val; } +#endif /* VLC decoding */ @@ -489,41 +442,3 @@ void free_vlc(VLC *vlc) 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 index aa8f9b54a..fd4bba129 100644 --- a/src/libffmpeg/libavcodec/common.h +++ b/src/libffmpeg/libavcodec/common.h @@ -3,14 +3,17 @@ #define FFMPEG_VERSION_INT 0x000406 #define FFMPEG_VERSION "0.4.6" -/* CVS version as 26-12-2001 */ -#undef DEBUG - -#if defined(WIN32) && !defined(__MINGW32__) +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) #define CONFIG_WIN32 #endif +//#define ALT_BITSTREAM_WRITER +//#define ALIGNED_BITSTREAM_WRITER +//#define ALT_BITSTREAM_READER +//#define ALIGNED_BITSTREAM +#define FAST_GET_FIRST_VLC + #ifdef HAVE_AV_CONFIG_H /* only include the following when compiling package */ #include "../config.h" @@ -127,6 +130,7 @@ typedef signed long long INT64; #endif /* !CONFIG_WIN32 */ + /* debug stuff */ #ifdef HAVE_AV_CONFIG_H @@ -142,19 +146,11 @@ inline void dprintf(const char* fmt,...) {} #else -#ifdef __GNUC__ #ifdef DEBUG #define dprintf(fmt,args...) printf(fmt, ## args) #else #define dprintf(fmt,args...) #endif -#else -#ifdef DEBUG -#define dprintf(fmt,...) printf(fmt, __VA_ARGS__) -#else -#define dprintf(fmt,...) -#endif -#endif #endif /* !CONFIG_WIN32 */ @@ -167,33 +163,40 @@ struct PutBitContext; typedef void (*WriteDataFunc)(void *, UINT8 *, int); typedef struct PutBitContext { +#ifdef ALT_BITSTREAM_WRITER + UINT8 *buf, *buf_end; + int index; +#else UINT32 bit_buf; - int bit_cnt; + int bit_left; UINT8 *buf, *buf_ptr, *buf_end; +#endif INT64 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); + INT64 get_bit_count(PutBitContext *s); /* XXX: change function name */ 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 { +#ifdef ALT_BITSTREAM_READER + int index; + UINT8 *buffer; +#else UINT32 bit_buf; int bit_cnt; UINT8 *buf, *buf_ptr, *buf_end; +#endif } GetBitContext; typedef struct VLC { @@ -203,13 +206,270 @@ typedef struct VLC { int table_size, table_allocated; } VLC; +/* used to avoid missaligned exceptions on some archs (alpha, ...) */ +#ifdef ARCH_X86 +#define unaligned32(a) (*(UINT32*)(a)) +#else +#ifdef __GNUC__ +static inline uint32_t unaligned32(const void *v) { + struct Unaligned { + uint32_t i; + } __attribute__((packed)); + + return ((const struct Unaligned *) v)->i; +} +#elif defined(__DECC) +static inline uint32_t unaligned32(const void *v) { + return *(const __unaligned uint32_t *) v; +} +#else +static inline uint32_t unaligned32(const void *v) { + return *(const uint32_t *) v; +} +#endif +#endif //!ARCH_X86 + +#ifndef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + +#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_left = s->bit_left; + + // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); + /* XXX: optimize */ + if (n < bit_left) { + bit_buf = (bit_buf<<n) | value; + bit_left-=n; + } else { + bit_buf<<=bit_left; + bit_buf |= value >> (n - bit_left); + *(UINT32 *)s->buf_ptr = be2me_32(bit_buf); + //printf("bitbuf = %08x\n", bit_buf); + s->buf_ptr+=4; + bit_left+=32 - n; + bit_buf = value; + } + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} +#endif + + +#ifdef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ +#ifdef ALIGNED_BITSTREAM_WRITER +#ifdef ARCH_X86 + asm volatile( + "movl %0, %%ecx \n\t" + "xorl %%eax, %%eax \n\t" + "shrdl %%cl, %1, %%eax \n\t" + "shrl %%cl, %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "andl $0xFFFFFFFC, %%ecx \n\t" + "bswapl %1 \n\t" + "orl %1, (%2, %%ecx) \n\t" + "bswapl %%eax \n\t" + "addl %3, %0 \n\t" + "movl %%eax, 4(%2, %%ecx) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) + : "%eax", "%ecx" + ); +#else + int index= s->index; + uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); + + value<<= 32-n; + + ptr[0] |= be2me_32(value>>(index&31)); + ptr[1] = be2me_32(value<<(32-(index&31))); +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +#endif +#else //ALIGNED_BITSTREAM_WRITER +#ifdef ARCH_X86 + asm volatile( + "movl $7, %%ecx \n\t" + "andl %0, %%ecx \n\t" + "addl %3, %%ecx \n\t" + "negl %%ecx \n\t" + "shll %%cl, %1 \n\t" + "bswapl %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "orl %1, (%%ecx, %2) \n\t" + "addl %3, %0 \n\t" + "movl $0, 4(%%ecx, %2) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) + : "%ecx" + ); +#else + int index= s->index; + uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); + + ptr[0] |= be2me_32(value<<(32-n-(index&7) )); + ptr[1] = 0; +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +#endif +#endif //!ALIGNED_BITSTREAM_WRITER +} +#endif + +#ifndef ALT_BITSTREAM_WRITER +/* for jpeg : escape 0xff with 0x00 after it */ +static inline void jput_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf, b; + int bit_left, i; + + assert(n == 32 || value < (1U << n)); + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + //printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); + /* XXX: optimize */ + if (n < bit_left) { + bit_buf = (bit_buf<<n) | value; + bit_left-=n; + } else { + bit_buf<<=bit_left; + bit_buf |= value >> (n - bit_left); + /* 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; + } + + bit_left+= 32 - n; + bit_buf = value; + } + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} +#endif + + +#ifdef ALT_BITSTREAM_WRITER +static inline void jput_bits(PutBitContext *s, int n, int value) +{ + int index= s->index; + uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); + int v= ptr[0]; +//if(n>24) printf("%d %d\n", n, value); + + v |= be2me_32(value<<(32-n-(index&7) )); + if(((v+0x01010101)^0xFFFFFFFF)&v&0x80808080) + { + /* handle idiotic (m)jpeg escapes */ + uint8_t *bPtr= (uint8_t*)ptr; + int numChecked= ((index+n)>>3) - (index>>3); + + v= be2me_32(v); + + *(bPtr++)= v>>24; + if((v&0xFF000000)==0xFF000000 && numChecked>0){ + *(bPtr++)= 0x00; + index+=8; + } + *(bPtr++)= (v>>16)&0xFF; + if((v&0x00FF0000)==0x00FF0000 && numChecked>1){ + *(bPtr++)= 0x00; + index+=8; + } + *(bPtr++)= (v>>8)&0xFF; + if((v&0x0000FF00)==0x0000FF00 && numChecked>2){ + *(bPtr++)= 0x00; + index+=8; + } + *(bPtr++)= v&0xFF; + if((v&0x000000FF)==0x000000FF && numChecked>3){ + *(bPtr++)= 0x00; + index+=8; + } + *((uint32_t*)bPtr)= 0; + } + else + { + ptr[0] = v; + ptr[1] = 0; + } + + index+= n; + s->index= index; + } +#endif + + +static inline uint8_t* pbBufPtr(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + return s->buf + (s->index>>3); +#else + return s->buf_ptr; +#endif +} + void init_get_bits(GetBitContext *s, UINT8 *buffer, int buffer_size); +#ifndef ALT_BITSTREAM_READER unsigned int get_bits_long(GetBitContext *s, int n); unsigned int show_bits_long(GetBitContext *s, int n); +#endif static inline unsigned int get_bits(GetBitContext *s, int n){ +#ifdef ALT_BITSTREAM_READER +#ifdef ALIGNED_BITSTREAM + int index= s->index; + uint32_t result1= be2me_32( ((uint32_t *)s->buffer)[index>>5] ); + uint32_t result2= be2me_32( ((uint32_t *)s->buffer)[(index>>5) + 1] ); +#ifdef ARCH_X86 + asm ("shldl %%cl, %2, %0\n\t" + : "=r" (result1) + : "0" (result1), "r" (result2), "c" (index)); +#else + result1<<= (index&0x1F); + result2= (result2>>1) >> (31-(index&0x1F)); + result1|= result2; +#endif + result1>>= 32 - n; + index+= n; + s->index= index; + + return result1; +#else //ALIGNED_BITSTREAM + int index= s->index; + uint32_t result= be2me_32( unaligned32( ((uint8_t *)s->buffer)+(index>>3) ) ); + + result<<= (index&0x07); + result>>= 32 - n; + index+= n; + s->index= index; + + return result; +#endif //!ALIGNED_BITSTREAM +#else //ALT_BITSTREAM_READER if(s->bit_cnt>=n){ /* most common case here */ unsigned int val = s->bit_buf >> (32 - n); @@ -221,9 +481,20 @@ static inline unsigned int get_bits(GetBitContext *s, int n){ return val; } return get_bits_long(s,n); +#endif //!ALT_BITSTREAM_READER } static inline unsigned int get_bits1(GetBitContext *s){ +#ifdef ALT_BITSTREAM_READER + int index= s->index; + uint8_t result= s->buffer[ index>>3 ]; + result<<= (index&0x07); + result>>= 8 - 1; + index++; + s->index= index; + + return result; +#else if(s->bit_cnt>0){ /* most common case here */ unsigned int val = s->bit_buf >> 31; @@ -235,6 +506,7 @@ static inline unsigned int get_bits1(GetBitContext *s){ return val; } return get_bits_long(s,1); +#endif } /* This function is identical to get_bits(), the only */ @@ -242,15 +514,46 @@ static inline unsigned int get_bits1(GetBitContext *s){ /* it is usefull to see the buffer. */ static inline unsigned int show_bits(GetBitContext *s, int n) { +#ifdef ALT_BITSTREAM_READER +#ifdef ALIGNED_BITSTREAM + int index= s->index; + uint32_t result1= be2me_32( ((uint32_t *)s->buffer)[index>>5] ); + uint32_t result2= be2me_32( ((uint32_t *)s->buffer)[(index>>5) + 1] ); +#ifdef ARCH_X86 + asm ("shldl %%cl, %2, %0\n\t" + : "=r" (result1) + : "0" (result1), "r" (result2), "c" (index)); +#else + result1<<= (index&0x1F); + result2= (result2>>1) >> (31-(index&0x1F)); + result1|= result2; +#endif + result1>>= 32 - n; + + return result1; +#else //ALIGNED_BITSTREAM + int index= s->index; + uint32_t result= be2me_32( unaligned32( ((uint8_t *)s->buffer)+(index>>3) ) ); + + result<<= (index&0x07); + result>>= 32 - n; + + return result; +#endif //!ALIGNED_BITSTREAM +#else //ALT_BITSTREAM_READER if(s->bit_cnt>=n) { /* most common case here */ unsigned int val = s->bit_buf >> (32 - n); return val; } return show_bits_long(s,n); +#endif //!ALT_BITSTREAM_READER } static inline void skip_bits(GetBitContext *s, int n){ +#ifdef ALT_BITSTREAM_READER + s->index+= n; +#else if(s->bit_cnt>=n){ /* most common case here */ s->bit_buf <<= n; @@ -261,9 +564,13 @@ static inline void skip_bits(GetBitContext *s, int n){ } else { get_bits_long(s,n); } +#endif } static inline void skip_bits1(GetBitContext *s){ +#ifdef ALT_BITSTREAM_READER + s->index++; +#else if(s->bit_cnt>0){ /* most common case here */ s->bit_buf <<= 1; @@ -274,11 +581,16 @@ static inline void skip_bits1(GetBitContext *s){ } else { get_bits_long(s,1); } +#endif } static inline int get_bits_count(GetBitContext *s) { +#ifdef ALT_BITSTREAM_READER + return s->index; +#else return (s->buf_ptr - s->buf) * 8 - s->bit_cnt; +#endif } void align_get_bits(GetBitContext *s); @@ -286,7 +598,36 @@ 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); + +#ifdef ALT_BITSTREAM_READER +#ifdef ALIGNED_BITSTREAM +#ifdef ARCH_X86 +#define SHOW_BITS(s, val, n) \ + val= be2me_32( ((uint32_t *)(s)->buffer)[bit_cnt>>5] );\ + {uint32_t result2= be2me_32( ((uint32_t *)(s)->buffer)[(bit_cnt>>5) + 1] );\ + asm ("shldl %%cl, %2, %0\n\t"\ + : "=r" (val)\ + : "0" (val), "r" (result2), "c" (bit_cnt));\ + ((uint32_t)val)>>= 32 - n;} +#else //ARCH_X86 +#define SHOW_BITS(s, val, n) \ + val= be2me_32( ((uint32_t *)(s)->buffer)[bit_cnt>>5] );\ + {uint32_t result2= be2me_32( ((uint32_t *)(s)->buffer)[(bit_cnt>>5) + 1] );\ + val<<= (bit_cnt&0x1F);\ + result2= (result2>>1) >> (31-(bit_cnt&0x1F));\ + val|= result2;\ + ((uint32_t)val)>>= 32 - n;} +#endif //!ARCH_X86 +#else //ALIGNED_BITSTREAM +#define SHOW_BITS(s, val, n) \ + val= be2me_32( unaligned32( ((uint8_t *)(s)->buffer)+(bit_cnt>>3) ) );\ + val<<= (bit_cnt&0x07);\ + ((uint32_t)val)>>= 32 - n; +#endif // !ALIGNED_BITSTREAM +#define FLUSH_BITS(n) bit_cnt+=n; +#define SAVE_BITS(s) bit_cnt= (s)->index; +#define RESTORE_BITS(s) (s)->index= bit_cnt; +#else /* macro to go faster */ /* n must be <= 24 */ @@ -328,6 +669,69 @@ int get_vlc(GetBitContext *s, VLC *vlc); (s)->bit_buf = bit_buf;\ (s)->bit_cnt = bit_cnt;\ } +#endif // !ALT_BITSTREAM_READER + +static inline int get_vlc(GetBitContext *s, VLC *vlc) +{ + int code, n, nb_bits, index; + INT16 *table_codes; + INT8 *table_bits; + int bit_cnt; +#ifndef ALT_BITSTREAM_READER + UINT32 bit_buf; + UINT8 *buf_ptr; +#endif + + SAVE_BITS(s); + nb_bits = vlc->bits; + table_codes = vlc->table_codes; + table_bits = vlc->table_bits; + +#ifdef FAST_GET_FIRST_VLC + SHOW_BITS(s, index, nb_bits); + code = table_codes[index]; + n = table_bits[index]; + if (n > 0) { + /* most common case (90%)*/ + FLUSH_BITS(n); + RESTORE_BITS(s); + return code; + } else if (n == 0) { + return -1; + } else { + FLUSH_BITS(nb_bits); + nb_bits = -n; + table_codes = vlc->table_codes + code; + table_bits = vlc->table_bits + code; + } +#endif + 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; +} + /* define it to include statistics code (useful only for optimizing codec efficiency */ diff --git a/src/libffmpeg/libavcodec/dsputil.c b/src/libffmpeg/libavcodec/dsputil.c index f699b2ef6..0e698f35c 100644 --- a/src/libffmpeg/libavcodec/dsputil.c +++ b/src/libffmpeg/libavcodec/dsputil.c @@ -15,9 +15,12 @@ * 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. + * + * gmc & q-pel support by Michael Niedermayer <michaelni@gmx.at> */ #include <stdlib.h> #include <stdio.h> +#include <math.h> #include "avcodec.h" #include "dsputil.h" #include "simple_idct.h" @@ -26,6 +29,7 @@ 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); +void (*gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); op_pixels_abs_func pix_abs16x16; op_pixels_abs_func pix_abs16x16_x2; @@ -49,6 +53,12 @@ UINT8 zigzag_direct[64] = { 53, 60, 61, 54, 47, 55, 62, 63 }; +/* not permutated inverse zigzag_direct + 1 for MMX quantizer */ +UINT16 __align8 inv_zigzag_direct16[64]; + +/* not permutated zigzag_direct for MMX quantizer */ +UINT8 zigzag_direct_noperm[64]; + UINT8 ff_alternate_horizontal_scan[64] = { 0, 1, 2, 3, 8, 9, 16, 17, 10, 11, 4, 5, 6, 7, 15, 14, @@ -71,6 +81,72 @@ UINT8 ff_alternate_vertical_scan[64] = { 38, 46, 54, 62, 39, 47, 55, 63, }; +/* Input permutation for the simple_idct_mmx */ +static UINT8 simple_mmx_permutation[64]={ + 0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D, + 0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D, + 0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D, + 0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F, + 0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F, + 0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D, + 0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F, + 0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F, +}; + +/* a*inverse[b]>>32 == a/b for all 0<=a<=65536 && 2<=b<=255 */ +UINT32 inverse[256]={ + 0, 4294967295U,2147483648U,1431655766, 1073741824, 858993460, 715827883, 613566757, + 536870912, 477218589, 429496730, 390451573, 357913942, 330382100, 306783379, 286331154, + 268435456, 252645136, 238609295, 226050911, 214748365, 204522253, 195225787, 186737709, + 178956971, 171798692, 165191050, 159072863, 153391690, 148102321, 143165577, 138547333, + 134217728, 130150525, 126322568, 122713352, 119304648, 116080198, 113025456, 110127367, + 107374183, 104755300, 102261127, 99882961, 97612894, 95443718, 93368855, 91382283, + 89478486, 87652394, 85899346, 84215046, 82595525, 81037119, 79536432, 78090315, + 76695845, 75350304, 74051161, 72796056, 71582789, 70409300, 69273667, 68174085, + 67108864, 66076420, 65075263, 64103990, 63161284, 62245903, 61356676, 60492498, + 59652324, 58835169, 58040099, 57266231, 56512728, 55778797, 55063684, 54366675, + 53687092, 53024288, 52377650, 51746594, 51130564, 50529028, 49941481, 49367441, + 48806447, 48258060, 47721859, 47197443, 46684428, 46182445, 45691142, 45210183, + 44739243, 44278014, 43826197, 43383509, 42949673, 42524429, 42107523, 41698712, + 41297763, 40904451, 40518560, 40139882, 39768216, 39403370, 39045158, 38693400, + 38347923, 38008561, 37675152, 37347542, 37025581, 36709123, 36398028, 36092163, + 35791395, 35495598, 35204650, 34918434, 34636834, 34359739, 34087043, 33818641, + 33554432, 33294321, 33038210, 32786010, 32537632, 32292988, 32051995, 31814573, + 31580642, 31350127, 31122952, 30899046, 30678338, 30460761, 30246249, 30034737, + 29826162, 29620465, 29417585, 29217465, 29020050, 28825284, 28633116, 28443493, + 28256364, 28071682, 27889399, 27709467, 27531842, 27356480, 27183338, 27012373, + 26843546, 26676816, 26512144, 26349493, 26188825, 26030105, 25873297, 25718368, + 25565282, 25414008, 25264514, 25116768, 24970741, 24826401, 24683721, 24542671, + 24403224, 24265352, 24129030, 23994231, 23860930, 23729102, 23598722, 23469767, + 23342214, 23216040, 23091223, 22967740, 22845571, 22724695, 22605092, 22486740, + 22369622, 22253717, 22139007, 22025474, 21913099, 21801865, 21691755, 21582751, + 21474837, 21367997, 21262215, 21157475, 21053762, 20951060, 20849356, 20748635, + 20648882, 20550083, 20452226, 20355296, 20259280, 20164166, 20069941, 19976593, + 19884108, 19792477, 19701685, 19611723, 19522579, 19434242, 19346700, 19259944, + 19173962, 19088744, 19004281, 18920561, 18837576, 18755316, 18673771, 18592933, + 18512791, 18433337, 18354562, 18276457, 18199014, 18122225, 18046082, 17970575, + 17895698, 17821442, 17747799, 17674763, 17602325, 17530479, 17459217, 17388532, + 17318417, 17248865, 17179870, 17111424, 17043522, 16976156, 16909321, 16843010, +}; + +/* used to skip zeros at the end */ +UINT8 zigzag_end[64]; + +UINT8 permutation[64]; +//UINT8 invPermutation[64]; + +static void build_zigzag_end() +{ + int lastIndex; + int lastIndexAfterPerm=0; + for(lastIndex=0; lastIndex<64; lastIndex++) + { + if(zigzag_direct[lastIndex] > lastIndexAfterPerm) + lastIndexAfterPerm= zigzag_direct[lastIndex]; + zigzag_end[lastIndex]= lastIndexAfterPerm + 1; + } +} + void get_pixels_c(DCTELEM *block, const UINT8 *pixels, int line_size) { DCTELEM *p; @@ -271,6 +347,282 @@ PIXOP(UINT8, avg_no_rnd, op_avg, line_size) #define avg2(a,b) ((a+b+1)>>1) #define avg4(a,b,c,d) ((a+b+c+d+2)>>2) +static void gmc1_c(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder) +{ + const int A=(16-x16)*(16-y16); + const int B=( x16)*(16-y16); + const int C=(16-x16)*( y16); + const int D=( x16)*( y16); + int i; + rounder= 128 - rounder; + + for(i=0; i<h; i++) + { + dst[0]= (A*src[0] + B*src[1] + C*src[srcStride+0] + D*src[srcStride+1] + rounder)>>8; + dst[1]= (A*src[1] + B*src[2] + C*src[srcStride+1] + D*src[srcStride+2] + rounder)>>8; + dst[2]= (A*src[2] + B*src[3] + C*src[srcStride+2] + D*src[srcStride+3] + rounder)>>8; + dst[3]= (A*src[3] + B*src[4] + C*src[srcStride+3] + D*src[srcStride+4] + rounder)>>8; + dst[4]= (A*src[4] + B*src[5] + C*src[srcStride+4] + D*src[srcStride+5] + rounder)>>8; + dst[5]= (A*src[5] + B*src[6] + C*src[srcStride+5] + D*src[srcStride+6] + rounder)>>8; + dst[6]= (A*src[6] + B*src[7] + C*src[srcStride+6] + D*src[srcStride+7] + rounder)>>8; + dst[7]= (A*src[7] + B*src[8] + C*src[srcStride+7] + D*src[srcStride+8] + rounder)>>8; + dst+= srcStride; + src+= srcStride; + } +} + +static void qpel_h_lowpass(UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int h, int r) +{ + UINT8 *cm = cropTbl + MAX_NEG_CROP; + int i; + for(i=0; i<h; i++) + { + dst[0]= cm[(((src[0]+src[1])*160 - (src[0]+src[2])*48 + (src[1]+src[3])*24 - (src[2]+src[4])*8 + r)>>8)]; + dst[1]= cm[(((src[1]+src[2])*160 - (src[0]+src[3])*48 + (src[0]+src[4])*24 - (src[1]+src[5])*8 + r)>>8)]; + dst[2]= cm[(((src[2]+src[3])*160 - (src[1]+src[4])*48 + (src[0]+src[5])*24 - (src[0]+src[6])*8 + r)>>8)]; + dst[3]= cm[(((src[3]+src[4])*160 - (src[2]+src[5])*48 + (src[1]+src[6])*24 - (src[0]+src[7])*8 + r)>>8)]; + dst[4]= cm[(((src[4]+src[5])*160 - (src[3]+src[6])*48 + (src[2]+src[7])*24 - (src[1]+src[8])*8 + r)>>8)]; + dst[5]= cm[(((src[5]+src[6])*160 - (src[4]+src[7])*48 + (src[3]+src[8])*24 - (src[2]+src[8])*8 + r)>>8)]; + dst[6]= cm[(((src[6]+src[7])*160 - (src[5]+src[8])*48 + (src[4]+src[8])*24 - (src[3]+src[7])*8 + r)>>8)]; + dst[7]= cm[(((src[7]+src[8])*160 - (src[6]+src[8])*48 + (src[5]+src[7])*24 - (src[4]+src[6])*8 + r)>>8)]; + dst+=dstStride; + src+=srcStride; + } +} + +static void qpel_v_lowpass(UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int w, int r) +{ + UINT8 *cm = cropTbl + MAX_NEG_CROP; + int i; + for(i=0; i<w; i++) + { + const int src0= src[0*srcStride]; + const int src1= src[1*srcStride]; + const int src2= src[2*srcStride]; + const int src3= src[3*srcStride]; + const int src4= src[4*srcStride]; + const int src5= src[5*srcStride]; + const int src6= src[6*srcStride]; + const int src7= src[7*srcStride]; + const int src8= src[8*srcStride]; + dst[0*dstStride]= cm[(((src0+src1)*160 - (src0+src2)*48 + (src1+src3)*24 - (src2+src4)*8 + r)>>8)]; + dst[1*dstStride]= cm[(((src1+src2)*160 - (src0+src3)*48 + (src0+src4)*24 - (src1+src5)*8 + r)>>8)]; + dst[2*dstStride]= cm[(((src2+src3)*160 - (src1+src4)*48 + (src0+src5)*24 - (src0+src6)*8 + r)>>8)]; + dst[3*dstStride]= cm[(((src3+src4)*160 - (src2+src5)*48 + (src1+src6)*24 - (src0+src7)*8 + r)>>8)]; + dst[4*dstStride]= cm[(((src4+src5)*160 - (src3+src6)*48 + (src2+src7)*24 - (src1+src8)*8 + r)>>8)]; + dst[5*dstStride]= cm[(((src5+src6)*160 - (src4+src7)*48 + (src3+src8)*24 - (src2+src8)*8 + r)>>8)]; + dst[6*dstStride]= cm[(((src6+src7)*160 - (src5+src8)*48 + (src4+src8)*24 - (src3+src7)*8 + r)>>8)]; + dst[7*dstStride]= cm[(((src7+src8)*160 - (src6+src8)*48 + (src5+src7)*24 - (src4+src6)*8 + r)>>8)]; + dst++; + src++; + } +} + +static inline void put_block(UINT8 *dst, UINT8 *src, int dstStride, int srcStride) +{ + int i; + for(i=0; i<8; i++) + { + dst[0]= src[0]; + dst[1]= src[1]; + dst[2]= src[2]; + dst[3]= src[3]; + dst[4]= src[4]; + dst[5]= src[5]; + dst[6]= src[6]; + dst[7]= src[7]; + dst+=dstStride; + src+=srcStride; + } +} + +static inline void avg2_block(UINT8 *dst, UINT8 *src1, UINT8 *src2, int dstStride, int srcStride, int r) +{ + int i; + for(i=0; i<8; i++) + { + dst[0]= (src1[0] + src2[0] + r)>>1; + dst[1]= (src1[1] + src2[1] + r)>>1; + dst[2]= (src1[2] + src2[2] + r)>>1; + dst[3]= (src1[3] + src2[3] + r)>>1; + dst[4]= (src1[4] + src2[4] + r)>>1; + dst[5]= (src1[5] + src2[5] + r)>>1; + dst[6]= (src1[6] + src2[6] + r)>>1; + dst[7]= (src1[7] + src2[7] + r)>>1; + dst+=dstStride; + src1+=srcStride; + src2+=8; + } +} + +static inline void avg4_block(UINT8 *dst, UINT8 *src1, UINT8 *src2, UINT8 *src3, UINT8 *src4, int dstStride, int srcStride, int r) +{ + int i; + for(i=0; i<8; i++) + { + dst[0]= (src1[0] + src2[0] + src3[0] + src4[0] + r)>>2; + dst[1]= (src1[1] + src2[1] + src3[1] + src4[1] + r)>>2; + dst[2]= (src1[2] + src2[2] + src3[2] + src4[2] + r)>>2; + dst[3]= (src1[3] + src2[3] + src3[3] + src4[3] + r)>>2; + dst[4]= (src1[4] + src2[4] + src3[4] + src4[4] + r)>>2; + dst[5]= (src1[5] + src2[5] + src3[5] + src4[5] + r)>>2; + dst[6]= (src1[6] + src2[6] + src3[6] + src4[6] + r)>>2; + dst[7]= (src1[7] + src2[7] + src3[7] + src4[7] + r)>>2; + dst+=dstStride; + src1+=srcStride; + src2+=8; + src3+=8; + src4+=8; + } +} + +#define QPEL_MC(r, name) \ +static void qpel_mc00_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + put_block(dst, src, dstStride, srcStride);\ +}\ +\ +static void qpel_mc10_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 half[64];\ + qpel_h_lowpass(half, src, 8, srcStride, 8, 128-r);\ + avg2_block(dst, src, half, dstStride, srcStride, 1-r);\ +}\ +\ +static void qpel_mc20_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + qpel_h_lowpass(dst, src, dstStride, srcStride, 8, 128-r);\ +}\ +\ +static void qpel_mc30_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 half[64];\ + qpel_h_lowpass(half, src, 8, srcStride, 8, 128-r);\ + avg2_block(dst, src+1, half, dstStride, srcStride, 1-r);\ +}\ +\ +static void qpel_mc01_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 half[64];\ + qpel_v_lowpass(half, src, 8, srcStride, 8, 128-r);\ + avg2_block(dst, src, half, dstStride, srcStride, 1-r);\ +}\ +\ +static void qpel_mc02_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + qpel_v_lowpass(dst, src, dstStride, srcStride, 8, 128-r);\ +}\ +\ +static void qpel_mc03_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 half[64];\ + qpel_v_lowpass(half, src, 8, srcStride, 8, 128-r);\ + avg2_block(dst, src+srcStride, half, dstStride, srcStride, 1-r);\ +}\ +static void qpel_mc11_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfV[64];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfV, src, 8, srcStride, 8, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg4_block(dst, src, halfH, halfV, halfHV, dstStride, srcStride, 2-r);\ +}\ +static void qpel_mc31_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfV[64];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfV, src+1, 8, srcStride, 8, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg4_block(dst, src+1, halfH, halfV, halfHV, dstStride, srcStride, 2-r);\ +}\ +static void qpel_mc13_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfV[64];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfV, src, 8, srcStride, 8, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg4_block(dst, src+srcStride, halfH+8, halfV, halfHV, dstStride, srcStride, 2-r);\ +}\ +static void qpel_mc33_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfV[64];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfV, src+1, 8, srcStride, 8, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg4_block(dst, src+srcStride+1, halfH+8, halfV, halfHV, dstStride, srcStride, 2-r);\ +}\ +static void qpel_mc21_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg2_block(dst, halfH, halfHV, dstStride, 8, 1-r);\ +}\ +static void qpel_mc23_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg2_block(dst, halfH+8, halfHV, dstStride, 8, 1-r);\ +}\ +static void qpel_mc12_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfV[64];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfV, src, 8, srcStride, 8, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg2_block(dst, halfV, halfHV, dstStride, 8, 1-r);\ +}\ +static void qpel_mc32_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + UINT8 halfV[64];\ + UINT8 halfHV[64];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(halfV, src+1, 8, srcStride, 8, 128-r);\ + qpel_v_lowpass(halfHV, halfH, 8, 8, 8, 128-r);\ + avg2_block(dst, halfV, halfHV, dstStride, 8, 1-r);\ +}\ +static void qpel_mc22_c ## name (UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my)\ +{\ + UINT8 halfH[72];\ + qpel_h_lowpass(halfH, src, 8, srcStride, 9, 128-r);\ + qpel_v_lowpass(dst, halfH, dstStride, 8, 8, 128-r);\ +}\ +qpel_mc_func qpel_mc ## name ## _tab[16]={ \ + qpel_mc00_c ## name, \ + qpel_mc10_c ## name, \ + qpel_mc20_c ## name, \ + qpel_mc30_c ## name, \ + qpel_mc01_c ## name, \ + qpel_mc11_c ## name, \ + qpel_mc21_c ## name, \ + qpel_mc31_c ## name, \ + qpel_mc02_c ## name, \ + qpel_mc12_c ## name, \ + qpel_mc22_c ## name, \ + qpel_mc32_c ## name, \ + qpel_mc03_c ## name, \ + qpel_mc13_c ## name, \ + qpel_mc23_c ## name, \ + qpel_mc33_c ## name, \ +}; + +QPEL_MC(0, _rnd) +QPEL_MC(1, _no_rnd) + int pix_abs16x16_c(UINT8 *pix1, UINT8 *pix2, int line_size, int h) { int s, i; @@ -390,24 +742,16 @@ int pix_abs16x16_xy2_c(UINT8 *pix1, UINT8 *pix2, int line_size, int h) /* permute block according so that it corresponds to the MMX idct order */ #ifdef SIMPLE_IDCT + /* general permutation, but perhaps slightly slower */ void block_permute(INT16 *block) { int i; INT16 temp[64]; -// for(i=0; i<64; i++) temp[i] = block[ block_permute_op(i) ]; for(i=0; i<64; i++) temp[ block_permute_op(i) ] = block[i]; for(i=0; i<64; i++) block[i] = temp[i]; -/* - for(i=0; i<64; i++) - { - if((i&7)==0) printf("\n"); - printf("%2d ", block[i]); - } -*/ } - #else void block_permute(INT16 *block) @@ -456,6 +800,7 @@ void dsputil_init(void) get_pixels = get_pixels_c; put_pixels_clamped = put_pixels_clamped_c; add_pixels_clamped = add_pixels_clamped_c; + gmc1= gmc1_c; pix_abs16x16 = pix_abs16x16_c; pix_abs16x16_x2 = pix_abs16x16_x2_c; @@ -475,11 +820,27 @@ void dsputil_init(void) dsputil_init_mlib(); use_permuted_idct = 0; #endif +#ifdef ARCH_ALPHA + dsputil_init_alpha(); + use_permuted_idct = 0; +#endif #ifdef SIMPLE_IDCT if(ff_idct == simple_idct) use_permuted_idct=0; #endif + if(use_permuted_idct) +#ifdef SIMPLE_IDCT + for(i=0; i<64; i++) permutation[i]= simple_mmx_permutation[i]; +#else + for(i=0; i<64; i++) permutation[i]= (i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2); +#endif + else + for(i=0; i<64; i++) permutation[i]=i; + + for(i=0; i<64; i++) inv_zigzag_direct16[zigzag_direct[i]]= i+1; + for(i=0; i<64; i++) zigzag_direct_noperm[i]= zigzag_direct[i]; + if (use_permuted_idct) { /* permute for IDCT */ for(i=0;i<64;i++) { @@ -493,4 +854,40 @@ void dsputil_init(void) block_permute(default_intra_matrix); block_permute(default_non_intra_matrix); } + + build_zigzag_end(); } + +void get_psnr(UINT8 *orig_image[3], UINT8 *coded_image[3], + int orig_linesize[3], int coded_linesize, + AVCodecContext *avctx) +{ + int quad, diff, x, y; + UINT8 *orig, *coded; + UINT32 *sq = squareTbl + 256; + + quad = 0; + diff = 0; + + /* Luminance */ + orig = orig_image[0]; + coded = coded_image[0]; + + for (y=0;y<avctx->height;y++) { + for (x=0;x<avctx->width;x++) { + diff = *(orig + x) - *(coded + x); + quad += sq[diff]; + } + orig += orig_linesize[0]; + coded += coded_linesize; + } + + avctx->psnr_y = (float) quad / (float) (avctx->width * avctx->height); + + if (avctx->psnr_y) { + avctx->psnr_y = (float) (255 * 255) / avctx->psnr_y; + avctx->psnr_y = 10 * (float) log10 (avctx->psnr_y); + } else + avctx->psnr_y = 99.99; +} + diff --git a/src/libffmpeg/libavcodec/dsputil.h b/src/libffmpeg/libavcodec/dsputil.h index 182b1e706..d0a6e68ba 100644 --- a/src/libffmpeg/libavcodec/dsputil.h +++ b/src/libffmpeg/libavcodec/dsputil.h @@ -2,7 +2,10 @@ #define DSPUTIL_H #include "common.h" +#include "avcodec.h" +#undef DEBUG +//#define DEBUG /* dct code */ typedef short DCTELEM; @@ -19,6 +22,9 @@ extern UINT8 ff_alternate_horizontal_scan[64]; extern UINT8 ff_alternate_vertical_scan[64]; extern UINT8 zigzag_direct[64]; +/* permutation table */ +extern UINT8 permutation[64]; + /* pixel operations */ #define MAX_NEG_CROP 384 @@ -34,6 +40,8 @@ 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); +extern void (*gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); + 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); @@ -41,11 +49,15 @@ 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); +typedef void (*qpel_mc_func)(UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int mx, int my); 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]; +extern qpel_mc_func qpel_mc_rnd_tab[16]; +extern qpel_mc_func qpel_mc_no_rnd_tab[16]; + /* sub pixel (encoding) */ extern void (*sub_pixels_tab[4])(DCTELEM *block, const UINT8 *pixels, int line_size, int h); @@ -67,45 +79,30 @@ 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); -#if defined (SIMPLE_IDCT) && defined (ARCH_X86) -static inline int block_permute_op(int j) -{ -static const int table[64]={ - 0x00, 0x08, 0x01, 0x09, 0x04, 0x0C, 0x05, 0x0D, - 0x10, 0x18, 0x11, 0x19, 0x14, 0x1C, 0x15, 0x1D, - 0x02, 0x0A, 0x03, 0x0B, 0x06, 0x0E, 0x07, 0x0F, - 0x12, 0x1A, 0x13, 0x1B, 0x16, 0x1E, 0x17, 0x1F, - 0x20, 0x28, 0x21, 0x29, 0x24, 0x2C, 0x25, 0x2D, - 0x30, 0x38, 0x31, 0x39, 0x34, 0x3C, 0x35, 0x3D, - 0x22, 0x2A, 0x23, 0x2B, 0x26, 0x2E, 0x27, 0x2F, - 0x32, 0x3A, 0x33, 0x3B, 0x36, 0x3E, 0x37, 0x3F, -}; - - return table[j]; -} -#elif defined (SIMPLE_IDCT) -static inline int block_permute_op(int j) -{ - return j; -} -#else static inline int block_permute_op(int j) { - return (j & 0x38) | ((j & 6) >> 1) | ((j & 1) << 2); + return permutation[j]; } -#endif void block_permute(INT16 *block); #if defined(ARCH_X86) +#define HAVE_MMX +#endif -#define HAVE_MMX 1 +#if defined(HAVE_MMX) -#include "xineutils.h" +#if 0 +#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 */ +#endif extern int mm_flags; -#define mm_support() xine_mm_accel() +int mm_support(void); #if 0 static inline void emms(void) @@ -143,6 +140,13 @@ void dsputil_init_armv4l(void); void dsputil_init_mlib(void); +#elif defined(ARCH_ALPHA) + +#define emms_c() +#define __align8 __attribute__ ((aligned (8))) + +void dsputil_init_alpha(void); + #else #define emms_c() @@ -151,4 +155,9 @@ void dsputil_init_mlib(void); #endif +/* PSNR */ +void get_psnr(UINT8 *orig_image[3], UINT8 *coded_image[3], + int orig_linesize[3], int coded_linesize, + AVCodecContext *avctx); + #endif diff --git a/src/libffmpeg/libavcodec/h263.c b/src/libffmpeg/libavcodec/h263.c index da694411f..79b74631d 100644 --- a/src/libffmpeg/libavcodec/h263.c +++ b/src/libffmpeg/libavcodec/h263.c @@ -25,6 +25,10 @@ #include "h263data.h" #include "mpeg4data.h" +//rounded divison & shift +#define RDIV(a,b) ((a) > 0 ? ((a)+((b)>>1))/(b) : ((a)-((b)>>1))/(b)) +#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b)) + static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n); static void h263_encode_motion(MpegEncContext * s, int val); @@ -62,8 +66,13 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) int format; align_put_bits(&s->pb); - put_bits(&s->pb, 22, 0x20); - put_bits(&s->pb, 8, ((s->picture_number * 30 * FRAME_RATE_BASE) / + + /* Update the pointer to last GOB */ + s->ptr_lastgob = pbBufPtr(&s->pb); + s->gob_number = 0; + + put_bits(&s->pb, 22, 0x20); /* PSC */ + put_bits(&s->pb, 8, (((INT64)s->picture_number * 30 * FRAME_RATE_BASE) / s->frame_rate) & 0xff); put_bits(&s->pb, 1, 1); /* marker */ @@ -147,26 +156,40 @@ int h263_encode_gob_header(MpegEncContext * s, int mb_line) /* Check to see if we need to put a new GBSC */ /* for RTP packetization */ if (s->rtp_mode) { - pdif = s->pb.buf_ptr - s->ptr_lastgob; + pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; if (pdif >= s->rtp_payload_size) { /* Bad luck, packet must be cut before */ align_put_bits(&s->pb); - s->ptr_lastgob = s->pb.buf_ptr; + flush_put_bits(&s->pb); + /* Call the RTP callback to send the last GOB */ + if (s->rtp_callback) { + pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; + s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number); + } + s->ptr_lastgob = pbBufPtr(&s->pb); put_bits(&s->pb, 17, 1); /* GBSC */ - s->gob_number = mb_line; + s->gob_number = mb_line / s->gob_index; put_bits(&s->pb, 5, s->gob_number); /* GN */ - put_bits(&s->pb, 2, 1); /* GFID */ + put_bits(&s->pb, 2, s->pict_type == I_TYPE); /* GFID */ put_bits(&s->pb, 5, s->qscale); /* GQUANT */ + //fprintf(stderr,"\nGOB: %2d size: %d", s->gob_number - 1, pdif); return pdif; } else if (pdif + s->mb_line_avgsize >= s->rtp_payload_size) { /* Cut the packet before we can't */ align_put_bits(&s->pb); - s->ptr_lastgob = s->pb.buf_ptr; + flush_put_bits(&s->pb); + /* Call the RTP callback to send the last GOB */ + if (s->rtp_callback) { + pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; + s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number); + } + s->ptr_lastgob = pbBufPtr(&s->pb); put_bits(&s->pb, 17, 1); /* GBSC */ - s->gob_number = mb_line; + s->gob_number = mb_line / s->gob_index; put_bits(&s->pb, 5, s->gob_number); /* GN */ - put_bits(&s->pb, 2, 1); /* GFID */ + put_bits(&s->pb, 2, s->pict_type == I_TYPE); /* GFID */ put_bits(&s->pb, 5, s->qscale); /* GQUANT */ + //fprintf(stderr,"\nGOB: %2d size: %d", s->gob_number - 1, pdif); return pdif; } } @@ -254,19 +277,101 @@ void h263_encode_mb(MpegEncContext * s, } } + +void h263_pred_acdc(MpegEncContext * s, INT16 *block, int n) +{ + int x, y, wrap, a, c, pred_dc, scale, i; + INT16 *dc_val, *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; + dc_val = s->dc_val[0]; + ac_val = s->ac_val[0][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]; + ac_val = s->ac_val[n - 4 + 1][0]; + scale = s->c_dc_scale; + } + + ac_val += ((y) * wrap + (x)) * 16; + ac_val1 = ac_val; + + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + pred_dc = 1024; + if (s->ac_pred) { + if (s->h263_aic_dir) { + /* left prediction */ + if (a != 1024) { + ac_val -= 16; + for(i=1;i<8;i++) { + block[block_permute_op(i*8)] += ac_val[i]; + } + pred_dc = a; + } + } else { + /* top prediction */ + if (c != 1024) { + ac_val -= 16 * wrap; + for(i=1;i<8;i++) { + block[block_permute_op(i)] += ac_val[i + 8]; + } + pred_dc = c; + } + } + } else { + /* just DC prediction */ + if (a != 1024 && c != 1024) + pred_dc = (a + c) >> 1; + else if (a != 1024) + pred_dc = a; + else + pred_dc = c; + } + + /* we assume pred is positive */ + block[0]=block[0]*scale + pred_dc; + + if (block[0] < 0) + block[0] = 0; + else if (!(block[0] & 1)) + block[0]++; + + /* Update AC/DC tables */ + dc_val[(x) + (y) * wrap] = block[0]; + + /* left copy */ + for(i=1;i<8;i++) + ac_val1[i] = block[block_permute_op(i * 8)]; + /* top copy */ + for(i=1;i<8;i++) + ac_val1[8 + i] = block[block_permute_op(i)]; +} + + static inline int mid_pred(int a, int b, int c) { int vmin, vmax; - vmin = a; + vmax = vmin = a; if (b < vmin) vmin = b; + else + vmax = b; + if (c < vmin) vmin = c; - - vmax = a; - if (b > vmax) - vmax = b; - if (c > vmax) + else if (c > vmax) vmax = c; return a + b + c - vmin - vmax; @@ -275,38 +380,39 @@ static inline int mid_pred(int a, int b, int c) INT16 *h263_pred_motion(MpegEncContext * s, int block, int *px, int *py) { - int x, y, wrap; + int xy, 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; + y = xy = 2 * s->mb_y + 1 + ((block >> 1) & 1); // y + xy *= wrap; // y * wrap + xy += 2 * s->mb_x + 1 + (block & 1); // x + y * wrap - mot_val = s->motion_val[(x) + (y) * wrap]; + mot_val = s->motion_val[xy]; /* special case for first line */ if (y == 1 || s->first_slice_line || s->first_gob_line) { - A = s->motion_val[(x-1) + (y) * wrap]; + A = s->motion_val[xy - 1]; *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]; + A = s->motion_val[xy - 1]; + B = s->motion_val[xy - wrap]; + C = s->motion_val[xy + 2 - 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]; + A = s->motion_val[xy - 1]; + B = s->motion_val[xy - wrap]; + C = s->motion_val[xy + 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]; + A = s->motion_val[xy - 1]; + B = s->motion_val[xy - 1 - wrap]; + C = s->motion_val[xy - wrap]; break; } *px = mid_pred(A[0], B[0], C[0]); @@ -413,20 +519,25 @@ static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n) RLTable *rl = &rl_inter; if (s->mb_intra) { - /* DC coef */ - level = block[0]; + /* 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; + /* 0 cannot be represented also */ + else if (!level) { + level = 1; + block[0] = 1; + } + if (level == 128) + put_bits(&s->pb, 8, 0xff); + else + put_bits(&s->pb, 8, level & 0xff); + i = 1; } else { - i = 0; + i = 0; } /* AC coefs */ @@ -465,7 +576,8 @@ 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, 16, 0); /* vop header */ + put_bits(&s->pb, 16, 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); @@ -513,20 +625,22 @@ void h263_dc_scale(MpegEncContext * s) 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; + int a, b, c, xy, 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; + xy = 2 * s->mb_y + 1 + ((n & 2) >> 1); + xy *= wrap; + xy += 2 * s->mb_x + 1 + (n & 1); 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; + xy = s->mb_y + 1; + xy *= wrap; + xy += s->mb_x + 1; dc_val = s->dc_val[n - 4 + 1]; scale = s->c_dc_scale; } @@ -534,9 +648,9 @@ static int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *di /* 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]; + a = dc_val[xy - 1]; + b = dc_val[xy - 1 - wrap]; + c = dc_val[xy - wrap]; if (abs(a - b) < abs(b - c)) { pred = c; @@ -549,7 +663,7 @@ static int mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *di pred = (pred + (scale >> 1)) / scale; /* prepare address for prediction update */ - *dc_val_ptr = &dc_val[(x) + (y) * wrap]; + *dc_val_ptr = &dc_val[xy]; return pred; } @@ -724,6 +838,7 @@ static VLC inter_MCBPC_vlc; static VLC cbpy_vlc; static VLC mv_vlc; static VLC dc_lum, dc_chrom; +static VLC sprite_trajectory; void init_rl(RLTable *rl) { @@ -794,14 +909,19 @@ void h263_decode_init_vlc(MpegEncContext *s) &mvtab[0][0], 2, 1); init_rl(&rl_inter); init_rl(&rl_intra); + init_rl(&rl_intra_aic); init_vlc_rl(&rl_inter); init_vlc_rl(&rl_intra); + init_vlc_rl(&rl_intra_aic); 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); + init_vlc(&sprite_trajectory, 9, 15, + &sprite_trajectory_tab[0][1], 4, 2, + &sprite_trajectory_tab[0][0], 4, 2); } } @@ -822,7 +942,7 @@ int h263_decode_gob_header(MpegEncContext *s) gfid = get_bits(&s->gb, 2); /* GFID */ s->qscale = get_bits(&s->gb, 5); /* GQUANT */ #ifdef DEBUG - fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale); + fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", s->gob_number, gfid, s->qscale); #endif return 1; } @@ -837,7 +957,7 @@ int h263_decode_mb(MpegEncContext *s, INT16 *mot_val; static INT8 quant_tab[4] = { -1, -2, 1, 2 }; - if (s->pict_type == P_TYPE) { + if (s->pict_type == P_TYPE || s->pict_type==S_TYPE) { if (get_bits1(&s->gb)) { /* skip mb */ s->mb_intra = 0; @@ -845,9 +965,25 @@ int h263_decode_mb(MpegEncContext *s, 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; + if(s->pict_type==S_TYPE && s->vol_sprite_usage==GMC_SPRITE){ + const int a= s->sprite_warping_accuracy; +// int l = (1 << (s->f_code - 1)) * 32; + + s->mcsel=1; + s->mv[0][0][0] = RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample); + s->mv[0][0][1] = RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample); +/* if (s->mv[0][0][0] < -l) s->mv[0][0][0]= -l; + else if (s->mv[0][0][0] >= l) s->mv[0][0][0]= l-1; + if (s->mv[0][0][1] < -l) s->mv[0][0][1]= -l; + else if (s->mv[0][0][1] >= l) s->mv[0][0][1]= l-1;*/ + + s->mb_skiped = 0; + }else{ + s->mcsel=0; + 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); @@ -870,6 +1006,9 @@ int h263_decode_mb(MpegEncContext *s, } if (!s->mb_intra) { + if(s->pict_type==S_TYPE && s->vol_sprite_usage==GMC_SPRITE && (cbpc & 16) == 0) + s->mcsel= get_bits1(&s->gb); + else s->mcsel= 0; cbpy = get_vlc(&s->gb, &cbpy_vlc); cbp = (cbpc & 3) | ((cbpy ^ 0xf) << 2); if (dquant) { @@ -886,15 +1025,29 @@ int h263_decode_mb(MpegEncContext *s, h263_pred_motion(s, 0, &pred_x, &pred_y); if (s->umvplus_dec) mx = h263p_decode_umotion(s, pred_x); - else + else if(!s->mcsel) mx = h263_decode_motion(s, pred_x); + else { + const int a= s->sprite_warping_accuracy; +// int l = (1 << (s->f_code - 1)) * 32; + mx= RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample); +// if (mx < -l) mx= -l; +// else if (mx >= l) mx= l-1; + } if (mx >= 0xffff) return -1; if (s->umvplus_dec) my = h263p_decode_umotion(s, pred_y); - else + else if(!s->mcsel) my = h263_decode_motion(s, pred_y); + else{ + const int a= s->sprite_warping_accuracy; +// int l = (1 << (s->f_code - 1)) * 32; + my= RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample); +// if (my < -l) my= -l; +// else if (my >= l) my= l-1; + } if (my >= 0xffff) return -1; s->mv[0][0][0] = mx; @@ -932,8 +1085,14 @@ int h263_decode_mb(MpegEncContext *s, } } else { s->ac_pred = 0; - if (s->h263_pred) { + if (s->h263_pred || s->h263_aic) { s->ac_pred = get_bits1(&s->gb); + if (s->ac_pred && s->h263_aic) + s->h263_aic_dir = get_bits1(&s->gb); + } + if (s->h263_aic) { + s->y_dc_scale = 2 * s->qscale; + s->c_dc_scale = 2 * s->qscale; } cbpy = get_vlc(&s->gb, &cbpy_vlc); cbp = (cbpc & 3) | (cbpy << 2); @@ -1032,9 +1191,20 @@ static int h263_decode_block(MpegEncContext * s, DCTELEM * block, { int code, level, i, j, last, run; RLTable *rl = &rl_inter; + const UINT8 *scan_table; - if (s->mb_intra) { - /* DC coef */ + scan_table = zigzag_direct; + if (s->h263_aic && s->mb_intra) { + rl = &rl_intra_aic; + i = 0; + if (s->ac_pred) { + if (s->h263_aic_dir) + scan_table = ff_alternate_vertical_scan; /* left */ + else + scan_table = ff_alternate_horizontal_scan; /* top */ + } + } else 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); @@ -1055,11 +1225,13 @@ static int h263_decode_block(MpegEncContext * s, DCTELEM * block, level = 128; } block[0] = level; - i = 1; + i = 1; } else { - i = 0; + i = 0; } if (!coded) { + if (s->mb_intra && s->h263_aic) + goto not_coded; s->block_last_index[n] = i - 1; return 0; } @@ -1088,12 +1260,17 @@ static int h263_decode_block(MpegEncContext * s, DCTELEM * block, i += run; if (i >= 64) return -1; - j = zigzag_direct[i]; + j = scan_table[i]; block[j] = level; if (last) break; i++; } +not_coded: + if (s->mb_intra && s->h263_aic) { + h263_pred_acdc(s, block, n); + i = 64; + } s->block_last_index[n] = i; return 0; } @@ -1241,8 +1418,8 @@ int h263_decode_picture_header(MpegEncContext *s) /* picture header */ if (get_bits(&s->gb, 22) != 0x20) return -1; - skip_bits(&s->gb, 8); /* picture timestamp */ - + s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */ + if (get_bits1(&s->gb) != 1) return -1; /* marker */ if (get_bits1(&s->gb) != 0) @@ -1298,7 +1475,10 @@ int h263_decode_picture_header(MpegEncContext *s) if (get_bits1(&s->gb) != 0) { s->mv_type = MV_TYPE_8X8; /* Advanced prediction mode */ } - skip_bits(&s->gb, 8); + if (get_bits1(&s->gb) != 0) { /* Advanced Intra Coding (AIC) */ + s->h263_aic = 1; + } + skip_bits(&s->gb, 7); skip_bits(&s->gb, 3); /* Reserved */ } else if (ufep != 0) return -1; @@ -1308,7 +1488,10 @@ int h263_decode_picture_header(MpegEncContext *s) if (s->pict_type != I_TYPE && s->pict_type != P_TYPE) return -1; - skip_bits(&s->gb, 7); + skip_bits(&s->gb, 2); + s->no_rounding = get_bits1(&s->gb); + //fprintf(stderr, "\nRTYPE: %d", s->no_rounding); + skip_bits(&s->gb, 4); /* Get the picture dimensions */ if (ufep) { @@ -1345,6 +1528,196 @@ int h263_decode_picture_header(MpegEncContext *s) return 0; } +static void mpeg4_decode_sprite_trajectory(MpegEncContext * s) +{ + int i; + int a= 2<<s->sprite_warping_accuracy; + int rho= 3-s->sprite_warping_accuracy; + int r=16/a; + const int vop_ref[4][2]= {{0,0}, {s->width,0}, {0, s->height}, {s->width, s->height}}; // only true for rectangle shapes + int d[4][2]={{0,0}, {0,0}, {0,0}, {0,0}}; + int sprite_ref[4][2]; + int virtual_ref[2][2]; + int w2, h2; + int alpha=0, beta=0; + int w= s->width; + int h= s->height; +//printf("SP %d\n", s->sprite_warping_accuracy); + for(i=0; i<s->num_sprite_warping_points; i++){ + int length; + int x=0, y=0; + + length= get_vlc(&s->gb, &sprite_trajectory); + if(length){ + x= get_bits(&s->gb, length); +//printf("lx %d %d\n", length, x); + if ((x >> (length - 1)) == 0) /* if MSB not set it is negative*/ + x = - (x ^ ((1 << length) - 1)); + } + if(!(s->divx_version==500 && s->divx_build==413)) skip_bits1(&s->gb); /* marker bit */ + + length= get_vlc(&s->gb, &sprite_trajectory); + if(length){ + y=get_bits(&s->gb, length); +//printf("ly %d %d\n", length, y); + if ((y >> (length - 1)) == 0) /* if MSB not set it is negative*/ + y = - (y ^ ((1 << length) - 1)); + } + skip_bits1(&s->gb); /* marker bit */ +//printf("%d %d %d %d\n", x, y, i, s->sprite_warping_accuracy); +//if(i>0 && (x!=0 || y!=0)) printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"); +//x=y=0; + d[i][0]= x; + d[i][1]= y; + } + + while((1<<alpha)<w) alpha++; + while((1<<beta )<h) beta++; // there seems to be a typo in the mpeg4 std for the definition of w' and h' + w2= 1<<alpha; + h2= 1<<beta; + +// Note, the 4th point isnt used for GMC +/* + sprite_ref[0][0]= (a>>1)*(2*vop_ref[0][0] + d[0][0]); + sprite_ref[0][1]= (a>>1)*(2*vop_ref[0][1] + d[0][1]); + sprite_ref[1][0]= (a>>1)*(2*vop_ref[1][0] + d[0][0] + d[1][0]); + sprite_ref[1][1]= (a>>1)*(2*vop_ref[1][1] + d[0][1] + d[1][1]); + sprite_ref[2][0]= (a>>1)*(2*vop_ref[2][0] + d[0][0] + d[2][0]); + sprite_ref[2][1]= (a>>1)*(2*vop_ref[2][1] + d[0][1] + d[2][1]); +*/ +//FIXME DIVX5 vs. mpeg4 ? + sprite_ref[0][0]= a*vop_ref[0][0] + d[0][0]; + sprite_ref[0][1]= a*vop_ref[0][1] + d[0][1]; + sprite_ref[1][0]= a*vop_ref[1][0] + d[0][0] + d[1][0]; + sprite_ref[1][1]= a*vop_ref[1][1] + d[0][1] + d[1][1]; + sprite_ref[2][0]= a*vop_ref[2][0] + d[0][0] + d[2][0]; + sprite_ref[2][1]= a*vop_ref[2][1] + d[0][1] + d[2][1]; +/* sprite_ref[3][0]= (a>>1)*(2*vop_ref[3][0] + d[0][0] + d[1][0] + d[2][0] + d[3][0]); + sprite_ref[3][1]= (a>>1)*(2*vop_ref[3][1] + d[0][1] + d[1][1] + d[2][1] + d[3][1]); */ + +// this is mostly identical to the mpeg4 std (and is totally unreadable because of that ...) +// perhaps it should be reordered to be more readable ... +// the idea behind this virtual_ref mess is to be able to use shifts later per pixel instead of divides +// so the distance between points is converted from w&h based to w2&h2 based which are of the 2^x form + virtual_ref[0][0]= 16*(vop_ref[0][0] + w2) + + RDIV(((w - w2)*(r*sprite_ref[0][0] - 16*vop_ref[0][0]) + w2*(r*sprite_ref[1][0] - 16*vop_ref[1][0])),w); + virtual_ref[0][1]= 16*vop_ref[0][1] + + RDIV(((w - w2)*(r*sprite_ref[0][1] - 16*vop_ref[0][1]) + w2*(r*sprite_ref[1][1] - 16*vop_ref[1][1])),w); + virtual_ref[1][0]= 16*vop_ref[0][0] + + RDIV(((h - h2)*(r*sprite_ref[0][0] - 16*vop_ref[0][0]) + h2*(r*sprite_ref[2][0] - 16*vop_ref[2][0])),h); + virtual_ref[1][1]= 16*(vop_ref[0][1] + h2) + + RDIV(((h - h2)*(r*sprite_ref[0][1] - 16*vop_ref[0][1]) + h2*(r*sprite_ref[2][1] - 16*vop_ref[2][1])),h); + + switch(s->num_sprite_warping_points) + { + case 0: + s->sprite_offset[0][0]= 0; + s->sprite_offset[0][1]= 0; + s->sprite_offset[1][0]= 0; + s->sprite_offset[1][1]= 0; + s->sprite_delta[0][0][0]= a; + s->sprite_delta[0][0][1]= 0; + s->sprite_delta[0][1][0]= 0; + s->sprite_delta[0][1][1]= a; + s->sprite_delta[1][0][0]= a; + s->sprite_delta[1][0][1]= 0; + s->sprite_delta[1][1][0]= 0; + s->sprite_delta[1][1][1]= a; + s->sprite_shift[0][0]= 0; + s->sprite_shift[0][1]= 0; + s->sprite_shift[1][0]= 0; + s->sprite_shift[1][1]= 0; + break; + case 1: //GMC only + s->sprite_offset[0][0]= sprite_ref[0][0] - a*vop_ref[0][0]; + s->sprite_offset[0][1]= sprite_ref[0][1] - a*vop_ref[0][1]; + s->sprite_offset[1][0]= ((sprite_ref[0][0]>>1)|(sprite_ref[0][0]&1)) - a*(vop_ref[0][0]/2); + s->sprite_offset[1][1]= ((sprite_ref[0][1]>>1)|(sprite_ref[0][1]&1)) - a*(vop_ref[0][1]/2); + s->sprite_delta[0][0][0]= a; + s->sprite_delta[0][0][1]= 0; + s->sprite_delta[0][1][0]= 0; + s->sprite_delta[0][1][1]= a; + s->sprite_delta[1][0][0]= a; + s->sprite_delta[1][0][1]= 0; + s->sprite_delta[1][1][0]= 0; + s->sprite_delta[1][1][1]= a; + s->sprite_shift[0][0]= 0; + s->sprite_shift[0][1]= 0; + s->sprite_shift[1][0]= 0; + s->sprite_shift[1][1]= 0; + break; + case 2: + case 3: //FIXME + s->sprite_offset[0][0]= (sprite_ref[0][0]<<(alpha+rho)) + + ((-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][0]) + +( r*sprite_ref[0][1] - virtual_ref[0][1])*(-vop_ref[0][1])); + s->sprite_offset[0][1]= (sprite_ref[0][1]<<(alpha+rho)) + + ((-r*sprite_ref[0][1] + virtual_ref[0][1])*(-vop_ref[0][0]) + +(-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][1])); + s->sprite_offset[1][0]= ((-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][0] + 1) + +( r*sprite_ref[0][1] - virtual_ref[0][1])*(-2*vop_ref[0][1] + 1) + +2*w2*r*sprite_ref[0][0] - 16*w2); + s->sprite_offset[1][1]= ((-r*sprite_ref[0][1] + virtual_ref[0][1])*(-2*vop_ref[0][0] + 1) + +(-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][1] + 1) + +2*w2*r*sprite_ref[0][1] - 16*w2); + s->sprite_delta[0][0][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); + s->sprite_delta[0][0][1]= ( r*sprite_ref[0][1] - virtual_ref[0][1]); + s->sprite_delta[0][1][0]= (-r*sprite_ref[0][1] + virtual_ref[0][1]); + s->sprite_delta[0][1][1]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); + s->sprite_delta[1][0][0]= 4*(-r*sprite_ref[0][0] + virtual_ref[0][0]); + s->sprite_delta[1][0][1]= 4*( r*sprite_ref[0][1] - virtual_ref[0][1]); + s->sprite_delta[1][1][0]= 4*(-r*sprite_ref[0][1] + virtual_ref[0][1]); + s->sprite_delta[1][1][1]= 4*(-r*sprite_ref[0][0] + virtual_ref[0][0]); + s->sprite_shift[0][0]= alpha+rho; + s->sprite_shift[0][1]= alpha+rho; + s->sprite_shift[1][0]= alpha+rho+2; + s->sprite_shift[1][1]= alpha+rho+2; + break; +// case 3: + break; + } +/*printf("%d %d\n", s->sprite_delta[0][0][0], a<<s->sprite_shift[0][0]); +printf("%d %d\n", s->sprite_delta[0][0][1], 0); +printf("%d %d\n", s->sprite_delta[0][1][0], 0); +printf("%d %d\n", s->sprite_delta[0][1][1], a<<s->sprite_shift[0][1]); +printf("%d %d\n", s->sprite_delta[1][0][0], a<<s->sprite_shift[1][0]); +printf("%d %d\n", s->sprite_delta[1][0][1], 0); +printf("%d %d\n", s->sprite_delta[1][1][0], 0); +printf("%d %d\n", s->sprite_delta[1][1][1], a<<s->sprite_shift[1][1]);*/ + /* try to simplify the situation */ + if( s->sprite_delta[0][0][0] == a<<s->sprite_shift[0][0] + && s->sprite_delta[0][0][1] == 0 + && s->sprite_delta[0][1][0] == 0 + && s->sprite_delta[0][1][1] == a<<s->sprite_shift[0][1] + && s->sprite_delta[1][0][0] == a<<s->sprite_shift[1][0] + && s->sprite_delta[1][0][1] == 0 + && s->sprite_delta[1][1][0] == 0 + && s->sprite_delta[1][1][1] == a<<s->sprite_shift[1][1]) + { + s->sprite_offset[0][0]>>=s->sprite_shift[0][0]; + s->sprite_offset[0][1]>>=s->sprite_shift[0][1]; + s->sprite_offset[1][0]>>=s->sprite_shift[1][0]; + s->sprite_offset[1][1]>>=s->sprite_shift[1][1]; + s->sprite_delta[0][0][0]= a; + s->sprite_delta[0][0][1]= 0; + s->sprite_delta[0][1][0]= 0; + s->sprite_delta[0][1][1]= a; + s->sprite_delta[1][0][0]= a; + s->sprite_delta[1][0][1]= 0; + s->sprite_delta[1][1][0]= 0; + s->sprite_delta[1][1][1]= a; + s->sprite_shift[0][0]= 0; + s->sprite_shift[0][1]= 0; + s->sprite_shift[1][0]= 0; + s->sprite_shift[1][1]= 0; + s->real_sprite_warping_points=1; + } + else + s->real_sprite_warping_points= s->num_sprite_warping_points; + +//FIXME convert stuff if accurace != 3 +} + /* decode mpeg4 VOP header */ int mpeg4_decode_picture_header(MpegEncContext * s) { @@ -1366,8 +1739,8 @@ int mpeg4_decode_picture_header(MpegEncContext * s) if (state == 0) return -1; } - - if (startcode == 0x120) { +//printf("startcode %X %d\n", startcode, get_bits_count(&s->gb)); + if (startcode == 0x120) { // Video Object Layer int time_increment_resolution, width, height, vo_ver_id; /* vol header */ @@ -1380,9 +1753,21 @@ int mpeg4_decode_picture_header(MpegEncContext * s) vo_ver_id = 1; } - skip_bits(&s->gb, 4); /* aspect_ratio_info */ - skip_bits1(&s->gb); /* vol control parameter */ + s->aspect_ratio_info= get_bits(&s->gb, 4); + if(s->aspect_ratio_info == EXTENDET_PAR){ + skip_bits(&s->gb, 8); //par_width + skip_bits(&s->gb, 8); // par_height + } + if(get_bits1(&s->gb)){ /* vol control parameter */ + printf("vol control parameter not supported\n"); + return -1; + } s->shape = get_bits(&s->gb, 2); /* vol shape */ + if(s->shape == GRAY_SHAPE && vo_ver_id != 1){ + printf("Gray shape not supported\n"); + skip_bits(&s->gb, 4); //video_object_layer_shape_extension + } + skip_bits1(&s->gb); /* marker */ time_increment_resolution = get_bits(&s->gb, 16); @@ -1395,8 +1780,8 @@ int mpeg4_decode_picture_header(MpegEncContext * s) skip_bits(&s->gb, s->time_increment_bits); } - if (s->shape != 2) { - if (s->shape == 0) { + if (s->shape != BIN_ONLY_SHAPE) { + if (s->shape == RECT_SHAPE) { skip_bits1(&s->gb); /* marker */ width = get_bits(&s->gb, 13); skip_bits1(&s->gb); /* marker */ @@ -1405,12 +1790,32 @@ int mpeg4_decode_picture_header(MpegEncContext * s) } skip_bits1(&s->gb); /* interlaced */ - skip_bits1(&s->gb); /* OBMC */ + if(!get_bits1(&s->gb)) printf("OBMC not supported\n"); /* OBMC Disable */ if (vo_ver_id == 1) { s->vol_sprite_usage = get_bits1(&s->gb); /* vol_sprite_usage */ } else { s->vol_sprite_usage = get_bits(&s->gb, 2); /* vol_sprite_usage */ } + if(s->vol_sprite_usage==STATIC_SPRITE) printf("Static Sprites not supported\n"); + if(s->vol_sprite_usage==STATIC_SPRITE || s->vol_sprite_usage==GMC_SPRITE){ + if(s->vol_sprite_usage==STATIC_SPRITE){ + s->sprite_width = get_bits(&s->gb, 13); + skip_bits1(&s->gb); /* marker */ + s->sprite_height= get_bits(&s->gb, 13); + skip_bits1(&s->gb); /* marker */ + s->sprite_left = get_bits(&s->gb, 13); + skip_bits1(&s->gb); /* marker */ + s->sprite_top = get_bits(&s->gb, 13); + skip_bits1(&s->gb); /* marker */ + } + s->num_sprite_warping_points= get_bits(&s->gb, 6); + s->sprite_warping_accuracy = get_bits(&s->gb, 2); + s->sprite_brightness_change= get_bits1(&s->gb); + if(s->vol_sprite_usage==STATIC_SPRITE) + s->low_latency_sprite= get_bits1(&s->gb); + } + // FIXME sadct disable bit if verid!=1 && shape not rect + if (get_bits1(&s->gb) == 1) { /* not_8_bit */ s->quant_precision = get_bits(&s->gb, 4); /* quant_precision */ skip_bits(&s->gb, 4); /* bits_per_pixel */ @@ -1418,26 +1823,88 @@ int mpeg4_decode_picture_header(MpegEncContext * s) s->quant_precision = 5; } - skip_bits1(&s->gb); /* vol_quant_type */ - skip_bits1(&s->gb); /* vol_quarter_pixel */ + // FIXME a bunch of grayscale shape things + if(get_bits1(&s->gb)) printf("Quant-Type not supported\n"); /* vol_quant_type */ //FIXME + if(vo_ver_id != 1) + s->quarter_sample= get_bits1(&s->gb); + else s->quarter_sample=0; +#if 0 + if(get_bits1(&s->gb)) printf("Complexity est disabled\n"); + if(get_bits1(&s->gb)) printf("resync disable\n"); +#else skip_bits1(&s->gb); /* complexity_estimation_disabled */ skip_bits1(&s->gb); /* resync_marker_disabled */ - skip_bits1(&s->gb); /* data_partioning_enabled */ - if (get_bits1(&s->gb) != 0) { /* scalability */ +#endif + s->data_partioning= get_bits1(&s->gb); + if(s->data_partioning){ + printf("data partitioning not supported\n"); + skip_bits1(&s->gb); // reversible vlc + } + + if(vo_ver_id != 1) { + s->new_pred= get_bits1(&s->gb); + if(s->new_pred){ + printf("new pred not supported\n"); + skip_bits(&s->gb, 2); /* requested upstream message type */ + skip_bits1(&s->gb); /* newpred segment type */ + } + s->reduced_res_vop= get_bits1(&s->gb); + if(s->reduced_res_vop) printf("reduced resolution VOP not supported\n"); + } + else{ + s->new_pred=0; + s->reduced_res_vop= 0; + } + + s->scalability= get_bits1(&s->gb); + if (s->scalability) { printf("bad scalability!!!\n"); return -1; } } +//printf("end Data %X %d\n", show_bits(&s->gb, 32), get_bits_count(&s->gb)&0x7); + goto redo; + } else if (startcode == 0x1b2) { //userdata + char buf[256]; + int i; + int e; + int ver, build; + +//printf("user Data %X\n", show_bits(&s->gb, 32)); + buf[0]= show_bits(&s->gb, 8); + for(i=1; i<256; i++){ + buf[i]= show_bits(&s->gb, 16)&0xFF; + if(buf[i]==0) break; + skip_bits(&s->gb, 8); + } + buf[255]=0; + e=sscanf(buf, "DivX%dBuild%d", &ver, &build); + if(e==2){ + s->divx_version= ver; + s->divx_build= build; + if(s->picture_number==0){ + printf("This file was encoded with DivX%d Build%d\n", ver, build); + if(ver==500 && build==413){ //most likely all version are indeed totally buggy but i dunno for sure ... + printf("WARNING: this version of DivX is not MPEG4 compatible, trying to workaround these bugs...\n"); + }else{ + printf("hmm, i havnt seen that version of divx yet, lets assume they fixed these bugs ...\n" + "using mpeg4 decoder, if it fails contact the developers (of ffmpeg)\n"); + } + } + } +//printf("User Data: %s\n", buf); goto redo; - } else if (startcode != 0x1b6) { + } else if (startcode != 0x1b6) { //VOP 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; - + if(s->pict_type == B_TYPE) + { + printf("B-VOP\n"); + return -1; + } + /* XXX: parse time base */ time_incr = 0; while (get_bits1(&s->gb) != 0) @@ -1450,14 +1917,16 @@ int mpeg4_decode_picture_header(MpegEncContext * s) if (get_bits1(&s->gb) != 1) goto redo; - if (s->shape != 2 && s->pict_type == P_TYPE) { + if (s->shape != BIN_ONLY_SHAPE && ( s->pict_type == P_TYPE + || (s->pict_type == S_TYPE && s->vol_sprite_usage==GMC_SPRITE))) { /* rounding type for motion estimation */ s->no_rounding = get_bits1(&s->gb); } else { s->no_rounding = 0; } - - if (s->shape != 0) { +//FIXME reduced res stuff + + if (s->shape != RECT_SHAPE) { if (s->vol_sprite_usage != 1 || s->pict_type != I_TYPE) { int width, height, hor_spat_ref, ver_spat_ref; @@ -1475,10 +1944,22 @@ int mpeg4_decode_picture_header(MpegEncContext * s) skip_bits(&s->gb, 8); /* constant_alpha_value */ } } - - if (s->shape != 2) { +//FIXME complexity estimation stuff + + if (s->shape != BIN_ONLY_SHAPE) { skip_bits(&s->gb, 3); /* intra dc VLC threshold */ - + //FIXME interlaced specific bits + } + + if(s->pict_type == S_TYPE && (s->vol_sprite_usage==STATIC_SPRITE || s->vol_sprite_usage==GMC_SPRITE)){ + if(s->num_sprite_warping_points){ + mpeg4_decode_sprite_trajectory(s); + } + if(s->sprite_brightness_change) printf("sprite_brightness_change not supported\n"); + if(s->vol_sprite_usage==STATIC_SPRITE) printf("static sprite not supported\n"); + } + + if (s->shape != BIN_ONLY_SHAPE) { /* note: we do not use quant_precision to avoid problem if no MPEG4 vol header as it is found on some old opendivx movies */ @@ -1487,10 +1968,18 @@ int mpeg4_decode_picture_header(MpegEncContext * s) if (s->pict_type != I_TYPE) { s->f_code = get_bits(&s->gb, 3); /* fcode_for */ } - if (s->shape && (s->pict_type != I_TYPE)) { - skip_bits1(&s->gb); // vop shape coding type + if (s->pict_type == B_TYPE) { + s->b_code = get_bits(&s->gb, 3); + } +//printf("quant:%d fcode:%d\n", s->qscale, s->f_code); + if(!s->scalability){ + if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) { + skip_bits1(&s->gb); // vop shape coding type + } } } +//printf("end Data %X %d\n", show_bits(&s->gb, 32), get_bits_count(&s->gb)&0x7); + s->picture_number++; // better than pic number==0 allways ;) return 0; } diff --git a/src/libffmpeg/libavcodec/h263data.h b/src/libffmpeg/libavcodec/h263data.h index d41996a3b..88e456ba2 100644 --- a/src/libffmpeg/libavcodec/h263data.h +++ b/src/libffmpeg/libavcodec/h263data.h @@ -125,6 +125,47 @@ static RLTable rl_inter = { inter_level, }; +/* table used for Advanced INTRA Coding, just RUN and LEVEL change */ +const INT8 inter_level_aic[102] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 2, 1, 2, 2, 4, 5, + 6, 7, 3, 2, 3, 4, 5, 2, + 3, 4, 2, 3, 1, 2, 25, 1, + 2, 24, 8, 2, 7, 4, 6, 1, + 9, 23, 2, 3, 1, 10, 12, 11, + 18, 17, 16, 15, 14, 13, 20, 19, + 22, 21, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 4, 1, 1, + 1, 1, 2, 2, 6, 5, 2, 2, + 3, 7, 3, 4, 9, 8, 1, 1, + 1, 2, 2, 2, 3, 10, +}; + +const INT8 inter_run_aic[102] = { + 0, 1, 3, 5, 7, 8, 9, 10, + 11, 4, 9, 13, 0, 1, 1, 1, + 1, 1, 0, 3, 2, 3, 0, 4, + 3, 0, 5, 5, 2, 6, 0, 4, + 7, 0, 0, 8, 0, 2, 0, 12, + 0, 0, 2, 1, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 20, 1, 19, 2, + 3, 0, 5, 6, 4, 0, 9, 10, + 11, 12, 13, 8, 7, 0, 17, 18, + 16, 15, 2, 1, 0, 0, 4, 3, + 1, 0, 2, 1, 0, 0, 21, 22, + 23, 7, 6, 5, 3, 0, +}; + +static RLTable rl_intra_aic = { + 102, + 58, + inter_vlc, + inter_run_aic, + inter_level_aic, +}; + static const UINT16 h263_format[8][2] = { { 0, 0 }, { 128, 96 }, diff --git a/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c index be76e3030..3733ed565 100644 --- a/src/libffmpeg/libavcodec/h263dec.c +++ b/src/libffmpeg/libavcodec/h263dec.c @@ -16,12 +16,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "config.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include "dsputil.h" #include "avcodec.h" #include "mpegvideo.h" +#include "xine-utils/xineutils.h" //#define DEBUG @@ -162,12 +164,34 @@ static int h263_decode_frame(AVCodecContext *avctx, s->c_dc_scale = 8; } +#ifdef HAVE_MMX + if (mm_flags & MM_MMX) { + asm volatile( + "pxor %%mm7, %%mm7 \n\t" + "movl $-128*6, %%eax \n\t" + "1: \n\t" + "movq %%mm7, (%0, %%eax) \n\t" + "movq %%mm7, 8(%0, %%eax) \n\t" + "movq %%mm7, 16(%0, %%eax) \n\t" + "movq %%mm7, 24(%0, %%eax) \n\t" + "addl $32, %%eax \n\t" + " js 1b \n\t" + : : "r" (((int)s->block)+128*6) + : "%eax" + ); + }else{ + memset(s->block, 0, sizeof(s->block)); + } +#else memset(s->block, 0, sizeof(s->block)); +#endif s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; if (s->h263_msmpeg4) { - if (msmpeg4_decode_mb(s, s->block) < 0) + if (msmpeg4_decode_mb(s, s->block) < 0) { + fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x); return -1; + } } else { if (h263_decode_mb(s, s->block) < 0) { fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x); @@ -191,6 +215,9 @@ static int h263_decode_frame(AVCodecContext *avctx, y, s->width, h); } } + + if (s->h263_msmpeg4 && s->pict_type==I_TYPE) + if(msmpeg4_decode_ext_header(s, buf_size) < 0) return -1; MPV_frame_end(s); @@ -202,6 +229,11 @@ static int h263_decode_frame(AVCodecContext *avctx, pict->linesize[2] = s->linesize / 2; avctx->quality = s->qscale; + + /* Return the Picture timestamp as the frame number */ + /* we substract 1 because it is added on utils.c */ + avctx->frame_number = s->picture_number - 1; + *data_size = sizeof(AVPicture); return buf_size; } diff --git a/src/libffmpeg/libavcodec/i386/dsputil_mmx.c b/src/libffmpeg/libavcodec/i386/dsputil_mmx.c index 8647ed187..37716a983 100644 --- a/src/libffmpeg/libavcodec/i386/dsputil_mmx.c +++ b/src/libffmpeg/libavcodec/i386/dsputil_mmx.c @@ -19,6 +19,7 @@ * MMX optimization by Nick Kurshev <nickols_k@mail.ru> */ +#include "xine-utils/xineutils.h" #include "../dsputil.h" #include "../simple_idct.h" @@ -962,7 +963,7 @@ static void sub_pixels_xy2_mmx( DCTELEM *block, const UINT8 *pixels, int line void dsputil_init_mmx(void) { - mm_flags = mm_support(); + mm_flags = xine_mm_accel(); #if 0 printf("CPU flags:"); if (mm_flags & MM_MMX) diff --git a/src/libffmpeg/libavcodec/i386/mpegvideo_mmx.c b/src/libffmpeg/libavcodec/i386/mpegvideo_mmx.c index b34d4eb03..b7a782f56 100644 --- a/src/libffmpeg/libavcodec/i386/mpegvideo_mmx.c +++ b/src/libffmpeg/libavcodec/i386/mpegvideo_mmx.c @@ -17,10 +17,22 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Optimized for ia32 cpus by Nick Kurshev <nickols_k@mail.ru> + * h263 dequantizer by Michael Niedermayer <michaelni@gmx.at> */ +#include "xine-utils/xineutils.h" #include "../dsputil.h" #include "../mpegvideo.h" +#include "../avcodec.h" +#include "../mangle.h" + +extern UINT8 zigzag_end[64]; +extern void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w); +extern int (*dct_quantize)(MpegEncContext *s, DCTELEM *block, int n, int qscale); + +extern UINT8 zigzag_direct_noperm[64]; +extern UINT16 inv_zigzag_direct16[64]; +extern UINT32 inverse[256]; #if 0 @@ -69,32 +81,38 @@ static const unsigned long long int mm_wone __attribute__ ((aligned(8))) = 0x000 static void dct_unquantize_h263_mmx(MpegEncContext *s, DCTELEM *block, int n, int qscale) { - int i, level, qmul, qadd; - + int i, level, qmul, qadd, nCoeffs; + qmul = s->qscale << 1; - qadd = (s->qscale - 1) | 1; + if (s->h263_aic && s->mb_intra) + qadd = 0; + else + qadd = (s->qscale - 1) | 1; if (s->mb_intra) { - if (n < 4) - block[0] = block[0] * s->y_dc_scale; - else - block[0] = block[0] * s->c_dc_scale; - - for(i=1; i<8; i++) { - level = block[i]; - if (level) { - if (level < 0) { - level = level * qmul - qadd; - } else { - level = level * qmul + qadd; - } - block[i] = level; - } - } + if (!s->h263_aic) { + if (n < 4) + block[0] = block[0] * s->y_dc_scale; + else + block[0] = block[0] * s->c_dc_scale; + } + for(i=1; i<8; i++) { + level = block[i]; + if (level) { + if (level < 0) { + level = level * qmul - qadd; + } else { + level = level * qmul + qadd; + } + block[i] = level; + } + } + nCoeffs=64; } else { i = 0; + nCoeffs= zigzag_end[ s->block_last_index[n] ]; } - +//printf("%d %d ", qmul, qadd); asm volatile( "movd %1, %%mm6 \n\t" //qmul "packssdw %%mm6, %%mm6 \n\t" @@ -138,9 +156,8 @@ asm volatile( "movq %%mm1, 8(%0, %3) \n\t" "addl $16, %3 \n\t" - "cmpl $128, %3 \n\t" - "jb 1b \n\t" - ::"r" (block), "g"(qmul), "g" (qadd), "r" (2*i) + "js 1b \n\t" + ::"r" (block+nCoeffs), "g"(qmul), "g" (qadd), "r" (2*(i-nCoeffs)) : "memory" ); } @@ -178,17 +195,22 @@ asm volatile( static void dct_unquantize_mpeg1_mmx(MpegEncContext *s, DCTELEM *block, int n, int qscale) { - int i, level; + int i, level, nCoeffs; const UINT16 *quant_matrix; + + if(s->alternate_scan) nCoeffs= 64; + else nCoeffs= nCoeffs= zigzag_end[ s->block_last_index[n] ]; + 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) { + /* isnt used anymore (we have a h263 unquantizer since some time) + if (s->out_format == FMT_H263) { i = 1; goto unquant_even; - } + }*/ /* XXX: only mpeg1 */ quant_matrix = s->intra_matrix; i=1; @@ -214,7 +236,7 @@ static void dct_unquantize_mpeg1_mmx(MpegEncContext *s, "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) { + for(;i<nCoeffs;i+=4) { __asm __volatile( "movq %1, %%mm0\n\t" "movq %%mm7, %%mm1\n\t" @@ -242,7 +264,7 @@ static void dct_unquantize_mpeg1_mmx(MpegEncContext *s, } } else { i = 0; - unquant_even: +// unquant_even: quant_matrix = s->non_intra_matrix; /* Align on 4 elements boundary */ while(i&7) @@ -258,7 +280,6 @@ static void dct_unquantize_mpeg1_mmx(MpegEncContext *s, } i++; } - asm volatile( "pcmpeqw %%mm7, %%mm7 \n\t" "psrlw $15, %%mm7 \n\t" @@ -307,14 +328,116 @@ asm volatile( "movq %%mm5, 8(%0, %3) \n\t" "addl $16, %3 \n\t" - "cmpl $128, %3 \n\t" - "jb 1b \n\t" - ::"r" (block), "r"(quant_matrix), "g" (qscale), "r" (2*i) + "js 1b \n\t" + ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "r" (2*(i-nCoeffs)) : "memory" ); } } +/* draw the edges of width 'w' of an image of size width, height + this mmx version can only handle w==8 || w==16 */ +static void draw_edges_mmx(UINT8 *buf, int wrap, int width, int height, int w) +{ + UINT8 *ptr, *last_line; + int i; + + last_line = buf + (height - 1) * wrap; + /* left and right */ + ptr = buf; + if(w==8) + { + asm volatile( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "punpckldq %%mm0, %%mm0 \n\t" + "movq %%mm0, -8(%0) \n\t" + "movq -8(%0, %2), %%mm1 \n\t" + "punpckhbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movq %%mm1, (%0, %2) \n\t" + "addl %1, %0 \n\t" + "cmpl %3, %0 \n\t" + " jb 1b \n\t" + : "+r" (ptr) + : "r" (wrap), "r" (width), "r" (ptr + wrap*height) + ); + } + else + { + asm volatile( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "punpckldq %%mm0, %%mm0 \n\t" + "movq %%mm0, -8(%0) \n\t" + "movq %%mm0, -16(%0) \n\t" + "movq -8(%0, %2), %%mm1 \n\t" + "punpckhbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movq %%mm1, (%0, %2) \n\t" + "movq %%mm1, 8(%0, %2) \n\t" + "addl %1, %0 \n\t" + "cmpl %3, %0 \n\t" + " jb 1b \n\t" + : "+r" (ptr) + : "r" (wrap), "r" (width), "r" (ptr + wrap*height) + ); + } + + for(i=0;i<w;i+=4) { + /* top and bottom (and hopefully also the corners) */ + ptr= buf - (i + 1) * wrap - w; + asm volatile( + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm0, (%0, %2) \n\t" + "movq %%mm0, (%0, %2, 2) \n\t" + "movq %%mm0, (%0, %3) \n\t" + "addl $8, %0 \n\t" + "cmpl %4, %0 \n\t" + " jb 1b \n\t" + : "+r" (ptr) + : "r" ((int)buf - (int)ptr - w), "r" (-wrap), "r" (-wrap*3), "r" (ptr+width+2*w) + ); + ptr= last_line + (i + 1) * wrap - w; + asm volatile( + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm0, (%0, %2) \n\t" + "movq %%mm0, (%0, %2, 2) \n\t" + "movq %%mm0, (%0, %3) \n\t" + "addl $8, %0 \n\t" + "cmpl %4, %0 \n\t" + " jb 1b \n\t" + : "+r" (ptr) + : "r" ((int)last_line - (int)ptr - w), "r" (wrap), "r" (wrap*3), "r" (ptr+width+2*w) + ); + } +} + +static volatile int esp_temp; + +void unused_var_warning_killer(){ + esp_temp++; +} + +#undef HAVE_MMX2 +#define RENAME(a) a ## _MMX +#include "mpegvideo_mmx_template.c" + +#define HAVE_MMX2 +#undef RENAME +#define RENAME(a) a ## _MMX2 +#include "mpegvideo_mmx_template.c" + void MPV_common_init_mmx(MpegEncContext *s) { if (mm_flags & MM_MMX) { @@ -322,5 +445,14 @@ void MPV_common_init_mmx(MpegEncContext *s) s->dct_unquantize = dct_unquantize_h263_mmx; else s->dct_unquantize = dct_unquantize_mpeg1_mmx; + + draw_edges = draw_edges_mmx; + + if(mm_flags & MM_MMXEXT){ + dct_quantize= dct_quantize_MMX2; + }else{ + dct_quantize= dct_quantize_MMX; + } } } + diff --git a/src/libffmpeg/libavcodec/mangle.h b/src/libffmpeg/libavcodec/mangle.h new file mode 100644 index 000000000..df7477774 --- /dev/null +++ b/src/libffmpeg/libavcodec/mangle.h @@ -0,0 +1,18 @@ +/* mangle.h - This file has some CPP macros to deal with different symbol + * mangling across binary formats. + * (c)2002 by Felix Buenemann <atmosfear at users.sourceforge.net> + * File licensed under the GPL, see http://www.fsf.org/ for more info. + */ + +#ifndef __MANGLE_H +#define __MANGLE_H + +/* Feel free to add more to the list, eg. a.out IMO */ +#if defined(__CYGWIN__) +#define MANGLE(a) "_" #a +#else +#define MANGLE(a) #a +#endif + +#endif /* !__MANGLE_H */ + diff --git a/src/libffmpeg/libavcodec/mjpeg.c b/src/libffmpeg/libavcodec/mjpeg.c index 08281a501..1eb35d2b8 100644 --- a/src/libffmpeg/libavcodec/mjpeg.c +++ b/src/libffmpeg/libavcodec/mjpeg.c @@ -17,9 +17,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ //#define DEBUG +#include "config.h" + #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" +#include "xine-utils/xineutils.h" typedef struct MJpegContext { UINT8 huff_size_dc_luminance[12]; @@ -243,7 +246,7 @@ static void jpeg_table_header(MpegEncContext *s) /* huffman table */ put_marker(p, DHT); flush_put_bits(p); - ptr = p->buf_ptr; + ptr = pbBufPtr(p); put_bits(p, 16, 0); /* patched later */ size = 2; size += put_huffman_table(s, 0, 0, bits_dc_luminance, val_dc_luminance); @@ -259,7 +262,7 @@ void mjpeg_picture_header(MpegEncContext *s) { put_marker(&s->pb, SOI); - jpeg_table_header(s); + if (s->mjpeg_write_tables) jpeg_table_header(s); put_marker(&s->pb, SOF0); @@ -271,20 +274,20 @@ void mjpeg_picture_header(MpegEncContext *s) /* 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, 4, s->mjpeg_hsample[0]); /* H factor */ + put_bits(&s->pb, 4, s->mjpeg_vsample[0]); /* 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, 4, s->mjpeg_hsample[1]); /* H factor */ + put_bits(&s->pb, 4, s->mjpeg_vsample[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, 4, s->mjpeg_hsample[2]); /* H factor */ + put_bits(&s->pb, 4, s->mjpeg_vsample[2]); /* V factor */ put_bits(&s->pb, 8, 0); /* select matrix */ /* scan header */ @@ -620,13 +623,11 @@ static int mjpeg_decode_sof0(MJpegDecodeContext *s, } for(i=0;i<nb_components;i++) { - int w, h, hh, vv; - hh = s->h_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; + int w, h; + w = (s->width + 8 * s->h_max - 1) / (8 * s->h_max); + h = (s->height + 8 * s->v_max - 1) / (8 * s->v_max); + w = w * 8 * s->h_count[i]; + h = h * 8 * s->v_count[i]; if (s->interlaced) w *= 2; s->linesize[i] = w; diff --git a/src/libffmpeg/libavcodec/motion_est.c b/src/libffmpeg/libavcodec/motion_est.c index d3e31fc42..084eb6038 100644 --- a/src/libffmpeg/libavcodec/motion_est.c +++ b/src/libffmpeg/libavcodec/motion_est.c @@ -17,6 +17,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "config.h" +#include "xine-utils/xineutils.h" #include <stdlib.h> #include <stdio.h> #include "avcodec.h" @@ -400,7 +402,7 @@ int estimate_motion(MpegEncContext * s, 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) @@ -409,13 +411,20 @@ int estimate_motion(MpegEncContext * s, if (s->unrestricted_mv) { xmin = -16; ymin = -16; - xmax = s->width; - ymax = s->height; + if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){ + xmax = s->mb_width*16; + ymax = s->mb_height*16; + }else { + /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise + (cuz the drawn edge isnt large enough))*/ + xmax = s->width; + ymax = s->height; + } } else { xmin = 0; ymin = 0; - xmax = s->width - 16; - ymax = s->height - 16; + xmax = s->mb_width*16 - 16; + ymax = s->mb_height*16 - 16; } switch(s->full_search) { @@ -451,9 +460,12 @@ int estimate_motion(MpegEncContext * s, vard = vard >> 8; sum = sum >> 8; varc = (varc >> 8) - (sum * sum); + s->mb_var[s->mb_width * mb_y + mb_x] = varc; + s->avg_mb_var += varc; + #if 0 - printf("varc=%d (sum=%d) vard=%d mx=%d my=%d\n", - varc, sum, vard, mx - xx, my - yy); + printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n", + varc, s->avg_mb_var, sum, vard, mx - xx, my - yy); #endif if (vard <= 64 || vard < varc) { if (s->full_search != ME_ZERO) { diff --git a/src/libffmpeg/libavcodec/mpeg12.c b/src/libffmpeg/libavcodec/mpeg12.c index 758124eea..41bf524e4 100644 --- a/src/libffmpeg/libavcodec/mpeg12.c +++ b/src/libffmpeg/libavcodec/mpeg12.c @@ -33,6 +33,8 @@ #define EXT_START_CODE 0x000001b5 #define USER_START_CODE 0x000001b2 +#define ABS(a) ((a)<0 ? -(a) : (a)) + static void mpeg1_encode_block(MpegEncContext *s, DCTELEM *block, int component); @@ -52,7 +54,8 @@ 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_bits(&s->pb, 16, header>>16); + put_bits(&s->pb, 16, header&0xFFFF); } /* put sequence header if needed */ @@ -103,7 +106,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) /* 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; + time_code = (INT64)s->fake_picture_number * FRAME_RATE_BASE; s->gop_picture_number = s->fake_picture_number; put_bits(&s->pb, 5, (UINT32)((time_code / (fps * 3600)) % 24)); put_bits(&s->pb, 6, (UINT32)((time_code / (fps * 60)) % 60)); @@ -118,7 +121,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) /* 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; + n = (((INT64)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); @@ -183,11 +186,38 @@ static void mpeg1_skip_picture(MpegEncContext *s, int pict_num) void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) { - static int done; + static int done=0; if (!done) { + int i; done = 1; init_rl(&rl_mpeg1); + + for(i=0; i<64; i++) + { + mpeg1_max_level[0][i]= rl_mpeg1.max_level[0][i]; + mpeg1_index_run[0][i]= rl_mpeg1.index_run[0][i]; + } + + /* build unified dc encoding tables */ + for(i=-255; i<256; i++) + { + int adiff, index; + int bits, code; + int diff=i; + + adiff = ABS(diff); + if(diff<0) diff--; + index = vlc_dc_table[adiff]; + + bits= vlc_dc_lum_bits[index] + index; + code= (vlc_dc_lum_code[index]<<index) + (diff & ((1 << index) - 1)); + mpeg1_lum_dc_uni[i+255]= bits + (code<<8); + + bits= vlc_dc_chroma_bits[index] + index; + code= (vlc_dc_chroma_code[index]<<index) + (diff & ((1 << index) - 1)); + mpeg1_chr_dc_uni[i+255]= bits + (code<<8); + } } mpeg1_encode_sequence_header(s); @@ -325,19 +355,16 @@ static void mpeg1_encode_motion(MpegEncContext *s, int val) 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]); + put_bits( + &s->pb, + mpeg1_lum_dc_uni[diff+255]&0xFF, + mpeg1_lum_dc_uni[diff+255]>>8); } 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))); + put_bits( + &s->pb, + mpeg1_chr_dc_uni[diff+255]&0xFF, + mpeg1_chr_dc_uni[diff+255]>>8); } } @@ -347,7 +374,7 @@ static void mpeg1_encode_block(MpegEncContext *s, { int alevel, level, last_non_zero, dc, diff, i, j, run, last_index, sign; int code, component; - RLTable *rl = &rl_mpeg1; +// RLTable *rl = &rl_mpeg1; last_index = s->block_last_index[n]; @@ -376,6 +403,7 @@ static void mpeg1_encode_block(MpegEncContext *s, /* now quantify & encode AC coefs */ last_non_zero = i - 1; + for(;i<=last_index;i++) { j = zigzag_direct[i]; level = block[j]; @@ -387,17 +415,38 @@ static void mpeg1_encode_block(MpegEncContext *s, /* encode using VLC */ if (level != 0) { run = i - last_non_zero - 1; +#ifdef ARCH_X86 + asm volatile( + "movl %2, %1 \n\t" + "movl %1, %0 \n\t" + "addl %1, %1 \n\t" + "sbbl %1, %1 \n\t" + "xorl %1, %0 \n\t" + "subl %1, %0 \n\t" + "andl $1, %1 \n\t" + : "=&r" (alevel), "=&r" (sign) + : "g" (level) + ); +#else 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); +#endif +// code = get_rl_index(rl, 0, run, alevel); + if (alevel > mpeg1_max_level[0][run]) + code= 111; /*rl->n*/ + else + code= mpeg1_index_run[0][run] + alevel - 1; + + if (code < 111 /* rl->n */) { + /* store the vlc & sign at once */ + put_bits(&s->pb, mpeg1_vlc[code][1]+1, (mpeg1_vlc[code][0]<<1) + sign); } else { + /* escape seems to be pretty rare <5% so i dont optimize it */ + put_bits(&s->pb, mpeg1_vlc[111/*rl->n*/][1], mpeg1_vlc[111/*rl->n*/][0]); /* escape: only clip in this case */ put_bits(&s->pb, 6, run); if (alevel < 128) { @@ -899,7 +948,7 @@ static int mpeg1_decode_block(MpegEncContext *s, block[j] = level; i++; } - s->block_last_index[n] = i; + s->block_last_index[n] = i-1; return 0; } diff --git a/src/libffmpeg/libavcodec/mpeg12data.h b/src/libffmpeg/libavcodec/mpeg12data.h index f7d29a5cb..65a8a2b9a 100644 --- a/src/libffmpeg/libavcodec/mpeg12data.h +++ b/src/libffmpeg/libavcodec/mpeg12data.h @@ -61,6 +61,10 @@ const unsigned char vlc_dc_chroma_bits[12] = { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, }; +/* simple include everything table for dc, first byte is bits number next 3 are code*/ +static UINT32 mpeg1_lum_dc_uni[512]; +static UINT32 mpeg1_chr_dc_uni[512]; + static const UINT16 mpeg1_vlc[113][2] = { { 0x3, 2 }, { 0x4, 4 }, { 0x5, 5 }, { 0x6, 7 }, { 0x26, 8 }, { 0x21, 8 }, { 0xa, 10 }, { 0x1d, 12 }, @@ -161,6 +165,9 @@ static const INT8 mpeg1_run[111] = { 25, 26, 27, 28, 29, 30, 31, }; +static UINT8 mpeg1_index_run[2][64]; +static INT8 mpeg1_max_level[2][64]; + static RLTable rl_mpeg1 = { 111, 111, diff --git a/src/libffmpeg/libavcodec/mpeg4data.h b/src/libffmpeg/libavcodec/mpeg4data.h index 3821a591c..4eed75654 100644 --- a/src/libffmpeg/libavcodec/mpeg4data.h +++ b/src/libffmpeg/libavcodec/mpeg4data.h @@ -1,3 +1,15 @@ +// shapes +#define RECT_SHAPE 0 +#define BIN_SHAPE 1 +#define BIN_ONLY_SHAPE 2 +#define GRAY_SHAPE 3 + +// aspect_ratio_info +#define EXTENDET_PAR 15 + +//vol_sprite_usage / sprite_enable +#define STATIC_SPRITE 1 +#define GMC_SPRITE 2 /* dc encoding for mpeg4 */ static const UINT8 DCtab_lum[13][2] = @@ -81,3 +93,9 @@ static RLTable rl_intra = { intra_run, intra_level, }; + +static const UINT16 sprite_trajectory_tab[15][2] = { + {0x00, 2}, {0x02, 3}, {0x03, 3}, {0x04, 3}, {0x05, 3}, {0x06, 3}, + {0x0E, 4}, {0x1E, 5}, {0x3E, 6}, {0x7E, 7}, {0xFE, 8}, + {0x1FE, 9},{0x3FE, 10},{0x7FE, 11},{0xFFE, 12}, +}; diff --git a/src/libffmpeg/libavcodec/mpegvideo.c b/src/libffmpeg/libavcodec/mpegvideo.c index 80a35635d..a8297a2c1 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.c +++ b/src/libffmpeg/libavcodec/mpegvideo.c @@ -20,6 +20,10 @@ #include <stdio.h> #include <math.h> #include <string.h> + +#include "config.h" +#include "xine-utils/xineutils.h" + #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" @@ -35,10 +39,12 @@ 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); +static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w); +static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); + +int (*dct_quantize)(MpegEncContext *s, DCTELEM *block, int n, int qscale)= dct_quantize_c; +void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edges_c; + #define EDGE_WIDTH 16 /* enable all paranoid tests for rounding, overflows, etc... */ @@ -68,29 +74,31 @@ static UINT8 h263_chroma_roundtab[16] = { /* default motion estimation */ int motion_estimation_method = ME_LOG; -/* XXX: should use variable shift ? */ -#define QMAT_SHIFT_MMX 19 -#define QMAT_SHIFT 25 +extern UINT8 zigzag_end[64]; -static void convert_matrix(int *qmat, const UINT16 *quant_matrix, int qscale) +static void convert_matrix(int *qmat, UINT16 *qmat16, 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 */ + /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ + /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */ + /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ - qmat[i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 11)) / - (aanscales[i] * qscale * quant_matrix[i])); + qmat[block_permute_op(i)] = (int)((UINT64_C(1) << (QMAT_SHIFT + 11)) / + (aanscales[i] * qscale * quant_matrix[block_permute_op(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 + So 16 <= qscale * quant_matrix[i] <= 7905 + so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 + so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 */ - qmat[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); + qmat[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); + qmat16[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[block_permute_op(i)]); } } } @@ -111,6 +119,7 @@ int MPV_common_init(MpegEncContext *s) #endif s->mb_width = (s->width + 15) / 16; s->mb_height = (s->height + 15) / 16; + s->mb_num = s->mb_width * s->mb_height; s->linesize = s->mb_width * 16 + 2 * EDGE_WIDTH; for(i=0;i<3;i++) { @@ -142,7 +151,30 @@ int MPV_common_init(MpegEncContext *s) s->aux_picture[i] = pict + pict_start; } } - + + if (s->encoding) { + /* Allocate MB type table */ + s->mb_type = av_mallocz(s->mb_num * sizeof(char)); + if (s->mb_type == NULL) { + perror("malloc"); + goto fail; + } + + s->mb_var = av_mallocz(s->mb_num * sizeof(INT16)); + if (s->mb_var == NULL) { + perror("malloc"); + goto fail; + } + /* Allocate MV table */ + /* By now we just have one MV per MB */ + s->mv_table[0] = av_mallocz(s->mb_num * sizeof(INT16)); + s->mv_table[1] = av_mallocz(s->mb_num * sizeof(INT16)); + if (s->mv_table[1] == NULL || s->mv_table[0] == NULL) { + perror("malloc"); + goto fail; + } + } + if (s->out_format == FMT_H263) { int size; /* MV prediction */ @@ -153,7 +185,7 @@ int MPV_common_init(MpegEncContext *s) memset(s->motion_val, 0, size * 2 * sizeof(INT16)); } - if (s->h263_pred) { + if (s->h263_pred || s->h263_plus) { int y_size, c_size, i, size; /* dc values */ @@ -180,13 +212,19 @@ int MPV_common_init(MpegEncContext *s) s->coded_block = av_mallocz(y_size); if (!s->coded_block) goto fail; + + /* which mb is a intra block */ + s->mbintra_table = av_mallocz(s->mb_num); + if (!s->mbintra_table) + goto fail; + memset(s->mbintra_table, 1, s->mb_num); } /* default structure is frame */ s->picture_structure = PICT_FRAME; /* init macroblock skip table */ if (!s->encoding) { - s->mbskip_table = av_mallocz(s->mb_width * s->mb_height); + s->mbskip_table = av_mallocz(s->mb_num); if (!s->mbskip_table) goto fail; } @@ -194,24 +232,7 @@ int MPV_common_init(MpegEncContext *s) 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]); - } + MPV_common_end(s); return -1; } @@ -220,18 +241,32 @@ void MPV_common_end(MpegEncContext *s) { int i; + if (s->mb_type) + free(s->mb_type); + if (s->mb_var) + free(s->mb_var); + if (s->mv_table[0]) + free(s->mv_table[0]); + if (s->mv_table[1]) + free(s->mv_table[1]); if (s->motion_val) free(s->motion_val); - if (s->h263_pred) { + 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->mbintra_table) + free(s->mbintra_table); + 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->last_picture_base[i]) + free(s->last_picture_base[i]); + if (s->next_picture_base[i]) + free(s->next_picture_base[i]); if (s->has_b_frames) free(s->aux_picture_base[i]); } @@ -251,6 +286,9 @@ int MPV_encode_init(AVCodecContext *avctx) s->gop_size = avctx->gop_size; s->rtp_mode = avctx->rtp_mode; s->rtp_payload_size = avctx->rtp_payload_size; + if (avctx->rtp_callback) + s->rtp_callback = avctx->rtp_callback; + s->avctx = avctx; if (s->gop_size <= 1) { s->intra_only = 1; @@ -261,7 +299,7 @@ int MPV_encode_init(AVCodecContext *avctx) 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; @@ -269,14 +307,21 @@ int MPV_encode_init(AVCodecContext *avctx) case CODEC_ID_MJPEG: s->out_format = FMT_MJPEG; s->intra_only = 1; /* force intra only for jpeg */ + s->mjpeg_write_tables = 1; /* write all tables */ + s->mjpeg_vsample[0] = 2; /* set up default sampling factors */ + s->mjpeg_vsample[1] = 1; /* the only currently supported values */ + s->mjpeg_vsample[2] = 1; + s->mjpeg_hsample[0] = 2; + s->mjpeg_hsample[1] = 1; + s->mjpeg_hsample[2] = 1; if (mjpeg_init(s) < 0) return -1; break; case CODEC_ID_H263: - if (h263_get_picture_format(s->width, s->height) == 7){ - printf("Input picture size isn't suitable for h263 codec! try h263+\n"); + if (h263_get_picture_format(s->width, s->height) == 7) { + printf("Input picture size isn't suitable for h263 codec! try h263+\n"); return -1; - } + } s->out_format = FMT_H263; break; case CODEC_ID_H263P: @@ -345,11 +390,12 @@ int MPV_encode_end(AVCodecContext *avctx) 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) +static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w) { UINT8 *ptr, *last_line; int i; @@ -402,17 +448,19 @@ void MPV_frame_start(MpegEncContext *s) void MPV_frame_end(MpegEncContext *s) { /* draw edge for correct motion prediction if outside */ - if (s->pict_type != B_TYPE) { -#if 1 + if (s->pict_type != B_TYPE && !s->intra_only) { + if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4 || s->divx_version==500){ draw_edges(s->current_picture[0], s->linesize, s->mb_width*16, s->mb_height*16, EDGE_WIDTH); draw_edges(s->current_picture[1], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); draw_edges(s->current_picture[2], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); -#else + }else{ + /* mpeg4? / opendivx / xvid */ 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); -#endif + } } + emms_c(); } int MPV_encode_picture(AVCodecContext *avctx, @@ -439,7 +487,7 @@ int MPV_encode_picture(AVCodecContext *avctx, 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]; @@ -454,12 +502,16 @@ int MPV_encode_picture(AVCodecContext *avctx, h >>= 1; } - for(j=0;j<h;j++) { - memcpy(dest, src, w); - dest += dest_wrap; - src += src_wrap; - } - s->new_picture[i] = s->current_picture[i]; + if(dest_wrap==src_wrap){ + s->new_picture[i] = pict->data[i]; + } else { + for(j=0;j<h;j++) { + memcpy(dest, src, w); + dest += dest_wrap; + src += src_wrap; + } + s->new_picture[i] = s->current_picture[i]; + } } encode_picture(s, s->picture_number); @@ -471,9 +523,16 @@ int MPV_encode_picture(AVCodecContext *avctx, mjpeg_picture_trailer(s); flush_put_bits(&s->pb); - s->total_bits += (s->pb.buf_ptr - s->pb.buf) * 8; + s->total_bits += (pbBufPtr(&s->pb) - s->pb.buf) * 8; + avctx->quality = s->qscale; - return s->pb.buf_ptr - s->pb.buf; + if (avctx->get_psnr) { + /* At this point pict->data should have the original frame */ + /* an s->current_picture should have the coded/decoded frame */ + get_psnr(pict->data, s->current_picture, + pict->linesize, s->linesize, avctx); + } + return pbBufPtr(&s->pb) - s->pb.buf; } static inline int clip(int a, int amin, int amax) @@ -486,6 +545,59 @@ static inline int clip(int a, int amin, int amax) return a; } +static inline void gmc1_motion(MpegEncContext *s, + UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, + int dest_offset, + UINT8 **ref_picture, int src_offset, + int h) +{ + UINT8 *ptr; + int dxy, offset, mx, my, src_x, src_y, height, linesize; + int motion_x, motion_y; + + if(s->real_sprite_warping_points>1) printf("Oops, thats bad, contact the developers\n"); + motion_x= s->sprite_offset[0][0]; + motion_y= s->sprite_offset[0][1]; + src_x = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy+1)); + src_y = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy+1)); + motion_x<<=(3-s->sprite_warping_accuracy); + motion_y<<=(3-s->sprite_warping_accuracy); + src_x = clip(src_x, -16, s->width); + if (src_x == s->width) + motion_x =0; + src_y = clip(src_y, -16, s->height); + if (src_y == s->height) + motion_y =0; + + linesize = s->linesize; + ptr = ref_picture[0] + (src_y * linesize) + src_x + src_offset; + + dest_y+=dest_offset; + gmc1(dest_y , ptr , linesize, h, motion_x&15, motion_y&15, s->no_rounding); + gmc1(dest_y+8, ptr+8, linesize, h, motion_x&15, motion_y&15, s->no_rounding); + + motion_x= s->sprite_offset[1][0]; + motion_y= s->sprite_offset[1][1]; + src_x = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy+1)); + src_y = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy+1)); + motion_x<<=(3-s->sprite_warping_accuracy); + motion_y<<=(3-s->sprite_warping_accuracy); + src_x = clip(src_x, -8, s->width>>1); + if (src_x == s->width>>1) + motion_x =0; + src_y = clip(src_y, -8, s->height>>1); + if (src_y == s->height>>1) + motion_y =0; + + offset = (src_y * linesize>>1) + src_x + (src_offset>>1); + ptr = ref_picture[1] + offset; + gmc1(dest_cb + (dest_offset>>1), ptr, linesize>>1, h>>1, motion_x&15, motion_y&15, s->no_rounding); + ptr = ref_picture[2] + offset; + gmc1(dest_cr + (dest_offset>>1), ptr, linesize>>1, h>>1, motion_x&15, motion_y&15, s->no_rounding); + + return; +} + /* 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, @@ -496,7 +608,11 @@ static inline void mpeg_motion(MpegEncContext *s, { UINT8 *ptr; int dxy, offset, mx, my, src_x, src_y, height, linesize; - +if(s->quarter_sample) +{ + motion_x>>=1; + motion_y>>=1; +} 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); @@ -547,10 +663,69 @@ static inline void mpeg_motion(MpegEncContext *s, pix_op[dxy](dest_cr + (dest_offset >> 1), ptr, linesize >> 1, h >> 1); } +static inline void qpel_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, + qpel_mc_func *qpix_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 & 3) << 2) | (motion_x & 3); + src_x = s->mb_x * 16 + (motion_x >> 2); + src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2); + + height = s->height >> field_based; + src_x = clip(src_x, -16, s->width); + if (src_x == s->width) + dxy &= ~3; + src_y = clip(src_y, -16, height); + if (src_y == height) + dxy &= ~12; + linesize = s->linesize << field_based; + ptr = ref_picture[0] + (src_y * linesize) + src_x + src_offset; + dest_y += dest_offset; +//printf("%d %d %d\n", src_x, src_y, dxy); + qpix_op[dxy](dest_y , ptr , linesize, linesize, motion_x&3, motion_y&3); + qpix_op[dxy](dest_y + 8, ptr + 8, linesize, linesize, motion_x&3, motion_y&3); + qpix_op[dxy](dest_y + linesize*8 , ptr + linesize*8 , linesize, linesize, motion_x&3, motion_y&3); + qpix_op[dxy](dest_y + linesize*8 + 8, ptr + linesize*8 + 8, linesize, linesize, motion_x&3, motion_y&3); + + mx= (motion_x>>1) | (motion_x&1); + my= (motion_y>>1) | (motion_y&1); + + dxy = 0; + if ((mx & 3) != 0) + dxy |= 1; + if ((my & 3) != 0) + dxy |= 2; + mx = mx >> 2; + my = my >> 2; + + 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) + op_pixels_func *pix_op, qpel_mc_func *qpix_op) { int dxy, offset, mx, my, src_x, src_y, motion_x, motion_y; int mb_x, mb_y, i; @@ -561,10 +736,30 @@ static inline void MPV_motion(MpegEncContext *s, 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); + if(s->mcsel){ +#if 0 + mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, 0, + 0, pix_op, + s->sprite_offset[0][0]>>3, + s->sprite_offset[0][1]>>3, + 16); +#else + gmc1_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, 0, + 16); +#endif + }else if(s->quarter_sample){ + qpel_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, 0, + 0, pix_op, qpix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 16); + }else{ + 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++) { @@ -663,7 +858,8 @@ static inline void add_dct(MpegEncContext *s, { if (s->block_last_index[i] >= 0) { if (!s->mpeg2) - s->dct_unquantize(s, block, i, s->qscale); + if(s->encoding || (!s->h263_msmpeg4)) + s->dct_unquantize(s, block, i, s->qscale); ff_idct (block); add_pixels_clamped(block, dest, line_size); } @@ -681,9 +877,10 @@ static inline void add_dct(MpegEncContext *s, */ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) { - int mb_x, mb_y, motion_x, motion_y; + int mb_x, mb_y; int dct_linesize, dct_offset; op_pixels_func *op_pix; + qpel_mc_func *op_qpix; mb_x = s->mb_x; mb_y = s->mb_y; @@ -695,50 +892,54 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) /* update DC predictors for P macroblocks */ if (!s->mb_intra) { - if (s->h263_pred) { - int wrap, x, y, v; + if (s->h263_pred || s->h263_aic) { + if(s->mbintra_table[mb_x + mb_y*s->mb_width]) + { + int wrap, xy, v; + s->mbintra_table[mb_x + mb_y*s->mb_width]=0; wrap = 2 * s->mb_width + 2; + xy = 2 * mb_x + 1 + (2 * mb_y + 1) * wrap; 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; + + s->dc_val[0][xy] = v; + s->dc_val[0][xy + 1] = v; + s->dc_val[0][xy + wrap] = v; + s->dc_val[0][xy + 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)); + memset(s->ac_val[0][xy], 0, 16 * sizeof(INT16)); + memset(s->ac_val[0][xy + 1], 0, 16 * sizeof(INT16)); + memset(s->ac_val[0][xy + wrap], 0, 16 * sizeof(INT16)); + memset(s->ac_val[0][xy + 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; + s->coded_block[xy] = 0; + s->coded_block[xy + 1] = 0; + s->coded_block[xy + wrap] = 0; + s->coded_block[xy + 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; + xy = mb_x + 1 + (mb_y + 1) * wrap; + s->dc_val[1][xy] = v; + s->dc_val[2][xy] = 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)); + memset(s->ac_val[1][xy], 0, 16 * sizeof(INT16)); + memset(s->ac_val[2][xy], 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; } } - + else if (s->h263_pred || s->h263_aic) + s->mbintra_table[mb_x + mb_y*s->mb_width]=1; + /* update motion predictor */ if (s->out_format == FMT_H263) { - int x, y, wrap; + int xy, wrap, motion_x, motion_y; - x = 2 * mb_x + 1; - y = 2 * mb_y + 1; wrap = 2 * s->mb_width + 2; + xy = 2 * mb_x + 1 + (2 * mb_y + 1) * wrap; if (s->mb_intra) { motion_x = 0; motion_y = 0; @@ -748,14 +949,14 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) 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; + s->motion_val[xy][0] = motion_x; + s->motion_val[xy][1] = motion_y; + s->motion_val[xy + 1][0] = motion_x; + s->motion_val[xy + 1][1] = motion_y; + s->motion_val[xy + wrap][0] = motion_x; + s->motion_val[xy + wrap][1] = motion_y; + s->motion_val[xy + 1 + wrap][0] = motion_x; + s->motion_val[xy + 1 + wrap][1] = motion_y; } } @@ -791,20 +992,23 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) if (!s->mb_intra) { /* motion handling */ - if (!s->no_rounding) + if (!s->no_rounding){ op_pix = put_pixels_tab; - else + op_qpix= qpel_mc_rnd_tab; + }else{ op_pix = put_no_rnd_pixels_tab; + op_qpix= qpel_mc_no_rnd_tab; + } if (s->mv_dir & MV_DIR_FORWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix); + MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix); 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); + MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix); } /* add dct residue */ @@ -832,7 +1036,7 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) static void encode_picture(MpegEncContext *s, int picture_number) { - int mb_x, mb_y, wrap, last_gob; + int mb_x, mb_y, wrap, last_gob, pdif = 0; UINT8 *ptr; int i, motion_x, motion_y; @@ -846,10 +1050,10 @@ static void encode_picture(MpegEncContext *s, int picture_number) 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); + convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, 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); + convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, s->qscale); + convert_matrix(s->q_non_intra_matrix, s->q_non_intra_matrix16, s->non_intra_matrix, s->qscale); } switch(s->out_format) { @@ -883,7 +1087,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->mv_dir = MV_DIR_FORWARD; /* Get the GOB height based on picture height */ - if (s->out_format == FMT_H263 && s->h263_plus) { + if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4) { if (s->height <= 400) s->gob_index = 1; else if (s->height <= 800) @@ -891,25 +1095,55 @@ static void encode_picture(MpegEncContext *s, int picture_number) else s->gob_index = 4; } - + + /* Reset the average MB variance */ + s->avg_mb_var = 0; + + /* Estimate motion for every MB */ + 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; + } + /* Store MB type and MV */ + s->mb_type[mb_y * s->mb_width + mb_x] = s->mb_intra; + s->mv_table[0][mb_y * s->mb_width + mb_x] = motion_x; + s->mv_table[1][mb_y * s->mb_width + mb_x] = motion_y; + } + } + + s->avg_mb_var = s->avg_mb_var / s->mb_num; + for(mb_y=0; mb_y < s->mb_height; mb_y++) { /* Put GOB header based on RTP MTU */ - if (!mb_y) { - s->ptr_lastgob = s->pb.buf_ptr; - s->ptr_last_mb_line = s->pb.buf_ptr; - } else if (s->out_format == FMT_H263 && s->h263_plus) { - last_gob = h263_encode_gob_header(s, mb_y); - if (last_gob) { - //fprintf(stderr,"\nLast GOB size: %d", last_gob); - s->first_gob_line = 1; - } else - s->first_gob_line = 0; + /* TODO: Put all this stuff in a separate generic function */ + if (s->rtp_mode) { + if (!mb_y) { + s->ptr_lastgob = s->pb.buf; + s->ptr_last_mb_line = s->pb.buf; + } else if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4 && !(mb_y % s->gob_index)) { + last_gob = h263_encode_gob_header(s, mb_y); + if (last_gob) { + s->first_gob_line = 1; + } + } } + for(mb_x=0; mb_x < s->mb_width; mb_x++) { s->mb_x = mb_x; s->mb_y = mb_y; - +#if 0 /* compute motion vector and macro block type (intra or non intra) */ motion_x = 0; motion_y = 0; @@ -920,7 +1154,12 @@ static void encode_picture(MpegEncContext *s, int picture_number) } else { s->mb_intra = 1; } +#endif + s->mb_intra = s->mb_type[mb_y * s->mb_width + mb_x]; + motion_x = s->mv_table[0][mb_y * s->mb_width + mb_x]; + motion_y = s->mv_table[1][mb_y * s->mb_width + mb_x]; + /* get the pixels */ wrap = s->linesize; ptr = s->new_picture[0] + (mb_y * 16 * wrap) + mb_x * 16; @@ -973,7 +1212,20 @@ static void encode_picture(MpegEncContext *s, int picture_number) sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy); } emms_c(); - + +#if 0 + { + float adap_parm; + + adap_parm = ((s->avg_mb_var << 1) + s->mb_var[s->mb_width*mb_y+mb_x] + 1.0) / + ((s->mb_var[s->mb_width*mb_y+mb_x] << 1) + s->avg_mb_var + 1.0); + + printf("\ntype=%c qscale=%2d adap=%0.2f dquant=%4.2f var=%4d avgvar=%4d", + (s->mb_type[s->mb_width*mb_y+mb_x] > 0) ? 'I' : 'P', + s->qscale, adap_parm, s->qscale*adap_parm, + s->mb_var[s->mb_width*mb_y+mb_x], s->avg_mb_var); + } +#endif /* DCT & quantize */ if (s->h263_msmpeg4) { msmpeg4_dc_scale(s); @@ -984,14 +1236,8 @@ static void encode_picture(MpegEncContext *s, int picture_number) 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; + s->block_last_index[i] = dct_quantize(s, s->block[i], i, s->qscale); } /* huffman encode */ @@ -1016,25 +1262,66 @@ static void encode_picture(MpegEncContext *s, int picture_number) MPV_decode_mb(s, s->block); } - /* Obtain average MB line size for RTP */ - if (!mb_y) - s->mb_line_avgsize = s->pb.buf_ptr - s->ptr_last_mb_line; - else - s->mb_line_avgsize = (s->mb_line_avgsize + s->pb.buf_ptr - s->ptr_last_mb_line) >> 1; - //fprintf(stderr, "\nMB line: %d\tSize: %u\tAvg. Size: %u", s->mb_y, - // (s->pb.buf_ptr - s->ptr_last_mb_line), s->mb_line_avgsize); - s->ptr_last_mb_line = s->pb.buf_ptr; + + + /* Obtain average GOB size for RTP */ + if (s->rtp_mode) { + if (!mb_y) + s->mb_line_avgsize = pbBufPtr(&s->pb) - s->ptr_last_mb_line; + else if (!(mb_y % s->gob_index)) { + s->mb_line_avgsize = (s->mb_line_avgsize + pbBufPtr(&s->pb) - s->ptr_last_mb_line) >> 1; + s->ptr_last_mb_line = pbBufPtr(&s->pb); + } + //fprintf(stderr, "\nMB line: %d\tSize: %u\tAvg. Size: %u", s->mb_y, + // (s->pb.buf_ptr - s->ptr_last_mb_line), s->mb_line_avgsize); + s->first_gob_line = 0; + } } + + if (s->h263_msmpeg4 && s->pict_type == I_TYPE) + msmpeg4_encode_ext_header(s); + //if (s->gob_number) // fprintf(stderr,"\nNumber of GOB: %d", s->gob_number); + + /* Send the last GOB if RTP */ + if (s->rtp_mode) { + flush_put_bits(&s->pb); + pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; + /* Call the RTP callback to send the last GOB */ + if (s->rtp_callback) + s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number); + s->ptr_lastgob = pbBufPtr(&s->pb); + //fprintf(stderr,"\nGOB: %2d size: %d (last)", s->gob_number, pdif); + } + } -static int dct_quantize(MpegEncContext *s, +static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale) { int i, j, level, last_non_zero, q; const int *qmat; + int minLevel, maxLevel; + + if(s->avctx!=NULL && s->avctx->codec->id==CODEC_ID_MPEG4){ + /* mpeg4 */ + minLevel= -2048; + maxLevel= 2047; + }else if(s->out_format==FMT_MPEG1){ + /* mpeg1 */ + minLevel= -255; + maxLevel= 255; + }else if(s->out_format==FMT_MJPEG){ + /* (m)jpeg */ + minLevel= -1023; + maxLevel= 1023; + }else{ + /* h263 / msmpeg4 */ + minLevel= -128; + maxLevel= 127; + } av_fdct (block); @@ -1107,74 +1394,11 @@ static int dct_quantize(MpegEncContext *s, 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; -} + if (level > maxLevel) + level = maxLevel; + else if (level < minLevel) + level = minLevel; -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); - - /* we need this permutation so that we correct the IDCT - permutation. will be moved into DCT code */ - block_permute(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 { @@ -1187,9 +1411,12 @@ static int dct_quantize_mmx(MpegEncContext *s, static void dct_unquantize_mpeg1_c(MpegEncContext *s, DCTELEM *block, int n, int qscale) { - int i, level; + int i, level, nCoeffs; const UINT16 *quant_matrix; + if(s->alternate_scan) nCoeffs= 64; + else nCoeffs= s->block_last_index[n]+1; + if (s->mb_intra) { if (n < 4) block[0] = block[0] * s->y_dc_scale; @@ -1197,47 +1424,49 @@ static void dct_unquantize_mpeg1_c(MpegEncContext *s, 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]; + for(i=1;i<nCoeffs;i++) { + int j= zigzag_direct[i]; + level = block[j]; if (level) { if (level < 0) { level = -level; - level = (int)(level * qscale * quant_matrix[i]) >> 3; + level = (int)(level * qscale * quant_matrix[j]) >> 3; level = (level - 1) | 1; level = -level; } else { - level = (int)(level * qscale * quant_matrix[i]) >> 3; + level = (int)(level * qscale * quant_matrix[j]) >> 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; + block[j] = level; } } } else { i = 0; quant_matrix = s->non_intra_matrix; - for(;i<64;i++) { - level = block[i]; + for(;i<nCoeffs;i++) { + int j= zigzag_direct[i]; + level = block[j]; if (level) { if (level < 0) { level = -level; level = (((level << 1) + 1) * qscale * - ((int) (quant_matrix[i]))) >> 4; + ((int) (quant_matrix[j]))) >> 4; level = (level - 1) | 1; level = -level; } else { level = (((level << 1) + 1) * qscale * - ((int) (quant_matrix[i]))) >> 4; + ((int) (quant_matrix[j]))) >> 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; + block[j] = level; } } } @@ -1247,21 +1476,29 @@ static void dct_unquantize_h263_c(MpegEncContext *s, DCTELEM *block, int n, int qscale) { int i, level, qmul, qadd; - + int nCoeffs; + 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->h263_aic) { + if (n < 4) + block[0] = block[0] * s->y_dc_scale; + else + block[0] = block[0] * s->c_dc_scale; + } i = 1; + nCoeffs= 64; //does not allways use zigzag table } else { i = 0; + nCoeffs= zigzag_end[ s->block_last_index[n] ]; } qmul = s->qscale << 1; - qadd = (s->qscale - 1) | 1; + if (s->h263_aic && s->mb_intra) + qadd = 0; + else + qadd = (s->qscale - 1) | 1; - for(;i<64;i++) { + for(;i<nCoeffs;i++) { level = block[i]; if (level) { if (level < 0) { @@ -1310,9 +1547,9 @@ static void rate_control_init(MpegEncContext *s) */ static int rate_estimate_qscale(MpegEncContext *s) { - INT64 total_bits = s->total_bits; + INT64 diff, total_bits = s->total_bits; float q; - int qscale, diff, qmin; + int qscale, qmin; if (s->pict_type == I_TYPE) { s->wanted_bits += s->I_frame_bits; @@ -1335,12 +1572,13 @@ static int rate_estimate_qscale(MpegEncContext *s) q = 31; qscale = (int)(q + 0.5); #if defined(DEBUG) - printf("%d: total=%0.0f br=%0.1f diff=%d qest=%0.1f\n", + printf("\n%d: total=%0.0f wanted=%0.0f br=%0.1f diff=%d qest=%2.1f\n", s->picture_number, (double)total_bits, + (double)s->wanted_bits, (float)s->frame_rate / FRAME_RATE_BASE * total_bits / s->picture_number, - diff, q); + (int)diff, q); #endif return qscale; } diff --git a/src/libffmpeg/libavcodec/mpegvideo.h b/src/libffmpeg/libavcodec/mpegvideo.h index 90559787b..01e477865 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.h +++ b/src/libffmpeg/libavcodec/mpegvideo.h @@ -21,6 +21,7 @@ #define I_TYPE 1 #define P_TYPE 2 #define B_TYPE 3 +#define S_TYPE 4 //S(GMC)-VOP MPEG4 enum OutputFormat { FMT_MPEG1, @@ -30,6 +31,9 @@ enum OutputFormat { #define MPEG_BUF_SIZE (16 * 1024) +#define QMAT_SHIFT_MMX 19 +#define QMAT_SHIFT 25 + typedef struct MpegEncContext { struct AVCodecContext *avctx; /* the following parameters must be initialized before encoding */ @@ -55,8 +59,9 @@ typedef struct MpegEncContext { 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 gop_picture_number; /* index of the first picture of a GOP */ int mb_width, mb_height; + int mb_num; /* number of MBs of a picture */ 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 */ @@ -75,6 +80,7 @@ typedef struct MpegEncContext { int mb_skiped; /* MUST BE SET only during DECODING */ UINT8 *mbskip_table; /* used to avoid copy if macroblock skipped (for black regions for example) */ + UINT8 *mbintra_table; /* used to kill a few memsets */ int qscale; int pict_type; @@ -84,6 +90,8 @@ typedef struct MpegEncContext { int h263_long_vectors; /* use horrible h263v1 long vector mode */ int f_code; /* resolution */ + int b_code; /* resolution for B Frames*/ + INT16 *mv_table[2]; /* MV table */ INT16 (*motion_val)[2]; /* used for MV prediction */ int full_search; int mv_dir; @@ -111,6 +119,9 @@ typedef struct MpegEncContext { int mb_x, mb_y; int mb_incr; int mb_intra; + INT16 *mb_var; /* Table for MB variances */ + char *mb_type; /* Table for MB type */ + /* matrix transmitted in the bitstream */ UINT16 intra_matrix[64]; UINT16 chroma_intra_matrix[64]; @@ -119,6 +130,9 @@ typedef struct MpegEncContext { /* precomputed matrix (combine qscale and DCT renorm) */ int q_intra_matrix[64]; int q_non_intra_matrix[64]; + /* identical to the above but for MMX & these are not permutated */ + UINT16 __align8 q_intra_matrix16[64] ; + UINT16 __align8 q_non_intra_matrix16[64]; int block_last_index[6]; /* last non zero coefficient in block */ void *opaque; /* private data for the user */ @@ -126,6 +140,7 @@ typedef struct MpegEncContext { /* bit rate control */ int I_frame_bits; /* wanted number of bits per I frame */ int P_frame_bits; /* same for P frame */ + int avg_mb_var; /* average MB variance for current frame */ INT64 wanted_bits; INT64 total_bits; @@ -133,16 +148,41 @@ typedef struct MpegEncContext { int gob_number; int gob_index; int first_gob_line; - + /* H.263+ specific */ int umvplus; int umvplus_dec; + int h263_aic; /* Advanded INTRA Coding (AIC) */ + int h263_aic_dir; /* AIC direction: 0 = left, 1 = top */ /* mpeg4 specific */ int time_increment_bits; int shape; int vol_sprite_usage; + int sprite_width; + int sprite_height; + int sprite_left; + int sprite_top; + int sprite_brightness_change; + int num_sprite_warping_points; + int real_sprite_warping_points; + int sprite_offset[2][2]; + int sprite_delta[2][2][2]; + int sprite_shift[2][2]; + int mcsel; int quant_precision; + int quarter_sample; + int scalability; + int new_pred; + int reduced_res_vop; + int aspect_ratio_info; + int sprite_warping_accuracy; + int low_latency_sprite; + int data_partioning; + + /* divx specific, used to workaround (many) bugs in divx5 */ + int divx_version; + int divx_build; /* RV10 specific */ int rv10_version; /* RV10 version: 0 or 3 */ @@ -150,6 +190,10 @@ typedef struct MpegEncContext { /* MJPEG specific */ struct MJpegContext *mjpeg_ctx; + int mjpeg_vsample[3]; /* vertical sampling factors, default = {2, 1, 1} */ + int mjpeg_hsample[3]; /* horizontal sampling factors, default = {2, 1, 1} */ + int mjpeg_write_tables; /* do we want to have quantisation- and + huffmantables in the jpeg file ? */ /* MSMPEG4 specific */ int mv_table_index; @@ -159,6 +203,8 @@ typedef struct MpegEncContext { int use_skip_mb_code; int slice_height; /* in macroblocks */ int first_slice_line; + int flipflop_rounding; + int bitrate; /* decompression specific */ GetBitContext gb; @@ -188,8 +234,10 @@ typedef struct MpegEncContext { int first_slice; /* RTP specific */ + /* These are explained on avcodec.h */ int rtp_mode; int rtp_payload_size; + void (*rtp_callback)(void *data, int size, int packet_number); UINT8 *ptr_lastgob; UINT8 *ptr_last_mb_line; UINT32 mb_line_avgsize; @@ -283,11 +331,13 @@ int rv_decode_dc(MpegEncContext *s, int n); /* msmpeg4.c */ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number); +void msmpeg4_encode_ext_header(MpegEncContext * s); 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_ext_header(MpegEncContext * s, int buf_size); int msmpeg4_decode_mb(MpegEncContext *s, DCTELEM block[6][64]); int msmpeg4_decode_init_vlc(MpegEncContext *s); diff --git a/src/libffmpeg/libavcodec/msmpeg4.c b/src/libffmpeg/libavcodec/msmpeg4.c index 01e3d5438..8fa9aefaa 100644 --- a/src/libffmpeg/libavcodec/msmpeg4.c +++ b/src/libffmpeg/libavcodec/msmpeg4.c @@ -21,6 +21,7 @@ #include "common.h" #include "dsputil.h" #include "mpegvideo.h" +#include "avcodec.h" /* * You can also call this codec : MPEG4 with a twist ! @@ -50,6 +51,8 @@ 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); +extern UINT32 inverse[256]; + #ifdef DEBUG int intra_count = 0; int frame_count = 0; @@ -185,7 +188,12 @@ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number) put_bits(&s->pb, 1, s->dc_table_index); put_bits(&s->pb, 1, s->mv_table_index); - s->no_rounding ^= 1; + + if(s->flipflop_rounding){ + s->no_rounding ^= 1; + }else{ + s->no_rounding = 0; + } } if (!init_done) { @@ -203,6 +211,18 @@ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number) #endif } +void msmpeg4_encode_ext_header(MpegEncContext * s) +{ + s->flipflop_rounding=1; + s->bitrate= 910; // FIXME + + put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29 + + put_bits(&s->pb, 11, s->bitrate); + + put_bits(&s->pb, 1, s->flipflop_rounding); +} + /* predict coded block */ static inline int coded_block_pred(MpegEncContext * s, int n, UINT8 **coded_block_ptr) { @@ -347,36 +367,57 @@ void msmpeg4_encode_mb(MpegEncContext * s, /* 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; + if (s->qscale < 5){ + s->y_dc_scale = 8; + s->c_dc_scale = 8; +// s->c_dc_scale = (s->qscale + 13)>>1; + }else if (s->qscale < 9){ + s->y_dc_scale = 2 * s->qscale; + s->c_dc_scale = (s->qscale + 13)>>1; + }else{ + s->y_dc_scale = s->qscale + 8; + s->c_dc_scale = (s->qscale + 13)>>1; + } + // this differs for quant >24 from mpeg4 + +// if(s->qscale==13) s->c_dc_scale=14; + +// if(s->qscale>=6) +// printf("%d", s->qscale); + + /* s->c_dc_scale values (found by Michael Nidermayer) + qscale=2 -> 8 (yes iam sure about that) + qscale=3 -> 8 + qscale=4 -> 8 + qscale=5 -> 9 + qscale=6 -> 9 + qscale=7 -> 10 + qscale=8 -> 10 + qscale=9 -> 11 + qscale=10-> 11 + */ } /* 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; + int a, b, c, xy, 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; + xy = 2 * s->mb_y + 1 + ((n & 2) >> 1); + xy *= wrap; + xy += 2 * s->mb_x + 1 + (n & 1); 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; + xy = s->mb_y + 1; + xy *= wrap; + xy += s->mb_x + 1; dc_val = s->dc_val[n - 4 + 1]; scale = s->c_dc_scale; } @@ -384,18 +425,48 @@ static int msmpeg4_pred_dc(MpegEncContext * s, int n, /* 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]; + a = dc_val[xy - 1]; + b = dc_val[xy - 1 - wrap]; + c = dc_val[xy - 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; - +#if defined ARCH_X86 && !defined PIC + asm volatile( + "movl %3, %%eax \n\t" + "shrl $1, %%eax \n\t" + "addl %%eax, %2 \n\t" + "addl %%eax, %1 \n\t" + "addl %0, %%eax \n\t" + "mull %4 \n\t" + "movl %%edx, %0 \n\t" + "movl %1, %%eax \n\t" + "mull %4 \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%eax \n\t" + "mull %4 \n\t" + "movl %%edx, %2 \n\t" + : "+b" (a), "+c" (b), "+D" (c) + : "g" (scale), "S" (inverse[scale]) + : "%eax", "%edx" + ); +#else + /* #elif defined (ARCH_ALPHA) */ + /* Divisions are extremely costly on Alpha; optimize the most + common case. But they are costly everywhere... + */ + if (scale == 8) { + a = (a + (8 >> 1)) / 8; + b = (b + (8 >> 1)) / 8; + c = (c + (8 >> 1)) / 8; + } else { + a = (a + (scale >> 1)) / scale; + b = (b + (scale >> 1)) / scale; + c = (c + (scale >> 1)) / scale; + } +#endif /* XXX: WARNING: they did not choose the same test as MPEG4. This is very important ! */ if (abs(a - b) <= abs(b - c)) { @@ -407,7 +478,7 @@ static int msmpeg4_pred_dc(MpegEncContext * s, int n, } /* update predictor */ - *dc_val_ptr = &dc_val[(x) + (y) * wrap]; + *dc_val_ptr = &dc_val[xy]; return pred; } @@ -623,6 +694,7 @@ int msmpeg4_decode_picture_header(MpegEncContext * s) code = get_bits(&s->gb, 5); /* 0x17: one slice, 0x18: three slices */ /* XXX: implement it */ + //printf("%d %d %d\n", code, s->slice_height, s->first_slice_line); if (code < 0x17) return -1; s->slice_height = s->mb_height / (code - 0x16); @@ -631,6 +703,11 @@ int msmpeg4_decode_picture_header(MpegEncContext * s) s->dc_table_index = get_bits1(&s->gb); s->no_rounding = 1; +/* printf(" %d %d %d %d \n", + s->qscale, + s->rl_chroma_table_index, + s->rl_table_index, + s->dc_table_index);*/ } else { s->use_skip_mb_code = get_bits1(&s->gb); @@ -640,15 +717,50 @@ int msmpeg4_decode_picture_header(MpegEncContext * s) s->dc_table_index = get_bits1(&s->gb); s->mv_table_index = get_bits1(&s->gb); - s->no_rounding ^= 1; +/* printf(" %d %d %d %d %d \n", + s->use_skip_mb_code, + s->rl_table_index, + s->rl_chroma_table_index, + s->dc_table_index, + s->mv_table_index);*/ + if(s->flipflop_rounding){ + s->no_rounding ^= 1; + }else{ + s->no_rounding = 0; + } +// printf("%d", s->no_rounding); } + + #ifdef DEBUG printf("*****frame %d:\n", frame_count++); #endif return 0; } -void memsetw(short *tab, int val, int n) +int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size) +{ + /* the alt_bitstream reader could read over the end so we need to check it */ + if(get_bits_count(&s->gb) + 16 < buf_size*8) + { + int fps; + + fps= get_bits(&s->gb, 5); + s->bitrate= get_bits(&s->gb, 11); + s->flipflop_rounding= get_bits1(&s->gb); + +// printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bitrate, s->flipflop_rounding); + } + else + { + s->flipflop_rounding= 0; + s->bitrate= 0; + } + + return 0; +} + +static inline void memsetw(short *tab, int val, int n) { int i; for(i=0;i<n;i++) @@ -659,7 +771,6 @@ int msmpeg4_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) { int cbp, code, i; - int pred, val; UINT8 *coded_val; /* special slice handling */ @@ -675,6 +786,16 @@ int msmpeg4_decode_mb(MpegEncContext *s, 1024, s->mb_width); memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap], 1024, s->mb_width); + + /* reset AC pred (set previous line to 0) */ + wrap = s->mb_width * 2 + 2; + memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16, + 0, 2 * s->mb_width*16); + wrap = s->mb_width + 2; + memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16, + 0, s->mb_width*16); + memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16, + 0, s->mb_width*16); s->first_slice_line = 1; } else { @@ -702,10 +823,8 @@ int msmpeg4_decode_mb(MpegEncContext *s, 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; + //s->mb_intra = (code & 0x40) ? 0 : 1; + s->mb_intra = (~code & 0x40) >> 6; cbp = code & 0x3f; } else { @@ -717,9 +836,9 @@ int msmpeg4_decode_mb(MpegEncContext *s, /* predict coded block pattern */ cbp = 0; for(i=0;i<6;i++) { - val = ((code >> (5 - i)) & 1); + int val = ((code >> (5 - i)) & 1); if (i < 4) { - pred = coded_block_pred(s, i, &coded_val); + int pred = coded_block_pred(s, i, &coded_val); val = val ^ pred; *coded_val = val; } @@ -744,7 +863,10 @@ int msmpeg4_decode_mb(MpegEncContext *s, for (i = 0; i < 6; i++) { if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0) - return -1; + { + fprintf(stderr,"\nIgnoring error while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + // return -1; + } } return 0; } @@ -756,8 +878,12 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, int dc_pred_dir; RLTable *rl; const UINT8 *scan_table; + int qmul, qadd; if (s->mb_intra) { + qmul=1; + qadd=0; + /* DC coef */ set_stat(ST_DC); level = msmpeg4_decode_dc(s, n, &dc_pred_dir); @@ -769,6 +895,7 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, } else { rl = &rl_table[3 + s->rl_chroma_table_index]; } + run_diff = 0; i = 1; if (!coded) { @@ -784,6 +911,8 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, } set_stat(ST_INTRA_AC); } else { + qmul = s->qscale << 1; + qadd = (s->qscale - 1) | 1; i = 0; rl = &rl_table[3 + s->rl_table_index]; run_diff = 1; @@ -808,6 +937,9 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, run = get_bits(&s->gb, 6); level = get_bits(&s->gb, 8); level = (level << 24) >> 24; /* sign extend */ + //level = level * qmul + (level>0) * qadd - (level<=0) * qadd ; + if (level>0) level= level * qmul + qadd; + else level= level * qmul - qadd; } else { /* second escape */ code = get_vlc(&s->gb, &rl->vlc); @@ -817,6 +949,7 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, level = rl->table_level[code]; last = code >= rl->last; run += rl->max_run[last][level] + run_diff; + level= level * qmul + qadd; if (get_bits1(&s->gb)) level = -level; } @@ -829,12 +962,13 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, level = rl->table_level[code]; last = code >= rl->last; level += rl->max_level[last][run]; + level= level * qmul + qadd; if (get_bits1(&s->gb)) level = -level; } } else { run = rl->table_run[code]; - level = rl->table_level[code]; + level = rl->table_level[code] * qmul + qadd; last = code >= rl->last; if (get_bits1(&s->gb)) level = -level; diff --git a/src/libffmpeg/libavcodec/simple_idct.c b/src/libffmpeg/libavcodec/simple_idct.c index 5459b81b3..a9653b187 100644 --- a/src/libffmpeg/libavcodec/simple_idct.c +++ b/src/libffmpeg/libavcodec/simple_idct.c @@ -23,6 +23,7 @@ #include <inttypes.h> #include "simple_idct.h" +#include "../config.h" #if 0 #define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */ @@ -45,33 +46,50 @@ #define ROW_SHIFT 11 #define COL_SHIFT 20 // 6 #endif -#if 1 -static void inline idctRow (int16_t * row) + +/* 8x8 Matrix used to do a trivial (slow) 8 point IDCT */ +static int coeff[64]={ + W4, W4, W4, W4, W4, W4, W4, W4, + W1, W3, W5, W7,-W7,-W5,-W3,-W1, + W2, W6,-W6,-W2,-W2,-W6, W6, W2, + W3,-W7,-W1,-W5, W5, W1, W7,-W3, + W4,-W4,-W4, W4, W4,-W4,-W4, W4, + W5,-W1, W7, W3,-W3,-W7, W1,-W5, + W6,-W2, W2,-W6,-W6, W2,-W2, W6, + W7,-W5, W3,-W1, W1,-W3, W5,-W7 +}; + +static int inline idctRowCondZ (int16_t * row) { int a0, a1, a2, a3, b0, b1, b2, b3; - const int C1 =W1; - const int C2 =W2; - const int C3 =W3; - const int C4 =W4; - const int C5 =W5; - const int C6 =W6; - const int C7 =W7; - - if( !(row[1] | row[2] |row[3] |row[4] |row[5] |row[6] | row[7])) { - row[0] = row[1] = row[2] = row[3] = row[4] = - row[5] = row[6] = row[7] = row[0]<<3; - return; + + if( !( ((uint32_t*)row)[0]|((uint32_t*)row)[1] |((uint32_t*)row)[2] |((uint32_t*)row)[3])) { +/* row[0] = row[1] = row[2] = row[3] = row[4] = + row[5] = row[6] = row[7] = 0;*/ + return 0; } - a0 = C4*row[0] + C2*row[2] + C4*row[4] + C6*row[6] + (1<<(ROW_SHIFT-1)); - a1 = C4*row[0] + C6*row[2] - C4*row[4] - C2*row[6] + (1<<(ROW_SHIFT-1)); - a2 = C4*row[0] - C6*row[2] - C4*row[4] + C2*row[6] + (1<<(ROW_SHIFT-1)); - a3 = C4*row[0] - C2*row[2] + C4*row[4] - C6*row[6] + (1<<(ROW_SHIFT-1)); + if(!( ((uint32_t*)row)[2] |((uint32_t*)row)[3] )){ + a0 = W4*row[0] + W2*row[2] + (1<<(ROW_SHIFT-1)); + a1 = W4*row[0] + W6*row[2] + (1<<(ROW_SHIFT-1)); + a2 = W4*row[0] - W6*row[2] + (1<<(ROW_SHIFT-1)); + a3 = W4*row[0] - W2*row[2] + (1<<(ROW_SHIFT-1)); + + b0 = W1*row[1] + W3*row[3]; + b1 = W3*row[1] - W7*row[3]; + b2 = W5*row[1] - W1*row[3]; + b3 = W7*row[1] - W5*row[3]; + }else{ + a0 = W4*row[0] + W2*row[2] + W4*row[4] + W6*row[6] + (1<<(ROW_SHIFT-1)); + a1 = W4*row[0] + W6*row[2] - W4*row[4] - W2*row[6] + (1<<(ROW_SHIFT-1)); + a2 = W4*row[0] - W6*row[2] - W4*row[4] + W2*row[6] + (1<<(ROW_SHIFT-1)); + a3 = W4*row[0] - W2*row[2] + W4*row[4] - W6*row[6] + (1<<(ROW_SHIFT-1)); - b0 = C1*row[1] + C3*row[3] + C5*row[5] + C7*row[7]; - b1 = C3*row[1] - C7*row[3] - C1*row[5] - C5*row[7]; - b2 = C5*row[1] - C1*row[3] + C7*row[5] + C3*row[7]; - b3 = C7*row[1] - C5*row[3] + C3*row[5] - C1*row[7]; + b0 = W1*row[1] + W3*row[3] + W5*row[5] + W7*row[7]; + b1 = W3*row[1] - W7*row[3] - W1*row[5] - W5*row[7]; + b2 = W5*row[1] - W1*row[3] + W7*row[5] + W3*row[7]; + b3 = W7*row[1] - W5*row[3] + W3*row[5] - W1*row[7]; + } row[0] = (a0 + b0) >> ROW_SHIFT; row[1] = (a1 + b1) >> ROW_SHIFT; @@ -81,151 +99,491 @@ static void inline idctRow (int16_t * row) row[5] = (a2 - b2) >> ROW_SHIFT; row[6] = (a1 - b1) >> ROW_SHIFT; row[7] = (a0 - b0) >> ROW_SHIFT; + + return 1; } -static void inline idctCol (int16_t * col) +#ifdef ARCH_ALPHA +/* 0: all entries 0, 1: only first entry nonzero, 2: otherwise */ +static int inline idctRowCondDC(int16_t *row) +{ + int_fast32_t a0, a1, a2, a3, b0, b1, b2, b3; + uint64_t *lrow = (uint64_t *) row; + + if (lrow[1] == 0) { + if (lrow[0] == 0) + return 0; + if ((lrow[0] & ~0xffffULL) == 0) { + uint64_t v; + + a0 = W4 * row[0]; + a0 += 1 << (ROW_SHIFT - 1); + a0 >>= ROW_SHIFT; + v = (uint16_t) a0; + v += v << 16; + v += v << 32; + lrow[0] = v; + lrow[1] = v; + + return 1; + } + } + + a0 = W4 * row[0]; + a1 = W4 * row[0]; + a2 = W4 * row[0]; + a3 = W4 * row[0]; + + if (row[2]) { + a0 += W2 * row[2]; + a1 += W6 * row[2]; + a2 -= W6 * row[2]; + a3 -= W2 * row[2]; + } + + if (row[4]) { + a0 += W4 * row[4]; + a1 -= W4 * row[4]; + a2 -= W4 * row[4]; + a3 += W4 * row[4]; + } + + if (row[6]) { + a0 += W6 * row[6]; + a1 -= W2 * row[6]; + a2 += W2 * row[6]; + a3 -= W6 * row[6]; + } + + a0 += 1 << (ROW_SHIFT - 1); + a1 += 1 << (ROW_SHIFT - 1); + a2 += 1 << (ROW_SHIFT - 1); + a3 += 1 << (ROW_SHIFT - 1); + + if (row[1]) { + b0 = W1 * row[1]; + b1 = W3 * row[1]; + b2 = W5 * row[1]; + b3 = W7 * row[1]; + } else { + b0 = 0; + b1 = 0; + b2 = 0; + b3 = 0; + } + + if (row[3]) { + b0 += W3 * row[3]; + b1 -= W7 * row[3]; + b2 -= W1 * row[3]; + b3 -= W5 * row[3]; + } + + if (row[5]) { + b0 += W5 * row[5]; + b1 -= W1 * row[5]; + b2 += W7 * row[5]; + b3 += W3 * row[5]; + } + + if (row[7]) { + b0 += W7 * row[7]; + b1 -= W5 * row[7]; + b2 += W3 * row[7]; + b3 -= W1 * row[7]; + } + + row[0] = (a0 + b0) >> ROW_SHIFT; + row[1] = (a1 + b1) >> ROW_SHIFT; + row[2] = (a2 + b2) >> ROW_SHIFT; + row[3] = (a3 + b3) >> ROW_SHIFT; + row[4] = (a3 - b3) >> ROW_SHIFT; + row[5] = (a2 - b2) >> ROW_SHIFT; + row[6] = (a1 - b1) >> ROW_SHIFT; + row[7] = (a0 - b0) >> ROW_SHIFT; + + return 2; +} +#else /* not ARCH_ALPHA */ +static int inline idctRowCondDC (int16_t * row) { int a0, a1, a2, a3, b0, b1, b2, b3; - const int C1 =W1; - const int C2 =W2; - const int C3 =W3; - const int C4 =W4; - const int C5 =W5; - const int C6 =W6; - const int C7 =W7; + + if( !( ((uint32_t*)row)[1] |((uint32_t*)row)[2] |((uint32_t*)row)[3]| row[1])) { +// row[0] = row[1] = row[2] = row[3] = row[4] = row[5] = row[6] = row[7] = row[0]<<3; + uint16_t temp= row[0]<<3; + ((uint32_t*)row)[0]=((uint32_t*)row)[1]= + ((uint32_t*)row)[2]=((uint32_t*)row)[3]= temp + (temp<<16); + return 0; + } + + if(!( ((uint32_t*)row)[2] |((uint32_t*)row)[3] )){ + a0 = W4*row[0] + W2*row[2] + (1<<(ROW_SHIFT-1)); + a1 = W4*row[0] + W6*row[2] + (1<<(ROW_SHIFT-1)); + a2 = W4*row[0] - W6*row[2] + (1<<(ROW_SHIFT-1)); + a3 = W4*row[0] - W2*row[2] + (1<<(ROW_SHIFT-1)); + + b0 = W1*row[1] + W3*row[3]; + b1 = W3*row[1] - W7*row[3]; + b2 = W5*row[1] - W1*row[3]; + b3 = W7*row[1] - W5*row[3]; + }else{ + a0 = W4*row[0] + W2*row[2] + W4*row[4] + W6*row[6] + (1<<(ROW_SHIFT-1)); + a1 = W4*row[0] + W6*row[2] - W4*row[4] - W2*row[6] + (1<<(ROW_SHIFT-1)); + a2 = W4*row[0] - W6*row[2] - W4*row[4] + W2*row[6] + (1<<(ROW_SHIFT-1)); + a3 = W4*row[0] - W2*row[2] + W4*row[4] - W6*row[6] + (1<<(ROW_SHIFT-1)); + + b0 = W1*row[1] + W3*row[3] + W5*row[5] + W7*row[7]; + b1 = W3*row[1] - W7*row[3] - W1*row[5] - W5*row[7]; + b2 = W5*row[1] - W1*row[3] + W7*row[5] + W3*row[7]; + b3 = W7*row[1] - W5*row[3] + W3*row[5] - W1*row[7]; + } + + row[0] = (a0 + b0) >> ROW_SHIFT; + row[7] = (a0 - b0) >> ROW_SHIFT; + row[1] = (a1 + b1) >> ROW_SHIFT; + row[6] = (a1 - b1) >> ROW_SHIFT; + row[2] = (a2 + b2) >> ROW_SHIFT; + row[5] = (a2 - b2) >> ROW_SHIFT; + row[3] = (a3 + b3) >> ROW_SHIFT; + row[4] = (a3 - b3) >> ROW_SHIFT; + + return 1; +} +#endif /* not ARCH_ALPHA */ + +static void inline idctCol (int16_t * col) +{ + /* if( !(col[8*1] | col[8*2] |col[8*3] |col[8*4] |col[8*5] |col[8*6] | col[8*7])) { col[8*0] = col[8*1] = col[8*2] = col[8*3] = col[8*4] = col[8*5] = col[8*6] = col[8*7] = col[8*0]<<3; return; }*/ + + int a0, a1, a2, a3, b0, b1, b2, b3; col[0] += (1<<(COL_SHIFT-1))/W4; - a0 = C4*col[8*0] + C2*col[8*2] + C4*col[8*4] + C6*col[8*6]; - a1 = C4*col[8*0] + C6*col[8*2] - C4*col[8*4] - C2*col[8*6]; - a2 = C4*col[8*0] - C6*col[8*2] - C4*col[8*4] + C2*col[8*6]; - a3 = C4*col[8*0] - C2*col[8*2] + C4*col[8*4] - C6*col[8*6]; + a0 = W4*col[8*0] + W2*col[8*2] + W4*col[8*4] + W6*col[8*6]; + a1 = W4*col[8*0] + W6*col[8*2] - W4*col[8*4] - W2*col[8*6]; + a2 = W4*col[8*0] - W6*col[8*2] - W4*col[8*4] + W2*col[8*6]; + a3 = W4*col[8*0] - W2*col[8*2] + W4*col[8*4] - W6*col[8*6]; - b0 = C1*col[8*1] + C3*col[8*3] + C5*col[8*5] + C7*col[8*7]; - b1 = C3*col[8*1] - C7*col[8*3] - C1*col[8*5] - C5*col[8*7]; - b2 = C5*col[8*1] - C1*col[8*3] + C7*col[8*5] + C3*col[8*7]; - b3 = C7*col[8*1] - C5*col[8*3] + C3*col[8*5] - C1*col[8*7]; + b0 = W1*col[8*1] + W3*col[8*3] + W5*col[8*5] + W7*col[8*7]; + b1 = W3*col[8*1] - W7*col[8*3] - W1*col[8*5] - W5*col[8*7]; + b2 = W5*col[8*1] - W1*col[8*3] + W7*col[8*5] + W3*col[8*7]; + b3 = W7*col[8*1] - W5*col[8*3] + W3*col[8*5] - W1*col[8*7]; col[8*0] = (a0 + b0) >> COL_SHIFT; + col[8*7] = (a0 - b0) >> COL_SHIFT; col[8*1] = (a1 + b1) >> COL_SHIFT; + col[8*6] = (a1 - b1) >> COL_SHIFT; col[8*2] = (a2 + b2) >> COL_SHIFT; + col[8*5] = (a2 - b2) >> COL_SHIFT; col[8*3] = (a3 + b3) >> COL_SHIFT; col[8*4] = (a3 - b3) >> COL_SHIFT; - col[8*5] = (a2 - b2) >> COL_SHIFT; - col[8*6] = (a1 - b1) >> COL_SHIFT; - col[8*7] = (a0 - b0) >> COL_SHIFT; } -void simple_idct (short *block) +static void inline idctSparseCol (int16_t * col) { - int i; - for(i=0; i<8; i++) - idctRow(block + 8*i); + int a0, a1, a2, a3, b0, b1, b2, b3; + col[0] += (1<<(COL_SHIFT-1))/W4; + a0 = W4*col[8*0]; + a1 = W4*col[8*0]; + a2 = W4*col[8*0]; + a3 = W4*col[8*0]; - for(i=0; i<8; i++) - idctCol(block + i); + if(col[8*2]){ + a0 += + W2*col[8*2]; + a1 += + W6*col[8*2]; + a2 += - W6*col[8*2]; + a3 += - W2*col[8*2]; + } -} + if(col[8*4]){ + a0 += + W4*col[8*4]; + a1 += - W4*col[8*4]; + a2 += - W4*col[8*4]; + a3 += + W4*col[8*4]; + } -#else + if(col[8*6]){ + a0 += + W6*col[8*6]; + a1 += - W2*col[8*6]; + a2 += + W2*col[8*6]; + a3 += - W6*col[8*6]; + } -#define W1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 -#define W2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 -#define W3 19266 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 -#define W4 16384 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 -#define W5 12873 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 -#define W6 8867 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 -#define W7 4520 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 -#define COL_SHIFT 31 // 6 + if(col[8*1]){ + b0 = W1*col[8*1]; + b1 = W3*col[8*1]; + b2 = W5*col[8*1]; + b3 = W7*col[8*1]; + }else{ + b0 = + b1 = + b2 = + b3 = 0; + } -static void inline idctRow (int32_t *out, int16_t * row) -{ - int a0, a1, a2, a3, b0, b1, b2, b3; - const int C1 =W1; - const int C2 =W2; - const int C3 =W3; - const int C4 =W4; - const int C5 =W5; - const int C6 =W6; - const int C7 =W7; -/* - if( !(row[1] | row[2] |row[3] |row[4] |row[5] |row[6] | row[7])) { - row[0] = row[1] = row[2] = row[3] = row[4] = - row[5] = row[6] = row[7] = row[0]<<14; - return; + if(col[8*3]){ + b0 += + W3*col[8*3]; + b1 += - W7*col[8*3]; + b2 += - W1*col[8*3]; + b3 += - W5*col[8*3]; } -*/ - a0 = C4*row[0] + C2*row[2] + C4*row[4] + C6*row[6]; - a1 = C4*row[0] + C6*row[2] - C4*row[4] - C2*row[6]; - a2 = C4*row[0] - C6*row[2] - C4*row[4] + C2*row[6]; - a3 = C4*row[0] - C2*row[2] + C4*row[4] - C6*row[6]; - - b0 = C1*row[1] + C3*row[3] + C5*row[5] + C7*row[7]; - b1 = C3*row[1] - C7*row[3] - C1*row[5] - C5*row[7]; - b2 = C5*row[1] - C1*row[3] + C7*row[5] + C3*row[7]; - b3 = C7*row[1] - C5*row[3] + C3*row[5] - C1*row[7]; - - out[0] = (a0 + b0); - out[1] = (a1 + b1); - out[2] = (a2 + b2); - out[3] = (a3 + b3); - out[4] = (a3 - b3); - out[5] = (a2 - b2); - out[6] = (a1 - b1); - out[7] = (a0 - b0); + + if(col[8*5]){ + b0 += + W5*col[8*5]; + b1 += - W1*col[8*5]; + b2 += + W7*col[8*5]; + b3 += + W3*col[8*5]; + } + + if(col[8*7]){ + b0 += + W7*col[8*7]; + b1 += - W5*col[8*7]; + b2 += + W3*col[8*7]; + b3 += - W1*col[8*7]; + } + +#ifndef ARCH_ALPHA + if(!(b0|b1|b2|b3)){ + col[8*0] = (a0) >> COL_SHIFT; + col[8*7] = (a0) >> COL_SHIFT; + col[8*1] = (a1) >> COL_SHIFT; + col[8*6] = (a1) >> COL_SHIFT; + col[8*2] = (a2) >> COL_SHIFT; + col[8*5] = (a2) >> COL_SHIFT; + col[8*3] = (a3) >> COL_SHIFT; + col[8*4] = (a3) >> COL_SHIFT; + }else{ +#endif + col[8*0] = (a0 + b0) >> COL_SHIFT; + col[8*7] = (a0 - b0) >> COL_SHIFT; + col[8*1] = (a1 + b1) >> COL_SHIFT; + col[8*6] = (a1 - b1) >> COL_SHIFT; + col[8*2] = (a2 + b2) >> COL_SHIFT; + col[8*5] = (a2 - b2) >> COL_SHIFT; + col[8*3] = (a3 + b3) >> COL_SHIFT; + col[8*4] = (a3 - b3) >> COL_SHIFT; +#ifndef ARCH_ALPHA + } +#endif } -static void inline idctCol (int32_t *in, int16_t * col) +static void inline idctSparse2Col (int16_t * col) { - int64_t a0, a1, a2, a3, b0, b1, b2, b3; - const int64_t C1 =W1; - const int64_t C2 =W2; - const int64_t C3 =W3; - const int64_t C4 =W4; - const int64_t C5 =W5; - const int64_t C6 =W6; - const int64_t C7 =W7; -/* - if( !(col[8*1] | col[8*2] |col[8*3] |col[8*4] |col[8*5] |col[8*6] | col[8*7])) { - col[8*0] = col[8*1] = col[8*2] = col[8*3] = col[8*4] = - col[8*5] = col[8*6] = col[8*7] = col[8*0]<<3; - return; - }*/ - in[0] += (1<<(COL_SHIFT-1))/W4; - a0 = C4*in[8*0] + C2*in[8*2] + C4*in[8*4] + C6*in[8*6]; - a1 = C4*in[8*0] + C6*in[8*2] - C4*in[8*4] - C2*in[8*6]; - a2 = C4*in[8*0] - C6*in[8*2] - C4*in[8*4] + C2*in[8*6]; - a3 = C4*in[8*0] - C2*in[8*2] + C4*in[8*4] - C6*in[8*6]; + int a0, a1, a2, a3, b0, b1, b2, b3; + col[0] += (1<<(COL_SHIFT-1))/W4; + a0 = W4*col[8*0]; + a1 = W4*col[8*0]; + a2 = W4*col[8*0]; + a3 = W4*col[8*0]; + + if(col[8*2]){ + a0 += + W2*col[8*2]; + a1 += + W6*col[8*2]; + a2 += - W6*col[8*2]; + a3 += - W2*col[8*2]; + } + + if(col[8*4]){ + a0 += + W4*col[8*4]; + a1 += - W4*col[8*4]; + a2 += - W4*col[8*4]; + a3 += + W4*col[8*4]; + } + + if(col[8*6]){ + a0 += + W6*col[8*6]; + a1 += - W2*col[8*6]; + a2 += + W2*col[8*6]; + a3 += - W6*col[8*6]; + } + + if(col[8*1] || 1){ + b0 = W1*col[8*1]; + b1 = W3*col[8*1]; + b2 = W5*col[8*1]; + b3 = W7*col[8*1]; + }else{ + b0 = + b1 = + b2 = + b3 = 0; + } - b0 = C1*in[8*1] + C3*in[8*3] + C5*in[8*5] + C7*in[8*7]; - b1 = C3*in[8*1] - C7*in[8*3] - C1*in[8*5] - C5*in[8*7]; - b2 = C5*in[8*1] - C1*in[8*3] + C7*in[8*5] + C3*in[8*7]; - b3 = C7*in[8*1] - C5*in[8*3] + C3*in[8*5] - C1*in[8*7]; + if(col[8*3]){ + b0 += + W3*col[8*3]; + b1 += - W7*col[8*3]; + b2 += - W1*col[8*3]; + b3 += - W5*col[8*3]; + } + + if(col[8*5]){ + b0 += + W5*col[8*5]; + b1 += - W1*col[8*5]; + b2 += + W7*col[8*5]; + b3 += + W3*col[8*5]; + } + + if(col[8*7]){ + b0 += + W7*col[8*7]; + b1 += - W5*col[8*7]; + b2 += + W3*col[8*7]; + b3 += - W1*col[8*7]; + } col[8*0] = (a0 + b0) >> COL_SHIFT; + col[8*7] = (a0 - b0) >> COL_SHIFT; col[8*1] = (a1 + b1) >> COL_SHIFT; + col[8*6] = (a1 - b1) >> COL_SHIFT; col[8*2] = (a2 + b2) >> COL_SHIFT; + col[8*5] = (a2 - b2) >> COL_SHIFT; col[8*3] = (a3 + b3) >> COL_SHIFT; col[8*4] = (a3 - b3) >> COL_SHIFT; - col[8*5] = (a2 - b2) >> COL_SHIFT; - col[8*6] = (a1 - b1) >> COL_SHIFT; - col[8*7] = (a0 - b0) >> COL_SHIFT; } -void simple_idct (short *block) +#ifdef ARCH_ALPHA +/* If all rows but the first one are zero after row transformation, + all rows will be identical after column transformation. */ +static inline void idctCol2(int16_t *col) { int i; - int32_t temp[64]; - for(i=0; i<8; i++) - idctRow(temp+8*i, block + 8*i); + uint64_t l, r; + uint64_t *lcol = (uint64_t *) col; - for(i=0; i<8; i++) - idctCol(temp+i, block + i); + for (i = 0; i < 8; ++i) { + int a0 = col[0] + (1 << (COL_SHIFT - 1)) / W4; + a0 *= W4; + col[0] = a0 >> COL_SHIFT; + ++col; + } + + l = lcol[0]; + r = lcol[1]; + lcol[ 2] = l; lcol[ 3] = r; + lcol[ 4] = l; lcol[ 5] = r; + lcol[ 6] = l; lcol[ 7] = r; + lcol[ 8] = l; lcol[ 9] = r; + lcol[10] = l; lcol[11] = r; + lcol[12] = l; lcol[13] = r; + lcol[14] = l; lcol[15] = r; } +#endif + +void simple_idct (short *block) +{ + + int i; + +#if 0 + int nonZero[8]; + int buffer[64]; + int nNonZero=0; + + idctRowCondDC(block); + + for(i=1; i<8; i++) + { + nonZero[nNonZero]=i; + nNonZero+= idctRowCondZ(block + i*8); + } + + if(nNonZero==0) + { + for(i=0; i<8; i++) + { + block[i ]= + block[i+8 ]= + block[i+16]= + block[i+24]= + block[i+32]= + block[i+40]= + block[i+48]= + block[i+56]= (W4*block[i] + (1<<(COL_SHIFT-1))) >> COL_SHIFT; + } + } + else if(nNonZero==1) + { + int index= nonZero[0]*8; + for(i=0; i<8; i++) + { + int bias= W4*block[i] + (1<<(COL_SHIFT-1)); + int c= block[i + index]; + block[i ]= (c*coeff[index ] + bias) >> COL_SHIFT; + block[i+8 ]= (c*coeff[index+1] + bias) >> COL_SHIFT; + block[i+16]= (c*coeff[index+2] + bias) >> COL_SHIFT; + block[i+24]= (c*coeff[index+3] + bias) >> COL_SHIFT; + block[i+32]= (c*coeff[index+4] + bias) >> COL_SHIFT; + block[i+40]= (c*coeff[index+5] + bias) >> COL_SHIFT; + block[i+48]= (c*coeff[index+6] + bias) >> COL_SHIFT; + block[i+56]= (c*coeff[index+7] + bias) >> COL_SHIFT; + } + } +/* else if(nNonZero==2) + { + int index1= nonZero[0]*8; + int index2= nonZero[1]*8; + for(i=0; i<8; i++) + { + int bias= W4*block[i] + (1<<(COL_SHIFT-1)); + int c1= block[i + index1]; + int c2= block[i + index2]; + block[i ]= (c1*coeff[index1 ] + c2*coeff[index2 ] + bias) >> COL_SHIFT; + block[i+8 ]= (c1*coeff[index1+1] + c2*coeff[index2+1] + bias) >> COL_SHIFT; + block[i+16]= (c1*coeff[index1+2] + c2*coeff[index2+2] + bias) >> COL_SHIFT; + block[i+24]= (c1*coeff[index1+3] + c2*coeff[index2+3] + bias) >> COL_SHIFT; + block[i+32]= (c1*coeff[index1+4] + c2*coeff[index2+4] + bias) >> COL_SHIFT; + block[i+40]= (c1*coeff[index1+5] + c2*coeff[index2+5] + bias) >> COL_SHIFT; + block[i+48]= (c1*coeff[index1+6] + c2*coeff[index2+6] + bias) >> COL_SHIFT; + block[i+56]= (c1*coeff[index1+7] + c2*coeff[index2+7] + bias) >> COL_SHIFT; + } + }*/ + else + { + for(i=0; i<8; i++) + idctSparse2Col(block + i); + } +#elif defined(ARCH_ALPHA) + int rowsZero = 1; /* all rows except row 0 zero */ + int rowsConstant = 1; /* all rows consist of a constant value */ + + for (i = 0; i < 8; i++) { + int sparseness = idctRowCondDC(block + 8 * i); + if (i > 0 && sparseness > 0) + rowsZero = 0; + if (sparseness == 2) + rowsConstant = 0; + } + + if (rowsZero) { + idctCol2(block); + } else if (rowsConstant) { + uint64_t *lblock = (uint64_t *) block; + + idctSparseCol(block); + for (i = 0; i < 8; i++) { + uint64_t v = (uint16_t) block[i * 8]; + + v += v << 16; + v += v << 32; + lblock[0] = v; + lblock[1] = v; + lblock += 2; + } + } else { + for (i = 0; i < 8; i++) + idctSparseCol(block + i); + } +#else + for(i=0; i<8; i++) + idctRowCondDC(block + i*8); + + for(i=0; i<8; i++) + idctSparseCol(block + i); #endif +} diff --git a/src/libffmpeg/libavcodec/utils.c b/src/libffmpeg/libavcodec/utils.c index aef27e342..f84b17e63 100644 --- a/src/libffmpeg/libavcodec/utils.c +++ b/src/libffmpeg/libavcodec/utils.c @@ -270,24 +270,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) enc->sample_rate, enc->channels == 2 ? "stereo" : "mono"); } - /* for PCM codecs, compute bitrate directly */ - switch(enc->codec_id) { - case CODEC_ID_PCM_S16LE: - case CODEC_ID_PCM_S16BE: - case CODEC_ID_PCM_U16LE: - case CODEC_ID_PCM_U16BE: - bitrate = enc->sample_rate * enc->channels * 16; - break; - case CODEC_ID_PCM_S8: - case CODEC_ID_PCM_U8: - case CODEC_ID_PCM_ALAW: - case CODEC_ID_PCM_MULAW: - bitrate = enc->sample_rate * enc->channels * 8; - break; - default: - bitrate = enc->bit_rate; - break; - } + bitrate = enc->bit_rate; break; default: abort(); @@ -390,20 +373,6 @@ void avcodec_init(void) /* 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(&mpeg4_encoder); - register_avcodec(&msmpeg4_encoder); -#endif /* CONFIG_ENCODERS */ - register_avcodec(&rawvideo_codec); - /* decoders */ #ifdef CONFIG_DECODERS register_avcodec(&h263_decoder); @@ -413,32 +382,8 @@ void avcodec_register_all(void) register_avcodec(&h263i_decoder); register_avcodec(&rv10_decoder); register_avcodec(&mjpeg_decoder); -#ifdef FF_AUDIO_CODECS - register_avcodec(&mp3_decoder); -#ifdef CONFIG_AC3 - register_avcodec(&ac3_decoder); -#endif -#endif #endif /* CONFIG_DECODERS */ -#ifdef FF_AUDIO_CODECS - /* pcm codecs */ - -#define PCM_CODEC(id, name) \ - register_avcodec(& name ## _encoder); \ - register_avcodec(& name ## _decoder); \ - -PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le); -PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be); -PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le); -PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be); -PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8); -PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8); -PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw); -PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw); - -#undef PCM_CODEC -#endif } static int encode_init(AVCodecContext *s) |