<p><br>
On Oct 1, 2013 1:44 AM, "Steve Borho" <<a href="mailto:steve@borho.org">steve@borho.org</a>> wrote:<br>
><br>
><br>
><br>
><br>
> On Fri, Sep 27, 2013 at 11:52 PM, Aarthi Thirumalai <<a href="mailto:aarthi@multicorewareinc.com">aarthi@multicorewareinc.com</a>> wrote:<br>
>><br>
>> # HG changeset patch<br>
>> # User Aarthi Thirumalai<br>
>> # Date 1380343885 -19800<br>
>> #      Sat Sep 28 10:21:25 2013 +0530<br>
>> # Node ID b1539ccab7bab1708433a9b8b18f5f8c090b1810<br>
>> # Parent  a8b00de495520f00a4648dac5d111e40b5570ca3<br>
>> integrated ssim computation for each CTURow<br>
>><br>
>> diff -r a8b00de49552 -r b1539ccab7ba source/encoder/frameencoder.cpp<br>
>> --- a/source/encoder/frameencoder.cpp   Sat Sep 28 10:18:23 2013 +0530<br>
>> +++ b/source/encoder/frameencoder.cpp   Sat Sep 28 10:21:25 2013 +0530<br>
>> @@ -91,6 +91,9 @@<br>
>>          delete[] m_rows;<br>
>>      }<br>
>><br>
>> +    if (tempBuf)<br>
><br>
><br>
> X265_FREE does the NULL check for you<br>
>  <br>
>><br>
>> +        X265_FREE(tempBuf);<br>
>> +<br>
>>      m_frameFilter.destroy();<br>
>><br>
>>      // wait for worker thread to exit<br>
>> @@ -106,6 +109,8 @@<br>
>>                          2 : (m_cfg->param.bEnableSAO || m_cfg->param.bEnableLoopFilter ? 1 : 0);<br>
>><br>
>>      m_rows = new CTURow[m_numRows];<br>
>> +    if(m_cfg->param.bEnableSsim)<br>
><br>
><br>
> white-space<br>
>  <br>
>><br>
>> +        CHECKED_MALLOC(tempBuf, int, m_cfg->param.bEnableSsim * 8 * (m_cfg->param.sourceWidth/4 + 3));<br>
>>      for (int i = 0; i < m_numRows; ++i)<br>
>>      {<br>
>>          m_rows[i].create(top);<br>
>> @@ -168,6 +173,8 @@<br>
>>          assert(0);<br>
>>      }<br>
>>      start();<br>
>> +fail:<br>
>> +    return;<br>
>>  }<br>
>><br>
>>  int FrameEncoder::getStreamHeaders(NALUnitEBSP **nalunits)<br>
>> @@ -540,6 +547,31 @@<br>
>>          slice->setSaoEnabledFlag((saoParam->bSaoFlag[0] == 1) ? true : false);<br>
>>      }<br>
>><br>
>> +    /*Compute SSIM if enabled*/<br>
>> +       if(m_cfg->param.bEnableSsim)<br>
><br>
> white-space <br>
>><br>
>> +       {<br>
>> +            pixel *rec = (pixel*)m_pic->getPicYuvRec()->getLumaAddr();<br>
>> +            pixel *org = (pixel*)m_pic->getPicYuvOrg()->getLumaAddr();<br>
>> +            int stride = m_pic->getPicYuvOrg()->getStride();<br>
>> +           for(int row = 0; row < m_numRows; row++)<br>
>> +           {<br>
>> +               int bEnd = ((row + 1) == (this->m_numRows - 1));<br>
>> +               int bStart = (row == 0);<br>
>> +               int minPixY = row * 64 - 4 * !bStart;<br>
>> +               int maxPixY = (row + 1)* 64 - 4 * !bEnd;<br>
>> +               int ssim_cnt;<br>
>> +               x265_emms();<br>
>> +               /* offset by 2 pixels to avoid alignment of ssim blocks with dct blocks,<br>
>> +               * and overlap by 4 */<br>
><br>
><br>
> do you understand what this comment implies?  I don't and we probably should<br>
> <br>
The function to calculate ssim for each row in this manner. Starting point : offset block by 2 in x axis. Do ssim for 2 4x4 blocks till row end. Offset by 4 in y axis from starting point n repeat above step for entire height(maxpicy - minpic) this offset is done so block positions don't match with dct sizes.<br>

>><br>
>> +                minPixY += bStart ? 2 : -6;<br>
>> +                slice->m_ssim +=<br>
>> +                calculateSSIM(<br>
>> +                rec + 2 + minPixY * stride, stride,<br>
>> +                org + 2 + minPixY * stride, stride,<br>
>> +                m_cfg->param.sourceWidth-2, maxPixY - minPixY, tempBuf, &ssim_cnt );<br>
><br>
><br>
> formatting<br>
>  <br>
>><br>
>> +                slice->m_ssimCnt += ssim_cnt;<br>
>> +            }<br>
>> +       }<br>
>>      entropyCoder->setBitstream(NULL);<br>
>><br>
>>      // Reconstruction slice<br>
>> @@ -687,6 +719,38 @@<br>
>>      delete bitstreamRedirect;<br>
>>  }<br>
>><br>
>> +/* Function to calculate SSIM for each row */<br>
>> +float FrameEncoder::calculateSSIM( pixel *pix1, intptr_t stride1,<br>
>> +                                   pixel *pix2, intptr_t stride2,<br>
>> +                                   int width, int height, void *buf, int *cnt )<br>
><br>
> coding-style <br>
>><br>
>> +{<br>
>> +    int z = 0;<br>
>> +    float ssim = 0.0;<br>
>> +    int (*sum0)[4] = (int (*)[4]) buf;<br>
>> +    int (*sum1)[4] = sum0 + (width >> 2) + 3;<br>
>> +    width >>= 2;<br>
>> +    height >>= 2;<br>
>> +    for( int y = 1; y < height; y++ )<br>
>> +    {<br>
>> +        for( ; z <= y; z++ )<br>
>> +        {<br>
>> +            void* swap = sum0;<br>
>> +            sum0 = sum1;<br>
>> +            sum1 = (int (*)[4])swap;<br>
>> +            for( int x = 0; x < width; x+=2 )<br>
>> +            {<br>
>> +                if(m_pic->getPicYuvRec() == 0 || x== 98){<br>
>> +                    int nullaalret = 1; nullaalret++;<br>
>> +                }<br>
>> +                primitives.ssim4x4x2Core( &pix1[4*(x+z*stride1)], stride1, &pix2[4*(x+z*stride2)], stride2, &sum0[x] );<br>
>> +            }<br>
>> +        }<br>
>> +        for( int x = 0; x < width-1; x += 4 )<br>
>> +            ssim += primitives.ssimEnd4( sum0+x, sum1+x, X265_MIN(4,width-x-1) );<br>
>> +    }<br>
>> +    *cnt = (height-1) * (width-1);<br>
>> +    return ssim;<br>
>> +}<br>
>>  void FrameEncoder::encodeSlice(TComOutputBitstream* substreams)<br>
>>  {<br>
>>      // choose entropy coder<br>
>> diff -r a8b00de49552 -r b1539ccab7ba source/encoder/frameencoder.h<br>
>> --- a/source/encoder/frameencoder.h     Sat Sep 28 10:18:23 2013 +0530<br>
>> +++ b/source/encoder/frameencoder.h     Sat Sep 28 10:21:25 2013 +0530<br>
>> @@ -153,6 +153,10 @@<br>
>>      // worker thread<br>
>>      void threadMain();<br>
>><br>
>> +    /* called by compressFrame to calculate SSIM for each row after applying deblock filter and SAO. */<br>
>> +    float calculateSSIM(pixel *pix1, intptr_t stride1,pixel *pix2, intptr_t stride2,<br>
>> +                        int width, int height, void *buf, int *cnt );<br>
>> +<br>
>>      Event                    m_enable;<br>
>>      Event                    m_done;<br>
>>      bool                     m_threadActive;<br>
>> @@ -185,6 +189,9 @@<br>
>>      int                      m_filterRowDelay;<br>
>>      CTURow*                  m_rows;<br>
>>      Event                    m_completionEvent;<br>
>> +<br>
>> +    /* Temp Storage that doesnt need repeated malloc */<br>
>> +    void *                   tempBuf;<br>
>>  };<br>
>>  }<br>
>><br>
>> _______________________________________________<br>
>> x265-devel mailing list<br>
>> <a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
>> <a href="https://mailman.videolan.org/listinfo/x265-devel">https://mailman.videolan.org/listinfo/x265-devel</a><br>
><br>
><br>
><br>
><br>
> -- <br>
> Steve Borho<br>
><br>
> _______________________________________________<br>
> x265-devel mailing list<br>
> <a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
> <a href="https://mailman.videolan.org/listinfo/x265-devel">https://mailman.videolan.org/listinfo/x265-devel</a><br>
><br>
</p>