UINT WINAPI CTimeShiftUtil::ReadThread(LPVOID param) { CoInitialize(NULL); CTimeShiftUtil* sys = (CTimeShiftUtil*)param; BYTE buff[188*256]; CPacketInit packetInit; { CBlockLock lock(&sys->ioLock); sys->readFile = CreateFile(sys->filePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if( sys->readFile == INVALID_HANDLE_VALUE ){ return FALSE; } sys->seekFile = CreateFile(sys->filePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if( sys->seekFile == INVALID_HANDLE_VALUE ){ CloseHandle(sys->readFile); sys->readFile = INVALID_HANDLE_VALUE; return FALSE; } } __int64 initTime = -1; __int64 base = -1; DWORD initTick = 0; vector<WORD> pcrPidList; DWORD errCount = 0; for(;;){ { __int64 wait = 0; if( base >= 0 ){ //レート調整 wait = ((base + 0x200000000LL - initTime) & 0x1FFFFFFFFLL) / 90 - (GetTickCount() - initTick); base = -1; }else if( errCount > 0 ){ //終端監視中 wait = 200; } for( ; wait > 0 && sys->readStopFlag == FALSE; wait -= 20 ){ Sleep(20); } if( sys->readStopFlag ){ break; } } CBlockLock lock(&sys->ioLock); LARGE_INTEGER liMove = {}; if( SetFilePointerEx(sys->readFile, liMove, &liMove, FILE_CURRENT) == FALSE ){ break; } if( liMove.QuadPart != sys->currentFilePos ){ //シークされた if( sys->currentFilePos >= sys->GetAvailableFileSize() ){ //有効なデータの終端に達した if( sys->fileMode || ++errCount > 50 ){ break; } continue; } liMove.QuadPart = sys->currentFilePos; if( SetFilePointerEx(sys->readFile, liMove, NULL, FILE_BEGIN) == FALSE ){ break; } packetInit.ClearBuff(); initTime = -1; } DWORD readSize; if( ReadFile(sys->readFile, buff, sizeof(buff), &readSize, NULL) == FALSE || readSize < (sys->fileMode ? 1 : sizeof(buff)) ){ //ファイル終端に達した if( sys->fileMode || ++errCount > 50 ){ break; } liMove.QuadPart = sys->currentFilePos; if( SetFilePointerEx(sys->readFile, liMove, NULL, FILE_BEGIN) == FALSE ){ break; } continue; } BYTE* data; DWORD dataSize; if( packetInit.GetTSData(buff, readSize, &data, &dataSize) == FALSE || dataSize <= 0 ){ if( sys->fileMode == FALSE && sys->currentFilePos + (__int64)sizeof(buff) > sys->GetAvailableFileSize() ){ //無効なデータ領域を読んでいる可能性がある if( ++errCount > 50 ){ break; } liMove.QuadPart = sys->currentFilePos; if( SetFilePointerEx(sys->readFile, liMove, NULL, FILE_BEGIN) == FALSE ){ break; } }else{ //不正なデータを読み飛ばす sys->currentFilePos += readSize; errCount = 0; } continue; } sys->currentFilePos += readSize; errCount = 0; for( DWORD i = 0; i < dataSize; i += 188 ){ CTSPacketUtil packet; if( packet.Set188TS(data + i, 188) ){ if( packet.adaptation_field_length > 0 && packet.PCR_flag == 1 ){ //最初に3回PCRが出現したPIDをPCR_PIDとする //PCR_PIDが現れることなく5回別のPCRが出現すればPCR_PIDを変更する if( packet.PID != sys->PCR_PID ){ pcrPidList.push_back(packet.PID); if( std::count(pcrPidList.begin(), pcrPidList.end(), packet.PID) >= (sys->PCR_PID == 0xFFFF ? 3 : 5) ){ sys->PCR_PID = packet.PID; initTime = -1; } } if( packet.PID == sys->PCR_PID ){ pcrPidList.clear(); base = packet.program_clock_reference_base; if( initTime < 0 ){ initTime = base; initTick = GetTickCount(); } } } } } if( sys->sendUdpIP.empty() == false ){ sys->sendUdp.SendData(data, dataSize); } if( sys->sendTcpIP.empty() == false ){ sys->sendTcp.SendData(data, dataSize); } } CBlockLock lock(&sys->ioLock); CloseHandle(sys->seekFile); sys->seekFile = INVALID_HANDLE_VALUE; CloseHandle(sys->readFile); sys->readFile = INVALID_HANDLE_VALUE; if( sys->readStopFlag == FALSE ){ return 0; } //無効PAT送って次回送信時にリセットされるようにする BYTE endBuff[188*512]; memset(endBuff, 0xFF, 188*512); map<WORD, CCreatePATPacket::PROGRAM_PID_INFO> PIDMap; CCreatePATPacket patUtil; patUtil.SetParam(1, &PIDMap); BYTE* patBuff; DWORD patSize=0; patUtil.GetPacket(&patBuff, &patSize); memcpy(endBuff, patBuff, patSize); for( int i=patSize; i<188*512; i+=188){ endBuff[i] = 0x47; endBuff[i+1] = 0x1F; endBuff[i+2] = 0xFF; endBuff[i+3] = 0x10; } if( sys->sendUdpIP.empty() == false ){ sys->sendUdp.SendData(endBuff, 188*512); } if( sys->sendTcpIP.empty() == false ){ sys->sendTcp.SendData(endBuff, 188*512); } CoUninitialize(); return 0; }
UINT WINAPI CTimeShiftUtil::ReadThread(LPVOID param) { CoInitialize(NULL); CTimeShiftUtil* sys = (CTimeShiftUtil*)param; BYTE buff[188*256]; CPacketInit packetInit; HANDLE file = CreateFile( sys->filePath.c_str(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( file == INVALID_HANDLE_VALUE ){ return FALSE; } DWORD lenH = 0; DWORD lenL = GetFileSize(file, &lenH); __int64 totlaFileSize = ((__int64)lenH)<<32 | lenL; if( totlaFileSize < sys->currentFilePos ){ sys->currentFilePos = totlaFileSize; } sys->totalFileSize = totlaFileSize; LONG setH = (LONG)(sys->currentFilePos>>32); LONG setL = (LONG)(sys->currentFilePos & 0x00000000FFFFFFFF); SetFilePointer(file, setL, &setH, FILE_BEGIN); __int64 initTime = -1; __int64 initTick = 0; DWORD errCount = 0; __int64 pcr_offset = 0; __int64 tick_offset = 0; for(;;){ if( ::WaitForSingleObject(sys->readStopEvent, 0) != WAIT_TIMEOUT ){ //キャンセルされた break; } __int64 totalReadSize = sys->currentFilePos; DWORD readSize = 0; DWORD buffSize = 188*256; if( sys->availableFileSize != -1 && sys->fileMode == FALSE ){ if( totalReadSize + buffSize > sys->availableFileSize ){ buffSize = (DWORD)(sys->availableFileSize-totalReadSize); } } if( totalReadSize + buffSize > sys->totalFileSize && sys->fileMode == FALSE){ //ファイルサイズ変わっていってるはずなので開き直す CloseHandle(file); file = CreateFile( sys->filePath.c_str(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( file == INVALID_HANDLE_VALUE ){ return FALSE; } setH = (LONG)(sys->currentFilePos>>32); setL = (LONG)(sys->currentFilePos & 0x00000000FFFFFFFF); SetFilePointer(file, setL, &setH, FILE_BEGIN); lenH = 0; lenL = GetFileSize(file, &lenH); __int64 newSize = ((__int64)lenH)<<32 | lenL; sys->totalFileSize = newSize; Sleep(50); errCount++; if( errCount > (1000/50)*10){ //10秒間ファイルサイズの更新ないから終端のはず CloseHandle(file); return FALSE; } continue; } BOOL ret = ReadFile( file, buff, buffSize, &readSize, NULL ); if( ret == FALSE || readSize < buffSize){ if( sys->fileMode == TRUE ){ //ファイルモードだからエラーは終端のはず CloseHandle(file); return FALSE; }else{ Sleep(50); errCount++; if( errCount > (1000/50)*10){ //10秒間ファイルサイズの更新ないから終端のはず CloseHandle(file); return FALSE; } } }else{ errCount = 0; } if( readSize == 0 ){ Sleep(50); continue; } BYTE* data = NULL; DWORD dataSize = 0; __int64 base = -1; if( packetInit.GetTSData(buff, readSize, &data, &dataSize) == TRUE ){ if( sys->LockBuff() == TRUE ){ for( DWORD i=0; i<dataSize; i+=188 ){ CTSPacketUtil packet; if( packet.Set188TS(data + i, 188) == TRUE ){ if( packet.transport_scrambling_control == 0 ){ //PMT if( packet.payload_unit_start_indicator == 1 && packet.data_byteSize > 0){ BYTE pointer = packet.data_byte[0]; if( pointer+1 < packet.data_byteSize ){ if( packet.data_byte[1+pointer] == 0x02 ){ //PMT map<WORD, CPMTUtil*>::iterator itrPmt; itrPmt = sys->pmtUtilMap.find(packet.PID); if( itrPmt == sys->pmtUtilMap.end() ){ CPMTUtil* util = new CPMTUtil; sys->pmtUtilMap.insert(pair<WORD, CPMTUtil*>(packet.PID, util)); if( util->AddPacket(&packet) == TRUE ){ if( sys->PCR_PID != util->PCR_PID ){ //チャンネル変わった? initTime = -1; initTick = 0; } sys->PCR_PID = util->PCR_PID; } }else{ if( itrPmt->second->AddPacket(&packet) == TRUE ){ if( sys->PCR_PID != itrPmt->second->PCR_PID ){ //チャンネル変わった? initTime = -1; initTick = 0; } sys->PCR_PID = itrPmt->second->PCR_PID; } } } } }else{ //PMTの2パケット目かチェック map<WORD, CPMTUtil*>::iterator itrPmt; itrPmt = sys->pmtUtilMap.find(packet.PID); if( itrPmt != sys->pmtUtilMap.end() ){ if( itrPmt->second->AddPacket(&packet) == TRUE ){ if( sys->PCR_PID != itrPmt->second->PCR_PID ){ //チャンネル変わった? initTime = -1; initTick = 0; } sys->PCR_PID = itrPmt->second->PCR_PID; } } } if( packet.adaptation_field_length > 0 && packet.PCR_flag == 1 ){ if( sys->PCR_PID == 0xFFFF ){ //最初に捕まえたPCRを暫定的に使う initTime = -1; sys->PCR_PID = packet.PID; } if( sys->PCR_PID == packet.PID ){ base = (__int64)packet.program_clock_reference_base/90; if( initTime == -1 ){ initTime = base; initTick = GetTickCount(); } } } } } } sys->UnLockBuff(); if( sys->sendUdp != NULL ){ sys->sendUdp->SendData(data, dataSize); } if( sys->sendTcp != NULL ){ sys->sendTcp->SendData(data, dataSize); } } sys->currentFilePos += readSize; } for(;;){ if( initTime != -1 && base != -1){ if( base+pcr_offset<initTime ){ //PCR巻き戻った? pcr_offset = 0x1FFFFFFFF; } __int64 tick = GetTickCount(); if( tick+tick_offset<initTick ){ tick_offset = 0xFFFFFFFF; } if( (base+pcr_offset)-initTime >tick+tick_offset-initTick+100){ if( ::WaitForSingleObject(sys->readStopEvent, 20) != WAIT_TIMEOUT ){ //キャンセルされた goto Err_End; } }else{ break; } }else{ break; } } }