• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2  * \copy
3  *     Copyright (c)  2009-2015, Cisco Systems
4  *     All rights reserved.
5  *
6  *     Redistribution and use in source and binary forms, with or without
7  *     modification, are permitted provided that the following conditions
8  *     are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *
13  *        * Redistributions in binary form must reproduce the above copyright
14  *          notice, this list of conditions and the following disclaimer in
15  *          the documentation and/or other materials provided with the
16  *          distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *     POSSIBILITY OF SUCH DAMAGE.
30  *
31  *
32  * \file    wels_task_management.cpp
33  *
34  * \brief   function for task management
35  *
36  * \date    5/14/2012 Created
37  *
38  *************************************************************************************
39  */
40 #include <string.h>
41 #include <assert.h>
42 
43 #include "typedefs.h"
44 #include "utils.h"
45 #include "WelsLock.h"
46 #include "memory_align.h"
47 
48 #include "wels_common_basis.h"
49 #include "encoder_context.h"
50 #include "wels_task_base.h"
51 #include "wels_task_encoder.h"
52 #include "wels_task_management.h"
53 
54 namespace WelsEnc {
55 
56 
57 
CreateTaskManage(sWelsEncCtx * pCtx,const int32_t iSpatialLayer,const bool bNeedLock)58 IWelsTaskManage*   IWelsTaskManage::CreateTaskManage (sWelsEncCtx* pCtx, const int32_t iSpatialLayer,
59     const bool bNeedLock) {
60   if (NULL == pCtx) {
61     return NULL;
62   }
63 
64   IWelsTaskManage* pTaskManage;
65   pTaskManage = WELS_NEW_OP (CWelsTaskManageBase(), CWelsTaskManageBase);
66   WELS_VERIFY_RETURN_IF (NULL, NULL == pTaskManage)
67 
68   if (ENC_RETURN_SUCCESS != pTaskManage->Init (pCtx)) {
69     pTaskManage->Uninit();
70     WELS_DELETE_OP (pTaskManage);
71   }
72   return pTaskManage;
73 }
74 
75 
CWelsTaskManageBase()76 CWelsTaskManageBase::CWelsTaskManageBase()
77   : m_pEncCtx (NULL),
78     m_pThreadPool (NULL),
79     m_iWaitTaskNum (0) {
80 
81   for (int32_t iDid = 0; iDid < MAX_DEPENDENCY_LAYER; iDid++) {
82     m_iTaskNum[iDid] = 0;
83     m_cEncodingTaskList[iDid] = new TASKLIST_TYPE();
84     m_cPreEncodingTaskList[iDid] = new TASKLIST_TYPE();
85   }
86 
87   WelsEventOpen (&m_hTaskEvent);
88   WelsMutexInit (&m_hEventMutex);
89 }
90 
~CWelsTaskManageBase()91 CWelsTaskManageBase::~CWelsTaskManageBase() {
92   //fprintf(stdout, "~CWelsTaskManageBase\n");
93   Uninit();
94 }
95 
Init(sWelsEncCtx * pEncCtx)96 WelsErrorType CWelsTaskManageBase::Init (sWelsEncCtx* pEncCtx) {
97   m_pEncCtx = pEncCtx;
98   m_iThreadNum = m_pEncCtx->pSvcParam->iMultipleThreadIdc;
99 
100   int32_t iReturn = ENC_RETURN_SUCCESS;
101   //fprintf(stdout, "m_pThreadPool = &(CWelsThreadPool::GetInstance, this=%x\n", this);
102   iReturn = CWelsThreadPool::SetThreadNum (m_iThreadNum);
103   m_pThreadPool = (CWelsThreadPool::AddReference());
104   if ((iReturn != ENC_RETURN_SUCCESS) && pEncCtx) {
105     int32_t current_thread_num = m_pThreadPool->GetThreadNum();
106     if (m_iThreadNum != current_thread_num) {
107       WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_WARNING,
108                "Set Thread Num to %d did not succeed, current thread num in use: %d",
109                m_iThreadNum, current_thread_num);
110     }
111   }
112   WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)
113   //fprintf(stdout, "m_pThreadPool = &(CWelsThreadPool::GetInstance3\n");
114 
115   iReturn = ENC_RETURN_SUCCESS;
116   for (int32_t iDid = 0; iDid < MAX_DEPENDENCY_LAYER; iDid++) {
117     m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_ENCODING][iDid] = m_cEncodingTaskList[iDid];
118     m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_UPDATEMBMAP][iDid] = m_cPreEncodingTaskList[iDid];
119     iReturn |= CreateTasks (pEncCtx, iDid);
120   }
121 
122   //fprintf(stdout, "CWelsTaskManageBase Init m_iThreadNum %d m_iCurrentTaskNum %d pEncCtx->iMaxSliceCount %d\n", m_iThreadNum, m_iCurrentTaskNum, pEncCtx->iMaxSliceCount);
123   return iReturn;
124 }
125 
Uninit()126 void   CWelsTaskManageBase::Uninit() {
127   DestroyTasks();
128   //fprintf(stdout, "m_pThreadPool = m_pThreadPool->RemoveInstance\n");
129   if (m_pThreadPool)
130     m_pThreadPool->RemoveInstance();
131   //WELS_DELETE_OP (m_pThreadPool);
132 
133   //fprintf(stdout, "m_pThreadPool = m_pThreadPool->RemoveInstance2\n");
134 
135   for (int32_t iDid = 0; iDid < MAX_DEPENDENCY_LAYER; iDid++) {
136     WELS_DELETE_OP (m_cEncodingTaskList[iDid]);
137     WELS_DELETE_OP (m_cPreEncodingTaskList[iDid]);
138   }
139   WelsEventClose (&m_hTaskEvent);
140   WelsMutexDestroy (&m_hEventMutex);
141 }
142 
CreateTasks(sWelsEncCtx * pEncCtx,const int32_t kiCurDid)143 WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiCurDid) {
144   CWelsBaseTask* pTask = NULL;
145   int32_t kiTaskCount;
146   uint32_t uiSliceMode = pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceArgument.uiSliceMode;
147 
148   if (uiSliceMode != SM_SIZELIMITED_SLICE) {
149     kiTaskCount = m_iTaskNum[kiCurDid] = pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceArgument.uiSliceNum;
150   } else {
151     kiTaskCount = m_iTaskNum[kiCurDid] = pEncCtx->iActiveThreadsNum;
152   }
153 
154   for (int idx = 0; idx < kiTaskCount; idx++) {
155     pTask = WELS_NEW_OP (CWelsUpdateMbMapTask (this, pEncCtx, idx), CWelsUpdateMbMapTask);
156     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
157     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, true != m_cPreEncodingTaskList[kiCurDid]->push_back (pTask));
158   }
159 
160   for (int idx = 0; idx < kiTaskCount; idx++) {
161     if (uiSliceMode == SM_SIZELIMITED_SLICE) {
162       pTask = WELS_NEW_OP (CWelsConstrainedSizeSlicingEncodingTask (this, pEncCtx, idx),
163                            CWelsConstrainedSizeSlicingEncodingTask);
164     } else {
165       if (pEncCtx->pSvcParam->bUseLoadBalancing) {
166         pTask = WELS_NEW_OP (CWelsLoadBalancingSlicingEncodingTask (this, pEncCtx, idx), CWelsLoadBalancingSlicingEncodingTask);
167       } else {
168         pTask = WELS_NEW_OP (CWelsSliceEncodingTask (this, pEncCtx, idx), CWelsSliceEncodingTask);
169       }
170     }
171     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
172     WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, true != m_cEncodingTaskList[kiCurDid]->push_back (pTask));
173   }
174 
175   //fprintf(stdout, "CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
176   return ENC_RETURN_SUCCESS;
177 }
178 
DestroyTaskList(TASKLIST_TYPE * pTargetTaskList)179 void CWelsTaskManageBase::DestroyTaskList (TASKLIST_TYPE* pTargetTaskList) {
180   //fprintf(stdout, "CWelsTaskManageBase: pTargetTaskList size=%d m_iTotalTaskNum=%d\n", static_cast<int32_t> (pTargetTaskList->size()), m_iTotalTaskNum);
181   while (NULL != pTargetTaskList->begin()) {
182     CWelsBaseTask* pTask = pTargetTaskList->begin();
183     WELS_DELETE_OP (pTask);
184     pTargetTaskList->pop_front();
185   }
186   pTargetTaskList = NULL;
187 }
188 
DestroyTasks()189 void CWelsTaskManageBase::DestroyTasks() {
190   for (int32_t iDid = 0; iDid < MAX_DEPENDENCY_LAYER; iDid++)  {
191     if (m_iTaskNum[iDid] > 0) {
192       DestroyTaskList (m_cEncodingTaskList[iDid]);
193       DestroyTaskList (m_cPreEncodingTaskList[iDid]);
194       m_iTaskNum[iDid] = 0;
195       m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_ENCODING][iDid] = NULL;
196     }
197   }
198   //fprintf(stdout, "[MT] CWelsTaskManageBase() DestroyTasks, cleaned %d tasks\n", m_iTotalTaskNum);
199 }
200 
OnTaskMinusOne()201 void  CWelsTaskManageBase::OnTaskMinusOne() {
202   //fprintf(stdout, "OnTaskMinusOne event %x m_iWaitTaskNum=%d\n", &m_hEventMutex, m_iWaitTaskNum);
203   WelsCommon::CWelsAutoLock cAutoLock (m_cWaitTaskNumLock);
204   WelsEventSignal (&m_hTaskEvent, &m_hEventMutex, &m_iWaitTaskNum);
205   /*WelsMutexLock(&m_hEventMutex);
206   m_iWaitTaskNum --;
207   WelsMutexUnlock(&m_hEventMutex);
208 
209   if (m_iWaitTaskNum <= 0) {
210     WelsEventSignal (&m_hTaskEvent);
211     fprintf(stdout, "OnTaskMinusOne WelsEventSignal m_iWaitTaskNum=%d\n", m_iWaitTaskNum);
212   }*/
213   //fprintf(stdout, "OnTaskMinusOne m_iWaitTaskNum=%d\n", m_iWaitTaskNum);
214 }
215 
OnTaskCancelled()216 WelsErrorType  CWelsTaskManageBase::OnTaskCancelled() {
217   OnTaskMinusOne();
218   return ENC_RETURN_SUCCESS;
219 }
220 
OnTaskExecuted()221 WelsErrorType  CWelsTaskManageBase::OnTaskExecuted() {
222   OnTaskMinusOne();
223   return ENC_RETURN_SUCCESS;
224 }
225 
ExecuteTaskList(TASKLIST_TYPE ** pTaskList)226 WelsErrorType  CWelsTaskManageBase::ExecuteTaskList (TASKLIST_TYPE** pTaskList) {
227   m_iWaitTaskNum = m_iTaskNum[m_iCurDid];
228   TASKLIST_TYPE* pTargetTaskList = (pTaskList[m_iCurDid]);
229   //fprintf(stdout, "ExecuteTaskList m_iWaitTaskNum=%d\n", m_iWaitTaskNum);
230   if (0 == m_iWaitTaskNum) {
231     return ENC_RETURN_SUCCESS;
232   }
233 
234   int32_t iCurrentTaskCount = m_iWaitTaskNum; //if directly use m_iWaitTaskNum in the loop make cause sync problem
235   int32_t iIdx = 0;
236   while (iIdx < iCurrentTaskCount) {
237     m_pThreadPool->QueueTask (pTargetTaskList->getNode (iIdx));
238     iIdx ++;
239   }
240 
241   WelsEventWait (&m_hTaskEvent, &m_hEventMutex, m_iWaitTaskNum);
242 
243   return ENC_RETURN_SUCCESS;
244 }
245 
InitFrame(const int32_t kiCurDid)246 void CWelsTaskManageBase::InitFrame (const int32_t kiCurDid) {
247   m_iCurDid = kiCurDid;
248   if (m_pEncCtx->pCurDqLayer->bNeedAdjustingSlicing) {
249     ExecuteTaskList (m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_UPDATEMBMAP]);
250   }
251 }
252 
ExecuteTasks(const CWelsBaseTask::ETaskType iTaskType)253 WelsErrorType  CWelsTaskManageBase::ExecuteTasks (const CWelsBaseTask::ETaskType iTaskType) {
254   return ExecuteTaskList (m_pcAllTaskList[iTaskType]);
255 }
256 
GetThreadPoolThreadNum()257 int32_t  CWelsTaskManageBase::GetThreadPoolThreadNum() {
258   return m_pThreadPool->GetThreadNum();
259 }
260 
261 // CWelsTaskManageOne is for test
Init(sWelsEncCtx * pEncCtx)262 WelsErrorType CWelsTaskManageOne::Init (sWelsEncCtx* pEncCtx) {
263   m_pEncCtx = pEncCtx;
264 
265   return CreateTasks (pEncCtx, pEncCtx->iMaxSliceCount);
266 }
267 
ExecuteTasks(const CWelsBaseTask::ETaskType iTaskType)268 WelsErrorType  CWelsTaskManageOne::ExecuteTasks (const CWelsBaseTask::ETaskType iTaskType) {
269   while (NULL != m_cEncodingTaskList[0]->begin()) {
270     (m_cEncodingTaskList[0]->begin())->Execute();
271     m_cEncodingTaskList[0]->pop_front();
272   }
273   return ENC_RETURN_SUCCESS;
274 }
275 // CWelsTaskManageOne is for test
276 
277 }
278 
279 
280 
281 
282