问题描述:
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;
}
......
}