HM2.0、2.1、2.2、3.0等在winows系统下的解码crash问题

问题描述:

HM早些版本比如HM2.0、2.1、2.2、3.0等,进行解码时,会出现crash。具体位置如下,函数位于TVideoIOBits.cpp文件中,主要用于码流的读取

int TVideoIOBitsStartCode::xFindNextStartCode(UInt& ruiPacketSize, UChar* pucBuffer)
{
  UInt uiDummy = 0;
  m_cHandle.read( reinterpret_cast(&uiDummy), 3 );
  if (m_cHandle.eof()) return -1;
  assert( 0 == uiDummy );
  
  m_cHandle.read( reinterpret_cast(&uiDummy), 1 );
  if ( m_cHandle.eof() ) return -1;
  assert( 1 == uiDummy );                                              //////在此处出现crash,crash原因为uiDummy值为0
  
  Int iNextStartCodeBytes = 0;
  Int iBytesRead = 0;
  UInt uiZeros = 0;
  while( true )
  {
    UChar ucByte = 0;
    m_cHandle.read( reinterpret_cast(&ucByte), 1 );
    if ( m_cHandle.eof() )
    {
      iNextStartCodeBytes = 0;
      break;
    }
    pucBuffer[iBytesRead++] = ucByte;
    if( 1 < ucByte )
    {
      uiZeros = 0;
    }
    else if( 0 == ucByte )
    {
      uiZeros++;
    }
    else if( uiZeros > 2)
    {
      iNextStartCodeBytes = 3 + 1;
      break;
    }
    else
    {
      uiZeros = 0;
    }
  }
  
  ruiPacketSize = iBytesRead - iNextStartCodeBytes;
  
  m_cHandle.seekg( -iNextStartCodeBytes, ios::cur );
  return 0;
}

原因分析

由于在所有帧解码完成之后发生crash,原因主要在于,码流读取过程的问题。此处可以参考 http://jingpin.jikexueyuan.com/article/3665.html
简单来说就是,在C++中,当读取文件时,遇见文件结束符EOF之后,seekg函数不再起作用。也就是在解码最后一帧之前读取到bin文件的文件结束符EOF之后,再运行 m_cHandle.seekg( -iNextStartCodeBytes, ios::cur ) 将会不起作用。也就是下一次调用这个函数时无法读取到EOF,导致错误。

解决办法

在遇到文件结束符EOF之后,先clear,具体代码如下

int TVideoIOBitsStartCode::xFindNextStartCode(UInt& ruiPacketSize, UChar* pucBuffer)
{
  UInt uiDummy = 0;
  m_cHandle.read( reinterpret_cast(&uiDummy), 3 );
  if (m_cHandle.eof()) return -1;
  assert( 0 == uiDummy );
  
  m_cHandle.read( reinterpret_cast(&uiDummy), 1 );
  if ( m_cHandle.eof() ) return -1;
  assert( 1 == uiDummy );                                              //////在此处出现crash,crash原因为uiDummy值为0
  
  Int iNextStartCodeBytes = 0;
  Int iBytesRead = 0;
  UInt uiZeros = 0;
  while( true )
  {
    UChar ucByte = 0;
    m_cHandle.read( reinterpret_cast(&ucByte), 1 );
    if ( m_cHandle.eof() )
    {
      iNextStartCodeBytes = 0;
      m_cHandle.clear();  /*********先clear*********/
      break;
    }
    ......
}

你可能感兴趣的:(HM2.0、2.1、2.2、3.0等在winows系统下的解码crash问题)