int64_t MultiFileReader::SetCurrentFilePointer(int64_t timeShiftBufferFilePos, long timeshiftBufferFileID) { RefreshTSBufferFile(); if (m_TSFileId != timeshiftBufferFileID) { // We have to switch to a different buffer file TSDEBUG(LOG_DEBUG, "Change buffer file from %i to %i", m_TSFileId, timeshiftBufferFileID); MultiFileReaderFile *file = NULL; std::vector<MultiFileReaderFile *>::iterator it = m_tsFiles.begin(); for (; it < m_tsFiles.end(); ++it) { file = *it; if (file->filePositionId == timeshiftBufferFileID) break; }; if (!file) { XBMC->Log(LOG_ERROR, "MultiFileReader::no buffer file with id=%i", timeshiftBufferFileID); XBMC->QueueNotification(QUEUE_ERROR, "No buffer file"); return m_currentPosition; } if (m_currentPosition < (file->startPosition + timeShiftBufferFilePos)) { m_TSFile.CloseFile(); m_TSFile.SetFileName(file->filename.c_str()); m_TSFile.OpenFile(); m_TSFileId = file->filePositionId; m_currentFileStartOffset = file->startPosition; TSDEBUG(LOG_DEBUG, "MultiFileReader::Read() Current File Changed to %s TS file id=%i\n", file->filename.c_str(), m_TSFileId); } } // Reposition the read pointer within the current timeshift buffer file TSDEBUG(LOG_DEBUG, "Move read pointer within buffer file %i; %I64d -> %i64d", m_TSFileId, m_currentPosition, m_currentFileStartOffset + timeShiftBufferFilePos); m_currentPosition = m_currentFileStartOffset + timeShiftBufferFilePos; if (m_currentPosition > m_endPosition) { XBMC->Log(LOG_ERROR, "Seeking beyond the end position: %I64d > %I64d", m_currentPosition, m_endPosition); m_currentPosition = m_endPosition; } return m_currentPosition; }
// // OpenFile // long MultiFileReader::OpenFile() { long hr = m_TSBufferFile.OpenFile(); //For radio the buffer sometimes needs some time to become available, so wait try it more than once unsigned long tc=GetTickCount(); while (RefreshTSBufferFile()==S_FALSE) { if (GetTickCount()-tc>MAX_BUFFER_TIMEOUT) { XBMC->Log(LOG_DEBUG, "MultiFileReader: timedout while waiting for buffer file to become available"); return S_FALSE; } } m_currentPosition = 0; m_llBufferPointer = 0; return hr; }
// // OpenFile // HRESULT MultiFileReader::OpenFile() { HRESULT hr = m_TSBufferFile.OpenFile(); //For radio the buffer sometimes needs some time to become available, so wait try it more than once DWORD tc=GetTickCount(); while (RefreshTSBufferFile()==S_FALSE) { if (GetTickCount()-tc>MAX_BUFFER_TIMEOUT) { LogDebug("MultiFileReader: timedout while waiting for buffer file to become available"); return S_FALSE; } } m_currentPosition = 0; m_llBufferPointer = 0; return hr; }
// // OpenFile // HRESULT MultiFileReader::OpenFile() { CAutoLock rLock (m_pAccessLock); SetStopping(false); HRESULT hr = m_TSBufferFile.OpenFile(); //For radio the buffer sometimes needs some time to become available, so wait try it more than once DWORD tc=GetTickCount(); while (RefreshTSBufferFile()==S_FALSE) { if (GetTickCount()-tc > MAX_BUFFER_TIMEOUT) { LogDebug("MultiFileReader: timed out while waiting for buffer file to become available"); return S_FALSE; } Sleep(50); } m_currentPosition = 0; //LogDebug("MultiFileReader::OpenFile()"); return hr; }
HRESULT MultiFileReader::Read(PBYTE pbData, ULONG lDataLength, ULONG *dwReadBytes) { HRESULT hr; // If the file has already been closed, don't continue if (m_TSBufferFile.IsFileInvalid()) return S_FALSE; RefreshTSBufferFile(); RefreshFileSize(); if (m_currentPosition < m_startPosition) m_currentPosition = m_startPosition; // Find out which file the currentPosition is in. MultiFileReaderFile *file = NULL; std::vector<MultiFileReaderFile *>::iterator it = m_tsFiles.begin(); for ( ; it < m_tsFiles.end() ; it++ ) { file = *it; if (m_currentPosition < (file->startPosition + file->length)) break; }; if(!file) { LogDebug("MultiFileReader::no file"); return S_FALSE; } if (m_currentPosition < (file->startPosition + file->length)) { if (m_TSFileId != file->filePositionId) { m_TSFile.CloseFile(); m_TSFile.SetFileName(file->filename); m_TSFile.OpenFile(); m_TSFileId = file->filePositionId; if (m_bDebugOutput) { USES_CONVERSION; TCHAR sz[MAX_PATH+128]; wsprintf(sz, TEXT("Current File Changed to %s\n"), W2T(file->filename)); //::OutputDebugString(sz); } } __int64 seekPosition = m_currentPosition - file->startPosition; m_TSFile.SetFilePointer(seekPosition, FILE_BEGIN); __int64 posSeeked=m_TSFile.GetFilePointer(); if (posSeeked!=seekPosition) { LogDebug("SEEK FAILED"); } ULONG bytesRead = 0; __int64 bytesToRead = file->length - seekPosition; if (lDataLength > bytesToRead) { hr = m_TSFile.Read(pbData, (ULONG)bytesToRead, &bytesRead); if (FAILED(hr)) { LogDebug("READ FAILED1"); } m_currentPosition += bytesToRead; hr = this->Read(pbData + bytesToRead, lDataLength - (ULONG)bytesToRead, dwReadBytes); if (FAILED(hr)) { LogDebug("READ FAILED2"); } *dwReadBytes += bytesRead; } else { hr = m_TSFile.Read(pbData, lDataLength, dwReadBytes); if (FAILED(hr)) { LogDebug("READ FAILED2"); } m_currentPosition += lDataLength; } } else { // The current position is past the end of the last file *dwReadBytes = 0; } return S_OK; }
__int64 MultiFileReader::GetFileSize() { CAutoLock rLock (m_pAccessLock); RefreshTSBufferFile(); return m_endPosition - m_startPosition; }
HRESULT MultiFileReader::ReadNoLock(PBYTE pbData, ULONG lDataLength, ULONG *dwReadBytes, bool refreshFile) { HRESULT hr = S_OK; // If the file has already been closed, don't continue if (m_TSBufferFile.IsFileInvalid()) { LogDebug("MultiFileReader::Read() - IsFileInvalid() failure"); *dwReadBytes = 0; return E_FAIL; } hr = RefreshTSBufferFile(); if (hr != S_OK) { //LogDebug("MultiFileReader::Read() - RefreshTSBufferFile() failure, HRESULT = 0x%x", hr); *dwReadBytes = 0; return E_FAIL; } if (m_currentPosition < m_startPosition) m_currentPosition = m_startPosition; __int64 oldCurrentPosn = m_currentPosition; // Find out which file the currentPosition is in (and the next file, if it exists) MultiFileReaderFile *file = NULL; MultiFileReaderFile *fileNext = NULL; bool fileFound = false; std::vector<MultiFileReaderFile *>::iterator it = m_tsFiles.begin(); for ( ; it < m_tsFiles.end() ; it++ ) { if (fileFound) { fileNext = *it; //This is the next file after the file we need to read break; } file = *it; if (m_currentPosition < (file->startPosition + file->length)) { fileFound = true; } }; if(!file) { LogDebug("MultiFileReader::no file"); *dwReadBytes = 0; return E_FAIL; } if(!fileFound) { // The current position is past the end of the last file *dwReadBytes = 0; return S_FALSE; } if (m_TSFileId != file->filePositionId) { if (!m_TSFile.IsFileInvalid()) { m_TSFile.CloseFile(); } m_TSFile.SetFileName(file->filename); m_TSFile.OpenFile(); m_TSFileId = file->filePositionId; if (m_TSFile.IsFileInvalid()) { LogDebug("MultiFileReader::new data file, OpenFile() failed"); *dwReadBytes = 0; m_TSFileId = -1; return E_FAIL; } } if (refreshFile) { // try to clear local / remote SMB file cache. This should happen when we close the filehandle if (!m_TSFile.IsFileInvalid()) { m_TSFile.CloseFile(); } Sleep(5); m_TSFile.OpenFile(); if (m_TSFile.IsFileInvalid()) { LogDebug("MultiFileReader::data file refresh, OpenFile() failed"); *dwReadBytes = 0; m_TSFileId = -1; return E_FAIL; } Sleep(5); } //Start of 'file next' SMB data cache workaround processing if(!fileNext && !m_TSFileNext.IsFileInvalid()) { m_TSFileNext.CloseFile(); m_TSFileIdNext = -1; } if (fileNext && m_bUseFileNext && m_pFileReadNextBuffer) { if (m_TSFileIdNext != fileNext->filePositionId) { if (!m_TSFileNext.IsFileInvalid()) { m_TSFileNext.CloseFile(); } m_TSFileNext.SetFileName(fileNext->filename); m_TSFileNext.OpenFile(); m_TSFileIdNext = fileNext->filePositionId; m_currPosnFileNext = 0; //char url[MAX_PATH]; //WideCharToMultiByte(CP_ACP, 0 ,fileNext->filename, -1, url, MAX_PATH, 0, 0); //LogDebug("MultiFileReader::FileNext Changed to %s", url); if (fileNext->length >= NEXT_READ_SIZE) { //Do a dummy read to try and refresh the SMB cache ULONG bytesNextRead = 0; m_TSFileNext.SetFilePointer(m_currPosnFileNext, FILE_BEGIN); m_TSFileNext.Read(m_pFileReadNextBuffer, NEXT_READ_SIZE, &bytesNextRead); m_lastFileNextRead = timeGetTime(); if (bytesNextRead != NEXT_READ_SIZE) { char url[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0 ,fileNext->filename, -1, url, MAX_PATH, 0, 0); LogDebug("MultiFileReader::FileNext read 1 failed, bytes %d, posn %I64d, file %s", bytesNextRead, m_currPosnFileNext, url); } m_currPosnFileNext += NEXT_READ_SIZE; m_currPosnFileNext %= NEXT_READ_ROLLOVER; } } else if ((fileNext->length >= (m_currPosnFileNext+NEXT_READ_SIZE)) && (timeGetTime() > (m_lastFileNextRead+1100))) { //Do a dummy read to try and refresh the SMB data cache ULONG bytesNextRead = 0; m_TSFileNext.SetFilePointer(m_currPosnFileNext, FILE_BEGIN); m_TSFileNext.Read(m_pFileReadNextBuffer, NEXT_READ_SIZE, &bytesNextRead); m_lastFileNextRead = timeGetTime(); if (bytesNextRead != NEXT_READ_SIZE) { char url[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0 ,fileNext->filename, -1, url, MAX_PATH, 0, 0); LogDebug("MultiFileReader::FileNext read 2 failed, bytes %d, posn %I64d, file %s", bytesNextRead, m_currPosnFileNext, url); } m_currPosnFileNext += NEXT_READ_SIZE; m_currPosnFileNext %= NEXT_READ_ROLLOVER; } } //End of 'file next' SMB data cache workaround processing __int64 seekPosition = m_currentPosition - file->startPosition; m_TSFile.SetFilePointer(seekPosition, FILE_BEGIN); __int64 posSeeked=m_TSFile.GetFilePointer(); if (posSeeked!=seekPosition) { LogDebug("MultiFileReader::SEEK FAILED"); *dwReadBytes = 0; m_currentPosition = oldCurrentPosn; return E_FAIL; } ULONG bytesRead = 0; __int64 bytesToRead = file->length - seekPosition; if (lDataLength > bytesToRead) { //LogDebug("MultiFileReader::multi-read 0, pbData=%d, lDataLength=%d, bytesToRead=%I64d, bytesRead=%d, m_currentPosition=%I64d, fileLength=%I64d", pbData, lDataLength, bytesToRead, bytesRead, m_currentPosition, file->length); hr = m_TSFile.Read(pbData, (ULONG)bytesToRead, &bytesRead); if (!SUCCEEDED(hr)) { if (!m_bIsStopping) { LogDebug("MultiFileReader::READ FAILED1"); } *dwReadBytes = 0; m_currentPosition = oldCurrentPosn; return E_FAIL; } m_currentPosition += (__int64)bytesRead; //LogDebug("MultiFileReader::multi-read 1, pbData=%d, lDataLength=%d, bytesToRead=%I64d, bytesRead=%d, m_currentPosition=%I64d, fileLength=%I64d", pbData, lDataLength, bytesToRead, bytesRead, m_currentPosition, file->length); if ((bytesRead < bytesToRead) || !fileNext) { //We haven't got all of the current file segment (so we can't read the next segment), //or there is no 'next file' to read so just return the data we have... //LogDebug("MultiFileReader::multi-read 1A, pbData=%d, lDataLength=%d, bytesToRead=%I64d, bytesRead=%d, m_currentPosition=%I64d", pbData, lDataLength, bytesToRead, bytesRead, m_currentPosition); *dwReadBytes = bytesRead; return S_FALSE; } hr = this->ReadNoLock(pbData + (ULONG)bytesToRead, lDataLength - (ULONG)bytesToRead, dwReadBytes, refreshFile); if (!SUCCEEDED(hr)) { if (!m_bIsStopping) { LogDebug("MultiFileReader::READ FAILED2"); } *dwReadBytes = 0; m_currentPosition = oldCurrentPosn; return E_FAIL; } //LogDebug("MultiFileReader::multi-read 2, pbData=%d, lDataLength=%d, bytesRead=%d, m_currentPosition=%I64d", (pbData + (ULONG)bytesToRead), (lDataLength - (ULONG)bytesToRead), *dwReadBytes, m_currentPosition); *dwReadBytes += bytesRead; } else { hr = m_TSFile.Read(pbData, lDataLength, dwReadBytes); if (!SUCCEEDED(hr)) { if (!m_bIsStopping) { LogDebug("MultiFileReader::READ FAILED3"); } *dwReadBytes = 0; m_currentPosition = oldCurrentPosn; return E_FAIL; } m_currentPosition += (__int64)*dwReadBytes; //LogDebug("MultiFileReader::multi-read 3, pbData=%d, lDataLength=%d, dwReadBytes=%d, m_currentPosition=%I64d, fileLength=%I64d", pbData, lDataLength, *dwReadBytes, m_currentPosition, file->length); } return hr; }
int64_t MultiFileReader::GetFileSize() { RefreshTSBufferFile(); return m_endPosition - m_startPosition; }
long MultiFileReader::Read(unsigned char* pbData, unsigned long lDataLength, unsigned long *dwReadBytes) { long hr; // If the file has already been closed, don't continue if (m_TSBufferFile.IsFileInvalid()) return S_FALSE; RefreshTSBufferFile(); if (m_currentReadPosition < m_startPosition) { XBMC->Log(LOG_DEBUG, "%s: current position adjusted from %%I64dd to %%I64dd.", __FUNCTION__, m_currentReadPosition, m_startPosition); m_currentReadPosition = m_startPosition; } // Find out which file the currentPosition is in. MultiFileReaderFile *file = NULL; std::vector<MultiFileReaderFile *>::iterator it = m_tsFiles.begin(); for (; it < m_tsFiles.end(); it++) { file = *it; if (m_currentReadPosition < (file->startPosition + file->length)) break; }; // XBMC->Log(LOG_DEBUG, "%s: reading %ld bytes. File %s, start %d, current %d, end %d.", __FUNCTION__, lDataLength, file->filename.c_str(), m_startPosition, m_currentPosition, m_endPosition); if (!file) { XBMC->Log(LOG_ERROR, "MultiFileReader::no file"); XBMC->QueueNotification(QUEUE_ERROR, "No buffer file"); return S_FALSE; } if (m_currentReadPosition < (file->startPosition + file->length)) { if (m_TSFileId != file->filePositionId) { m_TSFile.CloseFile(); m_TSFile.SetFileName(file->filename.c_str()); m_TSFile.OpenFile(); m_TSFileId = file->filePositionId; if (m_bDebugOutput) { XBMC->Log(LOG_DEBUG, "MultiFileReader::Read() Current File Changed to %s\n", file->filename.c_str()); } } int64_t seekPosition = m_currentReadPosition - file->startPosition; int64_t posSeeked = m_TSFile.GetFilePointer(); if (posSeeked != seekPosition) { m_TSFile.SetFilePointer(seekPosition, FILE_BEGIN); posSeeked = m_TSFile.GetFilePointer(); if (posSeeked != seekPosition) { XBMC->Log(LOG_ERROR, "SEEK FAILED"); } } unsigned long bytesRead = 0; int64_t bytesToRead = file->length - seekPosition; if ((int64_t)lDataLength > bytesToRead) { // XBMC->Log(LOG_DEBUG, "%s: datalength %lu bytesToRead %lli.", __FUNCTION__, lDataLength, bytesToRead); hr = m_TSFile.Read(pbData, (unsigned long)bytesToRead, &bytesRead); if (FAILED(hr)) { XBMC->Log(LOG_ERROR, "READ FAILED1"); } m_currentReadPosition += bytesToRead; hr = this->Read(pbData + bytesToRead, lDataLength - (unsigned long)bytesToRead, dwReadBytes); if (FAILED(hr)) { XBMC->Log(LOG_ERROR, "READ FAILED2"); } *dwReadBytes += bytesRead; } else { hr = m_TSFile.Read(pbData, lDataLength, dwReadBytes); if (FAILED(hr)) { XBMC->Log(LOG_ERROR, "READ FAILED3"); } m_currentReadPosition += lDataLength; } } else { // The current position is past the end of the last file *dwReadBytes = 0; } // XBMC->Log(LOG_DEBUG, "%s: read %lu bytes. start %lli, current %lli, end %lli.", __FUNCTION__, *dwReadBytes, m_startPosition, m_currentPosition, m_endPosition); return S_OK; }
long MultiFileReader::Read(unsigned char* pbData, unsigned long lDataLength, unsigned long *dwReadBytes) { long hr; // If the file has already been closed, don't continue if (m_TSBufferFile.IsFileInvalid()) return S_FALSE; RefreshTSBufferFile(); RefreshFileSize(); if (m_currentPosition < m_startPosition) m_currentPosition = m_startPosition; // Find out which file the currentPosition is in. MultiFileReaderFile *file = NULL; std::vector<MultiFileReaderFile *>::iterator it = m_tsFiles.begin(); for ( ; it < m_tsFiles.end() ; it++ ) { file = *it; if (m_currentPosition < (file->startPosition + file->length)) break; }; if(!file) { XBMC->Log(LOG_DEBUG, "MultiFileReader::no file"); return S_FALSE; } if (m_currentPosition < (file->startPosition + file->length)) { if (m_TSFileId != file->filePositionId) { m_TSFile.CloseFile(); m_TSFile.SetFileName(file->filename.c_str()); m_TSFile.OpenFile(); m_TSFileId = file->filePositionId; if (m_bDebugOutput) { XBMC->Log(LOG_DEBUG, "MultiFileReader::Read() Current File Changed to %s\n", file->filename.c_str()); } } int64_t seekPosition = m_currentPosition - file->startPosition; m_TSFile.SetFilePointer(seekPosition, FILE_BEGIN); int64_t posSeeked=m_TSFile.GetFilePointer(); if (posSeeked!=seekPosition) { XBMC->Log(LOG_DEBUG, "SEEK FAILED"); } unsigned long bytesRead = 0; int64_t bytesToRead = file->length - seekPosition; if (lDataLength > bytesToRead) { hr = m_TSFile.Read(pbData, (unsigned long)bytesToRead, &bytesRead); if (FAILED(hr)) { XBMC->Log(LOG_DEBUG, "READ FAILED1"); } m_currentPosition += bytesToRead; hr = this->Read(pbData + bytesToRead, lDataLength - (unsigned long)bytesToRead, dwReadBytes); if (FAILED(hr)) { XBMC->Log(LOG_DEBUG, "READ FAILED2"); } *dwReadBytes += bytesRead; } else { hr = m_TSFile.Read(pbData, lDataLength, dwReadBytes); if (FAILED(hr)) { XBMC->Log(LOG_DEBUG, "READ FAILED2"); } m_currentPosition += lDataLength; } } else { // The current position is past the end of the last file *dwReadBytes = 0; } return S_OK; }