|
1 /* |
|
2 * Copyright (c) 2008 - 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 /** |
|
20 @file |
|
21 @internalComponent |
|
22 */ |
|
23 |
|
24 #include "log.h" |
|
25 #include "comxil3gpdemuxerprocessingfunction.h" |
|
26 #include "comxil3gpdemuxerconfigmanager.h" |
|
27 #include "comxil3gpdemuxervideooutputport.h" |
|
28 #include "comxil3gpdemuxeraudiooutputport.h" |
|
29 #include "c3gpdemuxer.h" |
|
30 #include <openmax/il/common/omxilcallbacknotificationif.h> |
|
31 |
|
32 |
|
33 COmxIL3GPDemuxerProcessingFunction* COmxIL3GPDemuxerProcessingFunction::NewL(MOmxILCallbackNotificationIf& aCallbacks) |
|
34 { |
|
35 DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::NewL")); |
|
36 |
|
37 COmxIL3GPDemuxerProcessingFunction* self = new (ELeave) COmxIL3GPDemuxerProcessingFunction(aCallbacks); |
|
38 CleanupStack::PushL(self); |
|
39 self->ConstructL(); |
|
40 CleanupStack::Pop(self); |
|
41 return self; |
|
42 } |
|
43 |
|
44 COmxIL3GPDemuxerProcessingFunction::COmxIL3GPDemuxerProcessingFunction(MOmxILCallbackNotificationIf& aCallbacks) : |
|
45 COmxILProcessingFunction(aCallbacks) |
|
46 { |
|
47 } |
|
48 |
|
49 void COmxIL3GPDemuxerProcessingFunction::ConstructL() |
|
50 { |
|
51 DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::ConstructL")); |
|
52 |
|
53 iDemuxer = C3GPDemuxer::NewL(iCallbacks); |
|
54 |
|
55 // this is used in the Idle->Executing transition to issue the port changed events in the correct order |
|
56 // we create the callback now so it cannot fail later on |
|
57 iStreamDetectCallback = new(ELeave) CAsyncCallBack(TCallBack(StreamDetectCallBack, this), CAsyncCallBack::EPriorityHigh); |
|
58 |
|
59 iRequestHelper = COmxIL3GPDemuxerRequestHelper::NewL(this); |
|
60 } |
|
61 |
|
62 COmxIL3GPDemuxerProcessingFunction::~COmxIL3GPDemuxerProcessingFunction() |
|
63 { |
|
64 DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::~COmxIL3GPDemuxerProcessingFunction")); |
|
65 |
|
66 delete iDemuxer; |
|
67 delete iStreamDetectCallback; |
|
68 delete iRequestHelper; |
|
69 } |
|
70 |
|
71 void COmxIL3GPDemuxerProcessingFunction::SetConfigManager(COmxIL3GPDemuxerConfigManager& aConfigManager) |
|
72 { |
|
73 DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::SetConfigManager")); |
|
74 |
|
75 iConfigManager = &aConfigManager; |
|
76 iConfigManager->SetDemuxer(*iDemuxer); |
|
77 } |
|
78 |
|
79 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::StateTransitionIndication(TStateIndex aNewState) |
|
80 { |
|
81 DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::StateTransitionIndication")); |
|
82 |
|
83 return iRequestHelper->StateTransitionIndication(aNewState); |
|
84 } |
|
85 |
|
86 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::DoStateTransitionIndication(TStateIndex aNewState) |
|
87 { |
|
88 DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::DoStateTransitionIndication")); |
|
89 |
|
90 OMX_ERRORTYPE omxError = OMX_ErrorNone; |
|
91 |
|
92 switch(aNewState) |
|
93 { |
|
94 case EStateExecuting: |
|
95 { |
|
96 DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateExecuting")); |
|
97 |
|
98 // Cause PortFormatDetected and PortSettingsChanged with |
|
99 // the format detected from the file. |
|
100 |
|
101 // However, we want this to occur after the idle->executing |
|
102 // completion notification, which FsmTransition() will queue |
|
103 // after this function completes. So we use a CAsyncCallBack |
|
104 // to create the events at some time after FsmTransition() |
|
105 // completes. A high priority is chosen to avoid being starved |
|
106 // by other busy AOs, in particular the callback manager(s). |
|
107 |
|
108 if(!iStreamsDetected) |
|
109 { |
|
110 iStreamDetectCallback->CallBack(); |
|
111 } |
|
112 else |
|
113 { |
|
114 iDemuxer->Start(); |
|
115 iExecuting = ETrue; |
|
116 } |
|
117 |
|
118 break; |
|
119 } |
|
120 |
|
121 case ESubStateLoadedToIdle: |
|
122 { |
|
123 DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateLoadedToIdle")); |
|
124 |
|
125 const HBufC* filename = iConfigManager->Filename(); |
|
126 if(filename) |
|
127 { |
|
128 // get the maximum buffer count for a port |
|
129 omxError = iDemuxer->AcquireResources(*filename); |
|
130 } |
|
131 else |
|
132 { |
|
133 // no file name has been set |
|
134 omxError = OMX_ErrorUnsupportedSetting; |
|
135 } |
|
136 break; |
|
137 } |
|
138 |
|
139 case EStateIdle: |
|
140 { |
|
141 DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateIdle")); |
|
142 |
|
143 if (iExecuting) |
|
144 { |
|
145 iExecuting = EFalse; |
|
146 iDemuxer->Stop(); |
|
147 } |
|
148 break; |
|
149 } |
|
150 |
|
151 case EStateLoaded: |
|
152 { |
|
153 DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateLoaded")); |
|
154 |
|
155 iDemuxer->ReleaseResources(); |
|
156 iStreamsDetected = EFalse; |
|
157 break; |
|
158 } |
|
159 |
|
160 case EStatePause: |
|
161 { |
|
162 DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StatePause")); |
|
163 |
|
164 iDemuxer->Pause(); |
|
165 break; |
|
166 } |
|
167 |
|
168 default: |
|
169 { |
|
170 break; |
|
171 } |
|
172 } |
|
173 |
|
174 return omxError; |
|
175 } |
|
176 |
|
177 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::BufferFlushingIndication(TUint32 aPortIndex, |
|
178 OMX_DIRTYPE aDirection) |
|
179 { |
|
180 DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferFlushingIndication : aPortIndex[%d]"), aPortIndex); |
|
181 |
|
182 return iRequestHelper->BufferFlushingIndication(aPortIndex, aDirection); |
|
183 } |
|
184 |
|
185 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::DoBufferFlushingIndication(TUint32 aPortIndex, |
|
186 OMX_DIRTYPE /*aDirection*/) |
|
187 { |
|
188 DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::DoBufferFlushingIndication : aPortIndex[%d]"), aPortIndex); |
|
189 |
|
190 iDemuxer->FlushBuffers(aPortIndex); |
|
191 return OMX_ErrorNone; |
|
192 } |
|
193 |
|
194 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::ParamIndication(OMX_INDEXTYPE /*aParamIndex*/, |
|
195 const TAny* /*apComponentParameterStructure*/) |
|
196 { |
|
197 return OMX_ErrorNone; |
|
198 } |
|
199 |
|
200 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::ConfigIndication(OMX_INDEXTYPE /*aConfigIndex*/, |
|
201 const TAny* /*apComponentConfigStructure*/) |
|
202 { |
|
203 return OMX_ErrorNone; |
|
204 } |
|
205 |
|
206 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::BufferIndication(OMX_BUFFERHEADERTYPE* apBufferHeader, |
|
207 OMX_DIRTYPE /*aDirection*/) |
|
208 { |
|
209 DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferIndication >: [%X]"), apBufferHeader); |
|
210 |
|
211 // Check if the previous buffer processing invalidated the demuxer |
|
212 if (iDemuxer->Invalid()) |
|
213 { |
|
214 return OMX_ErrorInvalidState; |
|
215 } |
|
216 |
|
217 TUint32 portIndex; |
|
218 portIndex = apBufferHeader->nOutputPortIndex; |
|
219 |
|
220 if (portIndex >= COmxIL3GPDemuxer::EPortIndexMax) |
|
221 { |
|
222 return OMX_ErrorBadPortIndex; |
|
223 } |
|
224 |
|
225 TRAPD(err, iDemuxer->ProcessThisBufferL(apBufferHeader, portIndex)); |
|
226 |
|
227 DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferIndication :< size [%d]"), apBufferHeader->nFilledLen); |
|
228 |
|
229 if (err == KErrNone) |
|
230 { |
|
231 return OMX_ErrorNone; |
|
232 } |
|
233 else |
|
234 { |
|
235 return OMX_ErrorUndefined; |
|
236 } |
|
237 } |
|
238 |
|
239 OMX_BOOL COmxIL3GPDemuxerProcessingFunction::BufferRemovalIndication(OMX_BUFFERHEADERTYPE* apBufferHeader, |
|
240 OMX_DIRTYPE aDirection) |
|
241 { |
|
242 DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferRemovalIndication >: [%X]"), apBufferHeader); |
|
243 |
|
244 return iRequestHelper->BufferRemovalIndication(apBufferHeader, aDirection); |
|
245 } |
|
246 |
|
247 OMX_BOOL COmxIL3GPDemuxerProcessingFunction::DoBufferRemovalIndication(OMX_BUFFERHEADERTYPE* apBufferHeader, OMX_DIRTYPE aDirection) |
|
248 { |
|
249 DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::DoBufferRemovalIndication : BUFFER [%X]"), apBufferHeader); |
|
250 |
|
251 if (iDemuxer->RemoveBuffer(apBufferHeader, aDirection)) |
|
252 { |
|
253 return OMX_TRUE; |
|
254 } |
|
255 |
|
256 return OMX_FALSE; |
|
257 } |
|
258 |
|
259 OMX_U32 COmxIL3GPDemuxerProcessingFunction::NumAvailableStreams(COmxIL3GPDemuxer::TPortIndex aPortType) |
|
260 { |
|
261 switch(aPortType) |
|
262 { |
|
263 case COmxIL3GPDemuxer::EPortIndexVideoOutput: |
|
264 { |
|
265 TSize frameSize; |
|
266 TVideoFormat format; |
|
267 TBool videoAvailable = iDemuxer->GetVideoFormat(frameSize, format); |
|
268 return videoAvailable ? 1 : 0; |
|
269 } |
|
270 |
|
271 case COmxIL3GPDemuxer::EPortIndexAudioOutput: |
|
272 { |
|
273 TAudioFormat format; |
|
274 return iDemuxer->GetAudioFormat(format) ? 1 : 0; |
|
275 } |
|
276 |
|
277 default: |
|
278 User::Invariant(); |
|
279 return 0; |
|
280 } |
|
281 } |
|
282 |
|
283 OMX_U32 COmxIL3GPDemuxerProcessingFunction::ActiveStream(COmxIL3GPDemuxer::TPortIndex /*aPortType*/) |
|
284 { |
|
285 //TODO |
|
286 return 0; |
|
287 } |
|
288 |
|
289 OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::SetActiveStream(COmxIL3GPDemuxer::TPortIndex aPortType, OMX_U32 aActiveStream) |
|
290 { |
|
291 switch(aPortType) |
|
292 { |
|
293 case COmxIL3GPDemuxer::EPortIndexVideoOutput: |
|
294 { |
|
295 TSize frameSize; |
|
296 TVideoFormat format; |
|
297 TBool videoAvailable = iDemuxer->GetVideoFormat(frameSize, format); |
|
298 if(videoAvailable && aActiveStream == 0) |
|
299 { |
|
300 return OMX_ErrorNone; |
|
301 } |
|
302 else |
|
303 { |
|
304 return OMX_ErrorUnsupportedSetting; |
|
305 } |
|
306 } |
|
307 case COmxIL3GPDemuxer::EPortIndexAudioOutput: |
|
308 // TODO |
|
309 //ZK return OMX_ErrorNotImplemented; |
|
310 return OMX_ErrorNone; |
|
311 |
|
312 default: |
|
313 return OMX_ErrorUnsupportedIndex; |
|
314 } |
|
315 } |
|
316 |
|
317 void COmxIL3GPDemuxerProcessingFunction::SetVideoPort(COmxIL3GPDemuxerVideoOutputPort& aVideoPort) |
|
318 { |
|
319 iVideoPort = &aVideoPort; |
|
320 } |
|
321 |
|
322 void COmxIL3GPDemuxerProcessingFunction::SetAudioPort(COmxIL3GPDemuxerAudioOutputPort& aAudioPort) |
|
323 { |
|
324 iAudioPort = &aAudioPort; |
|
325 } |
|
326 |
|
327 TInt COmxIL3GPDemuxerProcessingFunction::StreamDetectCallBack(TAny* aPtr) |
|
328 { |
|
329 reinterpret_cast<COmxIL3GPDemuxerProcessingFunction*>(aPtr)->DoStreamDetect(); |
|
330 return KErrNone; |
|
331 } |
|
332 |
|
333 void COmxIL3GPDemuxerProcessingFunction::DoStreamDetect() |
|
334 { |
|
335 OMX_ERRORTYPE error = iDemuxer->DetectStreams(); |
|
336 if(error) |
|
337 { |
|
338 iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL); |
|
339 return; |
|
340 } |
|
341 |
|
342 // video format has been discovered |
|
343 // check against port definition |
|
344 // if autodetect, cause a PortSettingsChanged event |
|
345 // if not autodetect and detected format is different, cause an error event |
|
346 TSize size; |
|
347 TVideoFormat format; |
|
348 TBool videoAvailable = iDemuxer->GetVideoFormat(size, format); |
|
349 // errors from EventNotification are ignored - these will be |
|
350 // OMX_ErrorInsufficientResources if the callback could not be |
|
351 // created or added to the queue. In this case, we probably want |
|
352 // the callback manager to send an out-of-band error event to the |
|
353 // IL client but this does not happen in 1509 yet |
|
354 if(format.iCoding == OMX_VIDEO_CodingMax) |
|
355 { |
|
356 // format could not be mapped, and so is unsupported |
|
357 iCallbacks.EventNotification(OMX_EventError, (TUint32) OMX_ErrorFormatNotDetected, 0, NULL); |
|
358 // only send FormatNotDetected once for the component, not for both ports |
|
359 return; |
|
360 } |
|
361 else |
|
362 { |
|
363 if (iVideoPort->IsEnabled()) |
|
364 { |
|
365 iStreamsDetected = ETrue; |
|
366 if (iVideoPort->VideoFormat() == OMX_VIDEO_CodingAutoDetect) |
|
367 { |
|
368 if(videoAvailable) |
|
369 { |
|
370 iVideoPort->FormatDetected(size, format); |
|
371 } |
|
372 // TODO spec doesn't say what the params should be for PortFormatDetected |
|
373 iCallbacks.EventNotification(OMX_EventPortFormatDetected, COmxIL3GPDemuxer::EPortIndexVideoOutput, 0, NULL); |
|
374 iCallbacks.EventNotification(OMX_EventPortSettingsChanged, OMX_IndexParamPortDefinition, COmxIL3GPDemuxer::EPortIndexVideoOutput, NULL); |
|
375 } |
|
376 else |
|
377 { |
|
378 if (iVideoPort->VideoFormat() != format.iCoding) |
|
379 { |
|
380 iStreamsDetected = EFalse; |
|
381 iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL); |
|
382 return; |
|
383 } |
|
384 } |
|
385 } |
|
386 } |
|
387 |
|
388 TAudioFormat audioFormat; |
|
389 TBool audioAvailable = iDemuxer->GetAudioFormat(audioFormat); |
|
390 |
|
391 if(audioFormat.iCoding == OMX_AUDIO_CodingMax) |
|
392 { |
|
393 // format could not be mapped, and so is unsupported |
|
394 iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL); |
|
395 return; |
|
396 } |
|
397 else |
|
398 { |
|
399 if (iAudioPort->IsEnabled()) |
|
400 { |
|
401 iStreamsDetected = ETrue; |
|
402 if (iAudioPort->AudioFormat() == OMX_AUDIO_CodingAutoDetect) |
|
403 { |
|
404 if (audioAvailable) |
|
405 { |
|
406 iAudioPort->FormatDetected(audioFormat); |
|
407 } |
|
408 iCallbacks.EventNotification(OMX_EventPortFormatDetected, COmxIL3GPDemuxer::EPortIndexAudioOutput, 0, NULL); |
|
409 iCallbacks.EventNotification(OMX_EventPortSettingsChanged, OMX_IndexParamPortDefinition, COmxIL3GPDemuxer::EPortIndexAudioOutput, NULL); |
|
410 } |
|
411 else |
|
412 { |
|
413 if (iAudioPort->AudioFormat() != audioFormat.iCoding) |
|
414 { |
|
415 iStreamsDetected = EFalse; |
|
416 iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL); |
|
417 return; |
|
418 } |
|
419 } |
|
420 } |
|
421 } |
|
422 //Only start the demuxer if one of its ports is enabled. |
|
423 if (iStreamsDetected) |
|
424 { |
|
425 iDemuxer->Start(); |
|
426 iExecuting = ETrue; |
|
427 } |
|
428 } |
|
429 |