ref: 054a297ca79cd2cc609dfefa8b863d519b3f00ac
parent: 1a7a3e246272b9c0a478e27f32951059f24a85c0
author: Sijia Chen <sijchen@cisco.com>
date: Wed Oct 28 05:39:26 EDT 2015
adjust encoder tasks, add ut and enable new thread pool under some slice modes
--- a/codec/common/inc/WelsCircleQueue.h
+++ b/codec/common/inc/WelsCircleQueue.h
@@ -112,6 +112,18 @@
}
return NULL;
}
+
+ TNodeType* GetIndexNode (const int32_t iIdx) {
+ if (size() > 0) {
+ if ((iIdx + m_iCurrentListStart) < m_iMaxNodeCount) {
+ return m_pCurrentQueue[m_iCurrentListStart + iIdx];
+ } else {
+ return m_pCurrentQueue[m_iCurrentListStart + iIdx - m_iMaxNodeCount];
+ }
+ }
+ return NULL;
+ }
+
private:
int32_t InternalPushBack (TNodeType* pNode) {
m_pCurrentQueue[m_iCurrentListEnd] = pNode;
--- a/codec/common/src/WelsThreadLib.cpp
+++ b/codec/common/src/WelsThreadLib.cpp
@@ -313,6 +313,7 @@
*p_event = NULL;
return WELS_THREAD_ERROR_GENERAL;
} else {
+ //printf("event_open:%x, %s\n", p_event, event_name);
return WELS_THREAD_ERROR_OK;
}
#else
@@ -329,6 +330,7 @@
#endif
}
WELS_THREAD_ERROR_CODE WelsEventClose (WELS_EVENT* event, const char* event_name) {
+ //printf("event_close:%x, %s\n", event, event_name);
#ifdef __APPLE__
WELS_THREAD_ERROR_CODE err = sem_close (*event); // match with sem_open
if (event_name)
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -57,6 +57,7 @@
#include "mt_defs.h" // for multiple threadin,
#include "WelsThreadLib.h"
+#include "wels_task_management.h"
namespace WelsEnc {
@@ -134,7 +135,7 @@
SWelsFuncPtrList* pFuncList;
SSliceThreading* pSliceThreading;
- //IWelsTaskManage* pTaskManage; //was planning to put it under CWelsH264SVCEncoder but it may be updated (lock/no lock) when param is changed
+ IWelsTaskManage* pTaskManage; //was planning to put it under CWelsH264SVCEncoder but it may be updated (lock/no lock) when param is changed
// SSlice context
SSliceCtx* pSliceCtxList;// slice context table for each dependency quality layer
--- a/codec/encoder/core/inc/wels_task_encoder.h
+++ b/codec/encoder/core/inc/wels_task_encoder.h
@@ -61,6 +61,7 @@
virtual WelsErrorType Execute();
virtual WelsErrorType InitTask();
+ virtual WelsErrorType ExecuteTask();
virtual void FinishTask();
virtual uint32_t GetTaskType() const {
--- a/codec/encoder/core/inc/wels_task_management.h
+++ b/codec/encoder/core/inc/wels_task_management.h
@@ -56,7 +56,7 @@
virtual WelsErrorType Init (sWelsEncCtx* pEncCtx) = 0;
virtual void Uninit() = 0;
- virtual void InitFrame() {}
+ virtual void InitFrame (const int32_t kiCurDid) {}
virtual WelsErrorType ExecuteTasks() = 0;
static IWelsTaskManage* CreateTaskManage (sWelsEncCtx* pCtx, bool bNeedLock);
@@ -75,7 +75,7 @@
virtual WelsErrorType Init (sWelsEncCtx* pEncCtx);
void Uninit();
- virtual void InitFrame();
+ virtual void InitFrame (const int32_t kiCurDid);
virtual WelsErrorType ExecuteTasks();
//IWelsThreadPoolSink
@@ -88,6 +88,7 @@
protected:
sWelsEncCtx* m_pEncCtx;
+ WelsCommon::CWelsThreadPool* m_pThreadPool;
TASKLIST_TYPE* m_cTaskList;
int32_t m_iTaskNum;
@@ -94,7 +95,6 @@
//SLICE_PAIR_LIST *m_cSliceList;
- WelsCommon::CWelsThreadPool* m_pThreadPool;
int32_t m_iThreadNum;
int32_t m_iWaitTaskNum;
@@ -104,6 +104,7 @@
private:
DISALLOW_COPY_AND_ASSIGN (CWelsTaskManageBase);
+ void OnTaskMinusOne();
};
class CWelsTaskManageOne : public CWelsTaskManageBase {
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2930,6 +2930,10 @@
} else {
pCurDq->bBaseLayerAvailableFlag = false;
}
+
+ if (pCtx->pTaskManage) {
+ pCtx->pTaskManage->InitFrame(kiCurDid);
+ }
}
static inline void SetFastCodingFunc (SWelsFuncPtrList* pFuncList) {
@@ -4013,7 +4017,7 @@
iSliceCount);
return ENC_RETURN_UNEXPECTED;
}
-
+ if (SM_AUTO_SLICE == pParam->sSliceCfg.uiSliceMode) {
if (pSvcParam->iCountThreadsNum >= iSliceCount) { //THREAD_FULLY_FIRE_MODE
#if defined(MT_DEBUG)
int64_t t_bs_append = 0;
@@ -4101,6 +4105,19 @@
// all slices are finished coding here
// append exclusive slice 0 bs to pFrameBs
iLayerSize = AppendSliceToFrameBs (pCtx, pLayerBsInfo, iSliceCount);
+ }
+
+ } else {
+ pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
+ pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
+ pLayerBsInfo->uiSpatialId = pCtx->uiDependencyId;
+ pLayerBsInfo->uiTemporalId = pCtx->uiTemporalId;
+ pLayerBsInfo->uiQualityId = 0;
+ pLayerBsInfo->iNalCount = 0;
+ pCtx->pSliceBs[0].pBs = pLayerBsInfo->pBsBuf;
+
+ pCtx->pTaskManage->ExecuteTasks();
+ iLayerSize = AppendSliceToFrameBs (pCtx, pLayerBsInfo, iSliceCount);
}
}
// THREAD_FULLY_FIRE_MODE && SM_DYN_SLICE
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -333,6 +333,7 @@
int32_t iIdx = 0;
int16_t iMaxSliceNum = 1;
int32_t iReturn = ENC_RETURN_SUCCESS;
+ bool bWillUseTaskManage = false;
if (NULL == ppCtx || NULL == pCodingParam || NULL == *ppCtx || iCountBsLen <= 0)
return 1;
@@ -372,6 +373,10 @@
pSmt->pSliceConsumeTime[iIdx] = NULL;
pSmt->pSliceComplexRatio[iIdx] = NULL;
}
+
+ if ( pMso->uiSliceMode == SM_FIXEDSLCNUM_SLICE || pMso->uiSliceMode == SM_RASTER_SLICE || pMso->uiSliceMode == SM_ROWMB_SLICE) {
+ bWillUseTaskManage = true;
+ }
++ iIdx;
}
// NULL for pSliceConsumeTime[iIdx]: iIdx from iNumSpatialLayers to MAX_DEPENDENCY_LAYERS
@@ -430,9 +435,11 @@
pSmt->pThreadBsBuffer[iIdx] = NULL;
}
+ //previous conflict
WelsSnprintf (name, SEM_NAME_MAX, "scm%s", pSmt->eventNamespace);
err = WelsEventOpen (&pSmt->pSliceCodedMasterEvent, name);
MT_TRACE_LOG (*ppCtx, WELS_LOG_INFO, "[MT] Open pSliceCodedMasterEvent named(%s) ret%d err%d", name, err, errno);
+ //previous conflict ends
iReturn = SetMultiSliceBuffer (ppCtx, pMa, pSmt, iMaxSliceNum,
@@ -444,6 +451,11 @@
iReturn = WelsMutexInit (&pSmt->mutexSliceNumUpdate);
WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx))
+ if (bWillUseTaskManage) {
+ (*ppCtx)->pTaskManage = IWelsTaskManage::CreateTaskManage(*ppCtx, bDynamicSlice);
+ WELS_VERIFY_RETURN_PROC_IF (iReturn, (NULL == (*ppCtx)->pTaskManage), FreeMemorySvc (ppCtx))
+ }
+
memset(&pSmt->bThreadBsBufferUsage, 0, MAX_THREADS_NUM * sizeof(bool));
iReturn = WelsMutexInit (&pSmt->mutexThreadBsBufferUsage);
WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx))
@@ -530,6 +542,12 @@
pMa->WelsFree ((*ppCtx)->pSliceBs, "pSliceBs");
(*ppCtx)->pSliceBs = NULL;
}
+
+ if ((*ppCtx)->pTaskManage != NULL) {
+ delete (*ppCtx)->pTaskManage;
+ (*ppCtx)->pTaskManage = NULL;
+ }
+
iIdx = 0;
while (iIdx < pCodingParam->iSpatialLayerNum) {
if (pSmt->pSliceConsumeTime[iIdx]) {
@@ -1171,6 +1189,7 @@
void SetOneSliceBsBufferUnderMultithread (sWelsEncCtx* pCtx, const int32_t kiThreadIdx, const int32_t iSliceIdx) {
pCtx->pSliceBs[iSliceIdx].pBsBuffer = pCtx->pSliceThreading->pThreadBsBuffer[kiThreadIdx];
pCtx->pSliceBs[iSliceIdx].uiBsPos = 0;
+ //printf("SetOneSliceBsBufferUnderMultithread, thread %d, slice %d, buffer=%x\n", kiThreadIdx, iSliceIdx, pCtx->pSliceBs[iSliceIdx].pBsBuffer);
}
}
--- a/codec/encoder/core/src/wels_task_encoder.cpp
+++ b/codec/encoder/core/src/wels_task_encoder.cpp
@@ -63,6 +63,18 @@
CWelsSliceEncodingTask::~CWelsSliceEncodingTask() {
}
+WelsErrorType CWelsSliceEncodingTask::Execute() {
+ WelsThreadSetName ("OpenH264Enc_CWelsSliceEncodingTask_Execute");
+
+ int32_t iReturn = InitTask();
+ WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
+
+ iReturn = ExecuteTask();
+
+ FinishTask();
+ return ENC_RETURN_SUCCESS;
+}
+
WelsErrorType CWelsSliceEncodingTask::SetBoundary (int32_t iStartIdx, int32_t iEndIdx) {
m_iStartMbIdx = iStartIdx;
m_iEndMbIdx = iEndIdx;
@@ -88,10 +100,11 @@
m_iThreadIdx = QueryEmptyThread (m_pCtx->pSliceThreading->bThreadBsBufferUsage);
WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
if (m_iThreadIdx < 0) {
- printf ("cannot find avaialble thread %d\n", m_iThreadIdx);
+ WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
+ "[MT] CWelsSliceEncodingTask InitTask(), Cannot find available thread for m_iSliceIdx = %d", m_iSliceIdx);
return ENC_RETURN_UNEXPECTED;
}
- SetOneSliceBsBufferUnderMultithread (m_pCtx, m_iSliceIdx, m_iThreadIdx);
+ SetOneSliceBsBufferUnderMultithread (m_pCtx, m_iThreadIdx, m_iSliceIdx);
m_pSlice = &m_pCtx->pCurDqLayer->sLayerInfo.pSliceInLayer[m_iSliceIdx];
m_pSliceBs = &m_pCtx->pSliceBs[m_iSliceIdx];
@@ -101,9 +114,11 @@
assert ((void*) (&m_pSliceBs->sBsWrite) == (void*)m_pSlice->pSliceBsa);
InitBits (&m_pSliceBs->sBsWrite, m_pSliceBs->pBsBuffer, m_pSliceBs->uiSize);
+ //printf ("CWelsSliceEncodingTask_InitTask slice %d\n", m_iSliceIdx);
return ENC_RETURN_SUCCESS;
}
+
void CWelsSliceEncodingTask::FinishTask() {
WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
m_pCtx->pSliceThreading->bThreadBsBufferUsage[m_iThreadIdx] = false;
@@ -110,9 +125,7 @@
WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
}
-WelsErrorType CWelsSliceEncodingTask::Execute() {
- WelsThreadSetName ("OpenH264Enc_CWelsSliceEncodingTask_Execute");
-
+WelsErrorType CWelsSliceEncodingTask::ExecuteTask() {
#if MT_DEBUG_BS_WR
m_pSliceBs->bSliceCodedFlag = false;
#endif//MT_DEBUG_BS_WR
@@ -144,6 +157,10 @@
iLeftBufferSize,
m_iSliceIdx, m_iSliceSize);
if (ENC_RETURN_SUCCESS != iReturn) {
+ WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
+ "[MT] CWelsSliceEncodingTask ExecuteTask(), WriteSliceBs not successful: coding_idx %d, um_iSliceIdx %d",
+ m_pCtx->iCodingIndex,
+ m_iSliceIdx);
return iReturn;
}
if (0 == m_iSliceIdx) {
@@ -152,15 +169,11 @@
m_pCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (m_pCtx->pCurDqLayer, m_pCtx->pFuncList, m_iSliceIdx);
-#if defined(SLICE_INFO_OUTPUT)
- fprintf (stderr,
- "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n",
- m_iSliceIdx,
- (pEncPEncCtx->eSliceType == P_SLICE ? 'P' : 'I'),
- eNalRefIdc,
- iSliceSize
- );
-#endif//SLICE_INFO_OUTPUT
+ WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DETAIL,
+ "@pSlice=%-6d sliceType:%c idc:%d size:%-6d", m_iSliceIdx,
+ (m_pCtx->eSliceType == P_SLICE ? 'P' : 'I'),
+ m_eNalRefIdc,
+ m_iSliceSize);
#if MT_DEBUG_BS_WR
m_pSliceBs->bSliceCodedFlag = true;
--- a/codec/encoder/core/src/wels_task_management.cpp
+++ b/codec/encoder/core/src/wels_task_management.cpp
@@ -41,6 +41,7 @@
#include <assert.h>
#include "typedefs.h"
+#include "utils.h"
#include "WelsLock.h"
#include "memory_align.h"
@@ -74,8 +75,8 @@
CWelsTaskManageBase::CWelsTaskManageBase()
: m_pEncCtx (NULL),
- m_iTaskNum (0),
m_pThreadPool (NULL),
+ m_iTaskNum (0),
m_iWaitTaskNum (0) {
m_cTaskList = new TASKLIST_TYPE();
WelsEventOpen (&m_hTaskEvent);
@@ -120,8 +121,9 @@
}
void CWelsTaskManageBase::DestroyTasks() {
- if (m_iTaskNum == 0)
+ if (m_iTaskNum == 0) {
return;
+ }
if (m_cTaskList->size() != m_iTaskNum) {
//printf("m_cTaskList %d %d\n", static_cast<int32_t>(m_cTaskList->size()), m_iTaskNum);
@@ -133,41 +135,47 @@
WELS_DELETE_OP (pTask);
m_cTaskList->pop_front();
}
+ //WelsLog (&m_pEncCtx->sLogCtx, WELS_LOG_INFO,
+ // "[MT] CWelsTaskManageParallel()DestroyTasks, cleaned %d tasks", m_iTaskNum);
+ //printf ("[MT] CWelsTaskManageBase() DestroyTasks, cleaned %d tasks\n", m_iTaskNum);
m_iTaskNum = 0;
}
-void CWelsTaskManageBase::InitFrame() {
+void CWelsTaskManageBase::OnTaskMinusOne() {
+ WelsCommon::CWelsAutoLock cAutoLock (m_cWaitTaskNumLock);
+ m_iWaitTaskNum --;
+ if (m_iWaitTaskNum <= 0) {
+ WelsEventSignal (&m_hTaskEvent);
+ }
+ //printf("OnTaskMinusOne m_iWaitTaskNum=%d\n", m_iWaitTaskNum);
}
-WelsErrorType CWelsTaskManageBase::ExecuteTasks() {
- m_iWaitTaskNum = static_cast<int32_t> (m_cTaskList->size());
- while (NULL != m_cTaskList->begin()) {
- m_pThreadPool->QueueTask (m_cTaskList->begin());
- m_cTaskList->pop_front();
- }
- WelsEventWait (&m_hTaskEvent);
-
+WelsErrorType CWelsTaskManageBase::OnTaskCancelled (WelsCommon::IWelsTask* pTask) {
+ OnTaskMinusOne();
return ENC_RETURN_SUCCESS;
}
WelsErrorType CWelsTaskManageBase::OnTaskExecuted (WelsCommon::IWelsTask* pTask) {
- WelsCommon::CWelsAutoLock cAutoLock (m_cWaitTaskNumLock);
- m_iWaitTaskNum --;
- //WELS_INFO_TRACE("Waiting Task Num: " << m_iWaitTaskNum);
- if (m_iWaitTaskNum == 0) {
- WelsEventSignal (&m_hTaskEvent);
- //WELS_INFO_TRACE("Tasks over ");
- }
-
+ OnTaskMinusOne();
return ENC_RETURN_SUCCESS;
}
-WelsErrorType CWelsTaskManageBase::OnTaskCancelled (WelsCommon::IWelsTask* pTask) {
- WelsCommon::CWelsAutoLock cAutoLock (m_cWaitTaskNumLock);
- m_iWaitTaskNum --;
- if (m_iWaitTaskNum == 0) {
- WelsEventSignal (&m_hTaskEvent);
+void CWelsTaskManageBase::InitFrame (const int32_t kiCurDid) {
+ m_iWaitTaskNum = m_pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceCfg.sSliceArgument.uiSliceNum;
+ //printf("InitFrame m_iWaitTaskNum=%d, slice_mode=%d\n", m_iWaitTaskNum, m_pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceCfg.uiSliceMode);
+ //TODO: update mbmap;
+}
+
+WelsErrorType CWelsTaskManageBase::ExecuteTasks() {
+ //printf("ExecuteTasks m_iWaitTaskNum=%d\n", m_iWaitTaskNum);
+ int32_t iCurrentTaskCount = m_iWaitTaskNum; //if directly use m_iWaitTaskNum in the loop make cause sync problem
+ int32_t iIdx = 0;
+ while (iIdx < iCurrentTaskCount) {
+ m_pThreadPool->QueueTask (m_cTaskList->GetIndexNode(iIdx));
+ iIdx ++;
}
+ WelsEventWait (&m_hTaskEvent);
+
return ENC_RETURN_SUCCESS;
}
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -3727,4 +3727,71 @@
#endif
}
+TEST_F (EncodeDecodeTestAPI, DiffSlicingInDlayer) {
+ int iSpatialLayerNum = 3;
+ int iWidth = WelsClip3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, (64 << 2), MAX_WIDTH);
+ int iHeight = WelsClip3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, (64 << 2), 2240);//TODO: use MAX_HEIGHT after the limit is removed
+ float fFrameRate = rand() + 0.5f;
+ int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
+ // prepare params
+ SEncParamExt sParam;
+ encoder_->GetDefaultParams (&sParam);
+ prepareParamDefault (iSpatialLayerNum, 1, iWidth, iHeight, fFrameRate, &sParam);
+ sParam.iMultipleThreadIdc = (rand()%4) + 1;
+ sParam.bSimulcastAVC = 1;
+ sParam.sSpatialLayers[0].iVideoWidth = (iWidth >> 2);
+ sParam.sSpatialLayers[0].iVideoHeight = (iHeight >> 2);
+ sParam.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_ROWMB_SLICE;
+
+ sParam.sSpatialLayers[1].iVideoWidth = (iWidth >> 1);
+ sParam.sSpatialLayers[1].iVideoHeight = (iHeight >> 1);
+ sParam.sSpatialLayers[1].sSliceCfg.uiSliceMode = SM_RASTER_SLICE;
+ sParam.sSpatialLayers[1].sSliceCfg.sSliceArgument.uiSliceMbNum[0] = 30;
+ sParam.sSpatialLayers[1].sSliceCfg.sSliceArgument.uiSliceMbNum[1] = 32;
+
+ sParam.sSpatialLayers[2].iVideoWidth = iWidth;
+ sParam.sSpatialLayers[2].iVideoHeight = iHeight;
+ sParam.sSpatialLayers[2].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
+ sParam.sSpatialLayers[2].sSliceCfg.sSliceArgument.uiSliceNum = 4;
+
+ int rv = encoder_->InitializeExt (&sParam);
+ ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;
+
+ unsigned char* pBsBuf[MAX_SPATIAL_LAYER_NUM];
+ ISVCDecoder* decoder[MAX_SPATIAL_LAYER_NUM];
+
+ int iIdx = 0;
+
+ //create decoder
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ pBsBuf[iIdx] = static_cast<unsigned char*> (malloc (iWidth * iHeight * 3 * sizeof (unsigned char) / 2));
+ EXPECT_TRUE (pBsBuf[iIdx] != NULL);
+
+ long rv = WelsCreateDecoder (&decoder[iIdx]);
+ ASSERT_EQ (0, rv);
+ EXPECT_TRUE (decoder[iIdx] != NULL);
+
+ SDecodingParam decParam;
+ memset (&decParam, 0, sizeof (SDecodingParam));
+ decParam.eOutputColorFormat = videoFormatI420;
+ decParam.uiTargetDqLayer = UCHAR_MAX;
+ decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
+ decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+ rv = decoder[iIdx]->Initialize (&decParam);
+ ASSERT_EQ (0, rv);
+ }
+
+ TestOneSimulcastAVC (&sParam, decoder, pBsBuf, iSpatialLayerNum, iEncFrameNum, 0);
+
+ for (iIdx = 0; iIdx < iSpatialLayerNum; iIdx++) {
+ free (pBsBuf[iIdx]);
+
+ if (decoder[iIdx] != NULL) {
+ decoder[iIdx]->Uninitialize();
+ WelsDestroyDecoder (decoder[iIdx]);
+ }
+
+ }
+}
--- a/test/build/win32/codec_ut/codec_unittest.vcproj
+++ b/test/build/win32/codec_ut/codec_unittest.vcproj
@@ -866,6 +866,10 @@
/>
</FileConfiguration>
</File>
+ <File
+ RelativePath="..\..\..\common\WelsThreadPoolTest.cpp"
+ >
+ </File>
</Filter>
</Files>
<Globals>
--- a/test/common/CWelsCircleQueue.cpp
+++ b/test/common/CWelsCircleQueue.cpp
@@ -194,3 +194,50 @@
}
#endif
+
+TEST (CWelsCircleQueue, CWelsCircleQueueReadWithIdx) {
+ CWelsCircleQueue<int32_t> cThreadQueue;
+ const int kiIncreaseNum = (rand() % 1000) + 1;
+ const int kiDecreaseNum = rand() % kiIncreaseNum;
+
+ int32_t* pInput = static_cast<int32_t*> (malloc (kiIncreaseNum * 10 * sizeof (int32_t)));
+ if (!pInput) {
+ return;
+ }
+ for (int32_t i = 0; i < kiIncreaseNum * 10; i++) {
+ pInput[i] = i;
+ }
+
+ for (int j = 0; j < 10; j++) {
+ const int iBias = j * (kiIncreaseNum - kiDecreaseNum);
+ for (int i = 0; i < kiIncreaseNum; i++) {
+ cThreadQueue.push_back (&pInput[i + kiIncreaseNum * j]);
+ }
+ EXPECT_TRUE (kiIncreaseNum + iBias == cThreadQueue.size()) << "after push size=" <<
+ cThreadQueue.size() ;
+
+ EXPECT_TRUE ((kiDecreaseNum * j) == * (cThreadQueue.begin()));
+
+ for (int i = 0; i < kiIncreaseNum; i++) {
+ EXPECT_TRUE ((i + kiIncreaseNum * j) == * (cThreadQueue.GetIndexNode (i + iBias)));
+ }
+ for (int i = 0; i < cThreadQueue.size(); i++) {
+ EXPECT_TRUE ((i + kiDecreaseNum * j) == * (cThreadQueue.GetIndexNode (i)));
+ }
+
+ for (int i = kiDecreaseNum; i > 0; i--) {
+ cThreadQueue.pop_front();
+ }
+ EXPECT_TRUE ((j + 1) * (kiIncreaseNum - kiDecreaseNum) == cThreadQueue.size()) << "after pop size=" <<
+ cThreadQueue.size() ;
+
+ EXPECT_TRUE ((kiDecreaseNum * (j + 1)) == * (cThreadQueue.begin()));
+ }
+
+ //clean-up
+ while (NULL != cThreadQueue.begin()) {
+ cThreadQueue.pop_front();
+ }
+ EXPECT_TRUE (0 == cThreadQueue.size());
+ free (pInput);
+}
--- /dev/null
+++ b/test/common/WelsThreadPoolTest.cpp
@@ -1,0 +1,54 @@
+#include <gtest/gtest.h>
+#include <string.h>
+#include <string>
+#include <list>
+#include <map>
+
+#include "typedefs.h"
+#include "WelsThreadLib.h"
+#include "WelsThreadPool.h"
+#include "WelsTask.h"
+#include "WelsThreadPoolTest.h"
+
+#define TEST_TASK_NUM 20
+
+class CSimpleTask : public IWelsTask {
+ public:
+ static uint32_t id;
+
+ CSimpleTask() {
+ m_uiID = id ++;
+ }
+
+ virtual ~CSimpleTask() {
+ }
+
+ virtual int32_t Execute() {
+ WelsSleep (300 - m_uiID);
+ //printf ("Task %d executing\n", m_uiID);
+ return cmResultSuccess;
+ }
+
+ private:
+ uint32_t m_uiID;
+};
+
+uint32_t CSimpleTask::id = 0;
+
+
+TEST (CThreadPoolTest, CThreadPoolTest) {
+ CSimpleTask tasks[TEST_TASK_NUM];
+ CThreadPoolTest cThreadPoolTest;
+ CWelsThreadPool cThreadPool (&cThreadPoolTest);
+
+ int32_t i;
+
+ for (i = 0; i < TEST_TASK_NUM; i++) {
+ cThreadPool.QueueTask (&tasks[i]);
+ }
+
+ while (cThreadPoolTest.GetTaskCount() < TEST_TASK_NUM) {
+ WelsSleep (1);
+ }
+}
+
--- /dev/null
+++ b/test/common/WelsThreadPoolTest.h
@@ -1,0 +1,39 @@
+#ifndef _WELS_THREAD_POOL_TEST_H_
+#define _WELS_THREAD_POOL_TEST_H_
+
+#include "WelsThreadPool.h"
+
+using namespace WelsCommon;
+
+class CThreadPoolTest : public IWelsThreadPoolSink {
+ public:
+ CThreadPoolTest() {
+ m_iTaskCount = 0;
+ }
+
+ ~CThreadPoolTest() {}
+
+ virtual int32_t OnTaskExecuted (IWelsTask* pTask) {
+ m_iTaskCount ++;
+ //printf("Task execute over count is %d\n", m_iTaskCount);
+ return cmResultSuccess;
+ }
+
+ virtual int32_t OnTaskCancelled (IWelsTask* pTask) {
+ m_iTaskCount ++;
+ //printf("Task execute cancelled count is %d\n", m_iTaskCount);
+ return cmResultSuccess;
+ }
+
+ int32_t GetTaskCount() {
+ return m_iTaskCount;
+ }
+
+ private:
+ int32_t m_iTaskCount;
+};
+
+
+
+#endif
+
--- a/test/common/targets.mk
+++ b/test/common/targets.mk
@@ -1,8 +1,9 @@
COMMON_UNITTEST_SRCDIR=test/common
COMMON_UNITTEST_CPP_SRCS=\
- $(COMMON_UNITTEST_SRCDIR)/ExpandPicture.cpp\
$(COMMON_UNITTEST_SRCDIR)/CWelsCircleQueue.cpp\
$(COMMON_UNITTEST_SRCDIR)/CWelsListTest.cpp\
+ $(COMMON_UNITTEST_SRCDIR)/ExpandPicture.cpp\
+ $(COMMON_UNITTEST_SRCDIR)/WelsThreadPoolTest.cpp\
COMMON_UNITTEST_OBJS += $(COMMON_UNITTEST_CPP_SRCS:.cpp=.$(OBJ))