• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #include "pvmf_omx_enc_callbacks.h"
19 #include "pvmf_omx_enc_node.h"
20 
21 ////////////////////////////////////////////////////////////////////////////////////////////////
EventHandlerThreadSafeCallbackAOEnc(void * aObserver,uint32 aDepth,const char * aAOname,int32 aPriority)22 EventHandlerThreadSafeCallbackAOEnc::EventHandlerThreadSafeCallbackAOEnc(void* aObserver,
23         uint32 aDepth,
24         const char* aAOname,
25         int32 aPriority)
26         : ThreadSafeCallbackAO(aObserver, aDepth, aAOname, aPriority)
27 {
28 
29     iMemoryPool = ThreadSafeMemPoolFixedChunkAllocator::Create(aDepth + 2);
30     if (iMemoryPool == NULL)
31     {
32         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
33                         PVLOGMSG_ERR, (0, "EventHandlerTSCAO::CreateMemPool() Memory pool failed to allocate"));
34     }
35     // MUST do a dummy ALLOC HERE TO Create mempool. Otherwise the mempool will be
36     // created in the 2nd thread and will fail to deallocate properly.
37 
38     OsclAny *dummy = iMemoryPool->allocate(sizeof(EventHandlerSpecificData));
39     iMemoryPool->deallocate(dummy);
40 }
41 
~EventHandlerThreadSafeCallbackAOEnc()42 EventHandlerThreadSafeCallbackAOEnc::~EventHandlerThreadSafeCallbackAOEnc()
43 {
44     if (iMemoryPool)
45     {
46         iMemoryPool->removeRef();
47         iMemoryPool = NULL;
48     }
49 }
ProcessEvent(OsclAny * EventData)50 OsclReturnCode EventHandlerThreadSafeCallbackAOEnc::ProcessEvent(OsclAny* EventData)
51 {
52     // In this case, ProcessEvent calls the method of the primary test AO to process the Event
53     if (iObserver != NULL)
54     {
55         PVMFOMXEncNode* ptr = (PVMFOMXEncNode*) iObserver;
56 
57         if (ptr->IsAdded())
58         {
59             ptr->ProcessCallbackEventHandler_MultiThreaded(EventData);
60         }
61 
62     }
63     return OsclSuccess;
64 }
65 
66 // We override the Run to process multiple (i.e. all in the queue) events in one Run
67 
Run()68 void EventHandlerThreadSafeCallbackAOEnc::Run()
69 {
70     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EventHandlerThreadSafeCallbackAOEnc::Run() In"));
71 
72     OsclAny *P; // parameter to dequeue
73     OsclReturnCode status = OsclSuccess;
74 
75 
76     do
77     {
78 
79 
80         P = DeQueue(status);
81         // status is either OsclSuccess or OsclPending (if the last event was pulled
82         // from the queue)
83 
84         if ((status == OsclSuccess) || (status == OsclPending))
85         {
86             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EventHandlerThreadSafeCallbackAOEnc::Run() - Calling Process Event"));
87             ProcessEvent(P);
88         }
89         else
90         {
91             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EventHandlerThreadSafeCallbackAOEnc::Run() - could not dequeue event data"));
92         }
93 
94 
95         // it is possible that an event arrives between dequeueing the last event and this point.
96         // If this is the case, we will be rescheduled and process the event
97         // in the next Run
98 
99 
100     }
101     while (status == OsclSuccess);
102     // if the status is "OsclPending" there were no more events in the queue
103     // (if another event arrived in the meanwhile, AO will be rescheduled)
104 
105 
106 
107     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EventHandlerThreadSafeCallbackAOEnc::Run() Out"));
108 }
109 
110 // same as base-class DeQueue method, except no RunIfNotReady/PendForExec is called (since all events are processed in a loop)
111 // (i.e. PendForExec control is done in the loop in Run)
DeQueue(OsclReturnCode & stat)112 OsclAny* EventHandlerThreadSafeCallbackAOEnc::DeQueue(OsclReturnCode &stat)
113 {
114     OsclAny *pData;
115     OsclProcStatus::eOsclProcError sema_status;
116 
117     stat = OsclSuccess;
118 
119     // Protect the queue while accessing it:
120     Mutex.Lock();
121 
122     if (Q->NumElem == 0)
123     {
124         // nothing to de-queue
125         stat = OsclFailure;
126         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EventHandlerThreadSafeCallbackAOEnc::DeQueue() - No events in the queue - return ()"));
127         Mutex.Unlock();
128 
129         return NULL;
130     }
131 
132     pData = (Q->pFirst[Q->index_out]).pData;
133 
134     Q->index_out++;
135     // roll-over the index
136     if (Q->index_out == Q->MaxNumElements)
137         Q->index_out = 0;
138 
139     Q->NumElem--;
140 
141     // check if there is need to call waitforevent
142     if ((Q->NumElem) == 0)
143     {
144         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EventHandlerThreadSafeCallbackAOEnc::Run() - No more events, call PendForExec()"));
145         PendForExec();
146         stat = OsclPending; // let the Run know that the last event was pulled out of the queue
147         // so that it can get out of the loop
148     }
149 
150 
151     //release queue access
152     Mutex.Unlock();
153 
154     // Signal the semaphore that controls the remote thread.
155     // The remote thread might be blocked and waiting for an event to be processed in case the event queue is full
156     sema_status = RemoteThreadCtrlSema.Signal();
157     if (sema_status != OsclProcStatus::SUCCESS_ERROR)
158     {
159         stat = OsclFailure;
160         return NULL;
161     }
162 
163     return pData;
164 }
165 
166 
167 ////////////////////////////////////////////////////////////////////////////////////////////////
168 ////////////////////////////////////////////////////////////////////////////////////////////////
EmptyBufferDoneThreadSafeCallbackAOEnc(void * aObserver,uint32 aDepth,const char * aAOname,int32 aPriority)169 EmptyBufferDoneThreadSafeCallbackAOEnc::EmptyBufferDoneThreadSafeCallbackAOEnc(void* aObserver,
170         uint32 aDepth,
171         const char* aAOname,
172         int32 aPriority)
173         : ThreadSafeCallbackAO(aObserver, aDepth, aAOname, aPriority)
174 {
175 
176     iMemoryPool = ThreadSafeMemPoolFixedChunkAllocator::Create(aDepth + 2);
177     if (iMemoryPool == NULL)
178     {
179         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
180                         PVLOGMSG_ERR, (0, "EventHandlerTSCAO::CreateMemPool() Memory pool failed to allocate"));
181 
182     }
183     // MUST do a dummy ALLOC HERE TO Create mempool. Otherwise the mempool will be
184     // created in the 2nd thread and will fail to deallocate properly.
185 
186     OsclAny *dummy = iMemoryPool->allocate(sizeof(EmptyBufferDoneSpecificData));
187     iMemoryPool->deallocate(dummy);
188 }
189 
~EmptyBufferDoneThreadSafeCallbackAOEnc()190 EmptyBufferDoneThreadSafeCallbackAOEnc::~EmptyBufferDoneThreadSafeCallbackAOEnc()
191 {
192     if (iMemoryPool)
193     {
194 
195         iMemoryPool->removeRef();
196         iMemoryPool = NULL;
197     }
198 
199 }
ProcessEvent(OsclAny * EventData)200 OsclReturnCode EmptyBufferDoneThreadSafeCallbackAOEnc::ProcessEvent(OsclAny* EventData)
201 {
202     // In this case, ProcessEvent calls the method of the primary test AO to process the Event
203     if (iObserver != NULL)
204     {
205         PVMFOMXEncNode* ptr = (PVMFOMXEncNode *) iObserver;
206 
207         ptr->ProcessCallbackEmptyBufferDone_MultiThreaded(EventData);
208 
209     }
210     return OsclSuccess;
211 }
212 
213 // We override the Run to process multiple (i.e. all in the queue) events in one Run
214 
Run()215 void EmptyBufferDoneThreadSafeCallbackAOEnc::Run()
216 {
217     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EmptyBufferDoneThreadSafeCallbackAOEnc::Run() In"));
218 
219     OsclAny *P; // parameter to dequeue
220     OsclReturnCode status = OsclSuccess;
221 
222     do
223     {
224 
225 
226         P = DeQueue(status);
227 
228 
229         if ((status == OsclSuccess) || (status == OsclPending))
230         {
231             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EmptyBufferDoneThreadSafeCallbackAOEnc::Run() - Calling Process Event"));
232             ProcessEvent(P);
233         }
234         else
235         {
236             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EmptyBufferDoneThreadSafeCallbackAOEnc::Run() - could not dequeue event data"));
237         }
238 
239 
240         // it is possible that an event arrives between dequeueing the last event and this point.
241         // If this is the case, we will be rescheduled and process the event
242         // in the next Run
243 
244 
245     }
246     while (status == OsclSuccess);
247     // if the status is "OsclPending" there were no more events in the queue
248     // (if another event arrived in the meanwhile, AO will be rescheduled)
249 
250 
251     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EmptyBufferDoneThreadSafeCallbackAOEnc::Run() Out"));
252 }
253 
254 // same as base-class DeQueue method, except no RunIfNotReady/PendForExec is called (since all events are processed in a loop)
255 // (i.e. PendForExec control is done in the loop in Run)
DeQueue(OsclReturnCode & stat)256 OsclAny* EmptyBufferDoneThreadSafeCallbackAOEnc::DeQueue(OsclReturnCode &stat)
257 {
258     OsclAny *pData;
259     OsclProcStatus::eOsclProcError sema_status;
260 
261     stat = OsclSuccess;
262 
263     // Protect the queue while accessing it:
264     Mutex.Lock();
265 
266     if (Q->NumElem == 0)
267     {
268         // nothing to de-queue
269         stat = OsclFailure;
270         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EmptyBufferDoneThreadSafeCallbackAOEnc::DeQueue() - No events in the queue - return ()"));
271         Mutex.Unlock();
272 
273         return NULL;
274     }
275 
276     pData = (Q->pFirst[Q->index_out]).pData;
277 
278     Q->index_out++;
279     // roll-over the index
280     if (Q->index_out == Q->MaxNumElements)
281         Q->index_out = 0;
282 
283     Q->NumElem--;
284 
285     // check if there is need to call waitforevent
286     if ((Q->NumElem) == 0)
287     {
288         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "EmptyBufferDoneThreadSafeCallbackAOEnc::Run() - No more events, call PendForExec()"));
289         PendForExec();
290         stat = OsclPending; // let the Run know that the last event was pulled out of the queue
291         // so that it can get out of the loop
292     }
293 
294     //release queue access
295     Mutex.Unlock();
296 
297     // Signal the semaphore that controls the remote thread.
298     // The remote thread might be blocked and waiting for an event to be processed in case the event queue is full
299     sema_status = RemoteThreadCtrlSema.Signal();
300     if (sema_status != OsclProcStatus::SUCCESS_ERROR)
301     {
302         stat = OsclFailure;
303         return NULL;
304     }
305 
306     return pData;
307 }
308 
309 
310 
311 ////////////////////////////////////////////////////////////////////////////////////////////////
FillBufferDoneThreadSafeCallbackAOEnc(void * aObserver,uint32 aDepth,const char * aAOname,int32 aPriority)312 FillBufferDoneThreadSafeCallbackAOEnc::FillBufferDoneThreadSafeCallbackAOEnc(void* aObserver,
313         uint32 aDepth,
314         const char* aAOname,
315         int32 aPriority)
316         : ThreadSafeCallbackAO(aObserver, aDepth, aAOname, aPriority)
317 {
318 
319     iMemoryPool = ThreadSafeMemPoolFixedChunkAllocator::Create(aDepth + 2);
320     if (iMemoryPool == NULL)
321     {
322         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
323                         PVLOGMSG_ERR, (0, "EventHandlerTSCAO::CreateMemPool() Memory pool failed to allocate"));
324     }
325     // MUST do a dummy ALLOC HERE TO Create mempool. Otherwise the mempool will be
326     // created in the 2nd thread and will fail to deallocate properly.
327 
328     OsclAny *dummy = iMemoryPool->allocate(sizeof(FillBufferDoneSpecificData));
329     iMemoryPool->deallocate(dummy);
330 }
331 
~FillBufferDoneThreadSafeCallbackAOEnc()332 FillBufferDoneThreadSafeCallbackAOEnc::~FillBufferDoneThreadSafeCallbackAOEnc()
333 {
334     if (iMemoryPool)
335     {
336 
337         iMemoryPool->removeRef();
338         iMemoryPool = NULL;
339     }
340 }
341 
ProcessEvent(OsclAny * EventData)342 OsclReturnCode FillBufferDoneThreadSafeCallbackAOEnc::ProcessEvent(OsclAny* EventData)
343 {
344     // In this case, ProcessEvent calls the method of the primary test AO to process the Event
345     if (iObserver != NULL)
346     {
347         PVMFOMXEncNode* ptr = (PVMFOMXEncNode*) iObserver;
348 
349         ptr->ProcessCallbackFillBufferDone_MultiThreaded(EventData);
350 
351     }
352     return OsclSuccess;
353 }
354 
355 // We override the Run to process multiple (i.e. all in the queue) events in one Run
356 
Run()357 void FillBufferDoneThreadSafeCallbackAOEnc::Run()
358 {
359     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "FillBufferDoneThreadSafeCallbackAOEnc::Run() In"));
360 
361     OsclAny *P; // parameter to dequeue
362     OsclReturnCode status = OsclSuccess;
363 
364     do
365     {
366 
367 
368         P = DeQueue(status);
369 
370 
371         if ((status == OsclSuccess) || (status == OsclPending))
372         {
373             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "FillBufferDoneThreadSafeCallbackAOEnc::Run() - Calling Process Event"));
374             ProcessEvent(P);
375         }
376         else
377         {
378             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "FillBufferDoneThreadSafeCallbackAOEnc::Run() - could not dequeue event data"));
379         }
380 
381 
382         // it is possible that an event arrives between dequeueing the last event and this point.
383         // If this is the case, we will be rescheduled and process the event
384         // in the next Run
385 
386 
387     }
388     while (status == OsclSuccess);
389     // if the status is "OsclPending" there were no more events in the queue
390     // (if another event arrived in the meanwhile, AO will be rescheduled)
391 
392 
393 
394 
395 
396     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "FillBufferDoneThreadSafeCallbackAOEnc::Run() Out"));
397 }
398 
399 // same as base-class DeQueue method, except no RunIfNotReady/PendForExec is called (since all events are processed in a loop)
400 // (i.e. PendForExec control is done in the loop in Run)
DeQueue(OsclReturnCode & stat)401 OsclAny* FillBufferDoneThreadSafeCallbackAOEnc::DeQueue(OsclReturnCode &stat)
402 {
403     OsclAny *pData;
404     OsclProcStatus::eOsclProcError sema_status;
405 
406     stat = OsclSuccess;
407 
408     // Protect the queue while accessing it:
409     Mutex.Lock();
410 
411     if (Q->NumElem == 0)
412     {
413         // nothing to de-queue
414         stat = OsclFailure;
415         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "FillBufferDoneThreadSafeCallbackAOEnc::DeQueue() - No events in the queue - return ()"));
416         Mutex.Unlock();
417 
418         return NULL;
419     }
420 
421     pData = (Q->pFirst[Q->index_out]).pData;
422 
423     Q->index_out++;
424     // roll-over the index
425     if (Q->index_out == Q->MaxNumElements)
426         Q->index_out = 0;
427 
428     Q->NumElem--;
429     // check if there is need to call waitforevent
430     if ((Q->NumElem) == 0)
431     {
432         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "FillBufferDoneThreadSafeCallbackAOEnc::Run() - No more events, call PendForExec()"));
433         PendForExec();
434         stat = OsclPending; // let the Run know that the last event was pulled out of the queue
435         // so that it can get out of the loop
436     }
437 
438     //release queue access
439     Mutex.Unlock();
440 
441     // Signal the semaphore that controls the remote thread.
442     // The remote thread might be blocked and waiting for an event to be processed in case the event queue is full
443     sema_status = RemoteThreadCtrlSema.Signal();
444     if (sema_status != OsclProcStatus::SUCCESS_ERROR)
445     {
446         stat = OsclFailure;
447         return NULL;
448     }
449 
450     return pData;
451 }
452