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 "LinearMemoryStream.h"
10 
11 using namespace KODI;
12 using namespace RETRO;
13 
14 // Pad forward to nearest boundary of bytes
15 #define PAD_TO_CEIL(x, bytes) ((((x) + (bytes)-1) / (bytes)) * (bytes))
16 
CLinearMemoryStream()17 CLinearMemoryStream::CLinearMemoryStream()
18 {
19   Reset();
20 }
21 
Init(size_t frameSize,uint64_t maxFrameCount)22 void CLinearMemoryStream::Init(size_t frameSize, uint64_t maxFrameCount)
23 {
24   Reset();
25 
26   m_frameSize = frameSize;
27   m_paddedFrameSize = PAD_TO_CEIL(m_frameSize, sizeof(uint32_t));
28   m_maxFrames = maxFrameCount;
29 }
30 
Reset()31 void CLinearMemoryStream::Reset()
32 {
33   m_frameSize = 0;
34   m_paddedFrameSize = 0;
35   m_maxFrames = 0;
36   m_currentFrame.reset();
37   m_nextFrame.reset();
38   m_bHasCurrentFrame = false;
39   m_bHasNextFrame = false;
40   m_currentFrameHistory = 0;
41 }
42 
SetMaxFrameCount(uint64_t maxFrameCount)43 void CLinearMemoryStream::SetMaxFrameCount(uint64_t maxFrameCount)
44 {
45   if (maxFrameCount == 0)
46   {
47     Reset();
48   }
49   else
50   {
51     const uint64_t frameCount = BufferSize();
52     if (maxFrameCount < frameCount)
53       CullPastFrames(frameCount - maxFrameCount);
54   }
55 
56   m_maxFrames = maxFrameCount;
57 }
58 
BeginFrame()59 uint8_t* CLinearMemoryStream::BeginFrame()
60 {
61   if (m_paddedFrameSize == 0)
62     return nullptr;
63 
64   if (!m_bHasCurrentFrame)
65   {
66     if (!m_currentFrame)
67       m_currentFrame.reset(new uint32_t[m_paddedFrameSize]);
68     return reinterpret_cast<uint8_t*>(m_currentFrame.get());
69   }
70 
71   if (!m_nextFrame)
72     m_nextFrame.reset(new uint32_t[m_paddedFrameSize]);
73   return reinterpret_cast<uint8_t*>(m_nextFrame.get());
74 }
75 
CurrentFrame() const76 const uint8_t* CLinearMemoryStream::CurrentFrame() const
77 {
78   if (m_bHasCurrentFrame)
79     return reinterpret_cast<const uint8_t*>(m_currentFrame.get());
80 
81   return nullptr;
82 }
83 
SubmitFrame()84 void CLinearMemoryStream::SubmitFrame()
85 {
86   if (!m_bHasCurrentFrame)
87   {
88     m_bHasCurrentFrame = true;
89   }
90   else if (!m_bHasNextFrame)
91   {
92     m_bHasNextFrame = true;
93   }
94 
95   if (m_bHasNextFrame)
96   {
97     SubmitFrameInternal();
98   }
99 }
100 
BufferSize() const101 uint64_t CLinearMemoryStream::BufferSize() const
102 {
103   return PastFramesAvailable() + (m_bHasCurrentFrame ? 1 : 0);
104 }
105