AXRingBuffer.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /**********************************************************************************
  2. *
  3. * Copyright (c) 2019-2020 Beijing AXera Technology Co., Ltd. All Rights Reserved.
  4. *
  5. * This source file is the property of Beijing AXera Technology Co., Ltd. and
  6. * may not be copied or distributed in any isomorphic form without the prior
  7. * written consent of Beijing AXera Technology Co., Ltd.
  8. *
  9. **********************************************************************************/
  10. #ifndef _RING_BUFFER_3246FC57_D0F1_4176_A1C3_3A16FC46D1CF_H_
  11. #define _RING_BUFFER_3246FC57_D0F1_4176_A1C3_3A16FC46D1CF_H_
  12. #include "ax_base_type.h"
  13. #include <tuple>
  14. #include <mutex>
  15. #define COMM_RING_PRT(fmt...) \
  16. do {\
  17. printf("[RING][%s]: ", __FUNCTION__);\
  18. printf(fmt);\
  19. printf("\n");\
  20. }while(0)
  21. class CAXRingBuffer;
  22. class CAXRingElement {
  23. public:
  24. CAXRingElement() {
  25. this->pBuf = nullptr;
  26. this->nSize = 0;
  27. this->nChannel = 0;
  28. this->bIFrame = AX_FALSE;
  29. this->nPts = 0;
  30. this->nRefCount = 0;
  31. this->pParent = nullptr;
  32. }
  33. CAXRingElement(AX_U8* pBuf, AX_U32 nSize, AX_U32 nChn, AX_U64 u64PTS = 0, AX_BOOL isIFrame = AX_FALSE) {
  34. this->nIndex = -1;
  35. this->pBuf = pBuf;
  36. this->nSize = nSize;
  37. this->nChannel = nChn;
  38. this->nPts = u64PTS;
  39. this->bIFrame = isIFrame;
  40. this->nRefCount = 0;
  41. this->pParent = nullptr;
  42. }
  43. AX_VOID CopyFrom(CAXRingElement &element) {
  44. if(this->pBuf) {
  45. memcpy(this->pBuf, element.pBuf, element.nSize);
  46. }
  47. this->nSize = element.nSize;
  48. this->nChannel = element.nChannel;
  49. this->nPts = element.nPts;
  50. this->bIFrame = element.bIFrame;
  51. this->nRefCount = 0;
  52. this->pParent = nullptr;
  53. }
  54. AX_S32 IncreaseRefCount() {
  55. return ++nRefCount;
  56. }
  57. AX_S32 DecreaseRefCount(AX_BOOL bForceClear) {
  58. if (bForceClear) {
  59. nRefCount = 0;
  60. }
  61. else {
  62. --nRefCount;
  63. if (nRefCount < 0) {
  64. nRefCount = 0;
  65. }
  66. }
  67. return nRefCount;
  68. }
  69. AX_S32 GetRefCount() {
  70. return nRefCount;
  71. }
  72. AX_S32 GetIndex() {
  73. return nIndex;
  74. }
  75. AX_S32 SetIndex(AX_S32 nIndex) {
  76. return this->nIndex = nIndex;
  77. }
  78. private:
  79. AX_VOID Clear() {
  80. this->nSize = 0;
  81. this->nChannel = 0;
  82. this->bIFrame = AX_FALSE;
  83. this->nPts = 0;
  84. this->nRefCount = 0;
  85. }
  86. public:
  87. AX_U8* pBuf;
  88. AX_U32 nSize;
  89. AX_U32 nChannel;
  90. AX_U64 nPts;
  91. AX_BOOL bIFrame;
  92. CAXRingBuffer * pParent;
  93. private:
  94. AX_S32 nRefCount;
  95. AX_S32 nIndex;
  96. };
  97. #define AXRING "RING"
  98. class CAXRingBuffer
  99. {
  100. public:
  101. CAXRingBuffer(AX_U32 nElementBuffSize, AX_U32 nElementCount, const char * pszName=nullptr ) {
  102. m_nElementCount = nElementCount;
  103. m_nElementBuffSize = nElementBuffSize;
  104. m_pRing = new CAXRingElement[m_nElementCount];
  105. for (AX_U32 i = 0; i < m_nElementCount; i++) {
  106. m_pRing[i].pBuf = new AX_U8[m_nElementBuffSize];
  107. memset((AX_VOID *)m_pRing[i].pBuf, 0x0, m_nElementBuffSize);
  108. m_pRing[i].nSize = 0;
  109. m_pRing[i].pParent = this;
  110. m_pRing[i].SetIndex(i);
  111. }
  112. m_nHeader = 0;
  113. m_nTail = 0;
  114. m_bHasLost = AX_FALSE;
  115. m_szName[0] = 0;
  116. if (pszName && strlen(pszName)) {
  117. strncpy(m_szName, pszName, sizeof(m_szName));
  118. }
  119. }
  120. ~CAXRingBuffer(AX_VOID) {
  121. m_nHeader = 0;
  122. m_nTail = 0;
  123. if (nullptr == m_pRing) {
  124. return;
  125. }
  126. m_mutex.lock();
  127. for (AX_U32 i = 0; i < m_nElementCount; i++) {
  128. if (nullptr != m_pRing[i].pBuf) {
  129. delete[] m_pRing[i].pBuf;
  130. }
  131. }
  132. delete[] m_pRing;
  133. m_mutex.unlock();
  134. }
  135. AX_BOOL IsFull() {
  136. std::lock_guard<std::mutex> lck (m_mutex);
  137. return (m_nTail - m_nHeader) == m_nElementCount ? AX_TRUE : AX_FALSE;
  138. }
  139. AX_BOOL IsEmpty() {
  140. std::lock_guard<std::mutex> lck (m_mutex);
  141. return (m_nTail == m_nHeader) ? AX_TRUE : AX_FALSE;
  142. }
  143. AX_BOOL Put(CAXRingElement &element) {
  144. std::lock_guard<std::mutex> lck (m_mutex);
  145. //LOG_M(AXRING, "[%s] +++, tail=%llu, head=%llu, iFrame=%d", m_szName, m_nTail, m_nHeader,element.bIFrame);
  146. if (!m_pRing || element.nSize > m_nElementBuffSize) {
  147. // must not go to here
  148. if (element.bIFrame) {
  149. m_bHasLost = AX_TRUE;
  150. }
  151. COMM_RING_PRT("[%s] ---, drop one frame for size is big", m_szName);
  152. return AX_FALSE;
  153. }
  154. if ((m_nTail - m_nHeader) == m_nElementCount) {
  155. // is full
  156. COMM_RING_PRT("[%s] is full, tail=%llu, head=%llu", m_szName, m_nTail, m_nHeader);
  157. if (element.bIFrame) {
  158. // replace the tail with new I Frame
  159. AX_U64 nIndex = (m_nTail - 1) % m_nElementCount;
  160. AX_S32 nRefCount= m_pRing[nIndex].GetRefCount();
  161. if (nRefCount == 0) {
  162. m_nTail--;
  163. m_bHasLost = AX_FALSE;
  164. COMM_RING_PRT("[%s] ---, replace last one with i frame for is full", m_szName);
  165. } else {
  166. m_bHasLost = AX_TRUE;
  167. COMM_RING_PRT("[%s] ---, drop one i frame for is full", m_szName);
  168. return AX_FALSE;
  169. }
  170. }
  171. else {
  172. m_bHasLost = AX_TRUE; // mark to lost all behind P Frame
  173. COMM_RING_PRT("[%s] ---, drop one p frame for is full", m_szName);
  174. return AX_FALSE;
  175. }
  176. } else {
  177. if (element.bIFrame) {
  178. m_bHasLost = AX_FALSE; // add new I frame
  179. }
  180. else {
  181. if (m_bHasLost) {
  182. // drop this P Frame
  183. COMM_RING_PRT("[%s] ---, drop one p frame for lost yet", m_szName);
  184. return AX_FALSE;
  185. }
  186. }
  187. }
  188. AX_U64 nIndex = m_nTail % m_nElementCount;
  189. AX_S32 nRefCount= m_pRing[nIndex].GetRefCount();
  190. if (nRefCount != 0) {
  191. m_bHasLost = AX_TRUE;
  192. COMM_RING_PRT("[%s] ---, drop one frame for refcount is none zero, nIndex=%llu, nRefCount=%d", m_szName, nIndex, nRefCount);
  193. return AX_FALSE;
  194. }
  195. m_pRing[nIndex].CopyFrom(element);
  196. m_pRing[nIndex].IncreaseRefCount();
  197. m_pRing[nIndex].pParent = this;
  198. m_nTail++;
  199. //LOG_M(AXRING, "[%s] ---, tail=%llu, head=%llu, pBuf=%p, size=%u", m_szName, m_nTail, m_nHeader, m_pRing[nIndex].pBuf, m_pRing[nIndex].nSize);
  200. return AX_TRUE;
  201. }
  202. CAXRingElement* Get() {
  203. CAXRingElement* element = nullptr;
  204. std::lock_guard<std::mutex> lck (m_mutex);
  205. //LOG_M(AXRING, "[%s] +++, tail=%llu, head=%llu", m_szName, m_nTail, m_nHeader);
  206. if (m_nHeader == m_nTail) {
  207. // is emtpy
  208. //LOG_M(AXRING, "[%s] ---, empty, tail=%llu, head=%llu", m_szName, m_nTail, m_nHeader);
  209. return element;
  210. }
  211. AX_U64 nIndex = m_nHeader % m_nElementCount;
  212. m_pRing[nIndex].IncreaseRefCount();
  213. // AX_S32 nRefCount = m_pRing[nIndex].IncreaseRefCount();
  214. element = &m_pRing[nIndex];
  215. // LOG_M(AXRING, "[%s] ---, tail=%llu, head=%llu, pBuf=%p, size=%u, nRef=%d", m_szName, m_nTail, m_nHeader, element->pBuf, element->nSize, nRefCount);
  216. return element;
  217. }
  218. AX_BOOL Pop(AX_BOOL bForce=AX_TRUE) {
  219. std::lock_guard<std::mutex> lck (m_mutex);
  220. // LOG_M(AXRING, "[%s] +++, tail=%llu, head=%llu", m_szName, m_nTail, m_nHeader);
  221. if (m_nHeader == m_nTail) {
  222. // is emtpy
  223. //LOG_M(AXRING, "[%s] ---, no element to be pop, tail=%llu, head=%llu", m_szName, m_nTail, m_nHeader);
  224. return AX_FALSE;
  225. }
  226. AX_U64 nIndex = m_nHeader % m_nElementCount;
  227. // AX_S32 nRefCount = m_pRing[nIndex].DecreaseRefCount(bForce);
  228. m_pRing[nIndex].DecreaseRefCount(bForce);
  229. m_nHeader++;
  230. // LOG_M(AXRING, "[%s] ---, tail=%llu, head=%llu, nRef=%d", m_szName, m_nTail, m_nHeader, nRefCount);
  231. return AX_TRUE;
  232. }
  233. AX_VOID Free(CAXRingElement* ele, AX_BOOL bForce=AX_FALSE) {
  234. if(!ele) {
  235. return;
  236. }
  237. std::lock_guard<std::mutex> lck (m_mutex);
  238. AX_S32 nIndex = ele->GetIndex();
  239. if (nIndex >= 0 && nIndex < (AX_S32)m_nElementCount) {
  240. m_pRing[nIndex].DecreaseRefCount(bForce);
  241. // AX_S32 nRefCount= m_pRing[nIndex].DecreaseRefCount(bForce);
  242. // LOG_M(AXRING, "[%s] nIndex=%d, nRefCount=%d", m_szName, nIndex, nRefCount);
  243. }
  244. }
  245. AX_U32 Size() {
  246. if (m_nTail < m_nHeader) {
  247. return 0;
  248. }
  249. return m_nTail-m_nHeader;
  250. }
  251. private:
  252. CAXRingElement* m_pRing;
  253. AX_U32 m_nElementCount;
  254. AX_U32 m_nElementBuffSize;
  255. AX_U64 m_nHeader;
  256. AX_U64 m_nTail;
  257. AX_BOOL m_bHasLost;
  258. std::mutex m_mutex;
  259. char m_szName[64];
  260. };
  261. #endif // _RING_BUFFER_3246FC57_D0F1_4176_A1C3_3A16FC46D1CF_H_