欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
x264源碼閱讀筆記2(zhuantie)

寫(xiě)參數集x264_sps_write()和x264_pps_write()以及其中基本的bs_write()的過(guò)程。

挺有意思,挺巧妙的。他們就是負責碼流寫(xiě)入的過(guò)程,這個(gè)不同于寫(xiě)字節,直接COPY內存,用C語(yǔ)言實(shí)現對位的操作真的顯得比較笨拙,但是這里代碼還是很巧妙的。

說(shuō)基本的,static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )這個(gè)函數的作用就是,向s里寫(xiě)入i_bits流的前i_count位,s當然是以字節為單位了,所以夠8個(gè)位就寫(xiě)下個(gè),哎呀太麻煩了,引別人寫(xiě)的把,不知道他這個(gè)是什么時(shí)候版本,但是大概意思差不多。酬和看。

 

函數bs_write
static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
{
    while( i_count > 0 )
    {
        if( s->p >= s->p_end )
        {
            break;
        }
        i_count--;
        if( ( i_bits >> i_count )&0x01 )
         {
            *s->p |= 1 << ( s->i_left - 1 );
        }
        else
        {
            *s->p &= ~( 1 << ( s->i_left - 1 ) );
        }
        s->i_left--;
        if( s->i_left == 0 )
        {
            s->p++;
            s->i_left = 8;
         }
    }
}
函數功能:
i_count是循環(huán)的次數,i_bits是要編碼的數,i_left是當前空閑碼流的位數。
i_bits編為i_count位的碼流,每次循環(huán),I_count和I_left都會(huì )減1,I_count和I_left并不一定相等。當i_left==0時(shí),s->p指針指向下一個(gè)碼流單元,i_left更新為8。
函數流程
首先判斷I_count是否大于0,如果是,則判斷s->p是否大于s->p_end,若是則終止,否則,可以寫(xiě)入碼流。這個(gè)條件是在判斷是否有空閑的存儲空間供新的碼流寫(xiě)入。
若可以寫(xiě)碼流,則I_count--,表明可以進(jìn)行寫(xiě)一位的操作。注意,寫(xiě)I_bits是逐位寫(xiě)入的。
if( ( i_bits >> i_count )&0x01 )是用來(lái)判斷當前要寫(xiě)入的I_bits位是0還是1,從而選擇不同的算法來(lái)寫(xiě)入這個(gè)碼流。如果當前要寫(xiě)入的是0,則選擇*s->p &= ~( 1 << ( s->i_left - 1 ) )來(lái)把這個(gè)0寫(xiě)入碼流;如果當前要寫(xiě)入的是1,則選擇*s->p |= 1 << ( s->i_left - 1 )來(lái)把這個(gè)1寫(xiě)入碼流。
  
寫(xiě)完一位碼流后,初始的i_left被新寫(xiě)入的bit占了一位,所以i_left的值-1.
   這時(shí)判斷I_left是否等于0,如果I_left還大于0,表示當前的存儲單元中還有剩余的空間供碼流寫(xiě)入,則直接進(jìn)入下一次循環(huán)。如果I_left==0時(shí),表示當前存儲單元已被寫(xiě)滿(mǎn),所以s->p指針指向下一個(gè)存儲單元,I_left更新為8。這時(shí)再進(jìn)入下一循環(huán)。
  
在進(jìn)入下一循環(huán)的時(shí)候,先判斷I_count的值,如果非零,程序繼續;如果為0,表示碼流已經(jīng)全部寫(xiě)入,程序終止。
關(guān)鍵語(yǔ)句分析
if( ( i_bits >> i_count )&0x01 )
定位要寫(xiě)入的I_bits的位,比如I_bits=d(66)=b(0100 0010),I_count=8,首先I_count--,那么I_bits右移7位后就是0,而它與0x01(也就是0000 0001)位與后的值是0,這就確定了要寫(xiě)入的碼流是0。再比如I_count=6,則I_bits右移6位后是01,而01和0x01位與后得到的是1,這就表明要寫(xiě)入的碼流是1。
*s->p &= ~( 1 << ( s->i_left-1) )
此算式可以將0寫(xiě)入碼流。比如*s->p=1100 1101,I_bits=d(66)=b(0100 0010),I_count=7,I_left=8。
~(1<<s->I_left-1)=0111 1111,
1100 1101&
0111 1111 = 0100 1101,這樣就把0寫(xiě)入了存儲空間,得到碼流0100 1101。然后I_left=7
*s->p |= 1 << ( s->i_left - 1 );
此算式可以將1寫(xiě)入碼流。比如*s->p=1100 1101,I_bits=d(66)=b(0100 0010),I_count=6,I_left=7。
1<<(s->I_left-1)0100 0000
0100 1101 |
0100 0000 = 0100 1101 ,這樣就把1寫(xiě)入了存儲空間,得到碼流0100 1101,然后I_left=6.
函數bs_write1
static inline void bs_write1( bs_t *s, uint32_t i_bits )
{
    if( s->p < s->p_end )
    {   
        if( i_bits&0x01 )
        {
            *s->p |= 1 <<( s->i_left-1);
        }
        else
        {
            *s->p &= ~( 1 << (s->i_left-1) );
        }
        s->i_left--;
        if( s->i_left == 0 )
        {
            s->p++;
            s->i_left = 8;
        }
    }
}
bs_write1()相當于bs_write(bs_t *s,1, uint32_t i_bits)
就是只寫(xiě)入1 bit碼流。

地址
碼流值
十進(jìn)制值
ASCII碼值
i_bits
i_left
0x00890058
11001101
205
8
0x00890058
01001101
77
M
0
7
0x00890058
00001101
13
0
6
0x00890058
00101101
45
-
1
5

可以看到,存儲單元的初值為11011101,也就是0xCD,這是VC默認的初始化值。 我們首先要寫(xiě)入的是0,那么只需要把0放入11001101的最第一位(從左向右數),替換原來(lái)的1即可,變?yōu)?/span>01001101,它的十進(jìn)制值就是77;下一次仍要寫(xiě)入0,則把0放到01001101的第二位,變?yōu)?/span>00001101;最后要寫(xiě)入1,則把1放到00001101的第三位,變?yōu)?/span>00101101。就這樣依次逐位寫(xiě)入碼流,直到I_left=0為止。
下面是哥倫布編碼流
bs_write_ue( s, sps->i_id );
這里ue,是在語(yǔ)法中定義為指數哥倫布碼的編碼方法,其具體方法見(jiàn)規范第9章。應是一種變長(cháng)的編碼!簡(jiǎn)舉例,0階指數哥化布編碼:
Bit string form
Range of codeNum
1
0
0 1 x0
1-2
0 0 1 x1 x0
3-6
0 0 0 1 x2 x1 x0
7-14
0 0 0 0 1 x3 x2 x1 x0
15-30
0 0 0 0 0 1 x4 x3 x2 x1 x0
31-62
 
 
 

x264中bs.h文件部分函數解讀(許子皓)

 

本文結合寫(xiě)入、讀取碼流函數介紹哥倫布編碼方式。
1 寫(xiě)入碼流函數bs_write:
1) static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
該函數的作用是:向s里寫(xiě)入i_bits流的后i_count位,s以字節為單位,所以夠8個(gè)位就寫(xiě)下個(gè)(注意i_bits的單位是uint32_t)。

static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
{
    while( i_count > 0 )
    {
        if( s->p >= s->p_end )
        {
            break;
        }
        i_count--;
        if( ( i_bits >> i_count )&0x01 )
        {
            *s->p |= 1 << ( s->i_left - 1 );
        }
        else
        {
            *s->p &= ~( 1 << ( s->i_left - 1 ) );
        }
        s->i_left--;
        if( s->i_left == 0 )
        {
            s->p++;
            s->i_left = 8;
        }
    }
}
函數功能:
i_count是循環(huán)的次數即要寫(xiě)入的位數,i_bits是要編碼的數,i_left是當前空閑碼流的位數即記錄當前字節的空余位數。將i_bits編為i_count位的碼流,每次循環(huán),i_count和i_left都會(huì )減1,i_count和i_left并不一定相等。當i_left==0時(shí),s->p指針指向下一個(gè)碼流單元,i_left更新為8。
 
函數流程:
首先判斷i_count是否大于0,如果是,則判斷s->p是否大于s->p_end,若是則終止,否則,可以寫(xiě)入碼流。這個(gè)條件是在判斷是否有空閑的存儲空間供新的碼流寫(xiě)入。
若可以寫(xiě)碼流,則i_count--,表明可以進(jìn)行寫(xiě)一位的操作。注意,寫(xiě)i_bits是逐位寫(xiě)入的。
if( ( i_bits >> i_count )&0x01 )是用來(lái)判斷當前要寫(xiě)入的i_bits位是0還是1,從而選擇不同的算法來(lái)寫(xiě)入這個(gè)碼流。如果當前要寫(xiě)入的是0,則選擇*s->p &= ~( 1 << ( s->i_left - 1 ) )來(lái)把這個(gè)0寫(xiě)入碼流;如果當前要寫(xiě)入的是1,則選擇*s->p |= 1 << ( s->i_left - 1 )來(lái)把這個(gè)1寫(xiě)入碼流。
  
寫(xiě)完一位碼流后,初始的i_left被新寫(xiě)入的bit占了一位,所以i_left的值-1.
   這時(shí)判斷I_left是否等于0,如果i_left還大于0,表示當前的存儲單元中還有剩余的空間供碼流寫(xiě)入,則直接進(jìn)入下一次循環(huán)。如果i_left==0時(shí),表示當前存儲單元已被寫(xiě)滿(mǎn),所以s->p指針指向下一個(gè)存儲單元,i_left更新為8。這時(shí)再進(jìn)入下一循環(huán)。
  
在進(jìn)入下一循環(huán)的時(shí)候,先判斷i_count的值,如果非零,程序繼續;如果為0,表示碼流已經(jīng)全部寫(xiě)入,程序終止。

注:該函數是采用一個(gè)while循環(huán),一次寫(xiě)入一個(gè)位,循環(huán)i_count次將i_bits的前i_count位寫(xiě)入s中。

2)static inline void bs_write1( bs_t *s, uint32_t i_bits )
該函數的作用是:將i_bits流的后1位寫(xiě)入s。

static inline void bs_write1( bs_t *s, uint32_t i_bits )
{
    if( s->p < s->p_end )
     
        if( i_bits&0x01 )
        {
            *s->p |= 1 <<( s->i_left-1);
        }
        else
        {
            *s->p &= ~( 1 << (s->i_left-1) );
        }
         s->i_left--;
        if( s->i_left == 0 )
        {
            s->p++;
            s->i_left = 8;
        }
    }
}
 
bs_write1()相當于bs_write(bs_t *s,1, uint32_t i_bits) 就是只寫(xiě)入1 bit碼流。

函數流程:
首先判斷s->p是否大于s->p_end,若是則終止,否則,可以寫(xiě)入碼流。
if(  i_bits &0x01 )是用來(lái)判斷當前要寫(xiě)入的i_bits位是0還是1,如果當前要寫(xiě)入的是1,則選擇*s->p |= 1 <<( s->i_left-1)來(lái)把這個(gè)1寫(xiě)入碼流;如果當前要寫(xiě)入的是0,則選擇            *s->p &= ~( 1 << (s->i_left-1) )來(lái)把這個(gè)0寫(xiě)入碼流。
  
寫(xiě)完一位碼流后,初始的i_left被新寫(xiě)入的bit占了一位,所以i_left的值-1.
這時(shí)判斷I_left是否等于0,如果i_left==0時(shí),表示當前存儲單元已被寫(xiě)滿(mǎn),所以s->p指針指向下一個(gè)存儲單元,i_left更新為8。這時(shí)再進(jìn)入下一循環(huán)。
  
注:上面兩個(gè)write函數是從網(wǎng)上找的,一次寫(xiě)入一個(gè)位數,先判斷要寫(xiě)入的位是0或1,再直接寫(xiě)入0或1,比較繁瑣但是便于理解,故此附上以供參考。

 

 

以下介紹的都是來(lái)自x264中的源碼。

3)static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
該函數的作用是:向s里寫(xiě)入i_bits流的后i_count位。

static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
{
    if( s->p >= s->p_end - 4 )
        return;
    while( i_count > 0 )
    {
        if( i_count < 32 )
            i_bits &= (1<<i_count)-1;
        if( i_count < s->i_left )
        {
            *s->p = (*s->p << i_count) | i_bits;
            s->i_left -= i_count;
            break;
        }
        else
        {
            *s->p = (*s->p << s->i_left) | (i_bits >> (i_count - s->i_left));
            i_count -= s->i_left;
            s->p++;
            s->i_left = 8;
        }
    }
}

流程簡(jiǎn)介:
首先判斷是否有空閑的存儲空間供新的碼流寫(xiě)入,若剩余不足4個(gè)字節的空間,則認為空間不夠,直接返回(uint32_t是32位,要4個(gè)字節的存儲空間); i_count是否大于0,如果是,則可以寫(xiě)入碼流。這個(gè)條件是在判斷是否該開(kāi)始或繼續寫(xiě)入碼流。

可以寫(xiě)碼流,若i_count<32,則i_bits &= (1<<i_count)-1,將不需要寫(xiě)入的位置0。

注意,該函數寫(xiě)i_bits不是逐位寫(xiě)入的。
如果要寫(xiě)入的位數i_count < 本字節空余的位數s->i_left,則一次性將i_count位寫(xiě)入:            

 *s->p = (*s->p << i_count) | i_bits且s->i_left -= i_count,然后完成寫(xiě)入break;
否則,則先寫(xiě)入i_left位:*s->p = (*s->p << s->i_left) | (i_bits >> (i_count - s->i_left)),i_count -= s->i_left(要寫(xiě)入的數減少),s->p++(進(jìn)入s的下一個(gè)字節),i_left重新置位為8。
while循環(huán)直至寫(xiě)入i_count位。

注:該函數同1)小節中介紹的函數作用一樣,不過(guò)效率要高。后面函數流程就不再詳細介紹了,只說(shuō)明大概思路。

 

4)static inline void bs_write1( bs_t *s, uint32_t i_bit )
該函數的作用是:將i_bits流的后1位寫(xiě)入s。

static inline void bs_write1( bs_t *s, uint32_t i_bit )
{
    if( s->p < s->p_end )
    {
        *s->p <<= 1;
        *s->p |= i_bit;
        s->i_left--;
        if( s->i_left == 0 )
        {
            s->p++;
            s->i_left = 8;
        }
    }
}

思路:直接寫(xiě)入*s->p <<= 1;
             *s->p |= i_bit;

 

2 讀出碼流函數bs_read
1)static inline uint32_t bs_read( bs_t *s, int i_count )
該函數的作用是:從s中讀出i_count位,并將其做為uint32_t類(lèi)型返回。

static inline uint32_t bs_read( bs_t *s, int i_count )
{
     static uint32_t i_mask[33] ={0x00,
                                  0x01,      0x03,      0x07,      0x0f,
                                  0x1f,      0x3f,      0x7f,      0xff,
                                  0x1ff,     0x3ff,     0x7ff,     0xfff,
                                  0x1fff,    0x3fff,    0x7fff,    0xffff,
                                  0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
                                  0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
                                  0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
                                  0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
    int      i_shr;
    uint32_t i_result = 0;

    while( i_count > 0 )
    {
        if( s->p >= s->p_end )
        {
            break;
        }

        if( ( i_shr = s->i_left - i_count ) >= 0 )
        {
           
            i_result |= ( *s->p >> i_shr )&i_mask[i_count];
            s->i_left -= i_count;
            if( s->i_left == 0 )
            {
                s->p++;
                s->i_left = 8;
            }
            return( i_result );
        }
        else
        {
           
           i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
           i_count  -= s->i_left;
           s->p++;
           s->i_left = 8;
        }
    }
    return( i_result );
}

思路:若i_count>0且s流并未結束,則開(kāi)始或繼續讀取碼流;
     若s當前字節中剩余位數大于等于要讀取的位數i_count,則直接讀??;
     若s當前字節中剩余位數小于要讀取的位數i_count,則讀取剩余位,進(jìn)入s下一字節繼續讀取。
注:寫(xiě)入s時(shí),i_left表示s當前字節還沒(méi)被寫(xiě)入的位,若一個(gè)新的字節,則i_left=8;
    讀取s時(shí),i_left表示s當前字節還沒(méi)被讀取的位,若一個(gè)新的字節,則i_left=8。
    注意兩者的區別和聯(lián)系。

 

2)static inline uint32_t bs_read1( bs_t *s )
該函數的作用是:從s中讀出1位,并將其做為uint32_t類(lèi)型返回。

static inline uint32_t bs_read1( bs_t *s )
{
    if( s->p < s->p_end )
    {
        unsigned int i_result;

        s->i_left--;
        i_result = ( *s->p >> s->i_left )&0x01;
        if( s->i_left == 0 )
        {
            s->p++;
            s->i_left = 8;
        }
        return i_result;
    }

    return 0;
}

思路:若s流并未結束,則讀取一位。

 

3 指數哥倫布編碼ue(v)
1)static inline void bs_write_ue( bs_t *s, unsigned int val )
該函數的作用是:將val以哥倫布編碼ue(v)方式編碼并寫(xiě)入s中。

static inline void bs_write_ue( bs_t *s, unsigned int val )
{
    int i_size = 0;
    static const int i_size0_255[256] =
    {
        1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
        6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
        7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
        7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
    };

    if( val == 0 )
    {
        bs_write1( s, 1 );
    }
    else
    {
        unsigned int tmp = ++val;

        if( tmp >= 0x00010000 )//2^16=256*256
        {
            i_size += 16;
            tmp >>= 16;
        }
        if( tmp >= 0x100 )//2^8=256
        {
            i_size += 8;
            tmp >>= 8;
        }
        i_size += i_size0_255[tmp];

        bs_write( s, 2 * i_size - 1, val );
    }
}

思路:當val=0時(shí),寫(xiě)入1;
      當val?。?時(shí):該函數主要是通過(guò)i_size0_255[256]表計算出一個(gè)i_size,然后寫(xiě)入val的2*i_size-1位,注意
     tmp=++val,實(shí)際寫(xiě)入的val比傳入的val大1。
例:when val=9 ,val!=0, so tmp=10;
tmp<0x00010000 and tmp<0x100, so i_size=0+i_size0_255[10]=4;
tmp=10=00001010  and 2*i_size-1=7 ,so bs_write(s,7,00001010);
由上所述:當val=9時(shí),寫(xiě)入s的字串為:0001010

 

2)static inline int bs_read_ue( bs_t *s )
該函數的作用是:從s中解碼并讀出一個(gè)語(yǔ)法元素值。

static inline int bs_read_ue( bs_t *s )

{
    int i = 0;

    while( bs_read1( s ) == 0 && s->p < s->p_end && i < 32 )
    {
        i++;
    }
    return( ( 1 << i) - 1 + bs_read( s, i ) );
}

思路:從s的當前位讀取并計數,直至讀取到1為止;
while( bs_read1( s ) == 0 && s->p < s->p_end && i < 32 )這個(gè)循環(huán)用i記錄了s當前位置到1為止的0的個(gè)數,并丟棄讀到的第一個(gè)1;
返回2^i-1+bs_read(s,i)。
例:當s字節中存放的是0001010時(shí),1前有3個(gè)0,所以i=3;
返回的是:2^i-1+bs_read(s,i)即:8-1+010=9

 

3)static inline int bs_size_ue( unsigned int val )
該函數的作用是:計算val經(jīng)過(guò)ue(v)編碼后所對應的位。

static inline int bs_size_ue( unsigned int val )
{
    static const int i_size0_254[255] =
    {
        1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
        11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
        11,11,11,11,11,11,11,11,11,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
        13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
        13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
        13,13,13,13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
        15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
        15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
        15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
        15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
        15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
    };

    if( val < 255 )
    {
        return i_size0_254[val];
    }
    else
    {
        int i_size = 0;

        val++;

        if( val >= 0x10000 )
        {
            i_size += 32;
            val = (val >> 16) - 1;
        }
        if( val >= 0x100 )
        {
            i_size += 16;
            val = (val >> 8) - 1;
        }
        return i_size0_254[val] + i_size;
    }
}

思路:其實(shí)就是計算bs_write_ue( bs_t *s, unsigned int val )函數中的2*i_size-1的值。

 

4 指數哥倫布編碼se(v)
1)static inline void bs_write_se( bs_t *s, int val )
該函數的作用是:通過(guò)ue(v)編碼實(shí)現se(v)編碼的寫(xiě)入。

static inline void bs_write_se( bs_t *s, int val )
{
    bs_write_ue( s, val <= 0 ? -val * 2 : val * 2 - 1);
}

思路:se(v)表示有符號指數哥倫布編碼,當val<=0時(shí),codenum=-val*2;否則,codenum=val*2-1。
     然后,bs_write_ue(s,codenum);
注:在標準中的codenum只是一個(gè)假設的中間值,就像在函數中設置的一個(gè)變量一樣,val才是要得到的語(yǔ)法元素值。
    在ue(v)編碼中,val=codenum,標準中也這樣描述:“如果語(yǔ)法元素編碼為ue(v),語(yǔ)法元素值等于codeNum。”
    在se(v)編碼中,val與codenum的關(guān)系如下:當val<=0時(shí),codenum=-val*2;否則,codenum=val*2-1(參看標準9.1.1小節中的表9-3)。


2)static inline int bs_read_se( bs_t *s )
該函數的作用是:通過(guò)ue(v)編碼實(shí)現se(v)編碼的讀取。

static inline int bs_read_se( bs_t *s )
{
    int val = bs_read_ue( s );

    return val&0x01 ? (val+1)/2 : -(val/2);
}

思路:直接bs_read_ue( s )讀取出來(lái)的實(shí)際上是codenum的值,因為“當val<=0時(shí),codenum=-val*2;否則,codenum=val*2-1。
”,所以當codenum為奇數即 codenum&0x01>0 時(shí),val=(codenum+1)/2,否則val=-(codenum/2)。


3)static inline int bs_size_se( int val )
該函數的作用是:通過(guò)ue(v)編碼計算位數的方式實(shí)現se(v)編碼的位數計算。

static inline int bs_size_se( int val )
{
    return bs_size_ue( val <= 0 ? -val * 2 : val * 2 - 1);
}
注:原理同ue(v)。

 

5 指數哥倫布編碼te(v)
1)static inline void bs_write_te( bs_t *s, int x, int val )
該函數的作用是:通過(guò)ue(v)編碼實(shí)現te(v)編碼的寫(xiě)入。

static inline void bs_write_te( bs_t *s, int x, int val )
{
    if( x == 1 )
    {
        bs_write1( s, 1&~val );
    }
    else if( x > 1 )
    {
        bs_write_ue( s, val );
    }
}

思路:當x=1時(shí),將val最后一位的取反,然后寫(xiě)入;
      當x>1時(shí),編碼方式同ue(v)。
注:x表示語(yǔ)法元素的范圍。注意參考標準中關(guān)于te(v)與ue(v)關(guān)系的描述。
   

2)static inline int bs_read_te( bs_t *s, int x )
該函數的作用是:通過(guò)ue(v)編碼實(shí)現te(v)編碼的讀取。

static inline int bs_read_te( bs_t *s, int x )
{
    if( x == 1 )
    {
        return 1 - bs_read1( s );
    }
    else if( x > 1 )
    {
        return bs_read_ue( s );
    }
    return 0;
}

思路:當x=1時(shí),直接讀出一位,然后取反;
      當x>1時(shí),讀取方式同ue(v)。


3)static inline int bs_size_te( int x, int val )
該函數的作用是:通過(guò)ue(v)編碼計算位數的方式實(shí)現te(v)編碼的位數計算。

static inline int bs_size_te( int x, int val )
{
    if( x == 1 )
    {
        return 1;
    }
    else if( x > 1 )
    {
        return bs_size_ue( val );
    }
    return 0;
}

思路:當x=1時(shí),直接為1;
     當x>1時(shí),同ue(v)。

 
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
H264的I/P/B幀類(lèi)型判斷(一)
Linux學(xué)習第29節,從C語(yǔ)言源碼分析,信號量和自旋鎖有何區別
NV筆試2011 asic最后一題
H.264中的指數哥倫布編碼
返回類(lèi)型為指針的函數如int* func(....)
linux中函數test_bit :簡(jiǎn)單地返回這個(gè)位的當前值.
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久