📄 librarybuilderinternals.cpp
字号:
static const CLSID asfContent1 =
{ 0x75B22633, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C } };
static const CLSID asfProperties1 = // ???
{ 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 } };
static const CLSID asfStream1 =
{ 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 } };
static const CLSID asfVideo1 =
{ 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B } };
static const CLSID asfData1 =
{ 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c } };
// {D6E229D1-35DA-11d1-9034-00A0C90349BE}
static const CLSID asfHeader2 =
{ 0xD6E229D1, 0x35DA, 0x11d1, { 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE } };
// {D6E229D2-35DA-11d1-9034-00A0C90349BE}
static const CLSID asfData2 =
{ 0xD6E229D2, 0x35DA, 0x11d1, { 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE } };
// {D6E229D0-35DA-11d1-9034-00A0C90349BE}
static const CLSID asfProperties2 =
{ 0xD6E229D0, 0x35DA, 0x11d1, { 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE } };
// {D6E229D4-35DA-11d1-9034-00A0C90349BE}
static const CLSID asfStream2 =
{ 0xD6E229D4, 0x35DA, 0x11d1, { 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE } };
// {D6E229D5-35DA-11d1-9034-00A0C90349BE}
static const CLSID asfContent2 =
{ 0xD6E229D5, 0x35DA, 0x11d1, { 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE } };
// {D6E229E2-35DA-11d1-9034-00A0C90349BE}
static const CLSID asfAudio2 =
{ 0xD6E229E2, 0x35DA, 0x11d1, { 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE } };
// {D6E229E3-35DA-11d1-9034-00A0C90349BE}
static const CLSID asfVideo2 =
{ 0xD6E229E3, 0x35DA, 0x11d1, { 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE } };
// {2211B3FB-BD23-11D2-B4B7-00A0C955FC6E}
static const CLSID asfDRM1 =
{ 0x2211B3FB, 0xBD23, 0x11D2, { 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E } };
// {1EFB1A30-0B62-11D0-A39B-00A0C90348F6}
static const CLSID asfDRM2 =
{ 0x1EFB1A30, 0x0B62, 0x11D0, { 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 } };
BOOL CLibraryBuilderInternals::ReadASF( HANDLE hFile)
{
QWORD nSize;
DWORD nRead;
GUID pGUID;
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
ReadFile( hFile, &pGUID, sizeof(pGUID), &nRead, NULL );
if ( nRead != sizeof(pGUID) || ( pGUID != asfHeader1 && pGUID != asfHeader2 ) )
return SubmitCorrupted();
ReadFile( hFile, &nSize, sizeof(nSize), &nRead, NULL );
if ( nRead != sizeof(nSize) ) return SubmitCorrupted();
if ( pGUID == asfHeader1 ) SetFilePointer( hFile, 6, NULL, FILE_CURRENT );
CString strTitle, strAuthor, strCopyright, strDescription, strRating;
DWORD nBitrate = 0, nVideoWidth = 0, nVideoHeight = 0;
QWORD nContentLength = 0;
BOOL bVideo = FALSE;
BOOL bDRM = FALSE;
while ( TRUE )
{
DWORD dwPosition = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
ReadFile( hFile, &pGUID, sizeof(pGUID), &nRead, NULL );
if ( nRead != sizeof(pGUID) ) break;
ReadFile( hFile, &nSize, sizeof(nSize), &nRead, NULL );
if ( nRead != sizeof(nSize) || nSize >= 0x80000000 ) break;
if ( pGUID == asfProperties1 )
{
SetFilePointer( hFile, 48, NULL, FILE_CURRENT );
ReadFile( hFile, &nContentLength, sizeof(nContentLength), &nRead, NULL );
if ( nRead != sizeof(nContentLength) ) return FALSE;
}
else if ( pGUID == asfProperties2 )
{
SetFilePointer( hFile, 40, NULL, FILE_CURRENT );
ReadFile( hFile, &nContentLength, sizeof(nContentLength), &nRead, NULL );
if ( nRead != sizeof(nContentLength) ) return FALSE;
SetFilePointer( hFile, 8, NULL, FILE_CURRENT );
ReadFile( hFile, &nBitrate, sizeof(nBitrate), &nRead, NULL );
if ( nRead != sizeof(nBitrate) ) return FALSE;
}
else if ( pGUID == asfStream1 )
{
ReadFile( hFile, &pGUID, sizeof(pGUID), &nRead, NULL );
if ( nRead != sizeof(pGUID) ) return FALSE;
if ( pGUID == asfVideo1 )
{
bVideo = TRUE;
SetFilePointer( hFile, 38, NULL, FILE_CURRENT );
ReadFile( hFile, &nVideoWidth, sizeof(nVideoWidth), &nRead, NULL );
if ( nRead != sizeof(nVideoWidth) ) return FALSE;
ReadFile( hFile, &nVideoHeight, sizeof(nVideoHeight), &nRead, NULL );
if ( nRead != sizeof(nVideoHeight) ) return FALSE;
}
}
else if ( pGUID == asfStream2 )
{
ReadFile( hFile, &pGUID, sizeof(pGUID), &nRead, NULL );
if ( nRead != sizeof(pGUID) ) return FALSE;
if ( pGUID == asfVideo2 )
{
bVideo = TRUE;
/*
SetFilePointer( hFile, 68, NULL, FILE_CURRENT );
ReadFile( hFile, &nVideoWidth, sizeof(nVideoWidth), &nRead, NULL );
if ( nRead != sizeof(nVideoWidth) ) return FALSE;
nVideoHeight = nVideoWidth >> 16;
nVideoWidth &= 0xFFFF;
*/
}
}
else if ( pGUID == asfContent1 )
{
WORD nStrLen[5];
ReadFile( hFile, nStrLen, sizeof(nStrLen), &nRead, NULL );
if ( nRead != sizeof(nStrLen) ) break;
for ( int nStr = 0 ; nStr < 5 ; nStr++ )
{
if ( ! nStrLen[ nStr ] || nStrLen[ nStr ] & 1 ) continue;
WCHAR* pStr = new WCHAR[ nStrLen[ nStr ] / 2 ];
ReadFile( hFile, pStr, nStrLen[ nStr ], &nRead, NULL );
if ( nRead != nStrLen[ nStr ] ) return FALSE;
pStr[ nStrLen[ nStr ] / 2 - 1 ] = 0;
switch ( nStr )
{
case 0:
strTitle = pStr;
break;
case 1:
strAuthor = pStr;
break;
case 2:
strCopyright = pStr;
break;
case 3:
strDescription = pStr;
break;
case 4:
strRating = pStr;
break;
}
delete [] pStr;
}
}
else if ( pGUID == asfContent2 )
{
WORD nCount;
ReadFile( hFile, &nCount, sizeof(nCount), &nRead, NULL );
if ( nRead != sizeof(nCount) ) break;
while ( nCount-- )
{
WORD nLanguageID, nStreamID, nNameLen, nValueLen;
BYTE nFieldType;
WCHAR* pStr;
ReadFile( hFile, &nFieldType, sizeof(nFieldType), &nRead, NULL );
if ( nRead != sizeof(nFieldType) ) return FALSE;
ReadFile( hFile, &nLanguageID, sizeof(nLanguageID), &nRead, NULL );
if ( nRead != sizeof(nLanguageID) ) return FALSE;
ReadFile( hFile, &nStreamID, sizeof(nStreamID), &nRead, NULL );
if ( nRead != sizeof(nStreamID) ) return FALSE;
ReadFile( hFile, &nNameLen, sizeof(nNameLen), &nRead, NULL );
if ( nRead != sizeof(nNameLen) ) return FALSE;
ReadFile( hFile, &nValueLen, sizeof(nValueLen), &nRead, NULL );
if ( nRead != sizeof(nValueLen) ) return FALSE;
pStr = new WCHAR[ nNameLen + 1 ];
ReadFile( hFile, pStr, nNameLen * 2, &nRead, NULL );
if ( nRead != (DWORD)nNameLen * 2 ) return FALSE;
pStr[ nNameLen ] = 0;
delete [] pStr;
pStr = new WCHAR[ nValueLen + 1 ];
ReadFile( hFile, pStr, nValueLen * 2, &nRead, NULL );
if ( nRead != (DWORD)nValueLen * 2 ) return FALSE;
pStr[ nValueLen ] = 0;
switch ( nFieldType )
{
case 1:
strAuthor = pStr;
break;
case 2: case 20:
strTitle = pStr;
break;
case 3:
strCopyright = pStr;
break;
case 4:
strDescription = pStr;
break;
}
delete [] pStr;
}
}
else if ( pGUID == asfDRM1 || pGUID == asfDRM2 )
{
bDRM = TRUE;
}
else if ( pGUID == asfData1 || pGUID == asfData2 )
{
break;
}
SetFilePointer( hFile, dwPosition + (DWORD)nSize, NULL, FILE_BEGIN );
}
CXMLElement* pXML = new CXMLElement( NULL, bVideo ? _T("video") : _T("audio") );
CString strItem;
if ( strTitle.GetLength() ) pXML->AddAttribute( _T("title"), strTitle );
if ( strDescription.GetLength() ) pXML->AddAttribute( _T("description"), strDescription );
if ( bDRM )
{
pXML->AddAttribute( _T("drm"), _T("true") );
}
if ( bVideo )
{
if ( strAuthor.GetLength() ) pXML->AddAttribute( _T("producer"), strAuthor );
if ( strRating.GetLength() ) pXML->AddAttribute( _T("rating"), strRating );
if ( nContentLength > 0 )
{
DWORD nSeconds = (DWORD)( nContentLength / 10000000 );
strItem.Format( _T("%lu.%lu"), nSeconds / 60, ( ( nSeconds % 60 ) * 10 / 60 ) );
pXML->AddAttribute( _T("minutes"), strItem );
}
if ( nVideoWidth > 0 && nVideoHeight > 0 )
{
strItem.Format( _T("%lu"), nVideoWidth );
pXML->AddAttribute( _T("width"), strItem );
strItem.Format( _T("%lu"), nVideoHeight );
pXML->AddAttribute( _T("height"), strItem );
}
}
else
{
if ( strAuthor.GetLength() ) pXML->AddAttribute( _T("artist"), strAuthor );
if ( nContentLength > 0 )
{
strItem.Format( _T("%lu"), (DWORD)( nContentLength / 10000000 ) );
pXML->AddAttribute( _T("seconds"), strItem );
}
if ( nBitrate > 0 )
{
strItem.Format( _T("%lu"), nBitrate / 1000 );
pXML->AddAttribute( _T("bitrate"), strItem );
}
}
pXML->AddAttribute( _T("codec"), _T("WM") );
return SubmitMetadata( bVideo ? CSchema::uriVideo : CSchema::uriAudio, pXML );
}
//////////////////////////////////////////////////////////////////////
// CLibraryBuilderInternals MPEG (threaded)
BOOL CLibraryBuilderInternals::ReadMPEG( HANDLE hFile)
{
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
DWORD nHeader = 0;
for ( DWORD nSeek = 8192 ; nSeek > 0 ; nSeek--, nHeader <<= 8 )
{
DWORD nRead = 0;
ReadFile( hFile, &nHeader, 1, &nRead, NULL );
if ( nRead != 1 ) break;
if ( nHeader == 0x000001B3 ) break;
}
if ( ! nSeek ) return FALSE;
BYTE nBuffer[7];
ReadFile( hFile, nBuffer, 7, &nHeader, NULL );
if ( nHeader != 7 ) return FALSE;
CXMLElement* pXML = new CXMLElement( NULL, _T("video") );
CString strItem;
DWORD nWidth, nHeight;
nWidth = ( (DWORD)nBuffer[0] << 4 ) | (DWORD)nBuffer[1] >> 4;
nHeight = ( ( (DWORD)nBuffer[1] & 0x0F ) << 8 ) | (DWORD)nBuffer[2];
strItem.Format( _T("%lu"), nWidth );
pXML->AddAttribute( _T("width"), strItem );
strItem.Format( _T("%lu"), nHeight );
pXML->AddAttribute( _T("height"), strItem );
pXML->AddAttribute( _T("codec"), _T("MPEG") );
LPCTSTR pszFPS[] = { _T("23.976"), _T("24"), _T("25"), _T("29.97"), _T("30"), _T("50"), _T("59.94"), _T("60") };
int nFrameIndex = ( nBuffer[3] & 0x0F );
if ( nFrameIndex >= 1 && nFrameIndex <= 9 )
{
pXML->AddAttribute( _T("frameRate"), pszFPS[ nFrameIndex - 1 ] );
}
return SubmitMetadata( CSchema::uriVideo, pXML );
}
//////////////////////////////////////////////////////////////////////
// CLibraryBuilderInternals OGG VORBIS (threaded)
BOOL CLibraryBuilderInternals::ReadOGG( HANDLE hFile)
{
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
DWORD nDummy, nHeader = 0;
ReadFile( hFile, &nHeader, 4, &nDummy, NULL );
for ( DWORD nSeek = 0 ; nSeek < 16384 ; nSeek++ )
{
if ( nHeader == 'SggO' ) break;
nHeader >>= 8;
ReadFile( hFile, (BYTE*)&nHeader + 3, 1, &nDummy, NULL );
}
if ( nHeader != 'SggO' ) return SubmitCorrupted();
SetFilePointer( hFile, -4, NULL, FILE_CURRENT );
DWORD nOGG = 0;
BYTE* pOGG = ReadOGGPage( hFile, nOGG, 0x02, 0, 0x1E );
if ( ! pOGG ) return FALSE;
BYTE nChannels = pOGG[ 11 ];
DWORD nFrequency = *(DWORD*)&pOGG[12];
DWORD nBitrate = *(DWORD*)&pOGG[20];
delete [] pOGG;
BYTE* prOGG = pOGG = ReadOGGPage( hFile, nOGG, 0x00, 1, 1+6+4+4 );
if ( ! pOGG ) return FALSE;
pOGG += 1 + 6;
nOGG -= 1 + 6;
CString strComment;
if ( ! ReadOGGString( pOGG, nOGG, strComment ) || nOGG < 4 )
{
free( pOGG );
return FALSE;
}
DWORD nComments = *(DWORD*)pOGG;
pOGG += 4; nOGG -= 4;
CXMLElement* pXML = new CXMLElement( NULL, _T("audio") );
for ( ; nComments && nOGG > 4 ; nComments-- )
{
if ( ! ReadOGGString( pOGG, nOGG, strComment ) ) break;
int nEquals = strComment.Find( '=' );
if ( nEquals <= 0 ) continue;
CString strKey = strComment.Left( nEquals );
CString strValue = strComment.Mid( nEquals + 1 );
strKey.TrimLeft(); strKey.TrimRight(); strKey.MakeUpper();
strValue.TrimLeft(); strValue.TrimRight();
if ( strValue.IsEmpty() ) continue;
if ( strKey == _T("TITLE") )
{
pXML->AddAttribute( _T("title"), strValue );
}
else if ( strKey == _T("ALBUM") )
{
pXML->AddAttribute( _T("album"), strValue );
}
else if ( strKey == _T("TRACKNUMBER") )
{
pXML->AddAttribute( _T("track"), strValue );
}
else if ( strKey == _T("ARTIST") )
{
pXML->AddAttribute( _T("artist"), strValue );
}
else if ( strKey == _T("DESCRIPTION") )
{
pXML->AddAttribute( _T("description"), strValue );
}
else if ( strKey == _T("GENRE") )
{
pXML->AddAttribute( _T("genre"), strValue );
}
else if ( strKey == _T("DATE") )
{
pXML->AddAttribute( _T("year"), strValue );
}
}
delete [] prOGG;
if ( nComments )
{
if ( pXML ) delete pXML;
return FALSE;
}
DWORD nLength = 0;
for ( nComments = 2 ; ; nComments++ )
{
DWORD nTime = GetTickCount();
if ( ! ReadOGGPage( hFile, nOGG, 0xFF, nComments, 0xFFFFFFFF ) ) break;
nLength = max( nLength, nOGG );
m_nSleep = ( GetTickCount() - nTime ) * 3;
if ( m_nSleep > 0 ) Sleep( m_nSleep );
if ( ! m_pBuilder->m_bThread ) break;
}
if ( ! m_pBuilder->m_bThread )
{
delete pXML;
return FALSE;
}
if ( nFrequency > 0 && nLength > 0 && ( nLength / nFrequency ) > 0 )
{
strComment.Format( _T("%lu"), nLength / nFrequency );
pXML->AddAttribute( _T("seconds"), strComment );
nBitrate = GetFileSize( hFile, NULL ) / ( nLength / nFrequency ) * 8;
}
strComment.Format( _T("%lu"), nBitrate / 1000 );
pXML->AddAttribute( _T("bitrate"), strComment );
strComment.Format( _T("%lu"), nFrequency );
pXML->AddAttribute( _T("sampleRate"), strComment );
return SubmitMetadata( CSchema::uriAudio, pXML );
}
BYTE* CLibraryBuilderInternals::ReadOGGPage(HANDLE hFile, DWORD& nBuffer, BYTE nFlags, DWORD nSequence, DWORD nMinSize)
{
DWORD nMagic, nRead, nSample;
BYTE nByte, nChunk;
nBuffer = 0;
ReadFile( hFile, &nMagic, 4, &nRead, NULL );
if ( nRead != 4 || nMagic != 'SggO' ) return NULL;
ReadFile( hFile, &nByte, 1, &nRead, NULL );
if ( nRead != 1 || nByte != 0 ) return NULL;
ReadFile( hFile, &nByte, 1, &nRead, NULL );
if ( nRead != 1 ) return NULL;
if ( nFlags < 0xFF && nByte != nFlags ) return NULL;
ReadFile( hFile, &nSample, 4, &nRead, NULL );
if ( nRead != 4 ) return NULL;
SetFilePointer( hFile, 4 + 4, NULL, FILE_CURRENT );
ReadFile( hFile, &nMagic, 4, &nRead, NULL );
if ( nRead != 4 || nMagic != nSequence ) return NULL;
ReadFile( hFile, &nMagic, 4, &nRead, NULL );
if ( nRead != 4 ) return NULL;
ReadFile( hFile, &nByte, 1, &nRead, NULL );
if ( nRead != 1 ) return NULL;
for ( ; nByte ; nByte-- )
{
ReadFile( hFile, &nChunk, 1, &nRead, NULL );
if ( nRead != 1 ) break;
nBuffer += nChunk;
}
if ( nByte ) return NULL;
if ( nMinSize < 0xFFFFFFFF )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -