|
- /*
- * MSMPEG4 backend for encoder and decoder
- * Copyright (c) 2001 Fabrice Bellard
- * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
- *
- * msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
- *
- * This file is part of Libav.
- *
- * Libav is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * Libav is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
- /**
- * @file
- * MSMPEG4 backend for encoder and decoder
- */
-
- #include "avcodec.h"
- #include "idctdsp.h"
- #include "mpegvideo.h"
- #include "msmpeg4.h"
- #include "libavutil/x86/asm.h"
- #include "h263.h"
- #include "mpeg4video.h"
- #include "msmpeg4data.h"
- #include "mpegvideodata.h"
- #include "vc1data.h"
-
- /*
- * You can also call this codec: MPEG-4 with a twist!
- *
- * TODO:
- * - (encoding) select best mv table (two choices)
- * - (encoding) select best vlc/dc table
- */
-
- /* This table is practically identical to the one from H.263
- * except that it is inverted. */
- static av_cold void init_h263_dc_for_msmpeg4(void)
- {
- int level, uni_code, uni_len;
-
- for(level=-256; level<256; level++){
- int size, v, l;
- /* find number of bits */
- size = 0;
- v = abs(level);
- while (v) {
- v >>= 1;
- size++;
- }
-
- if (level < 0)
- l= (-level) ^ ((1 << size) - 1);
- else
- l= level;
-
- /* luminance H.263 */
- uni_code= ff_mpeg4_DCtab_lum[size][0];
- uni_len = ff_mpeg4_DCtab_lum[size][1];
- uni_code ^= (1<<uni_len)-1; //M$ does not like compatibility
-
- if (size > 0) {
- uni_code<<=size; uni_code|=l;
- uni_len+=size;
- if (size > 8){
- uni_code<<=1; uni_code|=1;
- uni_len++;
- }
- }
- ff_v2_dc_lum_table[level + 256][0] = uni_code;
- ff_v2_dc_lum_table[level + 256][1] = uni_len;
-
- /* chrominance H.263 */
- uni_code= ff_mpeg4_DCtab_chrom[size][0];
- uni_len = ff_mpeg4_DCtab_chrom[size][1];
- uni_code ^= (1<<uni_len)-1; //M$ does not like compatibility
-
- if (size > 0) {
- uni_code<<=size; uni_code|=l;
- uni_len+=size;
- if (size > 8){
- uni_code<<=1; uni_code|=1;
- uni_len++;
- }
- }
- ff_v2_dc_chroma_table[level + 256][0] = uni_code;
- ff_v2_dc_chroma_table[level + 256][1] = uni_len;
-
- }
- }
-
- av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
- {
- static int initialized=0;
-
- switch(s->msmpeg4_version){
- case 1:
- case 2:
- s->y_dc_scale_table=
- s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
- break;
- case 3:
- if(s->workaround_bugs){
- s->y_dc_scale_table= ff_old_ff_y_dc_scale_table;
- s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
- } else{
- s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table;
- s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table;
- }
- break;
- case 4:
- case 5:
- s->y_dc_scale_table= ff_wmv1_y_dc_scale_table;
- s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
- break;
- #if CONFIG_VC1_DECODER
- case 6:
- s->y_dc_scale_table= ff_wmv3_dc_scale_table;
- s->c_dc_scale_table= ff_wmv3_dc_scale_table;
- break;
- #endif
-
- }
-
-
- if(s->msmpeg4_version>=4){
- ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]);
- ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_wmv1_scantable[2]);
- ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_wmv1_scantable[3]);
- ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_wmv1_scantable[0]);
- }
- //Note the default tables are set in common_init in mpegvideo.c
-
- if(!initialized){
- initialized=1;
-
- init_h263_dc_for_msmpeg4();
- }
- }
-
- /* predict coded block */
- int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr)
- {
- int xy, wrap, pred, a, b, c;
-
- xy = s->block_index[n];
- wrap = s->b8_stride;
-
- /* B C
- * A X
- */
- a = s->coded_block[xy - 1 ];
- b = s->coded_block[xy - 1 - wrap];
- c = s->coded_block[xy - wrap];
-
- if (b == c) {
- pred = a;
- } else {
- pred = c;
- }
-
- /* store value */
- *coded_block_ptr = &s->coded_block[xy];
-
- return pred;
- }
-
- static int get_dc(uint8_t *src, int stride, int scale)
- {
- int y;
- int sum=0;
- for(y=0; y<8; y++){
- int x;
- for(x=0; x<8; x++){
- sum+=src[x + y*stride];
- }
- }
- return FASTDIV((sum + (scale>>1)), scale);
- }
-
- /* dir = 0: left, dir = 1: top prediction */
- int ff_msmpeg4_pred_dc(MpegEncContext *s, int n,
- int16_t **dc_val_ptr, int *dir_ptr)
- {
- int a, b, c, wrap, pred, scale;
- int16_t *dc_val;
-
- /* find prediction */
- if (n < 4) {
- scale = s->y_dc_scale;
- } else {
- scale = s->c_dc_scale;
- }
-
- wrap = s->block_wrap[n];
- dc_val= s->dc_val[0] + s->block_index[n];
-
- /* B C
- * A X
- */
- a = dc_val[ - 1];
- b = dc_val[ - 1 - wrap];
- c = dc_val[ - wrap];
-
- if(s->first_slice_line && (n&2)==0 && s->msmpeg4_version<4){
- b=c=1024;
- }
-
- /* 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 !) */
- #if ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE
- __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" (ff_inverse[scale])
- : "%eax", "%edx"
- );
- #else
- /* Divisions are costly everywhere; optimize the most common case. */
- if (scale == 8) {
- a = (a + (8 >> 1)) / 8;
- b = (b + (8 >> 1)) / 8;
- c = (c + (8 >> 1)) / 8;
- } else {
- a = FASTDIV((a + (scale >> 1)), scale);
- b = FASTDIV((b + (scale >> 1)), scale);
- c = FASTDIV((c + (scale >> 1)), scale);
- }
- #endif
- /* XXX: WARNING: they did not choose the same test as MPEG-4. This
- is very important ! */
- if(s->msmpeg4_version>3){
- if(s->inter_intra_pred){
- uint8_t *dest;
- int wrap;
-
- if(n==1){
- pred=a;
- *dir_ptr = 0;
- }else if(n==2){
- pred=c;
- *dir_ptr = 1;
- }else if(n==3){
- if (abs(a - b) < abs(b - c)) {
- pred = c;
- *dir_ptr = 1;
- } else {
- pred = a;
- *dir_ptr = 0;
- }
- }else{
- if(n<4){
- wrap= s->linesize;
- dest= s->current_picture.f->data[0] + (((n >> 1) + 2*s->mb_y) * 8* wrap ) + ((n & 1) + 2*s->mb_x) * 8;
- }else{
- wrap= s->uvlinesize;
- dest= s->current_picture.f->data[n - 3] + (s->mb_y * 8 * wrap) + s->mb_x * 8;
- }
- if(s->mb_x==0) a= (1024 + (scale>>1))/scale;
- else a= get_dc(dest-8, wrap, scale*8);
- if(s->mb_y==0) c= (1024 + (scale>>1))/scale;
- else c= get_dc(dest-8*wrap, wrap, scale*8);
-
- if (s->h263_aic_dir==0) {
- pred= a;
- *dir_ptr = 0;
- }else if (s->h263_aic_dir==1) {
- if(n==0){
- pred= c;
- *dir_ptr = 1;
- }else{
- pred= a;
- *dir_ptr = 0;
- }
- }else if (s->h263_aic_dir==2) {
- if(n==0){
- pred= a;
- *dir_ptr = 0;
- }else{
- pred= c;
- *dir_ptr = 1;
- }
- } else {
- pred= c;
- *dir_ptr = 1;
- }
- }
- }else{
- if (abs(a - b) < abs(b - c)) {
- pred = c;
- *dir_ptr = 1;
- } else {
- pred = a;
- *dir_ptr = 0;
- }
- }
- }else{
- if (abs(a - b) <= abs(b - c)) {
- pred = c;
- *dir_ptr = 1;
- } else {
- pred = a;
- *dir_ptr = 0;
- }
- }
-
- /* update predictor */
- *dc_val_ptr = &dc_val[0];
- return pred;
- }
|