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<char*>(&uiDummy), 3 );
  if (m_cHandle.eof()) return -1;
  assert( 0 == uiDummy );
  
  m_cHandle.read( reinterpret_cast<char*>(&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<char*>(&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<char*>(&uiDummy), 3 );
  if (m_cHandle.eof()) return -1;
  assert( 0 == uiDummy );
  
  m_cHandle.read( reinterpret_cast<char*>(&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<char*>(&ucByte), 1 );
    if ( m_cHandle.eof() )
    {
      iNextStartCodeBytes = 0;
      m_cHandle.clear();  /*********先clear*********/
      break;
    }
    ......
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 9,948评论 0 5
  • 一、SVN有时Update失败解决方法 1、可以使用SVN clean up来清除锁定(break lock)。 ...
    JavaIsMyLife阅读 2,823评论 0 0
  • 最早接触社区运营是13年的QQ群运营,那时候一个公司内部的人带领一群线上,零基础小白学习营销以及简单的课程学习,这...
    安娜_2020阅读 2,795评论 0 0