ref: 819f6f5d93b5c1bd4b08c0b1769f8dc4805bb1fd
parent: 490098915ff6d50ebda1e4296aebac658dbb0b8a
author: Sijia Chen <sijchen@cisco.com>
date: Mon Oct 19 18:48:28 EDT 2015
[Encoder] add encoder tasks and task-management class https://rbcommons.com/s/OpenH264/r/1334/
--- a/codec/build/iOS/enc/welsenc/welsenc.xcodeproj/project.pbxproj
+++ b/codec/build/iOS/enc/welsenc/welsenc.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
+ 0DD32A961B4A478B009181A1 /* wels_task_base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A951B4A478B009181A1 /* wels_task_base.cpp */; };
+ 0DD32A991B4A4997009181A1 /* wels_task_management.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A981B4A4997009181A1 /* wels_task_management.cpp */; };
+ 0DD32A9C1B4A4E8F009181A1 /* wels_task_encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A9B1B4A4E8F009181A1 /* wels_task_encoder.cpp */; };
4C23BC60195A77E0003B81FC /* intra_pred_sad_3_opt_aarch64_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4C23BC5F195A77E0003B81FC /* intra_pred_sad_3_opt_aarch64_neon.S */; };
4C34066D18C57D0400DFA14A /* intra_pred_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4C34066618C57D0400DFA14A /* intra_pred_neon.S */; };
4C34066E18C57D0400DFA14A /* intra_pred_sad_3_opt_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4C34066718C57D0400DFA14A /* intra_pred_sad_3_opt_neon.S */; };
@@ -66,6 +69,12 @@
/* Begin PBXFileReference section */
04FE0684196FD9370004D7CE /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = ../../../common/inc/version.h; sourceTree = "<group>"; };
+ 0DD32A951B4A478B009181A1 /* wels_task_base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wels_task_base.cpp; sourceTree = "<group>"; };
+ 0DD32A971B4A47D0009181A1 /* wels_task_base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wels_task_base.h; sourceTree = "<group>"; };
+ 0DD32A981B4A4997009181A1 /* wels_task_management.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wels_task_management.cpp; sourceTree = "<group>"; };
+ 0DD32A9A1B4A49AC009181A1 /* wels_task_management.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wels_task_management.h; sourceTree = "<group>"; };
+ 0DD32A9B1B4A4E8F009181A1 /* wels_task_encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wels_task_encoder.cpp; sourceTree = "<group>"; };
+ 0DD32A9D1B4A4E9C009181A1 /* wels_task_encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wels_task_encoder.h; sourceTree = "<group>"; };
4C23BC5F195A77E0003B81FC /* intra_pred_sad_3_opt_aarch64_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = intra_pred_sad_3_opt_aarch64_neon.S; path = arm64/intra_pred_sad_3_opt_aarch64_neon.S; sourceTree = "<group>"; };
4C34066618C57D0400DFA14A /* intra_pred_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = intra_pred_neon.S; sourceTree = "<group>"; };
4C34066718C57D0400DFA14A /* intra_pred_sad_3_opt_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = intra_pred_sad_3_opt_neon.S; sourceTree = "<group>"; };
@@ -296,6 +305,9 @@
4CE446D918BC605C0017DF25 /* wels_const.h */,
4CE446DA18BC605C0017DF25 /* wels_func_ptr_def.h */,
4CE446DB18BC605C0017DF25 /* wels_preprocess.h */,
+ 0DD32A971B4A47D0009181A1 /* wels_task_base.h */,
+ 0DD32A9D1B4A4E9C009181A1 /* wels_task_encoder.h */,
+ 0DD32A9A1B4A49AC009181A1 /* wels_task_management.h */,
);
path = inc;
sourceTree = "<group>";
@@ -331,6 +343,9 @@
4CE446F718BC605C0017DF25 /* svc_motion_estimate.cpp */,
4CE446F818BC605C0017DF25 /* svc_set_mb_syn_cavlc.cpp */,
4CE446FA18BC605C0017DF25 /* wels_preprocess.cpp */,
+ 0DD32A951B4A478B009181A1 /* wels_task_base.cpp */,
+ 0DD32A9B1B4A4E8F009181A1 /* wels_task_encoder.cpp */,
+ 0DD32A981B4A4997009181A1 /* wels_task_management.cpp */,
);
path = src;
sourceTree = "<group>";
@@ -422,6 +437,7 @@
4CE4471018BC605C0017DF25 /* decode_mb_aux.cpp in Sources */,
4CE4472018BC605C0017DF25 /* sample.cpp in Sources */,
6CA38DA31991CACE003EAAE0 /* svc_motion_estimation.S in Sources */,
+ 0DD32A9C1B4A4E8F009181A1 /* wels_task_encoder.cpp in Sources */,
4CE4471318BC605C0017DF25 /* encoder_data_tables.cpp in Sources */,
4C34067118C57D0400DFA14A /* pixel_neon.S in Sources */,
9AED665019469FC1009A3567 /* welsCodecTrace.cpp in Sources */,
@@ -454,8 +470,10 @@
4CE4471618BC605C0017DF25 /* get_intra_predictor.cpp in Sources */,
4CE4472E18BC605C0017DF25 /* welsEncoderExt.cpp in Sources */,
6CA38DA51991D31A003EAAE0 /* svc_motion_estimation_aarch64_neon.S in Sources */,
+ 0DD32A991B4A4997009181A1 /* wels_task_management.cpp in Sources */,
4CE4471418BC605C0017DF25 /* encoder_ext.cpp in Sources */,
4C34067218C57D0400DFA14A /* reconstruct_neon.S in Sources */,
+ 0DD32A961B4A478B009181A1 /* wels_task_base.cpp in Sources */,
F7E9994919EBD1F8009B1021 /* set_mb_syn_cabac.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
--- a/codec/build/win32/enc/WelsEncCore.vcproj
+++ b/codec/build/win32/enc/WelsEncCore.vcproj
@@ -474,6 +474,18 @@
>
</File>
<File
+ RelativePath="..\..\..\encoder\core\src\wels_task_base.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\encoder\core\src\wels_task_encoder.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\encoder\core\src\wels_task_management.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\common\src\WelsTaskThread.cpp"
>
</File>
--- a/codec/common/inc/WelsTask.h
+++ b/codec/common/inc/WelsTask.h
@@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*
- * \file WelsThreadPool.h
+ * \file WelsTask.h
*
* \brief Interfaces introduced in thread pool
*
@@ -49,7 +49,7 @@
public:
virtual ~IWelsTask() { }
- virtual CM_RETURN Execute() = 0;
+ virtual int Execute() = 0;
};
}
--- a/codec/common/inc/memory_align.h
+++ b/codec/common/inc/memory_align.h
@@ -104,6 +104,12 @@
#define WELS_SAFE_FREE(pPtr, pTag) if (pPtr) { WelsFree(pPtr, pTag); pPtr = NULL; }
+#define WELS_NEW_OP(object, type) \
+ (type*)(new object);
+
+#define WELS_DELETE_OP(p) \
+ delete p; \
+ p = NULL;
}
--- a/codec/common/src/WelsThreadLib.cpp
+++ b/codec/common/src/WelsThreadLib.cpp
@@ -302,7 +302,7 @@
if (p_event == NULL) {
return WELS_THREAD_ERROR_GENERAL;
}
- char strSuffix[16] = { 0 };
+ char strSuffix[100] = { 0 };
if (NULL == event_name) {
sprintf (strSuffix, "WelsSem%ld_p%ld", (intptr_t)p_event, (long) (getpid()));
event_name = &strSuffix[0];
@@ -341,6 +341,10 @@
#endif
}
+void WelsSleep (uint32_t dwMilliSecond) {
+ usleep (dwMilliSecond * 1000);
+}
+
WELS_THREAD_ERROR_CODE WelsEventSignal (WELS_EVENT* event) {
WELS_THREAD_ERROR_CODE err = 0;
// int32_t val = 0;
@@ -354,10 +358,6 @@
WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
return sem_wait (*event); // blocking until signaled
-}
-
-void WelsSleep (uint32_t dwMilliSecond) {
- usleep (dwMilliSecond * 1000);
}
WELS_THREAD_ERROR_CODE WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -60,6 +60,7 @@
namespace WelsEnc {
+class IWelsTaskManage;
/*
* reference list for each quality layer in SVC
*/
@@ -133,6 +134,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
// SSlice context
SSliceCtx* pSliceCtxList;// slice context table for each dependency quality layer
--- a/codec/encoder/core/inc/mt_defs.h
+++ b/codec/encoder/core/inc/mt_defs.h
@@ -88,6 +88,8 @@
#endif//MT_DEBUG
uint8_t* pThreadBsBuffer[MAX_THREADS_NUM]; //actual memory for slice buffer
+bool bThreadBsBufferUsage[MAX_THREADS_NUM];
+WELS_MUTEX mutexThreadBsBufferUsage;
} SSliceThreading;
#endif//MULTIPLE_THREADING_DEFINES_H__
--- a/codec/encoder/core/inc/slice_multi_threading.h
+++ b/codec/encoder/core/inc/slice_multi_threading.h
@@ -99,6 +99,11 @@
#endif//defined(MT_DEBUG)
void SetOneSliceBsBufferUnderMultithread(sWelsEncCtx* pCtx, const int32_t kiThreadIdx, const int32_t iSliceIdx);
+int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pDst,
+ int32_t* pNalLen,
+ int32_t iTotalLeftLength,
+ const int32_t iSliceIdx,
+ int32_t& iSliceSize);
}
#endif//SVC_SLICE_MULTIPLE_THREADING_H__
--- a/codec/encoder/core/inc/wels_common_basis.h
+++ b/codec/encoder/core/inc/wels_common_basis.h
@@ -45,6 +45,7 @@
namespace WelsEnc {
+typedef int32_t WelsErrorType;
struct SMVUnitXY { // each 4 Bytes
int16_t iMvX;
--- /dev/null
+++ b/codec/encoder/core/inc/wels_task_base.h
@@ -1,0 +1,75 @@
+/*!
+ * \copy
+ * Copyright (c) 2009-2015, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file wels_task_base.h
+ *
+ * \brief interface for base task
+ *
+ * \date 5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+
+
+#ifndef _WELS_BASE_TASK_H_
+#define _WELS_BASE_TASK_H_
+
+#include "typedefs.h"
+#include "WelsTask.h"
+
+namespace WelsEnc {
+
+class CWelsBaseTask : public WelsCommon::IWelsTask {
+ public:
+ enum {
+ WELS_ENC_TASK_ENCODE_FIXED_SLICE = 0,
+ WELS_ENC_TASK_ENCODE_SLICE_LOADBALANCING = 1,
+ WELS_ENC_TASK_ENCODE_SLICE_SIZECONSTRAINED = 2,
+ };
+
+ CWelsBaseTask();
+ virtual ~CWelsBaseTask();
+
+ virtual uint32_t GetTaskType() const = 0;
+
+ private:
+
+};
+
+}
+
+
+#endif
+
+
+
+
--- /dev/null
+++ b/codec/encoder/core/inc/wels_task_encoder.h
@@ -1,0 +1,127 @@
+/*!
+ * \copy
+ * Copyright (c) 2009-2015, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file wels_task_encoder.h
+ *
+ * \brief interface for encoder tasks
+ *
+ * \date 07/06/2015 Created
+ *
+ *************************************************************************************
+ */
+
+#ifndef _WELS_ENCODER_TASK_H_
+#define _WELS_ENCODER_TASK_H_
+
+#include "wels_task_base.h"
+#include "encoder_context.h"
+
+namespace WelsEnc {
+
+extern int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer,
+ const int32_t iSliceIdx,
+ int32_t& iSliceSize);
+extern int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pSliceBsBuf, const int32_t iSliceIdx, int32_t& iSliceSize);
+
+class CWelsSliceEncodingTask : public CWelsBaseTask {
+ public:
+ CWelsSliceEncodingTask (sWelsEncCtx* pCtx, const int32_t iSliceIdx);
+ virtual ~CWelsSliceEncodingTask();
+
+ CWelsSliceEncodingTask* CreateSliceEncodingTask (sWelsEncCtx* pCtx, const int32_t iSliceIdx);
+ WelsErrorType SetBoundary (int32_t iStartMbIdx, int32_t iEndMbIdx);
+
+ virtual WelsErrorType Execute();
+ virtual WelsErrorType InitTask();
+ virtual void FinishTask();
+
+ virtual uint32_t GetTaskType() const {
+ return WELS_ENC_TASK_ENCODE_FIXED_SLICE;
+ }
+ protected:
+ int32_t QueryEmptyThread (bool* pThreadBsBufferUsage);
+
+ sWelsEncCtx* m_pCtx;
+ SSliceThreadPrivateData* m_pPrivateData;
+ SLayerBSInfo* m_pLbi;
+ int32_t m_iStartMbIdx;
+ int32_t m_iEndMbIdx;
+
+ EWelsNalUnitType m_eNalType;
+ EWelsNalRefIdc m_eNalRefIdc;
+ bool m_bNeedPrefix;
+ uint32_t m_uiDependencyId;
+
+ SSlice* m_pSlice;
+ SWelsSliceBs* m_pSliceBs;
+ int32_t m_iSliceIdx;
+ int32_t m_iSliceSize;
+ int32_t m_iThreadIdx;
+};
+
+class CWelsLoadBalancingSlicingEncodingTask : public CWelsSliceEncodingTask {
+ public:
+ CWelsLoadBalancingSlicingEncodingTask (sWelsEncCtx* pCtx, const int32_t iSliceIdx);
+ ~CWelsLoadBalancingSlicingEncodingTask();
+
+ virtual WelsErrorType InitTask();
+ virtual void FinishTask();
+
+ virtual uint32_t GetTaskType() const {
+ return WELS_ENC_TASK_ENCODE_SLICE_LOADBALANCING;
+ }
+ private:
+ int64_t m_iSliceStart;
+};
+
+/*
+class CWelsConstrainedSizeSlicingEncodingTask : public CWelsSliceEncodingTask {
+ public:
+ CWelsConstrainedSizeSlicingEncodingTask (sWelsEncCtx* pCtx);
+ ~CWelsConstrainedSizeSlicingEncodingTask();
+
+ virtual WelsErrorType Execute();
+
+ WelsErrorType InitTask ();
+ virtual void FinishTask();
+
+ virtual uint32_t GetTaskType() const {
+ return WELS_ENC_TASK_ENCODE_SLICE_SIZECONSTRAINED;
+ }
+ protected:
+
+};
+*/
+
+
+} //namespace
+#endif //header guard
+
--- /dev/null
+++ b/codec/encoder/core/inc/wels_task_management.h
@@ -1,0 +1,128 @@
+/*!
+ * \copy
+ * Copyright (c) 2009-2015, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file wels_task_management.h
+ *
+ * \brief interface for task management
+ *
+ * \date 5/14/2012 Created
+ *
+ *************************************************************************************
+ */
+
+#ifndef _WELS_ENCODER_TASK_MANAGE_H_
+#define _WELS_ENCODER_TASK_MANAGE_H_
+
+#include "wels_common_basis.h"
+#include "WelsLock.h"
+#include "WelsThreadPool.h"
+
+namespace WelsEnc {
+
+class CWelsBaseTask;
+
+class IWelsTaskManage {
+ public:
+ virtual ~IWelsTaskManage() { }
+
+ virtual WelsErrorType Init (sWelsEncCtx* pEncCtx) = 0;
+ virtual void Uninit() = 0;
+
+ virtual void InitFrame() {}
+ virtual WelsErrorType ExecuteTasks() = 0;
+
+ static IWelsTaskManage* CreateTaskManage (sWelsEncCtx* pCtx, bool bNeedLock);
+};
+
+
+class CWelsTaskManageBase : public IWelsTaskManage, public WelsCommon::IWelsThreadPoolSink {
+ public:
+ typedef CWelsCircleQueue<CWelsBaseTask> TASKLIST_TYPE;
+ //typedef std::pair<int, int> SLICE_BOUNDARY_PAIR;
+ //typedef CWelsCircleQueue<SLICE_BOUNDARY_PAIR> SLICE_PAIR_LIST;
+
+ CWelsTaskManageBase();
+ virtual ~ CWelsTaskManageBase();
+
+ virtual WelsErrorType Init (sWelsEncCtx* pEncCtx);
+ void Uninit();
+
+ virtual void InitFrame();
+ virtual WelsErrorType ExecuteTasks();
+
+ //IWelsThreadPoolSink
+ virtual WelsErrorType OnTaskExecuted (WelsCommon::IWelsTask* pTask);
+ virtual WelsErrorType OnTaskCancelled (WelsCommon::IWelsTask* pTask);
+
+ protected:
+ virtual WelsErrorType CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount);
+ void DestroyTasks();
+
+ protected:
+ sWelsEncCtx* m_pEncCtx;
+
+ TASKLIST_TYPE* m_cTaskList;
+ int32_t m_iTaskNum;
+
+ //SLICE_PAIR_LIST *m_cSliceList;
+
+ WelsCommon::CWelsThreadPool* m_pThreadPool;
+ int32_t m_iThreadNum;
+
+ int32_t m_iWaitTaskNum;
+ WELS_EVENT m_hTaskEvent;
+
+ WelsCommon::CWelsLock m_cWaitTaskNumLock;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN (CWelsTaskManageBase);
+};
+
+class CWelsTaskManageOne : public CWelsTaskManageBase {
+ public:
+ CWelsTaskManageOne();
+ virtual ~CWelsTaskManageOne();
+
+ WelsErrorType Init (sWelsEncCtx* pEncCtx);
+ virtual WelsErrorType ExecuteTasks();
+};
+
+class CWelsTaskManageParallel : public CWelsTaskManageBase {
+ public:
+ virtual WelsErrorType ExecuteTasks();
+
+ protected:
+ virtual WelsErrorType CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount);
+};
+
+} //namespace
+#endif //header guard
+
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -62,6 +62,7 @@
#include "cpu.h"
#include "measure_time.h"
+#include "wels_task_management.h"
#if defined(ENABLE_TRACE_MT)
#define MT_TRACE_LOG(x, ...) WelsLog(x, __VA_ARGS__)
@@ -443,6 +444,10 @@
iReturn = WelsMutexInit (&pSmt->mutexSliceNumUpdate);
WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), 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))
+
iReturn = WelsMutexInit (& (*ppCtx)->mutexEncoderError);
WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx))
@@ -496,6 +501,7 @@
WelsEventClose (&pSmt->pSliceCodedMasterEvent, ename);
WelsMutexDestroy (&pSmt->mutexSliceNumUpdate);
+ WelsMutexDestroy (&pSmt->mutexThreadBsBufferUsage);
WelsMutexDestroy (& ((*ppCtx)->mutexEncoderError));
if (pSmt->pThreadPEncCtx != NULL) {
@@ -509,6 +515,7 @@
pSmt->pThreadBsBuffer[i] = NULL;
}
}
+ memset(&pSmt->bThreadBsBufferUsage, 0, MAX_THREADS_NUM * sizeof(bool));
pSliceB = (*ppCtx)->pSliceBs;
iIdx = 0;
--- /dev/null
+++ b/codec/encoder/core/src/wels_task_base.cpp
@@ -1,0 +1,55 @@
+/*!
+ * \copy
+ * Copyright (c) 2009-2015, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file wels_task_base.cpp
+ *
+ * \brief function for base task
+ *
+ * \date 5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+#include "wels_task_base.h"
+
+namespace WelsEnc {
+
+CWelsBaseTask::CWelsBaseTask() {
+}
+
+CWelsBaseTask::~CWelsBaseTask() {
+}
+
+
+}
+
+
+
--- /dev/null
+++ b/codec/encoder/core/src/wels_task_encoder.cpp
@@ -1,0 +1,208 @@
+/*!
+ * \copy
+ * Copyright (c) 2009-2015, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file wels_task_encoder.h
+ *
+ * \brief interface for encoder tasks
+ *
+ * \date 07/06/2015 Created
+ *
+ *************************************************************************************
+ */
+
+#include <string.h>
+#include <assert.h>
+
+#include "typedefs.h"
+#include "utils.h"
+#include "measure_time.h"
+#include "WelsTask.h"
+
+#include "wels_task_base.h"
+#include "wels_task_encoder.h"
+
+#include "svc_enc_golomb.h"
+#include "svc_encode_slice.h"
+#include "slice_multi_threading.h"
+
+namespace WelsEnc {
+
+CWelsSliceEncodingTask::CWelsSliceEncodingTask (sWelsEncCtx* pCtx, const int32_t iSliceIdx) {
+ m_pCtx = pCtx;
+ m_iSliceIdx = iSliceIdx;
+}
+
+CWelsSliceEncodingTask::~CWelsSliceEncodingTask() {
+}
+
+WelsErrorType CWelsSliceEncodingTask::SetBoundary (int32_t iStartIdx, int32_t iEndIdx) {
+ m_iStartMbIdx = iStartIdx;
+ m_iEndMbIdx = iEndIdx;
+ return ENC_RETURN_SUCCESS;
+}
+
+int32_t CWelsSliceEncodingTask::QueryEmptyThread (bool* pThreadBsBufferUsage) {
+ for (int32_t k = 0; k < MAX_THREADS_NUM; k++) {
+ if (pThreadBsBufferUsage[k] == false) {
+ pThreadBsBufferUsage[k] = true;
+ return k;
+ }
+ }
+ return -1;
+}
+
+WelsErrorType CWelsSliceEncodingTask::InitTask() {
+ m_eNalType = m_pCtx->eNalType;
+ m_eNalRefIdc = m_pCtx->eNalPriority;
+ m_bNeedPrefix = m_pCtx->bNeedPrefixNalFlag;
+
+ WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
+ 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);
+ return ENC_RETURN_UNEXPECTED;
+ }
+ SetOneSliceBsBufferUnderMultithread (m_pCtx, m_iSliceIdx, m_iThreadIdx);
+
+ m_pSlice = &m_pCtx->pCurDqLayer->sLayerInfo.pSliceInLayer[m_iSliceIdx];
+ m_pSliceBs = &m_pCtx->pSliceBs[m_iSliceIdx];
+
+ m_pSliceBs->uiBsPos = 0;
+ m_pSliceBs->iNalIndex = 0;
+
+ assert ((void*) (&m_pSliceBs->sBsWrite) == (void*)m_pSlice->pSliceBsa);
+ InitBits (&m_pSliceBs->sBsWrite, m_pSliceBs->pBsBuffer, m_pSliceBs->uiSize);
+
+ return ENC_RETURN_SUCCESS;
+}
+void CWelsSliceEncodingTask::FinishTask() {
+ WelsMutexLock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
+ m_pCtx->pSliceThreading->bThreadBsBufferUsage[m_iThreadIdx] = false;
+ WelsMutexUnlock (&m_pCtx->pSliceThreading->mutexThreadBsBufferUsage);
+}
+
+WelsErrorType CWelsSliceEncodingTask::Execute() {
+ WelsThreadSetName ("OpenH264Enc_CWelsSliceEncodingTask_Execute");
+
+#if MT_DEBUG_BS_WR
+ m_pSliceBs->bSliceCodedFlag = false;
+#endif//MT_DEBUG_BS_WR
+
+ if (m_bNeedPrefix) {
+ if (m_eNalRefIdc != NRI_PRI_LOWEST) {
+ WelsLoadNalForSlice (m_pSliceBs, NAL_UNIT_PREFIX, m_eNalRefIdc);
+ WelsWriteSVCPrefixNal (&m_pSliceBs->sBsWrite, m_eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == m_eNalType));
+ WelsUnloadNalForSlice (m_pSliceBs);
+ } else { // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension
+ WelsLoadNalForSlice (m_pSliceBs, NAL_UNIT_PREFIX, m_eNalRefIdc);
+ // No need write any syntax of prefix NAL Unit RBSP here
+ WelsUnloadNalForSlice (m_pSliceBs);
+ }
+ }
+
+ WelsLoadNalForSlice (m_pSliceBs, m_eNalType, m_eNalRefIdc);
+ int32_t iReturn = WelsCodeOneSlice (m_pCtx, m_iSliceIdx, m_eNalType);
+ if (ENC_RETURN_SUCCESS != iReturn) {
+ return iReturn;
+ }
+ WelsUnloadNalForSlice (m_pSliceBs);
+
+ m_iSliceSize = 0;
+ int32_t iLeftBufferSize = (m_iSliceIdx > 0) ? (m_pSliceBs->uiSize - (int32_t) (m_pSliceBs->sBsWrite.pCurBuf -
+ m_pSliceBs->sBsWrite.pStartBuf)) : (m_pCtx->iFrameBsSize - m_pCtx->iPosBsBuffer);
+ iReturn = WriteSliceBs (m_pCtx, m_pSliceBs->pBs,
+ &m_pSliceBs->iNalLen[0],
+ iLeftBufferSize,
+ m_iSliceIdx, m_iSliceSize);
+ if (ENC_RETURN_SUCCESS != iReturn) {
+ return iReturn;
+ }
+ if (0 == m_iSliceIdx) {
+ m_pCtx->iPosBsBuffer += m_iSliceSize;
+ }
+
+ 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
+
+#if MT_DEBUG_BS_WR
+ m_pSliceBs->bSliceCodedFlag = true;
+#endif//MT_DEBUG_BS_WR
+
+ return ENC_RETURN_SUCCESS;
+}
+
+
+// CWelsLoadBalancingSlicingEncodingTask
+CWelsLoadBalancingSlicingEncodingTask::CWelsLoadBalancingSlicingEncodingTask (sWelsEncCtx* pCtx,
+ const int32_t iSliceIdx) :
+ CWelsSliceEncodingTask (pCtx, iSliceIdx) {
+}
+
+CWelsLoadBalancingSlicingEncodingTask::~CWelsLoadBalancingSlicingEncodingTask() {
+}
+
+WelsErrorType CWelsLoadBalancingSlicingEncodingTask::InitTask() {
+ WelsErrorType iReturn = CWelsSliceEncodingTask::InitTask();
+ if (ENC_RETURN_SUCCESS != iReturn) {
+ return iReturn;
+ }
+
+ m_iSliceStart = WelsTime();
+ return ENC_RETURN_SUCCESS;
+}
+
+void CWelsLoadBalancingSlicingEncodingTask::FinishTask() {
+ CWelsSliceEncodingTask::FinishTask();
+
+ m_pCtx->pSliceThreading->pSliceConsumeTime[m_uiDependencyId][m_iSliceIdx] = (uint32_t) (WelsTime() - m_iSliceStart);
+ WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
+ "[MT] CodingSliceThreadProc(), coding_idx %d, um_iSliceIdx %d, pSliceConsumeTime %d, iSliceSize %d, pFirstMbInSlice %d, count_num_mb_in_slice %d",
+ m_pCtx->iCodingIndex,
+ m_iSliceIdx,
+ m_pCtx->pSliceThreading->pSliceConsumeTime[m_uiDependencyId][m_iSliceIdx],
+ m_iSliceSize,
+ m_pCtx->pCurDqLayer->pSliceEncCtx->pFirstMbInSlice[m_iSliceIdx],
+ m_pCtx->pCurDqLayer->pSliceEncCtx->pCountMbNumInSlice[m_iSliceIdx]);
+}
+
+}
+
+
--- /dev/null
+++ b/codec/encoder/core/src/wels_task_management.cpp
@@ -1,0 +1,213 @@
+/*!
+ * \copy
+ * Copyright (c) 2009-2015, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file wels_task_management.cpp
+ *
+ * \brief function for task management
+ *
+ * \date 5/14/2012 Created
+ *
+ *************************************************************************************
+ */
+#include <string.h>
+#include <assert.h>
+
+#include "typedefs.h"
+#include "WelsLock.h"
+#include "memory_align.h"
+
+#include "wels_common_basis.h"
+#include "encoder_context.h"
+#include "wels_task_base.h"
+#include "wels_task_encoder.h"
+#include "wels_task_management.h"
+
+namespace WelsEnc {
+
+
+
+IWelsTaskManage* IWelsTaskManage::CreateTaskManage (sWelsEncCtx* pCtx, bool bNeedLock) {
+ if (NULL == pCtx) {
+ return NULL;
+ }
+ IWelsTaskManage* pTaskManage;
+ if (bNeedLock) {
+ pTaskManage = WELS_NEW_OP (CWelsTaskManageParallel(), CWelsTaskManageParallel);
+ } else {
+ pTaskManage = WELS_NEW_OP (CWelsTaskManageBase(), CWelsTaskManageBase);
+ }
+
+ if (pTaskManage) {
+ pTaskManage->Init (pCtx);
+ }
+ return pTaskManage;
+}
+
+
+CWelsTaskManageBase::CWelsTaskManageBase()
+ : m_pEncCtx (NULL),
+ m_iTaskNum (0),
+ m_pThreadPool (NULL),
+ m_iWaitTaskNum (0) {
+ m_cTaskList = new TASKLIST_TYPE();
+ WelsEventOpen (&m_hTaskEvent);
+}
+
+CWelsTaskManageBase::~CWelsTaskManageBase() {
+ //printf("~CWelsTaskManageBase\n");
+ Uninit();
+}
+
+WelsErrorType CWelsTaskManageBase::Init (sWelsEncCtx* pEncCtx) {
+ m_pEncCtx = pEncCtx;
+
+ m_iThreadNum = m_pEncCtx->pSvcParam->iMultipleThreadIdc;
+ m_pThreadPool = WELS_NEW_OP (WelsCommon::CWelsThreadPool (this, m_iThreadNum),
+ WelsCommon::CWelsThreadPool);
+ WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)
+ //printf("CWelsTaskManageBase Init m_iThreadNum %d pEncCtx->iMaxSliceCount=%d\n", m_iThreadNum, pEncCtx->iMaxSliceCount);
+ return CreateTasks (pEncCtx, pEncCtx->iMaxSliceCount);
+}
+
+void CWelsTaskManageBase::Uninit() {
+ DestroyTasks();
+ WELS_DELETE_OP (m_pThreadPool);
+
+ delete m_cTaskList;
+ WelsEventClose (&m_hTaskEvent);
+}
+
+WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount) {
+ CWelsBaseTask* pTask = NULL;
+
+ for (int idx = 0; idx < kiTaskCount; idx++) {
+ pTask = WELS_NEW_OP (CWelsSliceEncodingTask (pEncCtx, idx), CWelsSliceEncodingTask);
+ WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
+ m_cTaskList->push_back (pTask);
+ }
+ m_iTaskNum = kiTaskCount;
+
+ //printf("CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
+ return ENC_RETURN_SUCCESS;
+}
+
+void CWelsTaskManageBase::DestroyTasks() {
+ 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);
+ //WELS_ERROR_TRACE ("CWelsTaskManage::DestroyTasks: Incorrect task numbers");
+ }
+
+ while (NULL != m_cTaskList->begin()) {
+ CWelsBaseTask* pTask = m_cTaskList->begin();
+ WELS_DELETE_OP (pTask);
+ m_cTaskList->pop_front();
+ }
+ m_iTaskNum = 0;
+}
+
+void CWelsTaskManageBase::InitFrame() {
+}
+
+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);
+
+ 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 ");
+ }
+
+ return ENC_RETURN_SUCCESS;
+}
+
+WelsErrorType CWelsTaskManageBase::OnTaskCancelled (WelsCommon::IWelsTask* pTask) {
+ WelsCommon::CWelsAutoLock cAutoLock (m_cWaitTaskNumLock);
+ m_iWaitTaskNum --;
+ if (m_iWaitTaskNum == 0) {
+ WelsEventSignal (&m_hTaskEvent);
+ }
+ return ENC_RETURN_SUCCESS;
+}
+
+WelsErrorType CWelsTaskManageOne::Init (sWelsEncCtx* pEncCtx) {
+ Uninit();
+ m_pEncCtx = pEncCtx;
+
+ return CreateTasks (pEncCtx, pEncCtx->iMaxSliceCount);
+}
+
+WelsErrorType CWelsTaskManageOne::ExecuteTasks() {
+ while (NULL != m_cTaskList->begin()) {
+ (m_cTaskList->begin())->Execute();
+ m_cTaskList->pop_front();
+ }
+ return ENC_RETURN_SUCCESS;
+}
+
+//TODO: at present there is no diff betweenCWelsTaskManageParallel and CWelsTaskManageBase, to finish later
+WelsErrorType CWelsTaskManageParallel::ExecuteTasks() {
+ WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)
+
+ // need lock here?
+ 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);
+
+ return ENC_RETURN_SUCCESS;
+}
+
+WelsErrorType CWelsTaskManageParallel::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount) {
+ return ENC_RETURN_SUCCESS;
+}
+
+}
+
+
+
+
--- a/codec/encoder/targets.mk
+++ b/codec/encoder/targets.mk
@@ -27,6 +27,9 @@
$(ENCODER_SRCDIR)/core/src/svc_set_mb_syn_cabac.cpp\
$(ENCODER_SRCDIR)/core/src/svc_set_mb_syn_cavlc.cpp\
$(ENCODER_SRCDIR)/core/src/wels_preprocess.cpp\
+ $(ENCODER_SRCDIR)/core/src/wels_task_base.cpp\
+ $(ENCODER_SRCDIR)/core/src/wels_task_encoder.cpp\
+ $(ENCODER_SRCDIR)/core/src/wels_task_management.cpp\
$(ENCODER_SRCDIR)/plus/src/welsEncoderExt.cpp\
ENCODER_OBJS += $(ENCODER_CPP_SRCS:.cpp=.$(OBJ))
--- /dev/null
+++ b/test/encoder/EncUT_EncoderTaskManagement.cpp
@@ -1,0 +1,34 @@
+#include <gtest/gtest.h>
+
+#include "utils/DataGenerator.h"
+#include "encoder_context.h"
+#include "wels_task_management.h"
+
+using namespace WelsEnc;
+
+
+TEST (EncoderTaskManagement, CWelsTaskManageBase) {
+ sWelsEncCtx sCtx;
+ SWelsSvcCodingParam sWelsSvcCodingParam;
+
+ sCtx.pSvcParam = &sWelsSvcCodingParam;
+ sWelsSvcCodingParam.iMultipleThreadIdc = 4;
+ sCtx.iMaxSliceCount = 35;
+ IWelsTaskManage* pTaskManage = IWelsTaskManage::CreateTaskManage (&sCtx, false);
+ ASSERT_TRUE (NULL != pTaskManage);
+
+ delete pTaskManage;
+}
+
+TEST (EncoderTaskManagement, CWelsTaskManageParallel) {
+ sWelsEncCtx sCtx;
+ SWelsSvcCodingParam sWelsSvcCodingParam;
+
+ sCtx.pSvcParam = &sWelsSvcCodingParam;
+ sWelsSvcCodingParam.iMultipleThreadIdc = 4;
+ sCtx.iMaxSliceCount = 35;
+ IWelsTaskManage* pTaskManage = IWelsTaskManage::CreateTaskManage (&sCtx, true);
+ ASSERT_TRUE (NULL != pTaskManage);
+
+ delete pTaskManage;
+}
\ No newline at end of file
--- a/test/encoder/targets.mk
+++ b/test/encoder/targets.mk
@@ -4,6 +4,7 @@
$(ENCODER_UNITTEST_SRCDIR)/EncUT_EncoderExt.cpp\
$(ENCODER_UNITTEST_SRCDIR)/EncUT_EncoderMb.cpp\
$(ENCODER_UNITTEST_SRCDIR)/EncUT_EncoderMbAux.cpp\
+ $(ENCODER_UNITTEST_SRCDIR)/EncUT_EncoderTaskManagement.cpp\
$(ENCODER_UNITTEST_SRCDIR)/EncUT_ExpGolomb.cpp\
$(ENCODER_UNITTEST_SRCDIR)/EncUT_GetIntraPredictor.cpp\
$(ENCODER_UNITTEST_SRCDIR)/EncUT_InterfaceTest.cpp\