1 /* 2 * Copyright (C) 2016-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #include "DeltaPairMemoryStream.h" 10 11 #include "utils/log.h" 12 13 using namespace KODI; 14 using namespace RETRO; 15 Reset()16void CDeltaPairMemoryStream::Reset() 17 { 18 CLinearMemoryStream::Reset(); 19 20 m_rewindBuffer.clear(); 21 } 22 SubmitFrameInternal()23void CDeltaPairMemoryStream::SubmitFrameInternal() 24 { 25 m_rewindBuffer.emplace_back(); 26 MemoryFrame& frame = m_rewindBuffer.back(); 27 28 // Record frame history 29 frame.frameHistoryCount = m_currentFrameHistory++; 30 31 uint32_t* currentFrame = m_currentFrame.get(); 32 uint32_t* nextFrame = m_nextFrame.get(); 33 34 for (size_t i = 0; i < m_paddedFrameSize; i++) 35 { 36 uint32_t xor_val = currentFrame[i] ^ nextFrame[i]; 37 if (xor_val) 38 { 39 DeltaPair pair = {i, xor_val}; 40 frame.buffer.push_back(pair); 41 } 42 } 43 44 // Delta is generated, bring the new frame forward (m_nextFrame is now disposable) 45 std::swap(m_currentFrame, m_nextFrame); 46 47 m_bHasNextFrame = false; 48 49 if (PastFramesAvailable() + 1 > MaxFrameCount()) 50 CullPastFrames(1); 51 } 52 PastFramesAvailable() const53uint64_t CDeltaPairMemoryStream::PastFramesAvailable() const 54 { 55 return static_cast<uint64_t>(m_rewindBuffer.size()); 56 } 57 RewindFrames(uint64_t frameCount)58uint64_t CDeltaPairMemoryStream::RewindFrames(uint64_t frameCount) 59 { 60 uint64_t rewound; 61 62 for (rewound = 0; rewound < frameCount; rewound++) 63 { 64 if (m_rewindBuffer.empty()) 65 break; 66 67 const MemoryFrame& frame = m_rewindBuffer.back(); 68 const DeltaPair* buffer = frame.buffer.data(); 69 70 size_t bufferSize = frame.buffer.size(); 71 72 // buffer pointer redirection violates data-dependency requirements... 73 // no vectorization for us :( 74 for (size_t i = 0; i < bufferSize; i++) 75 m_currentFrame[buffer[i].pos] ^= buffer[i].delta; 76 77 // Restore frame history 78 m_currentFrameHistory = frame.frameHistoryCount; 79 80 m_rewindBuffer.pop_back(); 81 } 82 83 return rewound; 84 } 85 CullPastFrames(uint64_t frameCount)86void CDeltaPairMemoryStream::CullPastFrames(uint64_t frameCount) 87 { 88 for (uint64_t removedCount = 0; removedCount < frameCount; removedCount++) 89 { 90 if (m_rewindBuffer.empty()) 91 { 92 CLog::Log(LOGDEBUG, 93 "CDeltaPairMemoryStream: Tried to cull %d frames too many. Check your math!", 94 frameCount - removedCount); 95 break; 96 } 97 m_rewindBuffer.pop_front(); 98 } 99 } 100