void setFrame(int frame) { if(frame >= numSamples) frame = numSamples - 1; lastSample = AVIStreamFindSample(stream,(LONG)frame,FIND_KEY | FIND_PREV); while((int)lastSample != frame) { decodeFrame(); lastSample++; } }
void AVIDump::StoreFrame(const void* data) { if (s_bitmap.biSizeImage > s_stored_frame_size) { void* temp_stored_frame = realloc(s_stored_frame, s_bitmap.biSizeImage); if (temp_stored_frame) { s_stored_frame = temp_stored_frame; } else { free(s_stored_frame); PanicAlertT("Something has gone seriously wrong.\n" "Stopping video recording.\n" "Your video will likely be broken."); Stop(); } s_stored_frame_size = s_bitmap.biSizeImage; memset(s_stored_frame, 0, s_bitmap.biSizeImage); } if (s_stored_frame) { //PanicAlertT("Width: %i, Height: %i, Bit Count: %i", s_bitmap.biWidth, s_bitmap.biHeight, s_bitmap.biBitCount); if (data && (s_file_count || !Movie::cmp_isRunning || s_frame_count > 0)) { bool lastSide = false, readOnly = false; if (Movie::cmp_isRunning && (Movie::cmp_leftFinished || Movie::cmp_rightFinished)) lastSide = true; if (lastSide && Movie::cmp_startTimerFrame > Movie::cmp_curentBranchFrame) //Dragonbane: Combine frames readOnly = true; else readOnly = false; if (readOnly && s_getFrame_temp) { size_t totalBytes = s_bitmap.biSizeImage / 2; size_t rowSize = (s_bitmap.biWidth * (s_bitmap.biBitCount / 8)) / 2; size_t currentByte = 0; if (s_last_key_temp < 2) { BOOL result = AVIStreamIsKeyFrame(s_stream_temp, s_last_key_temp); if (!result) s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp); } u64 samplePos = AVIStreamFindSample(s_stream_temp, s_last_key_temp, FIND_ANY); u64 s_last_key_old = s_last_key_temp; s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp); void* s_uncompressed_frame = AVIStreamGetFrame(s_getFrame_temp, samplePos); std::string movie_file_name; if (!s_uncompressed_frame || s_stopTempFile) { //Close current file if (s_getFrame_temp) { AVIStreamGetFrameClose(s_getFrame_temp); s_getFrame_temp = nullptr; } if (s_stream_temp) { AVIStreamClose(s_stream_temp); s_stream_temp = nullptr; } if (s_file_temp) { AVIFileRelease(s_file_temp); s_file_temp = nullptr; movie_file_name = GetCurrDumpFile(tempFileCount, true); if (File::Exists(movie_file_name)) File::Delete(movie_file_name); } //Check if we have another temp file tempFileCount++; s_stopTempFile = false; movie_file_name = GetCurrDumpFile(tempFileCount, true); if (File::Exists(movie_file_name)) //Dragonbane: Open temp file for reading { HRESULT h2 = AVIFileOpenA(&s_file_temp, movie_file_name.c_str(), OF_READ, nullptr); HRESULT h3 = AVIFileGetStream(s_file_temp, &s_stream_temp, streamtypeVIDEO, 0); s_last_key_temp = 0; //Not the first file anymore, so start from keyframe 0 s_getFrame_temp = AVIStreamGetFrameOpen(s_stream_temp, &s_bitmap); if (!s_getFrame_temp) { PanicAlertT("Your chosen compression codec can not be decompressed again! Can't continue video comparison!"); Movie::CancelComparison(); return; } BOOL result = AVIStreamIsKeyFrame(s_stream_temp, s_last_key_temp); if (!result) s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp); samplePos = AVIStreamFindSample(s_stream_temp, s_last_key_temp, FIND_ANY); s_last_key_old = s_last_key_temp; s_last_key_temp = AVIStreamNextKeyFrame(s_stream_temp, s_last_key_temp); s_uncompressed_frame = AVIStreamGetFrame(s_getFrame_temp, samplePos); if (!s_uncompressed_frame) { //PanicAlertT("Last frame stored. Start timer now!"); Movie::cmp_startTimerFrame = Movie::cmp_curentBranchFrame; memcpy(s_stored_frame, data, s_bitmap.biSizeImage); return; } } else { //PanicAlertT("Last frame stored. Start timer now!"); Movie::cmp_startTimerFrame = Movie::cmp_curentBranchFrame; memcpy(s_stored_frame, data, s_bitmap.biSizeImage); return; } } //Stop temp file on next frame if last frame is processed if (s_last_key_old == s_last_key_temp || AVIStreamFindSample(s_stream_temp, s_last_key_temp, FIND_ANY) == samplePos) s_stopTempFile = true; void* memptr1 = s_uncompressed_frame; memptr1 = static_cast<u8*>(memptr1) + sizeof(BITMAPINFOHEADER); if (Movie::cmp_leftFinished) { memcpy(s_stored_frame, memptr1, s_bitmap.biSizeImage); for (u64 currentRow = 0; currentRow < s_bitmap.biHeight; currentRow++) { currentByte += rowSize; void* memptr = s_stored_frame; const void* memptr2 = data; memptr = static_cast<u8*>(memptr) + currentByte; memptr2 = static_cast<const u8*>(memptr2) + currentByte; memcpy(memptr, memptr2, rowSize); currentByte += rowSize; } } else if (Movie::cmp_rightFinished) { memcpy(s_stored_frame, memptr1, s_bitmap.biSizeImage); //BITMAPINFOHEADER test; //memset(&test, 0, sizeof(BITMAPINFOHEADER)); //memcpy(&test, s_uncompressed_frame, sizeof(BITMAPINFOHEADER)); for (u64 currentRow = 0; currentRow < s_bitmap.biHeight; currentRow++) { void* memptr = s_stored_frame; const void* memptr2 = data; memptr = static_cast<u8*>(memptr) + currentByte; memptr2 = static_cast<const u8*>(memptr2) + currentByte; memcpy(memptr, memptr2, rowSize); currentByte += rowSize * 2; } } else { memcpy(s_stored_frame, data, s_bitmap.biSizeImage); } } else { memcpy(s_stored_frame, data, s_bitmap.biSizeImage); } } else // pitch black frame { memset(s_stored_frame, 0, s_bitmap.biSizeImage); } } }