123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- #include "FileProcessor.h"
- #include "FLVHeader.h"
- #include "FLVVideoHeader.h"
- static int64_t Seek64(HANDLE hf, int64_t distance, DWORD MoveMethod)
- {
- LARGE_INTEGER li;
- li.QuadPart = distance;
- li.LowPart = SetFilePointer(hf, li.LowPart, &li.HighPart, MoveMethod);
- if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
- {
- li.QuadPart = -1;
- }
- return li.QuadPart;
- }
- int64_t FileSize64(HANDLE file)
- {
- LARGE_INTEGER position;
- position.QuadPart=0;
- position.LowPart = GetFileSize(file, (LPDWORD)&position.HighPart);
- if (position.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
- return INVALID_FILE_SIZE;
- else
- return position.QuadPart;
- }
- FileProcessor::FileProcessor()
- {
- Init();
- }
- FileProcessor::FileProcessor(const wchar_t *filename)
- {
- Init();
- processedCursor=CreateFile(filename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
- readCursor=CreateFile(filename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
- writePosition=FileSize64(readCursor);
- }
- FileProcessor::~FileProcessor()
- {
- if (processedCursor != INVALID_HANDLE_VALUE)
- CloseHandle(processedCursor);
- if (readCursor != INVALID_HANDLE_VALUE)
- CloseHandle(readCursor);
- }
- void FileProcessor::Init()
- {
- processedPosition=0;
- processedCursor=INVALID_HANDLE_VALUE;
- writePosition=0;
- readCursor=INVALID_HANDLE_VALUE;
- flen=0;
- maxTimeStamp=0;
- headerOK=false;
- }
- int FileProcessor::Process()
- {
- int64_t oldPosition = Seek64(processedCursor, 0, FILE_CURRENT);
- // read file header if we're at the beginning
- if (processedPosition == 0)
- {
- if (writePosition-processedPosition >= 9) // need at least nine bytes for the FLV file header
- {
- uint8_t data[9] = {0};
- DWORD bytesRead=0;
- ReadFile(processedCursor, data, 9, &bytesRead, NULL);
- if (header.Read(data, bytesRead))
- {
- headerOK=true;
- Nullsoft::Utility::AutoLock lock(frameGuard);
- processedPosition += bytesRead;
- return FLV_OK; // we'll make our logic just a little bit more sane by only processing one frame per pass.
- }
- else
- return FLV_ERROR;
- }
- Seek64(processedCursor, oldPosition, FILE_BEGIN); // rollback
- return FLV_NEED_MORE_DATA;
- }
- if (writePosition-processedPosition >= 15) // need at least fifteen bytes for the FLV frame header
- {
- uint8_t data[15] = {0};
- DWORD bytesRead=0;
- ReadFile(processedCursor, data, 15, &bytesRead, NULL);
- FrameData frameData;
- if (frameData.header.Read(data, bytesRead))
- {
- if (frameData.header.dataSize + processedPosition + 15 <= writePosition)
- {
- frameData.keyFrame = false;
- if (frameData.header.type == FLV::FRAME_TYPE_VIDEO)
- {
- FLVVideoHeader videoHeader;
- DWORD videoHeaderRead=0;
- ReadFile(processedCursor, data, 1, &videoHeaderRead, NULL);
- if (videoHeader.Read(data, bytesRead))
- {
- if (videoHeader.frameType == FLV::VIDEO_FRAMETYPE_KEYFRAME)
- {
- frameData.keyFrame = true;
- }
- }
- Seek64(processedCursor, -(int64_t)videoHeaderRead, FILE_CURRENT);
- // roll back file cursor from ReadFile
- }
- { // critsec enter
- Nullsoft::Utility::AutoLock lock(frameGuard);
- // record the offset where we found it
- frameData.location = processedPosition;
- maxTimeStamp=max(maxTimeStamp, frameData.header.timestamp);
- frames.push_back(frameData);
- } // critsec leave
- Seek64(processedCursor, frameData.header.dataSize, FILE_CURRENT);
- Nullsoft::Utility::AutoLock lock(frameGuard);
- processedPosition+=bytesRead+frameData.header.dataSize;
- return FLV_OK;
- }
- Seek64(processedCursor, oldPosition, FILE_BEGIN); // rollback
- return FLV_NEED_MORE_DATA;
- }
- else
- {
- return FLV_ERROR;
- }
- }
- Seek64(processedCursor, oldPosition, FILE_BEGIN); // rollback
- return FLV_NEED_MORE_DATA;
- }
- uint32_t FileProcessor::GetMaxTimestamp()
- {
- return maxTimeStamp;
- }
- bool FileProcessor::GetFrame(size_t frameIndex, FrameData &frameData)
- {
- Nullsoft::Utility::AutoLock lock(frameGuard);
- if (frameIndex < frames.size())
- {
- frameData = frames[frameIndex];
- return true;
- }
- return false;
- }
- uint64_t FileProcessor::GetProcessedPosition()
- {
- Nullsoft::Utility::AutoLock lock(frameGuard);
- return processedPosition;
- }
- size_t FileProcessor::Read(void *data, size_t bytes)
- {
- DWORD bytesRead = 0;
- ReadFile(readCursor, data, (DWORD)bytes, &bytesRead, NULL);
- return bytesRead;
- }
- uint64_t FileProcessor::Seek(uint64_t position)
- {
- return Seek64(readCursor, position, FILE_BEGIN);
- }
- bool FileProcessor::GetPosition(int time_in_ms, size_t *frameIndex, bool needVideoKeyFrame)
- {
- Nullsoft::Utility::AutoLock lock(frameGuard);
- // TODO: binary search
- for (size_t f=0;f!=frames.size();f++)
- {
- if (frames[f].header.timestamp >= (uint32_t)time_in_ms)
- {
- if (needVideoKeyFrame)
- {
- while (f != 0 && !frames[f].keyFrame)
- f--;
- }
- *frameIndex = f;
- return true;
- }
- }
- return false;
- }
- FLVHeader *FileProcessor::GetHeader()
- {
- if (headerOK)
- return &header;
- else
- return 0;
- }
|