DWORD CTSSrcFilter::AddTS(BYTE* data, DWORD size) { DWORD addVideo = 0; for( DWORD i=0; i<size; i+=188 ){ CTSPacketUtil packet; if( packet.Set188TS(data + i, 188) == TRUE ){ if( packet.transport_scrambling_control == 0 ){ //PMT map<WORD, CPMTUtil*>::iterator itrPmt; 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 = this->pmtUtilMap.find(packet.PID); if( itrPmt == this->pmtUtilMap.end() ){ CPMTUtil* util = new CPMTUtil; this->pmtUtilMap.insert(pair<WORD, CPMTUtil*>(packet.PID, util)); if( util->AddPacket(&packet) == TRUE ){ CheckPID(); } }else{ if( itrPmt->second->AddPacket(&packet) == TRUE ){ CheckPID(); } } } } }else{ //PMTの2パケット目かチェック map<WORD, CPMTUtil*>::iterator itrPmt; itrPmt = this->pmtUtilMap.find(packet.PID); if( itrPmt != this->pmtUtilMap.end() ){ if( itrPmt->second->AddPacket(&packet) == TRUE ){ CheckPID(); } } } if( packet.PID == videoPID ){ videoBuff.Add188TS(&packet); BYTE* buff = NULL; DWORD buffSize = 0; BOOL ret = videoBuff.GetSectionBuff(&buff, &buffSize); if( ret == TRUE ){ CPESHeadInfo info; info.SetData(buff, buffSize); LONGLONG pts = 0; LONGLONG time = 0; if( info.PTS_DTS_flags == 3 ){ if(this->startTSV == 0){ this->startTSV = info.DTS; } if( this->startTS == 0 ){ this->startTS = this->startTSV; } pts = info.DTS; }else if( info.PTS_DTS_flags == 2 ){ if(this->startTSV == 0){ this->startTSV = info.PTS; } if( this->startTS == 0 ){ this->startTS = this->startTSV; } pts = info.PTS; } if( this->startTSV > pts ){ pts += 0x1FFFFFFFF; } time = ((pts-this->startTS)/90)*10000; if( info.PES_packet_data_byte_size > 0 && time >= 0){ this->m_pVideoPin->AddData(info.PES_packet_data_byte, info.PES_packet_data_byte_size, time); addVideo++; } } }else if( packet.PID == audioPID ){ audioBuff.Add188TS(&packet); BYTE* buff = NULL; DWORD buffSize = 0; BOOL ret = audioBuff.GetSectionBuff(&buff, &buffSize); if( ret == TRUE ){ CPESHeadInfo info; info.SetData(buff, buffSize); LONGLONG pts = 0; LONGLONG time = 0; if( info.PTS_DTS_flags == 3 ){ if(this->startTSA == 0){ this->startTSA = info.DTS; } if( this->startTS == 0 ){ this->startTS = this->startTSV; } pts = info.DTS; }else if( info.PTS_DTS_flags == 2 ){ if(this->startTSA == 0){ this->startTSA = info.PTS; } if( this->startTS == 0 ){ this->startTS = this->startTSV; } pts = info.PTS; } if( this->startTSA > pts ){ pts += 0x1FFFFFFFF; } time = ((pts-this->startTS)/90)*10000; if( info.PES_packet_data_byte_size > 0 && time >= 0){ this->m_pAudioPin->AddData(info.PES_packet_data_byte, info.PES_packet_data_byte_size, time); } } } } } } return addVideo; }
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; } } }