1
0

FileProcessor.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #include "FileProcessor.h"
  2. #include "FLVHeader.h"
  3. #include "FLVVideoHeader.h"
  4. static int64_t Seek64(HANDLE hf, int64_t distance, DWORD MoveMethod)
  5. {
  6. LARGE_INTEGER li;
  7. li.QuadPart = distance;
  8. li.LowPart = SetFilePointer(hf, li.LowPart, &li.HighPart, MoveMethod);
  9. if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
  10. {
  11. li.QuadPart = -1;
  12. }
  13. return li.QuadPart;
  14. }
  15. int64_t FileSize64(HANDLE file)
  16. {
  17. LARGE_INTEGER position;
  18. position.QuadPart=0;
  19. position.LowPart = GetFileSize(file, (LPDWORD)&position.HighPart);
  20. if (position.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
  21. return INVALID_FILE_SIZE;
  22. else
  23. return position.QuadPart;
  24. }
  25. FileProcessor::FileProcessor()
  26. {
  27. Init();
  28. }
  29. FileProcessor::FileProcessor(const wchar_t *filename)
  30. {
  31. Init();
  32. processedCursor=CreateFile(filename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  33. readCursor=CreateFile(filename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  34. writePosition=FileSize64(readCursor);
  35. }
  36. FileProcessor::~FileProcessor()
  37. {
  38. if (processedCursor != INVALID_HANDLE_VALUE)
  39. CloseHandle(processedCursor);
  40. if (readCursor != INVALID_HANDLE_VALUE)
  41. CloseHandle(readCursor);
  42. }
  43. void FileProcessor::Init()
  44. {
  45. processedPosition=0;
  46. processedCursor=INVALID_HANDLE_VALUE;
  47. writePosition=0;
  48. readCursor=INVALID_HANDLE_VALUE;
  49. flen=0;
  50. maxTimeStamp=0;
  51. headerOK=false;
  52. }
  53. int FileProcessor::Process()
  54. {
  55. int64_t oldPosition = Seek64(processedCursor, 0, FILE_CURRENT);
  56. // read file header if we're at the beginning
  57. if (processedPosition == 0)
  58. {
  59. if (writePosition-processedPosition >= 9) // need at least nine bytes for the FLV file header
  60. {
  61. uint8_t data[9] = {0};
  62. DWORD bytesRead=0;
  63. ReadFile(processedCursor, data, 9, &bytesRead, NULL);
  64. if (header.Read(data, bytesRead))
  65. {
  66. headerOK=true;
  67. Nullsoft::Utility::AutoLock lock(frameGuard);
  68. processedPosition += bytesRead;
  69. return FLV_OK; // we'll make our logic just a little bit more sane by only processing one frame per pass.
  70. }
  71. else
  72. return FLV_ERROR;
  73. }
  74. Seek64(processedCursor, oldPosition, FILE_BEGIN); // rollback
  75. return FLV_NEED_MORE_DATA;
  76. }
  77. if (writePosition-processedPosition >= 15) // need at least fifteen bytes for the FLV frame header
  78. {
  79. uint8_t data[15] = {0};
  80. DWORD bytesRead=0;
  81. ReadFile(processedCursor, data, 15, &bytesRead, NULL);
  82. FrameData frameData;
  83. if (frameData.header.Read(data, bytesRead))
  84. {
  85. if (frameData.header.dataSize + processedPosition + 15 <= writePosition)
  86. {
  87. frameData.keyFrame = false;
  88. if (frameData.header.type == FLV::FRAME_TYPE_VIDEO)
  89. {
  90. FLVVideoHeader videoHeader;
  91. DWORD videoHeaderRead=0;
  92. ReadFile(processedCursor, data, 1, &videoHeaderRead, NULL);
  93. if (videoHeader.Read(data, bytesRead))
  94. {
  95. if (videoHeader.frameType == FLV::VIDEO_FRAMETYPE_KEYFRAME)
  96. {
  97. frameData.keyFrame = true;
  98. }
  99. }
  100. Seek64(processedCursor, -(int64_t)videoHeaderRead, FILE_CURRENT);
  101. // roll back file cursor from ReadFile
  102. }
  103. { // critsec enter
  104. Nullsoft::Utility::AutoLock lock(frameGuard);
  105. // record the offset where we found it
  106. frameData.location = processedPosition;
  107. maxTimeStamp=max(maxTimeStamp, frameData.header.timestamp);
  108. frames.push_back(frameData);
  109. } // critsec leave
  110. Seek64(processedCursor, frameData.header.dataSize, FILE_CURRENT);
  111. Nullsoft::Utility::AutoLock lock(frameGuard);
  112. processedPosition+=bytesRead+frameData.header.dataSize;
  113. return FLV_OK;
  114. }
  115. Seek64(processedCursor, oldPosition, FILE_BEGIN); // rollback
  116. return FLV_NEED_MORE_DATA;
  117. }
  118. else
  119. {
  120. return FLV_ERROR;
  121. }
  122. }
  123. Seek64(processedCursor, oldPosition, FILE_BEGIN); // rollback
  124. return FLV_NEED_MORE_DATA;
  125. }
  126. uint32_t FileProcessor::GetMaxTimestamp()
  127. {
  128. return maxTimeStamp;
  129. }
  130. bool FileProcessor::GetFrame(size_t frameIndex, FrameData &frameData)
  131. {
  132. Nullsoft::Utility::AutoLock lock(frameGuard);
  133. if (frameIndex < frames.size())
  134. {
  135. frameData = frames[frameIndex];
  136. return true;
  137. }
  138. return false;
  139. }
  140. uint64_t FileProcessor::GetProcessedPosition()
  141. {
  142. Nullsoft::Utility::AutoLock lock(frameGuard);
  143. return processedPosition;
  144. }
  145. size_t FileProcessor::Read(void *data, size_t bytes)
  146. {
  147. DWORD bytesRead = 0;
  148. ReadFile(readCursor, data, (DWORD)bytes, &bytesRead, NULL);
  149. return bytesRead;
  150. }
  151. uint64_t FileProcessor::Seek(uint64_t position)
  152. {
  153. return Seek64(readCursor, position, FILE_BEGIN);
  154. }
  155. bool FileProcessor::GetPosition(int time_in_ms, size_t *frameIndex, bool needVideoKeyFrame)
  156. {
  157. Nullsoft::Utility::AutoLock lock(frameGuard);
  158. // TODO: binary search
  159. for (size_t f=0;f!=frames.size();f++)
  160. {
  161. if (frames[f].header.timestamp >= (uint32_t)time_in_ms)
  162. {
  163. if (needVideoKeyFrame)
  164. {
  165. while (f != 0 && !frames[f].keyFrame)
  166. f--;
  167. }
  168. *frameIndex = f;
  169. return true;
  170. }
  171. }
  172. return false;
  173. }
  174. FLVHeader *FileProcessor::GetHeader()
  175. {
  176. if (headerOK)
  177. return &header;
  178. else
  179. return 0;
  180. }