問(wèn)題描述:
HM早些版本比如HM2.0、2.1膏孟、2.2眯分、3.0等,進(jìn)行解碼時(shí)柒桑,會(huì)出現(xiàn)crash弊决。具體位置如下,函數(shù)位于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 ); //////在此處出現(xiàn)crash魁淳,crash原因?yàn)閡iDummy值為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;
}
原因分析
由于在所有幀解碼完成之后發(fā)生crash飘诗,原因主要在于,碼流讀取過(guò)程的問(wèn)題界逛。此處可以參考 http://jingpin.jikexueyuan.com/article/3665.html
簡(jiǎn)單來(lái)說(shuō)就是昆稿,在C++中,當(dāng)讀取文件時(shí)息拜,遇見(jiàn)文件結(jié)束符EOF之后溉潭,seekg函數(shù)不再起作用。也就是在解碼最后一幀之前讀取到bin文件的文件結(jié)束符EOF之后少欺,再運(yùn)行 m_cHandle.seekg( -iNextStartCodeBytes, ios::cur ) 將會(huì)不起作用喳瓣。也就是下一次調(diào)用這個(gè)函數(shù)時(shí)無(wú)法讀取到EOF,導(dǎo)致錯(cuò)誤狈茉。
解決辦法
在遇到文件結(jié)束符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 ); //////在此處出現(xiàn)crash氯庆,crash原因?yàn)閡iDummy值為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;
}
......
}