[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / cores / AudioEngine / Utils / AERingBuffer.h
blob8a2a1aaf7400491e4c4c95ad92c962a7fd6e08fe
1 /*
2 * Copyright (C) 2010-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #pragma once
11 #define AE_RING_BUFFER_OK 0;
12 #define AE_RING_BUFFER_EMPTY 1;
13 #define AE_RING_BUFFER_FULL 2;
14 #define AE_RING_BUFFER_NOTAVAILABLE 3;
16 //#define AE_RING_BUFFER_DEBUG
18 #include "utils/log.h"
19 #include "utils/MemUtils.h"
21 #include <string.h>
23 /**
24 * This buffer can be used by one read and one write thread at any one time
25 * without the risk of data corruption.
26 * If you intend to call the Reset() method, please use Locks.
27 * All other operations are thread-safe.
29 class AERingBuffer {
31 public:
32 AERingBuffer() = default;
34 AERingBuffer(unsigned int size, unsigned int planes = 1) { Create(size, planes); }
36 ~AERingBuffer()
38 #ifdef AE_RING_BUFFER_DEBUG
39 CLog::Log(LOGDEBUG, "AERingBuffer::~AERingBuffer: Deleting buffer.");
40 #endif
41 for (unsigned int i = 0; i < m_planes; i++)
42 KODI::MEMORY::AlignedFree(m_Buffer[i]);
43 delete[] m_Buffer;
46 /**
47 * Allocates space for buffer, and sets it's contents to 0.
49 * @return true on success, false otherwise
51 bool Create(int size, unsigned int planes = 1)
53 m_Buffer = new unsigned char*[planes];
54 for (unsigned int i = 0; i < planes; i++)
56 m_Buffer[i] = static_cast<unsigned char*>(KODI::MEMORY::AlignedMalloc(size, 16));
57 if (!m_Buffer[i])
58 return false;
59 memset(m_Buffer[i], 0, size);
61 m_iSize = size;
62 m_planes = planes;
63 return true;
66 /**
67 * Fills the buffer with zeros and resets the pointers.
68 * This method is not thread-safe, so before using this method
69 * please acquire a Lock()
71 void Reset() {
72 #ifdef AE_RING_BUFFER_DEBUG
73 CLog::Log(LOGDEBUG, "AERingBuffer::Reset: Buffer reset.");
74 #endif
75 m_iWritten = 0;
76 m_iRead = 0;
77 m_iReadPos = 0;
78 m_iWritePos = 0;
81 /**
82 * Writes data to buffer.
83 * Attempt to write more bytes than available results in AE_RING_BUFFER_FULL.
85 * @return AE_RING_BUFFER_OK on success, otherwise an error code
87 int Write(unsigned char *src, unsigned int size, unsigned int plane = 0)
89 unsigned int space = GetWriteSize();
91 //do we have enough space for all the data?
92 if (size > space || plane >= m_planes)
94 #ifdef AE_RING_BUFFER_DEBUG
95 CLog::Log(LOGDEBUG,
96 "AERingBuffer: Not enough space, ignoring data. Requested: {} Available: {}", size,
97 space);
98 #endif
99 return AE_RING_BUFFER_FULL;
102 //no wrapping?
103 if ( m_iSize > size + m_iWritePos )
105 #ifdef AE_RING_BUFFER_DEBUG
106 CLog::Log(LOGDEBUG, "AERingBuffer: Written to: {} size: {} space before: {}", m_iWritePos,
107 size, space);
108 #endif
109 memcpy(m_Buffer[plane] + m_iWritePos, src, size);
111 //need to wrap
112 else
114 unsigned int first = m_iSize - m_iWritePos;
115 unsigned int second = size - first;
116 #ifdef AE_RING_BUFFER_DEBUG
117 CLog::Log(LOGDEBUG,
118 "AERingBuffer: Written to (split) first: {} second: {} size: {} space before: {}",
119 first, second, size, space);
120 #endif
121 memcpy(m_Buffer[plane] + m_iWritePos, src, first);
122 memcpy(m_Buffer[plane], src + first, second);
124 if (plane + 1 == m_planes)
125 WriteFinished(size);
127 return AE_RING_BUFFER_OK;
131 * Reads data from buffer.
132 * Attempt to read more bytes than available results in RING_BUFFER_NOTAVAILABLE.
133 * Reading from empty buffer returns AE_RING_BUFFER_EMPTY
135 * @return AE_RING_BUFFER_OK on success, otherwise an error code
137 int Read(unsigned char *dest, unsigned int size, unsigned int plane = 0)
139 unsigned int space = GetReadSize();
141 //want to read more than we have written?
142 if( space == 0 )
144 #ifdef AE_RING_BUFFER_DEBUG
145 CLog::Log(LOGDEBUG, "AERingBuffer: Can't read from empty buffer.");
146 #endif
147 return AE_RING_BUFFER_EMPTY;
150 //want to read more than we have available
151 if( size > space || plane >= m_planes)
153 #ifdef AE_RING_BUFFER_DEBUG
154 CLog::Log(LOGDEBUG, "AERingBuffer: Can't read {} bytes when we only have {}.", size, space);
155 #endif
156 return AE_RING_BUFFER_NOTAVAILABLE;
159 //no wrapping?
160 if ( size + m_iReadPos < m_iSize )
162 #ifdef AE_RING_BUFFER_DEBUG
163 CLog::Log(LOGDEBUG, "AERingBuffer: Reading from: {} size: {} space before: {}", m_iWritePos,
164 size, space);
165 #endif
166 if (dest)
167 memcpy(dest, m_Buffer[plane] + m_iReadPos, size);
169 //need to wrap
170 else
172 unsigned int first = m_iSize - m_iReadPos;
173 unsigned int second = size - first;
174 #ifdef AE_RING_BUFFER_DEBUG
175 CLog::Log(LOGDEBUG,
176 "AERingBuffer: Reading from (split) first: {} second: {} size: {} space before: {}",
177 first, second, size, space);
178 #endif
179 if (dest)
181 memcpy(dest, m_Buffer[plane] + m_iReadPos, first);
182 memcpy(dest + first, m_Buffer[plane], second);
185 if (plane + 1 == m_planes)
186 ReadFinished(size);
188 return AE_RING_BUFFER_OK;
192 * Dumps the buffer.
194 void Dump()
196 unsigned char *bufferContents = static_cast<unsigned char*>(KODI::MEMORY::AlignedMalloc(m_iSize * m_planes + 1, 16));
197 unsigned char *dest = bufferContents;
198 for (unsigned int j = 0; j < m_planes; j++)
200 for (unsigned int i=0; i<m_iSize; i++)
202 if (i >= m_iReadPos && i<m_iWritePos)
203 *dest++ = m_Buffer[j][i];
204 else
205 *dest++ = '_';
208 bufferContents[m_iSize*m_planes] = '\0';
209 CLog::LogF(LOGDEBUG, "Buffer Content: {}", reinterpret_cast<const char*>(bufferContents));
210 KODI::MEMORY::AlignedFree(bufferContents);
214 * Returns available space for writing to buffer.
215 * Attempt to write more bytes than available results in AE_RING_BUFFER_FULL.
217 unsigned int GetWriteSize()
219 return m_iSize - ( m_iWritten - m_iRead );
223 * Returns available space for reading from buffer.
224 * Attempt to read more bytes than available results in AE_RING_BUFFER_EMPTY.
226 unsigned int GetReadSize()
228 return m_iWritten - m_iRead;
232 * Returns the buffer size.
234 unsigned int GetMaxSize()
236 return m_iSize;
240 * Returns the number of planes
242 unsigned int NumPlanes() const
244 return m_planes;
246 private:
248 * Increments the write pointer.
249 * Called at the end of writing to all planes.
251 void WriteFinished(unsigned int size)
253 if ( m_iSize > size + m_iWritePos )
254 m_iWritePos += size;
255 else // wrapping
256 m_iWritePos = size - (m_iSize - m_iWritePos);
258 //we can increase the write count now
259 m_iWritten+=size;
263 * Increments the read pointer.
264 * Called at the end of reading to all planes.
266 void ReadFinished(unsigned int size)
268 if ( size + m_iReadPos < m_iSize )
269 m_iReadPos += size;
270 else
271 m_iReadPos = size - (m_iSize - m_iReadPos);
273 //we can increase the read count now
274 m_iRead+=size;
277 unsigned int m_iReadPos = 0;
278 unsigned int m_iWritePos = 0;
279 unsigned int m_iRead = 0;
280 unsigned int m_iWritten = 0;
281 unsigned int m_iSize = 0;
282 unsigned int m_planes = 0;
283 unsigned char** m_Buffer = nullptr;