• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/cabac.h

Go to the documentation of this file.
00001 /*
00002  * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
00003  * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #ifndef AVCODEC_CABAC_H
00028 #define AVCODEC_CABAC_H
00029 
00030 #include "put_bits.h"
00031 
00032 //#undef NDEBUG
00033 #include <assert.h>
00034 #include "libavutil/x86_cpu.h"
00035 
00036 #define CABAC_BITS 16
00037 #define CABAC_MASK ((1<<CABAC_BITS)-1)
00038 #define BRANCHLESS_CABAC_DECODER 1
00039 //#define ARCH_X86_DISABLED 1
00040 
00041 typedef struct CABACContext{
00042     int low;
00043     int range;
00044     int outstanding_count;
00045 #ifdef STRICT_LIMITS
00046     int symCount;
00047 #endif
00048     const uint8_t *bytestream_start;
00049     const uint8_t *bytestream;
00050     const uint8_t *bytestream_end;
00051     PutBitContext pb;
00052 }CABACContext;
00053 
00054 extern uint8_t ff_h264_mlps_state[4*64];
00055 extern uint8_t ff_h264_lps_range[4*2*64];  
00056 extern uint8_t ff_h264_mps_state[2*64];     
00057 extern uint8_t ff_h264_lps_state[2*64];     
00058 extern const uint8_t ff_h264_norm_shift[512];
00059 
00060 
00061 void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size);
00062 void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size);
00063 void ff_init_cabac_states(CABACContext *c);
00064 
00065 
00066 static inline void put_cabac_bit(CABACContext *c, int b){
00067     put_bits(&c->pb, 1, b);
00068     for(;c->outstanding_count; c->outstanding_count--){
00069         put_bits(&c->pb, 1, 1-b);
00070     }
00071 }
00072 
00073 static inline void renorm_cabac_encoder(CABACContext *c){
00074     while(c->range < 0x100){
00075         //FIXME optimize
00076         if(c->low<0x100){
00077             put_cabac_bit(c, 0);
00078         }else if(c->low<0x200){
00079             c->outstanding_count++;
00080             c->low -= 0x100;
00081         }else{
00082             put_cabac_bit(c, 1);
00083             c->low -= 0x200;
00084         }
00085 
00086         c->range+= c->range;
00087         c->low += c->low;
00088     }
00089 }
00090 
00091 #ifdef TEST
00092 static void put_cabac(CABACContext *c, uint8_t * const state, int bit){
00093     int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state];
00094 
00095     if(bit == ((*state)&1)){
00096         c->range -= RangeLPS;
00097         *state= ff_h264_mps_state[*state];
00098     }else{
00099         c->low += c->range - RangeLPS;
00100         c->range = RangeLPS;
00101         *state= ff_h264_lps_state[*state];
00102     }
00103 
00104     renorm_cabac_encoder(c);
00105 
00106 #ifdef STRICT_LIMITS
00107     c->symCount++;
00108 #endif
00109 }
00110 
00111 static void put_cabac_static(CABACContext *c, int RangeLPS, int bit){
00112     assert(c->range > RangeLPS);
00113 
00114     if(!bit){
00115         c->range -= RangeLPS;
00116     }else{
00117         c->low += c->range - RangeLPS;
00118         c->range = RangeLPS;
00119     }
00120 
00121     renorm_cabac_encoder(c);
00122 
00123 #ifdef STRICT_LIMITS
00124     c->symCount++;
00125 #endif
00126 }
00127 
00131 static void put_cabac_bypass(CABACContext *c, int bit){
00132     c->low += c->low;
00133 
00134     if(bit){
00135         c->low += c->range;
00136     }
00137 //FIXME optimize
00138     if(c->low<0x200){
00139         put_cabac_bit(c, 0);
00140     }else if(c->low<0x400){
00141         c->outstanding_count++;
00142         c->low -= 0x200;
00143     }else{
00144         put_cabac_bit(c, 1);
00145         c->low -= 0x400;
00146     }
00147 
00148 #ifdef STRICT_LIMITS
00149     c->symCount++;
00150 #endif
00151 }
00152 
00157 static int put_cabac_terminate(CABACContext *c, int bit){
00158     c->range -= 2;
00159 
00160     if(!bit){
00161         renorm_cabac_encoder(c);
00162     }else{
00163         c->low += c->range;
00164         c->range= 2;
00165 
00166         renorm_cabac_encoder(c);
00167 
00168         assert(c->low <= 0x1FF);
00169         put_cabac_bit(c, c->low>>9);
00170         put_bits(&c->pb, 2, ((c->low>>7)&3)|1);
00171 
00172         flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong
00173     }
00174 
00175 #ifdef STRICT_LIMITS
00176     c->symCount++;
00177 #endif
00178 
00179     return (put_bits_count(&c->pb)+7)>>3;
00180 }
00181 
00185 static void put_cabac_u(CABACContext *c, uint8_t * state, int v, int max, int max_index, int truncated){
00186     int i;
00187 
00188     assert(v <= max);
00189 
00190 #if 1
00191     for(i=0; i<v; i++){
00192         put_cabac(c, state, 1);
00193         if(i < max_index) state++;
00194     }
00195     if(truncated==0 || v<max)
00196         put_cabac(c, state, 0);
00197 #else
00198     if(v <= max_index){
00199         for(i=0; i<v; i++){
00200             put_cabac(c, state+i, 1);
00201         }
00202         if(truncated==0 || v<max)
00203             put_cabac(c, state+i, 0);
00204     }else{
00205         for(i=0; i<=max_index; i++){
00206             put_cabac(c, state+i, 1);
00207         }
00208         for(; i<v; i++){
00209             put_cabac(c, state+max_index, 1);
00210         }
00211         if(truncated==0 || v<max)
00212             put_cabac(c, state+max_index, 0);
00213     }
00214 #endif
00215 }
00216 
00220 static void put_cabac_ueg(CABACContext *c, uint8_t * state, int v, int max, int is_signed, int k, int max_index){
00221     int i;
00222 
00223     if(v==0)
00224         put_cabac(c, state, 0);
00225     else{
00226         const int sign= v < 0;
00227 
00228         if(is_signed) v= FFABS(v);
00229 
00230         if(v<max){
00231             for(i=0; i<v; i++){
00232                 put_cabac(c, state, 1);
00233                 if(i < max_index) state++;
00234             }
00235 
00236             put_cabac(c, state, 0);
00237         }else{
00238             int m= 1<<k;
00239 
00240             for(i=0; i<max; i++){
00241                 put_cabac(c, state, 1);
00242                 if(i < max_index) state++;
00243             }
00244 
00245             v -= max;
00246             while(v >= m){ //FIXME optimize
00247                 put_cabac_bypass(c, 1);
00248                 v-= m;
00249                 m+= m;
00250             }
00251             put_cabac_bypass(c, 0);
00252             while(m>>=1){
00253                 put_cabac_bypass(c, v&m);
00254             }
00255         }
00256 
00257         if(is_signed)
00258             put_cabac_bypass(c, sign);
00259     }
00260 }
00261 #endif /* TEST */
00262 
00263 static void refill(CABACContext *c){
00264 #if CABAC_BITS == 16
00265         c->low+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1);
00266 #else
00267         c->low+= c->bytestream[0]<<1;
00268 #endif
00269     c->low -= CABAC_MASK;
00270     c->bytestream+= CABAC_BITS/8;
00271 }
00272 
00273 #if ! ( ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE && !defined(BROKEN_RELOCATIONS) )
00274 static void refill2(CABACContext *c){
00275     int i, x;
00276 
00277     x= c->low ^ (c->low-1);
00278     i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)];
00279 
00280     x= -CABAC_MASK;
00281 
00282 #if CABAC_BITS == 16
00283         x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1);
00284 #else
00285         x+= c->bytestream[0]<<1;
00286 #endif
00287 
00288     c->low += x<<i;
00289     c->bytestream+= CABAC_BITS/8;
00290 }
00291 #endif
00292 
00293 static inline void renorm_cabac_decoder(CABACContext *c){
00294     while(c->range < 0x100){
00295         c->range+= c->range;
00296         c->low+= c->low;
00297         if(!(c->low & CABAC_MASK))
00298             refill(c);
00299     }
00300 }
00301 
00302 static inline void renorm_cabac_decoder_once(CABACContext *c){
00303 #ifdef ARCH_X86_DISABLED
00304     int temp;
00305 #if 0
00306     //P3:683    athlon:475
00307     __asm__(
00308         "lea -0x100(%0), %2         \n\t"
00309         "shr $31, %2                \n\t"  //FIXME 31->63 for x86-64
00310         "shl %%cl, %0               \n\t"
00311         "shl %%cl, %1               \n\t"
00312         : "+r"(c->range), "+r"(c->low), "+c"(temp)
00313     );
00314 #elif 0
00315     //P3:680    athlon:474
00316     __asm__(
00317         "cmp $0x100, %0             \n\t"
00318         "setb %%cl                  \n\t"  //FIXME 31->63 for x86-64
00319         "shl %%cl, %0               \n\t"
00320         "shl %%cl, %1               \n\t"
00321         : "+r"(c->range), "+r"(c->low), "+c"(temp)
00322     );
00323 #elif 1
00324     int temp2;
00325     //P3:665    athlon:517
00326     __asm__(
00327         "lea -0x100(%0), %%eax      \n\t"
00328         "cltd                       \n\t"
00329         "mov %0, %%eax              \n\t"
00330         "and %%edx, %0              \n\t"
00331         "and %1, %%edx              \n\t"
00332         "add %%eax, %0              \n\t"
00333         "add %%edx, %1              \n\t"
00334         : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)
00335     );
00336 #elif 0
00337     int temp2;
00338     //P3:673    athlon:509
00339     __asm__(
00340         "cmp $0x100, %0             \n\t"
00341         "sbb %%edx, %%edx           \n\t"
00342         "mov %0, %%eax              \n\t"
00343         "and %%edx, %0              \n\t"
00344         "and %1, %%edx              \n\t"
00345         "add %%eax, %0              \n\t"
00346         "add %%edx, %1              \n\t"
00347         : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)
00348     );
00349 #else
00350     int temp2;
00351     //P3:677    athlon:511
00352     __asm__(
00353         "cmp $0x100, %0             \n\t"
00354         "lea (%0, %0), %%eax        \n\t"
00355         "lea (%1, %1), %%edx        \n\t"
00356         "cmovb %%eax, %0            \n\t"
00357         "cmovb %%edx, %1            \n\t"
00358         : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2)
00359     );
00360 #endif
00361 #else
00362     //P3:675    athlon:476
00363     int shift= (uint32_t)(c->range - 0x100)>>31;
00364     c->range<<= shift;
00365     c->low  <<= shift;
00366 #endif
00367     if(!(c->low & CABAC_MASK))
00368         refill(c);
00369 }
00370 
00371 static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){
00372     //FIXME gcc generates duplicate load/stores for c->low and c->range
00373 #define LOW          "0"
00374 #define RANGE        "4"
00375 #if ARCH_X86_64
00376 #define BYTESTART   "16"
00377 #define BYTE        "24"
00378 #define BYTEEND     "32"
00379 #else
00380 #define BYTESTART   "12"
00381 #define BYTE        "16"
00382 #define BYTEEND     "20"
00383 #endif
00384 #if ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE && !defined(BROKEN_RELOCATIONS)
00385     int bit;
00386 
00387 #ifndef BRANCHLESS_CABAC_DECODER
00388     __asm__ volatile(
00389         "movzbl (%1), %0                        \n\t"
00390         "movl "RANGE    "(%2), %%ebx            \n\t"
00391         "movl "RANGE    "(%2), %%edx            \n\t"
00392         "andl $0xC0, %%ebx                      \n\t"
00393         "movzbl "MANGLE(ff_h264_lps_range)"(%0, %%ebx, 2), %%esi\n\t"
00394         "movl "LOW      "(%2), %%ebx            \n\t"
00395 //eax:state ebx:low, edx:range, esi:RangeLPS
00396         "subl %%esi, %%edx                      \n\t"
00397         "movl %%edx, %%ecx                      \n\t"
00398         "shll $17, %%ecx                        \n\t"
00399         "cmpl %%ecx, %%ebx                      \n\t"
00400         " ja 1f                                 \n\t"
00401 
00402 #if 1
00403         //athlon:4067 P3:4110
00404         "lea -0x100(%%edx), %%ecx               \n\t"
00405         "shr $31, %%ecx                         \n\t"
00406         "shl %%cl, %%edx                        \n\t"
00407         "shl %%cl, %%ebx                        \n\t"
00408 #else
00409         //athlon:4057 P3:4130
00410         "cmp $0x100, %%edx                      \n\t" //FIXME avoidable
00411         "setb %%cl                              \n\t"
00412         "shl %%cl, %%edx                        \n\t"
00413         "shl %%cl, %%ebx                        \n\t"
00414 #endif
00415         "movzbl "MANGLE(ff_h264_mps_state)"(%0), %%ecx   \n\t"
00416         "movb %%cl, (%1)                        \n\t"
00417 //eax:state ebx:low, edx:range, esi:RangeLPS
00418         "test %%bx, %%bx                        \n\t"
00419         " jnz 2f                                \n\t"
00420         "mov  "BYTE     "(%2), %%"REG_S"        \n\t"
00421         "subl $0xFFFF, %%ebx                    \n\t"
00422         "movzwl (%%"REG_S"), %%ecx              \n\t"
00423         "bswap %%ecx                            \n\t"
00424         "shrl $15, %%ecx                        \n\t"
00425         "add  $2, %%"REG_S"                     \n\t"
00426         "addl %%ecx, %%ebx                      \n\t"
00427         "mov  %%"REG_S", "BYTE    "(%2)         \n\t"
00428         "jmp 2f                                 \n\t"
00429         "1:                                     \n\t"
00430 //eax:state ebx:low, edx:range, esi:RangeLPS
00431         "subl %%ecx, %%ebx                      \n\t"
00432         "movl %%esi, %%edx                      \n\t"
00433         "movzbl " MANGLE(ff_h264_norm_shift) "(%%esi), %%ecx   \n\t"
00434         "shll %%cl, %%ebx                       \n\t"
00435         "shll %%cl, %%edx                       \n\t"
00436         "movzbl "MANGLE(ff_h264_lps_state)"(%0), %%ecx   \n\t"
00437         "movb %%cl, (%1)                        \n\t"
00438         "add  $1, %0                            \n\t"
00439         "test %%bx, %%bx                        \n\t"
00440         " jnz 2f                                \n\t"
00441 
00442         "mov  "BYTE     "(%2), %%"REG_c"        \n\t"
00443         "movzwl (%%"REG_c"), %%esi              \n\t"
00444         "bswap %%esi                            \n\t"
00445         "shrl $15, %%esi                        \n\t"
00446         "subl $0xFFFF, %%esi                    \n\t"
00447         "add  $2, %%"REG_c"                     \n\t"
00448         "mov  %%"REG_c", "BYTE    "(%2)         \n\t"
00449 
00450         "leal -1(%%ebx), %%ecx                  \n\t"
00451         "xorl %%ebx, %%ecx                      \n\t"
00452         "shrl $15, %%ecx                        \n\t"
00453         "movzbl " MANGLE(ff_h264_norm_shift) "(%%ecx), %%ecx   \n\t"
00454         "neg %%ecx                              \n\t"
00455         "add $7, %%ecx                          \n\t"
00456 
00457         "shll %%cl , %%esi                      \n\t"
00458         "addl %%esi, %%ebx                      \n\t"
00459         "2:                                     \n\t"
00460         "movl %%edx, "RANGE    "(%2)            \n\t"
00461         "movl %%ebx, "LOW      "(%2)            \n\t"
00462         :"=&a"(bit) //FIXME this is fragile gcc either runs out of registers or miscompiles it (for example if "+a"(bit) or "+m"(*state) is used
00463         :"r"(state), "r"(c)
00464         : "%"REG_c, "%ebx", "%edx", "%"REG_S, "memory"
00465     );
00466     bit&=1;
00467 #else /* BRANCHLESS_CABAC_DECODER */
00468 
00469 
00470 #if HAVE_FAST_CMOV
00471 #define BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
00472         "mov    "tmp"       , %%ecx                                     \n\t"\
00473         "shl    $17         , "tmp"                                     \n\t"\
00474         "cmp    "low"       , "tmp"                                     \n\t"\
00475         "cmova  %%ecx       , "range"                                   \n\t"\
00476         "sbb    %%ecx       , %%ecx                                     \n\t"\
00477         "and    %%ecx       , "tmp"                                     \n\t"\
00478         "sub    "tmp"       , "low"                                     \n\t"\
00479         "xor    %%ecx       , "ret"                                     \n\t"
00480 #else /* HAVE_FAST_CMOV */
00481 #define BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
00482         "mov    "tmp"       , %%ecx                                     \n\t"\
00483         "shl    $17         , "tmp"                                     \n\t"\
00484         "sub    "low"       , "tmp"                                     \n\t"\
00485         "sar    $31         , "tmp"                                     \n\t" /*lps_mask*/\
00486         "sub    %%ecx       , "range"                                   \n\t" /*RangeLPS - range*/\
00487         "and    "tmp"       , "range"                                   \n\t" /*(RangeLPS - range)&lps_mask*/\
00488         "add    %%ecx       , "range"                                   \n\t" /*new range*/\
00489         "shl    $17         , %%ecx                                     \n\t"\
00490         "and    "tmp"       , %%ecx                                     \n\t"\
00491         "sub    %%ecx       , "low"                                     \n\t"\
00492         "xor    "tmp"       , "ret"                                     \n\t"
00493 #endif /* HAVE_FAST_CMOV */
00494 
00495 
00496 #define BRANCHLESS_GET_CABAC(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
00497         "movzbl "statep"    , "ret"                                     \n\t"\
00498         "mov    "range"     , "tmp"                                     \n\t"\
00499         "and    $0xC0       , "range"                                   \n\t"\
00500         "movzbl "MANGLE(ff_h264_lps_range)"("ret", "range", 2), "range" \n\t"\
00501         "sub    "range"     , "tmp"                                     \n\t"\
00502         BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\
00503         "movzbl " MANGLE(ff_h264_norm_shift) "("range"), %%ecx          \n\t"\
00504         "shl    %%cl        , "range"                                   \n\t"\
00505         "movzbl "MANGLE(ff_h264_mlps_state)"+128("ret"), "tmp"          \n\t"\
00506         "mov    "tmpbyte"   , "statep"                                  \n\t"\
00507         "shl    %%cl        , "low"                                     \n\t"\
00508         "test   "lowword"   , "lowword"                                 \n\t"\
00509         " jnz   1f                                                      \n\t"\
00510         "mov "BYTE"("cabac"), %%"REG_c"                                 \n\t"\
00511         "movzwl (%%"REG_c")     , "tmp"                                 \n\t"\
00512         "bswap  "tmp"                                                   \n\t"\
00513         "shr    $15         , "tmp"                                     \n\t"\
00514         "sub    $0xFFFF     , "tmp"                                     \n\t"\
00515         "add    $2          , %%"REG_c"                                 \n\t"\
00516         "mov    %%"REG_c"   , "BYTE    "("cabac")                       \n\t"\
00517         "lea    -1("low")   , %%ecx                                     \n\t"\
00518         "xor    "low"       , %%ecx                                     \n\t"\
00519         "shr    $15         , %%ecx                                     \n\t"\
00520         "movzbl " MANGLE(ff_h264_norm_shift) "(%%ecx), %%ecx            \n\t"\
00521         "neg    %%ecx                                                   \n\t"\
00522         "add    $7          , %%ecx                                     \n\t"\
00523         "shl    %%cl        , "tmp"                                     \n\t"\
00524         "add    "tmp"       , "low"                                     \n\t"\
00525         "1:                                                             \n\t"
00526 
00527     __asm__ volatile(
00528         "movl "RANGE    "(%2), %%esi            \n\t"
00529         "movl "LOW      "(%2), %%ebx            \n\t"
00530         BRANCHLESS_GET_CABAC("%0", "%2", "(%1)", "%%ebx", "%%bx", "%%esi", "%%edx", "%%dl")
00531         "movl %%esi, "RANGE    "(%2)            \n\t"
00532         "movl %%ebx, "LOW      "(%2)            \n\t"
00533 
00534         :"=&a"(bit)
00535         :"r"(state), "r"(c)
00536         : "%"REG_c, "%ebx", "%edx", "%esi", "memory"
00537     );
00538     bit&=1;
00539 #endif /* BRANCHLESS_CABAC_DECODER */
00540 #else /* ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE && !defined(BROKEN_RELOCATIONS) */
00541     int s = *state;
00542     int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s];
00543     int bit, lps_mask av_unused;
00544 
00545     c->range -= RangeLPS;
00546 #ifndef BRANCHLESS_CABAC_DECODER
00547     if(c->low < (c->range<<(CABAC_BITS+1))){
00548         bit= s&1;
00549         *state= ff_h264_mps_state[s];
00550         renorm_cabac_decoder_once(c);
00551     }else{
00552         bit= ff_h264_norm_shift[RangeLPS];
00553         c->low -= (c->range<<(CABAC_BITS+1));
00554         *state= ff_h264_lps_state[s];
00555         c->range = RangeLPS<<bit;
00556         c->low <<= bit;
00557         bit= (s&1)^1;
00558 
00559         if(!(c->low & CABAC_MASK)){
00560             refill2(c);
00561         }
00562     }
00563 #else /* BRANCHLESS_CABAC_DECODER */
00564     lps_mask= ((c->range<<(CABAC_BITS+1)) - c->low)>>31;
00565 
00566     c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask;
00567     c->range += (RangeLPS - c->range) & lps_mask;
00568 
00569     s^=lps_mask;
00570     *state= (ff_h264_mlps_state+128)[s];
00571     bit= s&1;
00572 
00573     lps_mask= ff_h264_norm_shift[c->range];
00574     c->range<<= lps_mask;
00575     c->low  <<= lps_mask;
00576     if(!(c->low & CABAC_MASK))
00577         refill2(c);
00578 #endif /* BRANCHLESS_CABAC_DECODER */
00579 #endif /* ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE && !defined(BROKEN_RELOCATIONS) */
00580     return bit;
00581 }
00582 
00583 static int av_noinline av_unused get_cabac_noinline(CABACContext *c, uint8_t * const state){
00584     return get_cabac_inline(c,state);
00585 }
00586 
00587 static int av_unused get_cabac(CABACContext *c, uint8_t * const state){
00588     return get_cabac_inline(c,state);
00589 }
00590 
00591 static int av_unused get_cabac_bypass(CABACContext *c){
00592 #if 0 //not faster
00593     int bit;
00594     __asm__ volatile(
00595         "movl "RANGE    "(%1), %%ebx            \n\t"
00596         "movl "LOW      "(%1), %%eax            \n\t"
00597         "shl $17, %%ebx                         \n\t"
00598         "add %%eax, %%eax                       \n\t"
00599         "sub %%ebx, %%eax                       \n\t"
00600         "cltd                                   \n\t"
00601         "and %%edx, %%ebx                       \n\t"
00602         "add %%ebx, %%eax                       \n\t"
00603         "test %%ax, %%ax                        \n\t"
00604         " jnz 1f                                \n\t"
00605         "movl "BYTE     "(%1), %%"REG_b"        \n\t"
00606         "subl $0xFFFF, %%eax                    \n\t"
00607         "movzwl (%%"REG_b"), %%ecx              \n\t"
00608         "bswap %%ecx                            \n\t"
00609         "shrl $15, %%ecx                        \n\t"
00610         "addl $2, %%"REG_b"                     \n\t"
00611         "addl %%ecx, %%eax                      \n\t"
00612         "movl %%"REG_b", "BYTE     "(%1)        \n\t"
00613         "1:                                     \n\t"
00614         "movl %%eax, "LOW      "(%1)            \n\t"
00615 
00616         :"=&d"(bit)
00617         :"r"(c)
00618         : "%eax", "%"REG_b, "%ecx", "memory"
00619     );
00620     return bit+1;
00621 #else
00622     int range;
00623     c->low += c->low;
00624 
00625     if(!(c->low & CABAC_MASK))
00626         refill(c);
00627 
00628     range= c->range<<(CABAC_BITS+1);
00629     if(c->low < range){
00630         return 0;
00631     }else{
00632         c->low -= range;
00633         return 1;
00634     }
00635 #endif
00636 }
00637 
00638 
00639 static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){
00640 #if ARCH_X86 && HAVE_EBX_AVAILABLE
00641     __asm__ volatile(
00642         "movl "RANGE    "(%1), %%ebx            \n\t"
00643         "movl "LOW      "(%1), %%eax            \n\t"
00644         "shl $17, %%ebx                         \n\t"
00645         "add %%eax, %%eax                       \n\t"
00646         "sub %%ebx, %%eax                       \n\t"
00647         "cltd                                   \n\t"
00648         "and %%edx, %%ebx                       \n\t"
00649         "add %%ebx, %%eax                       \n\t"
00650         "xor %%edx, %%ecx                       \n\t"
00651         "sub %%edx, %%ecx                       \n\t"
00652         "test %%ax, %%ax                        \n\t"
00653         " jnz 1f                                \n\t"
00654         "mov  "BYTE     "(%1), %%"REG_b"        \n\t"
00655         "subl $0xFFFF, %%eax                    \n\t"
00656         "movzwl (%%"REG_b"), %%edx              \n\t"
00657         "bswap %%edx                            \n\t"
00658         "shrl $15, %%edx                        \n\t"
00659         "add  $2, %%"REG_b"                     \n\t"
00660         "addl %%edx, %%eax                      \n\t"
00661         "mov  %%"REG_b", "BYTE     "(%1)        \n\t"
00662         "1:                                     \n\t"
00663         "movl %%eax, "LOW      "(%1)            \n\t"
00664 
00665         :"+c"(val)
00666         :"r"(c)
00667         : "%eax", "%"REG_b, "%edx", "memory"
00668     );
00669     return val;
00670 #else
00671     int range, mask;
00672     c->low += c->low;
00673 
00674     if(!(c->low & CABAC_MASK))
00675         refill(c);
00676 
00677     range= c->range<<(CABAC_BITS+1);
00678     c->low -= range;
00679     mask= c->low >> 31;
00680     range &= mask;
00681     c->low += range;
00682     return (val^mask)-mask;
00683 #endif
00684 }
00685 
00690 static int av_unused get_cabac_terminate(CABACContext *c){
00691     c->range -= 2;
00692     if(c->low < c->range<<(CABAC_BITS+1)){
00693         renorm_cabac_decoder_once(c);
00694         return 0;
00695     }else{
00696         return c->bytestream - c->bytestream_start;
00697     }
00698 }
00699 
00700 #if 0
00701 
00704 static int get_cabac_u(CABACContext *c, uint8_t * state, int max, int max_index, int truncated){
00705     int i;
00706 
00707     for(i=0; i<max; i++){
00708         if(get_cabac(c, state)==0)
00709             return i;
00710 
00711         if(i< max_index) state++;
00712     }
00713 
00714     return truncated ? max : -1;
00715 }
00716 
00720 static int get_cabac_ueg(CABACContext *c, uint8_t * state, int max, int is_signed, int k, int max_index){
00721     int i, v;
00722     int m= 1<<k;
00723 
00724     if(get_cabac(c, state)==0)
00725         return 0;
00726 
00727     if(0 < max_index) state++;
00728 
00729     for(i=1; i<max; i++){
00730         if(get_cabac(c, state)==0){
00731             if(is_signed && get_cabac_bypass(c)){
00732                 return -i;
00733             }else
00734                 return i;
00735         }
00736 
00737         if(i < max_index) state++;
00738     }
00739 
00740     while(get_cabac_bypass(c)){
00741         i+= m;
00742         m+= m;
00743     }
00744 
00745     v=0;
00746     while(m>>=1){
00747         v+= v + get_cabac_bypass(c);
00748     }
00749     i += v;
00750 
00751     if(is_signed && get_cabac_bypass(c)){
00752         return -i;
00753     }else
00754         return i;
00755 }
00756 #endif /* 0 */
00757 
00758 #endif /* AVCODEC_CABAC_H */

Generated on Fri Sep 16 2011 17:17:34 for FFmpeg by  doxygen 1.7.1