00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include <initguid.h>
00024 #include <uuids.h>
00025 #include "cdxareader.h"
00026 #include "..\..\..\..\include\matroska\matroska.h"
00027 #include "..\..\..\..\include\ogg\OggDS.h"
00028 #include "..\..\..\..\include\moreuuids.h"
00029 #include "..\..\..\DSUtil\DSUtil.h"
00030
00032
00033 static DWORD EDC_crctable[256] =
00034 {
00035 0x00000000l, 0x90910101l, 0x91210201l, 0x01b00300l,
00036 0x92410401l, 0x02d00500l, 0x03600600l, 0x93f10701l,
00037 0x94810801l, 0x04100900l, 0x05a00a00l, 0x95310b01l,
00038 0x06c00c00l, 0x96510d01l, 0x97e10e01l, 0x07700f00l,
00039 0x99011001l, 0x09901100l, 0x08201200l, 0x98b11301l,
00040 0x0b401400l, 0x9bd11501l, 0x9a611601l, 0x0af01700l,
00041 0x0d801800l, 0x9d111901l, 0x9ca11a01l, 0x0c301b00l,
00042 0x9fc11c01l, 0x0f501d00l, 0x0ee01e00l, 0x9e711f01l,
00043 0x82012001l, 0x12902100l, 0x13202200l, 0x83b12301l,
00044 0x10402400l, 0x80d12501l, 0x81612601l, 0x11f02700l,
00045 0x16802800l, 0x86112901l, 0x87a12a01l, 0x17302b00l,
00046 0x84c12c01l, 0x14502d00l, 0x15e02e00l, 0x85712f01l,
00047 0x1b003000l, 0x8b913101l, 0x8a213201l, 0x1ab03300l,
00048 0x89413401l, 0x19d03500l, 0x18603600l, 0x88f13701l,
00049 0x8f813801l, 0x1f103900l, 0x1ea03a00l, 0x8e313b01l,
00050 0x1dc03c00l, 0x8d513d01l, 0x8ce13e01l, 0x1c703f00l,
00051 0xb4014001l, 0x24904100l, 0x25204200l, 0xb5b14301l,
00052 0x26404400l, 0xb6d14501l, 0xb7614601l, 0x27f04700l,
00053 0x20804800l, 0xb0114901l, 0xb1a14a01l, 0x21304b00l,
00054 0xb2c14c01l, 0x22504d00l, 0x23e04e00l, 0xb3714f01l,
00055 0x2d005000l, 0xbd915101l, 0xbc215201l, 0x2cb05300l,
00056 0xbf415401l, 0x2fd05500l, 0x2e605600l, 0xbef15701l,
00057 0xb9815801l, 0x29105900l, 0x28a05a00l, 0xb8315b01l,
00058 0x2bc05c00l, 0xbb515d01l, 0xbae15e01l, 0x2a705f00l,
00059 0x36006000l, 0xa6916101l, 0xa7216201l, 0x37b06300l,
00060 0xa4416401l, 0x34d06500l, 0x35606600l, 0xa5f16701l,
00061 0xa2816801l, 0x32106900l, 0x33a06a00l, 0xa3316b01l,
00062 0x30c06c00l, 0xa0516d01l, 0xa1e16e01l, 0x31706f00l,
00063 0xaf017001l, 0x3f907100l, 0x3e207200l, 0xaeb17301l,
00064 0x3d407400l, 0xadd17501l, 0xac617601l, 0x3cf07700l,
00065 0x3b807800l, 0xab117901l, 0xaaa17a01l, 0x3a307b00l,
00066 0xa9c17c01l, 0x39507d00l, 0x38e07e00l, 0xa8717f01l,
00067 0xd8018001l, 0x48908100l, 0x49208200l, 0xd9b18301l,
00068 0x4a408400l, 0xdad18501l, 0xdb618601l, 0x4bf08700l,
00069 0x4c808800l, 0xdc118901l, 0xdda18a01l, 0x4d308b00l,
00070 0xdec18c01l, 0x4e508d00l, 0x4fe08e00l, 0xdf718f01l,
00071 0x41009000l, 0xd1919101l, 0xd0219201l, 0x40b09300l,
00072 0xd3419401l, 0x43d09500l, 0x42609600l, 0xd2f19701l,
00073 0xd5819801l, 0x45109900l, 0x44a09a00l, 0xd4319b01l,
00074 0x47c09c00l, 0xd7519d01l, 0xd6e19e01l, 0x46709f00l,
00075 0x5a00a000l, 0xca91a101l, 0xcb21a201l, 0x5bb0a300l,
00076 0xc841a401l, 0x58d0a500l, 0x5960a600l, 0xc9f1a701l,
00077 0xce81a801l, 0x5e10a900l, 0x5fa0aa00l, 0xcf31ab01l,
00078 0x5cc0ac00l, 0xcc51ad01l, 0xcde1ae01l, 0x5d70af00l,
00079 0xc301b001l, 0x5390b100l, 0x5220b200l, 0xc2b1b301l,
00080 0x5140b400l, 0xc1d1b501l, 0xc061b601l, 0x50f0b700l,
00081 0x5780b800l, 0xc711b901l, 0xc6a1ba01l, 0x5630bb00l,
00082 0xc5c1bc01l, 0x5550bd00l, 0x54e0be00l, 0xc471bf01l,
00083 0x6c00c000l, 0xfc91c101l, 0xfd21c201l, 0x6db0c300l,
00084 0xfe41c401l, 0x6ed0c500l, 0x6f60c600l, 0xfff1c701l,
00085 0xf881c801l, 0x6810c900l, 0x69a0ca00l, 0xf931cb01l,
00086 0x6ac0cc00l, 0xfa51cd01l, 0xfbe1ce01l, 0x6b70cf00l,
00087 0xf501d001l, 0x6590d100l, 0x6420d200l, 0xf4b1d301l,
00088 0x6740d400l, 0xf7d1d501l, 0xf661d601l, 0x66f0d700l,
00089 0x6180d800l, 0xf111d901l, 0xf0a1da01l, 0x6030db00l,
00090 0xf3c1dc01l, 0x6350dd00l, 0x62e0de00l, 0xf271df01l,
00091 0xee01e001l, 0x7e90e100l, 0x7f20e200l, 0xefb1e301l,
00092 0x7c40e400l, 0xecd1e501l, 0xed61e601l, 0x7df0e700l,
00093 0x7a80e800l, 0xea11e901l, 0xeba1ea01l, 0x7b30eb00l,
00094 0xe8c1ec01l, 0x7850ed00l, 0x79e0ee00l, 0xe971ef01l,
00095 0x7700f000l, 0xe791f101l, 0xe621f201l, 0x76b0f300l,
00096 0xe541f401l, 0x75d0f500l, 0x7460f600l, 0xe4f1f701l,
00097 0xe381f801l, 0x7310f900l, 0x72a0fa00l, 0xe231fb01l,
00098 0x71c0fc00l, 0xe151fd01l, 0xe0e1fe01l, 0x7070ff00l
00099 };
00100
00101 static DWORD build_edc(const void* in, unsigned from, unsigned upto)
00102 {
00103 const BYTE* p = (BYTE*)in + from;
00104 DWORD result = 0;
00105
00106 for(; from < upto; from++)
00107 result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
00108
00109 return result;
00110 }
00111
00113
00114 #ifdef REGISTER_FILTER
00115
00116 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00117 {
00118 {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL}
00119 };
00120
00121 const AMOVIESETUP_PIN sudOpPin[] =
00122 {
00123 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00124 };
00125
00126 const AMOVIESETUP_FILTER sudFilter[] =
00127 {
00128 {&__uuidof(CCDXAReader), L"CDXA Reader", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin}
00129 };
00130
00131 CFactoryTemplate g_Templates[] =
00132 {
00133 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CCDXAReader>, NULL, &sudFilter[0]}
00134 };
00135
00136 int g_cTemplates = countof(g_Templates);
00137
00138 STDAPI DllRegisterServer()
00139 {
00140 SetRegKeyValue(
00141 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"),
00142 _T("0"), _T("0,4,,52494646,8,4,,43445841"));
00143
00144 SetRegKeyValue(
00145 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"),
00146 _T("Source Filter"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"));
00147
00148 return AMovieDllRegisterServer2(TRUE);
00149 }
00150
00151 STDAPI DllUnregisterServer()
00152 {
00153 DeleteRegKey(_T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"));
00154
00155 return AMovieDllRegisterServer2(FALSE);
00156 }
00157
00158 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00159
00160 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00161 {
00162 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00163 }
00164
00165 #endif
00166
00167
00168
00169
00170
00171 CCDXAReader::CCDXAReader(IUnknown* pUnk, HRESULT* phr)
00172 : CAsyncReader(NAME("CCDXAReader"), pUnk, &m_stream, phr, __uuidof(this))
00173 {
00174 if(phr) *phr = S_OK;
00175 }
00176
00177 CCDXAReader::~CCDXAReader()
00178 {
00179 }
00180
00181 STDMETHODIMP CCDXAReader::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00182 {
00183 return
00184 QI(IFileSourceFilter)
00185 __super::NonDelegatingQueryInterface(riid, ppv);
00186 }
00187
00188 STDMETHODIMP CCDXAReader::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt)
00189 {
00190 CMediaType mt;
00191 m_mt = mt;
00192
00193 if(!m_stream.Load(pszFileName))
00194 return E_FAIL;
00195
00196 m_fn = pszFileName;
00197
00198 mt.majortype = MEDIATYPE_Stream;
00199 mt.subtype = m_stream.m_subtype;
00200 m_mt = mt;
00201
00202 return S_OK;
00203 }
00204
00205 STDMETHODIMP CCDXAReader::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt)
00206 {
00207 if(!ppszFileName) return E_POINTER;
00208
00209 if(!(*ppszFileName = (LPOLESTR)CoTaskMemAlloc((m_fn.GetLength()+1)*sizeof(WCHAR))))
00210 return E_OUTOFMEMORY;
00211
00212 wcscpy(*ppszFileName, m_fn);
00213
00214 return S_OK;
00215 }
00216
00217
00218
00219 CCDXAStream::CCDXAStream()
00220 {
00221 m_subtype = MEDIASUBTYPE_NULL;
00222
00223 m_hFile = INVALID_HANDLE_VALUE;
00224
00225 m_llPosition = m_llLength = 0;
00226 m_nFirstSector = 0;
00227 m_nBufferedSector = -1;
00228 }
00229
00230 CCDXAStream::~CCDXAStream()
00231 {
00232 if(m_hFile != INVALID_HANDLE_VALUE)
00233 {
00234 CloseHandle(m_hFile);
00235 m_hFile = INVALID_HANDLE_VALUE;
00236 }
00237 }
00238
00239 bool CCDXAStream::Load(const WCHAR* fnw)
00240 {
00241 if(m_hFile != INVALID_HANDLE_VALUE)
00242 {
00243 CloseHandle(m_hFile);
00244 m_hFile = INVALID_HANDLE_VALUE;
00245 }
00246
00247 m_hFile = CreateFile(CString(fnw), GENERIC_READ, FILE_SHARE_READ, NULL,
00248 OPEN_EXISTING, FILE_ATTRIBUTE_READONLY|FILE_FLAG_SEQUENTIAL_SCAN, (HANDLE)NULL);
00249 if(m_hFile == INVALID_HANDLE_VALUE)
00250 {
00251 return(false);
00252 }
00253
00254 BYTE hdr[RIFFCDXA_HEADER_SIZE];
00255 DWORD NumberOfBytesRead;
00256 if(!ReadFile(m_hFile, (LPVOID)hdr, RIFFCDXA_HEADER_SIZE, &NumberOfBytesRead, NULL)
00257 || *((DWORD*)&hdr[0]) != 'FFIR' || *((DWORD*)&hdr[8]) != 'AXDC'
00258 || *((DWORD*)&hdr[4]) != (*((DWORD*)&hdr[0x28])+0x24))
00259 {
00260 CloseHandle(m_hFile);
00261 m_hFile = INVALID_HANDLE_VALUE;
00262 return(false);
00263 }
00264
00265 LARGE_INTEGER size = {0, 0};
00266 size.LowPart = (LONG)GetFileSize(m_hFile, (LPDWORD)&size.HighPart);
00267
00268 m_llLength = int((size.QuadPart - RIFFCDXA_HEADER_SIZE) / RAW_SECTOR_SIZE) * RAW_DATA_SIZE;
00269
00270 if(!LookForMediaSubType())
00271 {
00272 m_llPosition = m_llLength = 0;
00273 CloseHandle(m_hFile);
00274 m_hFile = INVALID_HANDLE_VALUE;
00275 return(false);
00276 }
00277
00278 m_llPosition = 0;
00279
00280 m_nBufferedSector = -1;
00281
00282 return(true);
00283 }
00284
00285 HRESULT CCDXAStream::SetPointer(LONGLONG llPos)
00286 {
00287 return (llPos >= 0 && llPos < m_llLength) ? m_llPosition = llPos, S_OK : S_FALSE;
00288 }
00289
00290 HRESULT CCDXAStream::Read(PBYTE pbBuffer, DWORD dwBytesToRead, BOOL bAlign, LPDWORD pdwBytesRead)
00291 {
00292 CAutoLock lck(&m_csLock);
00293
00294 PBYTE pbBufferOrg = pbBuffer;
00295 LONGLONG pos = m_llPosition;
00296
00297 while(pos >= 0 && pos < m_llLength && dwBytesToRead > 0)
00298 {
00299 UINT sector = m_nFirstSector + int(pos/RAW_DATA_SIZE);
00300 __int64 offset = pos%RAW_DATA_SIZE;
00301
00302 if(m_nBufferedSector != sector)
00303 {
00304 LARGE_INTEGER FilePointer;
00305 FilePointer.QuadPart = RIFFCDXA_HEADER_SIZE + sector*RAW_SECTOR_SIZE;
00306 SetFilePointer(m_hFile, (LONG)FilePointer.LowPart, (PLONG)&FilePointer.HighPart, FILE_BEGIN);
00307
00308 memset(m_sector, 0, sizeof(m_sector));
00309
00310 DWORD NumberOfBytesRead = 0;
00311
00312 int nRetries = 3;
00313 while(nRetries--)
00314 {
00315 NumberOfBytesRead = 0;
00316 if(!ReadFile(m_hFile, m_sector, RAW_SECTOR_SIZE, &NumberOfBytesRead, NULL)
00317 || NumberOfBytesRead != RAW_SECTOR_SIZE)
00318 break;
00319
00320 if(*(DWORD*)&m_sector[RAW_SECTOR_SIZE-4] == 0)
00321 break;
00322
00323 if(build_edc(m_sector, RAW_SYNC_SIZE + RAW_HEADER_SIZE, RAW_SECTOR_SIZE) == 0)
00324 break;
00325
00326 TRACE(_T("CCDXAStream: CRC error at sector %d (fp=0x%I64x, retriesleft=%d)\n"), sector, FilePointer.QuadPart, nRetries);
00327 }
00328
00329 m_nBufferedSector = sector;
00330 }
00331
00332 DWORD l = min(min(dwBytesToRead, RAW_DATA_SIZE - offset), m_llLength - pos);
00333 memcpy(pbBuffer, &m_sector[RAW_SYNC_SIZE + RAW_HEADER_SIZE + RAW_SUBHEADER_SIZE + offset], l);
00334
00335 pbBuffer += l;
00336 pos += l;
00337 dwBytesToRead -= l;
00338 }
00339
00340 if(pdwBytesRead) *pdwBytesRead = pbBuffer - pbBufferOrg;
00341 m_llPosition += pbBuffer - pbBufferOrg;
00342
00343 if(dwBytesToRead != 0) return S_FALSE;
00344
00345 return S_OK;
00346 }
00347
00348 LONGLONG CCDXAStream::Size(LONGLONG* pSizeAvailable)
00349 {
00350 if(pSizeAvailable) *pSizeAvailable = m_llLength;
00351 return m_llLength;
00352 }
00353
00354 DWORD CCDXAStream::Alignment()
00355 {
00356 return 1;
00357 }
00358
00359 void CCDXAStream::Lock()
00360 {
00361 m_csLock.Lock();
00362 }
00363
00364 void CCDXAStream::Unlock()
00365 {
00366 m_csLock.Unlock();
00367 }
00368
00369
00370
00371 bool CCDXAStream::LookForMediaSubType()
00372 {
00373 BYTE buff[RAW_DATA_SIZE];
00374
00375 m_subtype = MEDIASUBTYPE_NULL;
00376
00377 m_llPosition = 0;
00378
00379 for(int iSectorsRead = 0;
00380 Read(buff, RAW_DATA_SIZE, 1, NULL) == S_OK && iSectorsRead < 1000;
00381 iSectorsRead++)
00382 {
00383 if(*((DWORD*)&buff[0]) == 0xba010000)
00384 {
00385 m_llPosition = 0;
00386 m_llLength -= iSectorsRead*RAW_DATA_SIZE;
00387 m_nFirstSector = iSectorsRead;
00388
00389 if((buff[4]&0xc4) == 0x44) m_subtype = MEDIASUBTYPE_MPEG2_PROGRAM;
00390 else if((buff[4]&0xf1) == 0x21) m_subtype = MEDIASUBTYPE_MPEG1System;
00391
00392 return m_subtype != MEDIASUBTYPE_NULL;
00393 }
00394 else if(*((DWORD*)&buff[0]) == 'SggO')
00395 {
00396 m_llPosition = 0;
00397 m_llLength -= iSectorsRead*RAW_DATA_SIZE;
00398 m_nFirstSector = iSectorsRead;
00399
00400 m_subtype = MEDIASUBTYPE_Ogg;
00401
00402 return(true);
00403 }
00404 else if(*((DWORD*)&buff[0]) == 0xA3DF451A)
00405 {
00406 m_llPosition = 0;
00407 m_llLength -= iSectorsRead*RAW_DATA_SIZE;
00408 m_nFirstSector = iSectorsRead;
00409
00410 m_subtype = MEDIASUBTYPE_Matroska;
00411
00412 return(true);
00413 }
00414 else if(*((DWORD*)&buff[0]) == 'FMR.')
00415 {
00416 m_llPosition = 0;
00417 m_llLength -= iSectorsRead*RAW_DATA_SIZE;
00418 m_nFirstSector = iSectorsRead;
00419
00420 m_subtype = MEDIASUBTYPE_RealMedia;
00421
00422 return(true);
00423 }
00424 else if(*((DWORD*)&buff[0]) == 'FFIR' && *((DWORD*)&buff[8]) == ' IVA')
00425 {
00426 m_llPosition = 0;
00427 m_llLength = min(m_llLength, *((DWORD*)&buff[4])+8);
00428 m_nFirstSector = iSectorsRead;
00429
00430 m_subtype = MEDIASUBTYPE_Avi;
00431
00432 return(true);
00433 }
00434 else if(*((DWORD*)&buff[4]) == 'voom' || *((DWORD*)&buff[4]) == 'tadm'
00435 || *((DWORD*)&buff[4]) == 'pytf' && *((DWORD*)&buff[8]) == 'mosi' && *((DWORD*)&buff[16]) == '14pm')
00436 {
00437 m_llPosition = 0;
00438 m_llLength -= iSectorsRead*RAW_DATA_SIZE;
00439 m_nFirstSector = iSectorsRead;
00440
00441 m_subtype = MEDIASUBTYPE_QTMovie;
00442
00443 return(true);
00444 }
00445 }
00446
00447 m_llPosition = 0;
00448
00449 CRegKey majorkey;
00450 CString majortype = _T("\\Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}");
00451 if(ERROR_SUCCESS == majorkey.Open(HKEY_CLASSES_ROOT, majortype, KEY_READ))
00452 {
00453 TCHAR subtype[256+1];
00454 DWORD len = 256;
00455 for(int i = 0; ERROR_SUCCESS == majorkey.EnumKey(i, subtype, &len); i++, len = 256)
00456 {
00457 CRegKey subkey;
00458 if(ERROR_SUCCESS != subkey.Open(HKEY_CLASSES_ROOT, majortype + _T("\\") + subtype, KEY_READ))
00459 continue;
00460
00461 for(int j = 0; true; j++)
00462 {
00463 TCHAR number[10];
00464 _stprintf(number, _T("%d"), j);
00465
00466 TCHAR pattern[256+1];
00467 ULONG len = 256;
00468 if(ERROR_SUCCESS != subkey.QueryStringValue(number, pattern, &len))
00469 break;
00470
00471 CString p = pattern;
00472 p += ',';
00473
00474 __int64 offset = 0;
00475 DWORD cb = 0;
00476 CByteArray mask, val;
00477
00478 int nMatches = 0, nTries = 0;
00479
00480 for(int k = 0, l; nTries >= 0 && (l = p.Find(',', k)) >= 0; k = l+1, nTries++)
00481 {
00482 CString s = p.Mid(k, l-k);
00483 TRACE(s + '\n');
00484
00485 TCHAR* end = NULL;
00486
00487 switch(nTries&3)
00488 {
00489 case 0: offset = _tcstol(s, &end, 10); break;
00490 case 1: cb = _tcstol(s, &end, 10); break;
00491 case 2: StringToBin(s, mask); break;
00492 case 3: StringToBin(s, val); break;
00493 default: nTries = -1; break;
00494 }
00495
00496 if(nTries >= 0 && (nTries&3) == 3)
00497 {
00498 if(cb > 0 && val.GetSize() > 0 && cb == val.GetSize())
00499 {
00500 if(offset >= 0 && S_OK == SetPointer(offset)
00501 || S_OK == SetPointer(m_llLength + offset))
00502 {
00503 CAutoVectorPtr<BYTE> pData;
00504 if(pData.Allocate(cb))
00505 {
00506 DWORD BytesRead = 0;
00507 if(S_OK == Read(pData, cb, 1, &BytesRead) && cb == BytesRead)
00508 {
00509 if(mask.GetSize() < cb)
00510 {
00511 int i = mask.GetSize();
00512 mask.SetSize(cb);
00513 for(; i < cb; i++) mask[i] = 0xff;
00514 }
00515
00516 for(int i = 0; i < cb; i++)
00517 pData[i] &= (BYTE)mask[i];
00518
00519 if(memcmp(pData, val.GetData(), cb) == 0)
00520 nMatches++;
00521 }
00522 }
00523 }
00524
00525 offset = 0; cb = 0;
00526 mask.RemoveAll(); val.RemoveAll();
00527 }
00528 }
00529 }
00530
00531 if(nMatches > 0 && nMatches*4 == nTries)
00532 {
00533 m_subtype = GUIDFromCString(subtype);
00534 return S_OK;
00535 }
00536 }
00537 }
00538 }
00539
00540 return(false);
00541 }