<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:SimSun;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:SimSun;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:SimSun;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        text-align:justify;
        text-justify:inter-ideograph;
        font-size:10.5pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin:0cm;
        margin-bottom:.0001pt;
        text-align:justify;
        text-justify:inter-ideograph;
        text-indent:21.0pt;
        font-size:10.5pt;
        font-family:"Calibri","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
/* Page Definitions */
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:426312713;
        mso-list-type:hybrid;
        mso-list-template-ids:-271927280 -692821878 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l0:level1
        {mso-level-text:"%1\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:18.0pt;
        text-indent:-18.0pt;}
@list l0:level2
        {mso-level-number-format:alpha-lower;
        mso-level-text:"%2\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:42.0pt;
        text-indent:-21.0pt;}
@list l0:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:63.0pt;
        text-indent:-21.0pt;}
@list l0:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:84.0pt;
        text-indent:-21.0pt;}
@list l0:level5
        {mso-level-number-format:alpha-lower;
        mso-level-text:"%5\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:105.0pt;
        text-indent:-21.0pt;}
@list l0:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:126.0pt;
        text-indent:-21.0pt;}
@list l0:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:147.0pt;
        text-indent:-21.0pt;}
@list l0:level8
        {mso-level-number-format:alpha-lower;
        mso-level-text:"%8\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:168.0pt;
        text-indent:-21.0pt;}
@list l0:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:189.0pt;
        text-indent:-21.0pt;}
ol
        {margin-bottom:0cm;}
ul
        {margin-bottom:0cm;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="ZH-CN" link="blue" vlink="purple" style="text-justify-trim:punctuation">
<div class="WordSection1">
<p class="MsoNormal"><span lang="EN-US">Hi experts:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">I’m writing a vp8 parser for gstreamer (used by gst-vaapi).<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">though it works on my side now, I have some question on the RAC (randomized arithmetic coding) part.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">I start with GstBitReader for VP8 parser, but fail to parse token_prob_update and mv_prob_update parts since these two parts use RAC.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Then I copied RAC code from ffmpeg to make it work.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Now my questions are:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1">
<![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">1)<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">Is there existing RAC code in gst to use?<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1">
<![if !supportLists]><span lang="EN-US"><span style="mso-list:Ignore">2)<span style="font:7.0pt "Times New Roman"">      
</span></span></span><![endif]><span lang="EN-US">If not, should I extend GstBitReader for RAC or use the ffmpeg directly? (both gst codec parses and ffmpeg follows LGPL, it seems there is no legal issue).<o:p></o:p></span></p>
<p class="MsoListParagraph" style="margin-left:18.0pt;text-indent:0cm"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoListParagraph" style="margin-left:18.0pt;text-indent:0cm"><span lang="EN-US">Thanks.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">Here are the ffmpeg RAC code for your reference:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">void ff_vp56_init_range_decoder(VP56RangeCoder *c, const guint8 *buf, int buf_size)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->high = 255;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->bits = -16;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->buffer = buf;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->end = buf + buf_size;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->code_word = bytestream_get_be24(&c->buffer);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">// rounding is different than vp56_rac_get, is vp56_rac_get wrong?<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static av_always_inline int vp8_rac_get(VP56RangeCoder *c)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    return vp56_rac_get_prob(c, 128);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static av_always_inline unsigned int vp56_rac_renorm(VP56RangeCoder *c)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    int shift = ff_vp56_norm_shift[c->high];<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    int bits = c->bits;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    unsigned int code_word = c->code_word;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->high   <<= shift;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    code_word <<= shift;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    bits       += shift;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    if(bits >= 0 && c->buffer < c->end) {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">        code_word |= bytestream_get_be16(&c->buffer) << bits;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">        bits -= 16;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->bits = bits;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    return code_word;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static av_always_inline int vp56_rac_get_prob(VP56RangeCoder *c, guint8 prob)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    static int count = 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    unsigned int code_word = vp56_rac_renorm(c);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    unsigned int low = 1 + (((c->high - 1) * prob) >> 8);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    unsigned int low_shift = low << 16;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    int bit = code_word >= low_shift;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    // PRINTF("count: %4d, prob: %4x, c->code_word: %8x, code_word: %8x, low: %8x, bit: %d ", count, prob, c->code_word, code_word, low, bit);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->high = bit ? c->high - low : low;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->code_word = bit ? code_word - low_shift : code_word;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    // PRINTF(" #### c->high: %8x, c->code_word: %8x, c->bits: %d\n", c->high, c->code_word, c->bits);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    count++;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    return bit;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">// branchy variant, to be used where there's a branch based on the bit decoded<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static av_always_inline int vp56_rac_get_prob_branchy(VP56RangeCoder *c, int prob)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    unsigned long code_word = vp56_rac_renorm(c);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    unsigned low = 1 + (((c->high - 1) * prob) >> 8);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    unsigned low_shift = low << 16;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    if (code_word >= low_shift) {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">        c->high     -= low;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">        c->code_word = code_word - low_shift;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">        return 1;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->high = low;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    c->code_word = code_word;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    return 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">static av_unused int vp8_rac_get_uint(VP56RangeCoder *c, int bits)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">{<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    int value = 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    while (bits--) {<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">        value = (value << 1) | vp8_rac_get(c);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    }<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">    return value;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>
</div>
</body>
</html>