1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 |
|
17 /** |
|
18 @file |
|
19 @internalComponent |
|
20 */ |
|
21 |
|
22 #include "log.h" |
|
23 #include "omxilcallbackmanagerifimpl.h" |
|
24 #include "omxilportmanager.h" |
|
25 #include "omxilfsm.h" |
|
26 |
|
27 |
|
28 EXPORT_C |
|
29 XOmxILCallbackManagerIfImpl::XOmxILCallbackManagerIfImpl(OMX_HANDLETYPE apComponentHandle, |
|
30 OMX_PTR apAppData, |
|
31 OMX_CALLBACKTYPE* apCallbacks) |
|
32 : |
|
33 ipHandle(static_cast<OMX_COMPONENTTYPE*>(apComponentHandle)), |
|
34 ipAppData(apAppData), |
|
35 ipCallbacks(apCallbacks), |
|
36 iRegisteredTunnels(), |
|
37 iBufferMarkPropagationPorts(), |
|
38 iBufferMarks(), |
|
39 ipPortManager(0), |
|
40 ipFsm(0) |
|
41 { |
|
42 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::XOmxILCallbackManagerIfImpl")); |
|
43 } |
|
44 |
|
45 EXPORT_C |
|
46 XOmxILCallbackManagerIfImpl::~XOmxILCallbackManagerIfImpl() |
|
47 { |
|
48 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::~XOmxILCallbackManagerIfImpl")); |
|
49 // These pointers are cleared to make sure that any further calls on this |
|
50 // object will fail (e.g., from a threaded PF) |
|
51 ipHandle = 0; |
|
52 ipAppData = 0; |
|
53 ipCallbacks = 0; |
|
54 |
|
55 iRegisteredTunnels.Close(); |
|
56 iBufferMarkPropagationPorts.Close(); |
|
57 iBufferMarks.Close(); |
|
58 |
|
59 ipPortManager = 0; |
|
60 |
|
61 ipFsm = 0; |
|
62 |
|
63 } |
|
64 |
|
65 EXPORT_C void |
|
66 XOmxILCallbackManagerIfImpl::DoSetPortManager(COmxILPortManager& apPortManager) |
|
67 { |
|
68 ipPortManager = &apPortManager; |
|
69 } |
|
70 |
|
71 EXPORT_C void |
|
72 XOmxILCallbackManagerIfImpl::DoSetFsm(COmxILFsm& apFsm) |
|
73 { |
|
74 ipFsm = &apFsm; |
|
75 } |
|
76 |
|
77 EXPORT_C OMX_ERRORTYPE |
|
78 XOmxILCallbackManagerIfImpl::DoRegisterComponentHandle(OMX_HANDLETYPE aComponentHandle) |
|
79 { |
|
80 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::DoRegisterComponentHandle")); |
|
81 |
|
82 __ASSERT_DEBUG(aComponentHandle, |
|
83 User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
84 |
|
85 ipHandle = static_cast<OMX_COMPONENTTYPE *>(aComponentHandle); |
|
86 |
|
87 return OMX_ErrorNone; |
|
88 |
|
89 } |
|
90 |
|
91 |
|
92 EXPORT_C OMX_ERRORTYPE |
|
93 XOmxILCallbackManagerIfImpl::DoRegisterILClientCallbacks(const OMX_CALLBACKTYPE* apCallbacks, |
|
94 const OMX_PTR apAppData) |
|
95 { |
|
96 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::DoRegisterILClientCallbacks")); |
|
97 |
|
98 ipAppData = const_cast<OMX_PTR>(apAppData); |
|
99 ipCallbacks = const_cast<OMX_CALLBACKTYPE*>(apCallbacks); |
|
100 |
|
101 return OMX_ErrorNone; |
|
102 |
|
103 } |
|
104 |
|
105 EXPORT_C OMX_ERRORTYPE |
|
106 XOmxILCallbackManagerIfImpl::DoRegisterTunnelCallback( |
|
107 OMX_U32 aLocalPortIndex, |
|
108 OMX_DIRTYPE aLocalPortDirection, |
|
109 OMX_HANDLETYPE aTunnelledComponentHandle, |
|
110 OMX_U32 aTunnelledPortIndex) |
|
111 { |
|
112 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::DoRegisterTunnelCallback")); |
|
113 |
|
114 OMX_ERRORTYPE omxError = OMX_ErrorNone; |
|
115 |
|
116 if (aTunnelledComponentHandle) |
|
117 { |
|
118 // Register tunnelled port |
|
119 TInt err = iRegisteredTunnels.Append( |
|
120 TTunnelRegistrationInfo(aLocalPortIndex, |
|
121 aLocalPortDirection, |
|
122 aTunnelledComponentHandle, |
|
123 aTunnelledPortIndex)); |
|
124 if (KErrNone != err) |
|
125 { |
|
126 switch (err) |
|
127 { |
|
128 case KErrNoMemory: |
|
129 { |
|
130 omxError = OMX_ErrorInsufficientResources; |
|
131 } |
|
132 break; |
|
133 default: |
|
134 { |
|
135 omxError = OMX_ErrorUndefined; |
|
136 } |
|
137 }; |
|
138 } |
|
139 |
|
140 } |
|
141 else |
|
142 { |
|
143 // Deregister tunnelled port |
|
144 const TUint tunnelCount = iRegisteredTunnels.Count(); |
|
145 for (TUint i=0; i<tunnelCount; ++i) |
|
146 { |
|
147 if (iRegisteredTunnels[i].iLocalPortIndex == |
|
148 aLocalPortIndex) |
|
149 { |
|
150 iRegisteredTunnels.Remove(i); |
|
151 break; |
|
152 } |
|
153 } |
|
154 } |
|
155 |
|
156 return omxError; |
|
157 |
|
158 } |
|
159 |
|
160 EXPORT_C OMX_ERRORTYPE |
|
161 XOmxILCallbackManagerIfImpl::DoRegisterBufferMarkPropagationPort( |
|
162 OMX_U32 aPortIndex, |
|
163 OMX_U32 aPropagationPortIndex) |
|
164 { |
|
165 DEBUG_PRINTF3(_L8("XOmxILCallbackManagerIfImpl::DoRegisterBufferMarkPropagationPort : aPortIndex[%d] aPropagationPortIndex[%d] "),aPortIndex, aPropagationPortIndex); |
|
166 |
|
167 TInt err = iBufferMarkPropagationPorts.Append( |
|
168 TBufferMarkPropagationInfo(aPortIndex, |
|
169 aPropagationPortIndex)); |
|
170 |
|
171 OMX_ERRORTYPE omxError = OMX_ErrorNone; |
|
172 if (KErrNone != err) |
|
173 { |
|
174 switch (err) |
|
175 { |
|
176 case KErrNoMemory: |
|
177 { |
|
178 omxError = OMX_ErrorInsufficientResources; |
|
179 } |
|
180 break; |
|
181 default: |
|
182 { |
|
183 omxError = OMX_ErrorUndefined; |
|
184 } |
|
185 }; |
|
186 } |
|
187 |
|
188 return omxError; |
|
189 |
|
190 } |
|
191 |
|
192 |
|
193 |
|
194 EXPORT_C OMX_ERRORTYPE |
|
195 XOmxILCallbackManagerIfImpl::DoTransitionCompleteNotification(OMX_STATETYPE aOmxState) |
|
196 { |
|
197 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::DoTransitionCompleteNotification")); |
|
198 |
|
199 return DoEventNotification(OMX_EventCmdComplete, |
|
200 OMX_CommandStateSet, |
|
201 aOmxState, |
|
202 0); |
|
203 |
|
204 } |
|
205 |
|
206 |
|
207 EXPORT_C OMX_ERRORTYPE |
|
208 XOmxILCallbackManagerIfImpl::DoCommandCompleteNotification(OMX_COMMANDTYPE aOmxCommand, |
|
209 OMX_U32 aOmxPortIndex) |
|
210 { |
|
211 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::DoCommandCompleteNotification")); |
|
212 |
|
213 return DoEventNotification(OMX_EventCmdComplete, |
|
214 aOmxCommand, |
|
215 aOmxPortIndex, |
|
216 0); |
|
217 |
|
218 } |
|
219 |
|
220 |
|
221 EXPORT_C OMX_ERRORTYPE |
|
222 XOmxILCallbackManagerIfImpl::DoErrorEventNotification(OMX_ERRORTYPE aOmxError) |
|
223 { |
|
224 DEBUG_PRINTF2(_L8("XOmxILCallbackManagerIfImpl::DoErrorEventNotification : aOmxError[%X] "), aOmxError); |
|
225 |
|
226 return DoEventNotification(OMX_EventError, |
|
227 aOmxError, |
|
228 0, |
|
229 0); |
|
230 |
|
231 } |
|
232 |
|
233 EXPORT_C OMX_ERRORTYPE |
|
234 XOmxILCallbackManagerIfImpl::DoEventNotification(OMX_EVENTTYPE aEvent, |
|
235 TUint32 aData1, |
|
236 TUint32 aData2, |
|
237 OMX_STRING aExtraInfo) |
|
238 { |
|
239 DEBUG_PRINTF4(_L8("XOmxILCallbackManagerIfImpl::DoEventNotification : aEvent[%u] aData1[%u] aData2[%u]"), aEvent, aData1, aData2); |
|
240 |
|
241 __ASSERT_DEBUG(ipHandle && ipCallbacks, User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
242 |
|
243 ipCallbacks->EventHandler(ipHandle, |
|
244 ipAppData, |
|
245 aEvent, |
|
246 aData1, |
|
247 aData2, |
|
248 aExtraInfo); |
|
249 return OMX_ErrorNone; |
|
250 |
|
251 } |
|
252 |
|
253 |
|
254 EXPORT_C OMX_ERRORTYPE |
|
255 XOmxILCallbackManagerIfImpl::DoBufferDoneNotification(OMX_BUFFERHEADERTYPE* apBufferHeader, |
|
256 OMX_U32 aLocalPortIndex, |
|
257 OMX_DIRTYPE aLocalPortDirection) |
|
258 { |
|
259 DEBUG_PRINTF5(_L8("XOmxILCallbackManagerIfImpl::DoBufferDoneNotification : HANDLE [%X] BUFFER [%X] PORT[%d] DIR[%d]"), ipHandle, apBufferHeader, aLocalPortIndex, aLocalPortDirection); |
|
260 |
|
261 __ASSERT_ALWAYS(apBufferHeader && |
|
262 (OMX_DirInput == aLocalPortDirection || |
|
263 OMX_DirOutput == aLocalPortDirection), |
|
264 User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
265 |
|
266 __ASSERT_ALWAYS(apBufferHeader->nOffset + apBufferHeader->nFilledLen |
|
267 <= apBufferHeader->nAllocLen, |
|
268 User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
269 |
|
270 __ASSERT_DEBUG(ipHandle && ipCallbacks, User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
271 |
|
272 // Look for buffer marks to be signalled or propagated |
|
273 SignalOrPropagateBufferMarks(apBufferHeader, |
|
274 aLocalPortDirection); |
|
275 |
|
276 // find out whether the port is tunnelled or not |
|
277 TBool tunnelled = EFalse; |
|
278 TUint tunnelInfoArrayIndex = 0; |
|
279 const TUint tunnelCount = iRegisteredTunnels.Count(); |
|
280 for (TUint i=0; i<tunnelCount; ++i) |
|
281 { |
|
282 if (iRegisteredTunnels[i].iLocalPortIndex == |
|
283 aLocalPortIndex) |
|
284 { |
|
285 tunnelled = ETrue; |
|
286 tunnelInfoArrayIndex = i; |
|
287 break; |
|
288 } |
|
289 } |
|
290 |
|
291 if (tunnelled) |
|
292 { |
|
293 OMX_COMPONENTTYPE* ipTunnelledComponent = |
|
294 static_cast<OMX_COMPONENTTYPE*>( |
|
295 iRegisteredTunnels[tunnelInfoArrayIndex]. |
|
296 iTunnelledComponentHandle); |
|
297 |
|
298 __ASSERT_DEBUG(ipTunnelledComponent, |
|
299 User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
300 |
|
301 // From OMX_Core.h "Callbacks should not return an error to the |
|
302 // component, so if an error occurs, the application shall handle it |
|
303 // internally". Callback return error ignored here. |
|
304 if (OMX_DirInput == aLocalPortDirection) |
|
305 { |
|
306 OMX_FillThisBuffer(ipTunnelledComponent, apBufferHeader); |
|
307 } |
|
308 else |
|
309 { |
|
310 OMX_EmptyThisBuffer(ipTunnelledComponent, apBufferHeader); |
|
311 } |
|
312 |
|
313 } |
|
314 else |
|
315 { |
|
316 OMX_ERRORTYPE (*fp2CBackHandler) |
|
317 (OMX_HANDLETYPE, OMX_PTR, OMX_BUFFERHEADERTYPE*) = |
|
318 (aLocalPortDirection == OMX_DirInput ? |
|
319 ipCallbacks->EmptyBufferDone : |
|
320 ipCallbacks->FillBufferDone); |
|
321 |
|
322 // From OMX_Core.h "Callbacks should not return an error to the |
|
323 // component, so if an error occurs, the application shall handle it |
|
324 // internally". Callback return error ignored here. |
|
325 fp2CBackHandler(ipHandle, |
|
326 ipAppData, |
|
327 apBufferHeader); |
|
328 } |
|
329 |
|
330 return OMX_ErrorNone; |
|
331 |
|
332 } |
|
333 |
|
334 EXPORT_C OMX_ERRORTYPE |
|
335 XOmxILCallbackManagerIfImpl::DoPortSettingsChangeNotification( |
|
336 OMX_U32 aLocalPortIndex, |
|
337 TUint aPortSettingsIndex, |
|
338 const TDesC8& aPortSettings) |
|
339 { |
|
340 DEBUG_PRINTF2(_L8("XOmxILCallbackManagerIfImpl::DoPortSettingsChangeNotification : aLocalPortIndex[%d]"), aLocalPortIndex); |
|
341 |
|
342 __ASSERT_DEBUG(ipHandle && |
|
343 ipCallbacks && |
|
344 ipPortManager, |
|
345 User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
346 |
|
347 HBufC8* pPortSettings = HBufC8::New(aPortSettings.Length()); |
|
348 if (!pPortSettings) |
|
349 { |
|
350 return OMX_ErrorInsufficientResources; |
|
351 } |
|
352 *pPortSettings = aPortSettings; |
|
353 |
|
354 // This is an event that the port may want to convey to the IL Client... |
|
355 OMX_EVENTTYPE eventForILClient = OMX_EventMax; |
|
356 OMX_ERRORTYPE omxRetError = |
|
357 ipPortManager->PortSettingsChangeIndication(aLocalPortIndex, |
|
358 aPortSettingsIndex, |
|
359 *pPortSettings, |
|
360 eventForILClient); |
|
361 |
|
362 delete pPortSettings; |
|
363 pPortSettings = NULL; |
|
364 |
|
365 // Inform the IL Client that some value in one of the ports' configuration |
|
366 // structures has changed... |
|
367 if (OMX_EventMax != eventForILClient) |
|
368 { |
|
369 // Only allow these two port events... |
|
370 __ASSERT_ALWAYS(eventForILClient == OMX_EventPortSettingsChanged || |
|
371 eventForILClient == OMX_EventPortFormatDetected, |
|
372 User::Panic(KOmxILCallbackManagerIfImplPanicCategory, 1)); |
|
373 |
|
374 // From OMX_Core.h "Callbacks should not return an error to the component, |
|
375 // so if an error occurs, the application shall handle it |
|
376 // internally". Callback return error ignored here. |
|
377 ipCallbacks->EventHandler(ipHandle, |
|
378 ipAppData, |
|
379 eventForILClient, |
|
380 aLocalPortIndex, |
|
381 0, |
|
382 0); |
|
383 } |
|
384 |
|
385 return OMX_ErrorNone; |
|
386 |
|
387 } |
|
388 |
|
389 EXPORT_C void |
|
390 XOmxILCallbackManagerIfImpl::SignalOrPropagateBufferMarks( |
|
391 OMX_BUFFERHEADERTYPE* apBufferHeader, |
|
392 OMX_U32 aLocalPortIndex) |
|
393 { |
|
394 DEBUG_PRINTF(_L8("XOmxILCallbackManagerIfImpl::SignalOrPropagateBufferMarks()")); |
|
395 |
|
396 // Look for buffer marks to be signalled or propagated |
|
397 if (apBufferHeader->hMarkTargetComponent) |
|
398 { |
|
399 // See if this component is the buffer mark target component... |
|
400 if (apBufferHeader->hMarkTargetComponent == ipHandle) |
|
401 { |
|
402 // Inform the IL Client that a marked buffer has been processed... |
|
403 ipCallbacks->EventHandler(ipHandle, |
|
404 ipAppData, |
|
405 OMX_EventMark, |
|
406 0, |
|
407 0, |
|
408 apBufferHeader->pMarkData); |
|
409 |
|
410 // At this point, the mark has been delivered to the IL |
|
411 // Client...Remove the mark from the processed header... |
|
412 apBufferHeader->hMarkTargetComponent = 0; |
|
413 apBufferHeader->pMarkData = 0; |
|
414 |
|
415 } |
|
416 else |
|
417 { |
|
418 // Propagate the mark... |
|
419 |
|
420 // First find the buffer mark propagation port... |
|
421 const TInt index = iBufferMarkPropagationPorts.Find( |
|
422 TBufferMarkPropagationInfo(aLocalPortIndex), |
|
423 TIdentityRelation<TBufferMarkPropagationInfo>( |
|
424 &TBufferMarkPropagationInfo::Compare)); |
|
425 |
|
426 // Note that sink components don't propagate marks... |
|
427 if (index != KErrNotFound) |
|
428 { |
|
429 const TBufferMarkPropagationInfo& propInfo = |
|
430 iBufferMarkPropagationPorts[index]; |
|
431 |
|
432 // Let's check for the special case: The case for a source |
|
433 // component where the output port is both the port that marks |
|
434 // the headers and the port that propagates them ... Therefore |
|
435 // no need to store the mark for later propagation... |
|
436 if (propInfo.iPropagationPortIndex != aLocalPortIndex) |
|
437 { |
|
438 // Now, store temporarily the mark so the next time we send |
|
439 // a buffer done callback in that propagation port, we mark |
|
440 // that header accordingly... |
|
441 // Unsuccessful insertion is ignored. |
|
442 iBufferMarks.Append( |
|
443 TOutputPortBufferMarkInfo( |
|
444 propInfo.iPropagationPortIndex, |
|
445 apBufferHeader->hMarkTargetComponent, |
|
446 apBufferHeader->pMarkData)); |
|
447 |
|
448 // At this point the mark has been set for propagation to |
|
449 // an output port. Remove the mark from the processed |
|
450 // header... |
|
451 apBufferHeader->hMarkTargetComponent = 0; |
|
452 apBufferHeader->pMarkData = 0; |
|
453 } |
|
454 } |
|
455 } |
|
456 } |
|
457 else |
|
458 { |
|
459 if(iBufferMarks.Count() != 0) |
|
460 { |
|
461 // Let's see if we have a mark waiting to go out...This will find the |
|
462 // first mark in the local list of marks ... |
|
463 const TInt index = iBufferMarks.Find( |
|
464 TOutputPortBufferMarkInfo(aLocalPortIndex), |
|
465 TIdentityRelation<TOutputPortBufferMarkInfo>( |
|
466 &TOutputPortBufferMarkInfo::Compare)); |
|
467 if (index != KErrNotFound) |
|
468 { |
|
469 const TOutputPortBufferMarkInfo& markInfo = |
|
470 iBufferMarks[index]; |
|
471 |
|
472 // Mark the header... |
|
473 apBufferHeader->hMarkTargetComponent = markInfo.ipMarkTargetComponent; |
|
474 apBufferHeader->pMarkData = markInfo.ipMarkData; |
|
475 |
|
476 // Remove the mark info from the local store |
|
477 iBufferMarks.Remove(index); |
|
478 } |
|
479 } |
|
480 |
|
481 } |
|
482 |
|
483 |
|
484 } |
|
485 |
|
486 EXPORT_C void |
|
487 XOmxILCallbackManagerIfImpl::HandleInsufficientResources() |
|
488 { |
|
489 DEBUG_PRINTF3(_L8("XOmxILCallbackManagerIfImpl::HandleInsufficientResources : ipCallbacks[%X] ipHandle[%X]"), ipCallbacks, ipHandle); |
|
490 |
|
491 if (ipCallbacks && ipHandle) |
|
492 { |
|
493 // This is a best-effort action, let's try to inform the IL Client of |
|
494 // the lack of resources... |
|
495 ipCallbacks->EventHandler(ipHandle, |
|
496 ipAppData, |
|
497 OMX_EventError, |
|
498 (OMX_U32)OMX_ErrorInsufficientResources, |
|
499 0, |
|
500 0); |
|
501 } |
|
502 } |
|