HEVC/H265 HM10.0 分析(三)TAppDecTop.cpp

來源:互聯網
上載者:User

在TAppDecTop.cpp  ,最重要的是decode 函數,下面將對其進行分析,是解碼上層的一個重要函數。

代碼如下,代碼後將進行分析。

Void TAppDecTop::decode(){  Int                 poc;  TComList<TComPic*>* pcListPic = NULL;  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);  if (!bitstreamFile)  {    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);    exit(EXIT_FAILURE);  }  InputByteStream bytestream(bitstreamFile);  // create & initialize internal classes  xCreateDecLib();  xInitDecLib  ();  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.  // main decoder loop  Bool recon_opened = false; // reconstruction file not yet opened. (must be performed after SPS is seen)  while (!!bitstreamFile)  {    /* location serves to work around a design fault in the decoder, whereby     * the process of reading a new slice that is the first slice of a new frame     * requires the TDecTop::decode() method to be called again with the same     * nal unit. */    streampos location = bitstreamFile.tellg();    AnnexBStats stats = AnnexBStats();    Bool bPreviousPictureDecoded = false;    vector<uint8_t> nalUnit;    InputNALUnit nalu;    byteStreamNALUnit(bytestream, nalUnit, stats);    // call actual decoding function    Bool bNewPicture = false;    if (nalUnit.empty())    {      /* this can happen if the following occur:       *  - empty input file       *  - two back-to-back start_code_prefixes       *  - start_code_prefix immediately followed by EOF       */      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");    }    else    {      read(nalu, nalUnit);      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )      {        if(bPreviousPictureDecoded)        {          bNewPicture = true;          bPreviousPictureDecoded = false;        }        else        {          bNewPicture = false;        }      }      else      {        bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay);        if (bNewPicture)        {          bitstreamFile.clear();          /* location points to the current nalunit payload[1] due to the           * need for the annexB parser to read three extra bytes.           * [1] except for the first NAL unit in the file           *     (but bNewPicture doesn't happen then) */          bitstreamFile.seekg(location-streamoff(3));          bytestream.reset();        }        bPreviousPictureDecoded = true;       }    }    if (bNewPicture || !bitstreamFile)    {      m_cTDecTop.executeLoopFilters(poc, pcListPic);  printf("\npoc =%d\n",poc);    }    if( pcListPic )    {printf("\nnaluType =%d\n",nalu.m_nalUnitType);      if ( m_pchReconFile && !recon_opened )      {        if (!m_outputBitDepthY) { m_outputBitDepthY = g_bitDepthY; }        if (!m_outputBitDepthC) { m_outputBitDepthC = g_bitDepthC; }        m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepthY, m_outputBitDepthC, g_bitDepthY, g_bitDepthC ); // write mode        recon_opened = true;      }      if ( bNewPicture &&            (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLANT            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA ) )      {        xFlushOutput( pcListPic );      }      // write reconstruction to file      if(bNewPicture)      {        xWriteOutput( pcListPic, nalu.m_temporalId );      }    }  }    xFlushOutput( pcListPic );  // delete buffers  m_cTDecTop.deletePicBuffer();    // destroy internal classes  xDestroyDecLib();}

代碼xCreateDecLib 和 xInitDecLib 重要是初始化四叉樹和解碼需要的全域變數和申請記憶體。

當提供一個碼流檔案的檔案名稱後,進行ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary); 以二進位方式開啟檔案名稱,碼流以位元組方式InputByteStream bytestream(bitstreamFile);進行讀操作。

我們都知道,HEVC/H265 是以NAL方式組織資料的,解析VPS,SPS,PPS,SEI,SEI_SUFFIX 後,其他的是一個個slice的NAL資料,而Deblocking & SAO Filters 等濾波是對整個picuture進行濾波操作,出現從第二幀開始,每幀的第一個slice兩次進行解析,這是參考軟體的一個bug或不好的地方,其實完全可以知道是否是最後一個slice,不必進行兩次開啟。

所以出現:

bitstreamFile.clear();

bitstreamFile.seekg(location-streamoff(3));
bytestream.reset();

大家有興趣,可以先增加一個變數,判斷是否是最後一個slice,就不需要執行上面代碼了。

如下代碼是從來不會執行,因為HEVC/H265沒有cavlc,也就不會有slice part A ,slice part B,slice part C ,是現實的編解碼告訴了設計者,slice part A ,slice part B,slice part C 沒有人使用,就被拋棄了,實際的編解碼從來沒有實現slice part A ,slice part B,slice part C 等編解碼的。

 if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )
      {
        if(bPreviousPictureDecoded)
        {
          bNewPicture = true;
          bPreviousPictureDecoded = false;
        }
        else
        {
          bNewPicture = false;
        }
      }

解碼和濾波後當然就是輸出重構資料,xWriteOutput( pcListPic, nalu.m_temporalId ), 如果slice是NAL_UNIT_CODED_SLICE_IDR,NAL_UNIT_CODED_SLICE_IDR_N_LP,NAL_UNIT_CODED_SLICE_BLA_N_LP,NAL_UNIT_CODED_SLICE_BLANT,NAL_UNIT_CODED_SLICE_BLA中的一種,將解碼產生的picture全部清空,沒有任何參考幀,相當於一個新的sequence進行解碼了。

其他的代碼很簡單,請自己分析。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.