|
1 // Copyright (c) 2004-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 /** @file |
|
17 @internalTechnology */ |
|
18 #include <f32file.h> |
|
19 #include <ecom/ecom.h> |
|
20 |
|
21 #include "MngChunks.h" |
|
22 #include "MngReadStream.h" |
|
23 #include "MngProcessor.h" |
|
24 #include "PngProcessor.h" |
|
25 #include "MngRenderer.h" |
|
26 #include "MngPanic.h" |
|
27 #include "MngPlayerObserver.h" |
|
28 #include "StreamDecoderIFace.h" |
|
29 #include "StreamDecoderIFace.hrh" |
|
30 #include "icl/imagedisplayplugin.h" |
|
31 |
|
32 #include "logger.h" |
|
33 |
|
34 #include "MngPlayer.h" |
|
35 |
|
36 const CMngPlayer::TObserverNotifyEvent KDecodingStopError =CImageDisplayPlugin::EStatusNoMoreToDecode |
|
37 | CImageDisplayPlugin::EStatusPaused; |
|
38 |
|
39 const CMngPlayer::TObserverNotifyEvent KNotReadyToDecode =CImageDisplayPlugin::EStatusBusy; |
|
40 |
|
41 const CMngPlayer::TObserverNotifyEvent KFrameReady =CImageDisplayPlugin::EStatusFrameReady; |
|
42 |
|
43 const CMngPlayer::TObserverNotifyEvent KLastFrameReady =CImageDisplayPlugin::EStatusFrameReady |
|
44 | CImageDisplayPlugin::EStatusNoMoreToDecode; |
|
45 |
|
46 const CMngPlayer::TObserverNotifyEvent KFinishedClearOutput =CImageDisplayPlugin::EStatusEraseOutputContents |
|
47 | CImageDisplayPlugin::EStatusNoMoreToDecode; |
|
48 |
|
49 const CMngPlayer::TObserverNotifyEvent KFinishedKeepOutput =CImageDisplayPlugin::EStatusDisplayThisFrameIndefinetely |
|
50 | CImageDisplayPlugin::EStatusNoMoreToDecode; |
|
51 |
|
52 |
|
53 const CMngPlayer::TObserverNotifyEvent KFinishedEraseOutputFlag=CImageDisplayPlugin::EStatusEraseOutputContents; |
|
54 |
|
55 const CMngPlayer::TObserverNotifyEvent KFinishedKeepOutputFlag=CImageDisplayPlugin::EStatusDisplayThisFrameIndefinetely; |
|
56 |
|
57 const CMngPlayer::TObserverNotifyEvent KInitComplete=0; |
|
58 |
|
59 /*static*/ |
|
60 CMngPlayer* CMngPlayer::NewL(CMngFileReadStream* aReadStream, MMngPlayerObserver& aObserver, TBool aMngSubframesNoLoops) //Subframes with No Loops |
|
61 { |
|
62 CMngPlayer* self=new (ELeave) CMngPlayer(aObserver, aMngSubframesNoLoops); //Subframes with No Loops |
|
63 CleanupStack::PushL(self); |
|
64 self->ConstructL(aReadStream); |
|
65 |
|
66 CleanupStack::Pop(self); |
|
67 return self; |
|
68 } |
|
69 |
|
70 CMngPlayer::CMngPlayer(MMngPlayerObserver& aObserver, TBool aMngSubframesNoLoops):CActive(EPriorityIdle), //Subframes with No Loops |
|
71 iMngSubframesNoLoops(aMngSubframesNoLoops), //Subframes with No Loops |
|
72 iObserver(aObserver), |
|
73 iPerformFrameDelayInternally(ETrue), |
|
74 i1stFrameInterframeDelay(-1), |
|
75 iFrameNumberToTerminate(-1), |
|
76 iNeedsChange(ETrue) |
|
77 { |
|
78 CActiveScheduler::Add(this); |
|
79 } |
|
80 |
|
81 void CMngPlayer::ConstructL(CMngFileReadStream* aReadStream) |
|
82 { |
|
83 TUid DtorKey; |
|
84 iDecoderFactory = reinterpret_cast<MImageStreamDecoderFactory*> |
|
85 (REComSession::CreateImplementationL(TUid::Uid(KPngStreamDecoderFactoryImplUidValue), DtorKey)); |
|
86 iDecoderFactory->SetDtorKey(DtorKey); |
|
87 |
|
88 iExecTimer = CDelayTimer::NewL(*this); |
|
89 |
|
90 iMngStream = aReadStream; |
|
91 iMngStream->AddRef(); |
|
92 iMngProcessor = CMngProcessor::NewL(*this, iMngSubframesNoLoops); //Subframes with No Loops |
|
93 iPngProcessor = CPngProcessor::NewL(*this); |
|
94 |
|
95 iMngProcessor->AddSubProcessor(*iPngProcessor); |
|
96 } |
|
97 |
|
98 CMngPlayer::~CMngPlayer() |
|
99 { |
|
100 Cancel(); |
|
101 delete iExecTimer; |
|
102 if (NULL != iMngProcessor) |
|
103 { |
|
104 iMngProcessor->Stop(); |
|
105 } |
|
106 delete iMngProcessor; |
|
107 delete iPngProcessor; |
|
108 if (NULL != iMngStream) |
|
109 { |
|
110 iMngStream->Release(); |
|
111 iMngStream = NULL; |
|
112 } |
|
113 delete iMngRenderer; |
|
114 iObjectList.Destroy(); |
|
115 iLoopStack.Close(); |
|
116 iChunkProviders.Close(); |
|
117 delete iMngHeader; |
|
118 delete iTerminationCtrl; |
|
119 if (NULL != iDecoderFactory) |
|
120 { |
|
121 iDecoderFactory->Release(); |
|
122 } |
|
123 } |
|
124 |
|
125 void CMngPlayer::InitL(TMhdrChunk*& aHeaderChunk) |
|
126 { |
|
127 SetMngHeader(aHeaderChunk); |
|
128 |
|
129 if (iGotHeaderFromStream) |
|
130 { |
|
131 User::Leave(KErrCorrupt); |
|
132 } |
|
133 |
|
134 iGotHeaderFromStream = ETrue; |
|
135 |
|
136 if (iMngHeader->iProfileValidity && (iMngHeader->iJngPresence |
|
137 #ifdef STRICT_MNG_LC |
|
138 || iMngHeader->iDeltaPngPresence ==1 |
|
139 #endif // STRICT_MNG_LC |
|
140 )) |
|
141 { |
|
142 User::Leave(KErrNotSupported); |
|
143 } |
|
144 |
|
145 iMngRenderer = CMngRenderer::NewL(TSize(iMngHeader->iFrameWidth, iMngHeader->iFrameHeight), |
|
146 IsAlphaNeeded(), iDestDisplayMode, iMaskDisplayMode ); |
|
147 |
|
148 NotifyObserver(KInitComplete, KErrNone, TTimeIntervalMicroSeconds32(0)); |
|
149 } |
|
150 |
|
151 void CMngPlayer::Decode() |
|
152 { |
|
153 if (iExecTimer->IsActive()) |
|
154 { |
|
155 return; // we'are just awating for delay to elapse |
|
156 } |
|
157 if (iOutstandingNotify) |
|
158 { |
|
159 iOutstandingNotify = EFalse; |
|
160 iExecTimer->After(TTimeIntervalMicroSeconds32(0)); |
|
161 iIsPaused = EFalse; |
|
162 return; |
|
163 } |
|
164 |
|
165 switch (iState) |
|
166 { |
|
167 case EStJustBorn: |
|
168 iMngProcessor->Start(*iMngStream, iStatus); |
|
169 iMngStream->Release(); |
|
170 iMngStream = NULL; |
|
171 iState = EStReadingFormat; |
|
172 SetActive(); |
|
173 break; |
|
174 case EStReadingFormat: |
|
175 iMngProcessor->Resume(); |
|
176 break; |
|
177 default: |
|
178 if (iIsPaused) |
|
179 { |
|
180 if (!IsActive() && !iExecTimer->IsActive()) |
|
181 { |
|
182 RunAgain(); |
|
183 } |
|
184 } |
|
185 else |
|
186 { |
|
187 if (iState != EStPlaying) |
|
188 { |
|
189 StartPlay(); |
|
190 } |
|
191 } |
|
192 } |
|
193 iIsPaused = EFalse; |
|
194 } |
|
195 |
|
196 void CMngPlayer::StopDecode() |
|
197 { |
|
198 iOutstandingNotify = EFalse; |
|
199 if (iState == EStReadingFormat) |
|
200 { |
|
201 iMngProcessor->Pause(); |
|
202 return; |
|
203 } |
|
204 Cancel(); |
|
205 if (NULL != iExecTimer) |
|
206 { |
|
207 iExecTimer->Cancel(); |
|
208 } |
|
209 iIsPaused = EFalse; |
|
210 iFrameNumberToTerminate =-1; |
|
211 i1stFrameInterframeDelay=-1; |
|
212 |
|
213 if (EStPlaying == iState) |
|
214 { |
|
215 iState = EStReadyToPlay; |
|
216 } |
|
217 |
|
218 if (iTerminationCtrl) |
|
219 { |
|
220 iTerminationCtrl->Reset(); |
|
221 } |
|
222 } |
|
223 |
|
224 void CMngPlayer::Pause() |
|
225 { |
|
226 if (iIsPaused) |
|
227 { |
|
228 return; |
|
229 } |
|
230 switch (iState) |
|
231 { |
|
232 case EStJustBorn: |
|
233 break; |
|
234 case EStReadingFormat: |
|
235 iMngProcessor->Pause(); |
|
236 break; |
|
237 default: |
|
238 (void)0; |
|
239 } |
|
240 iIsPaused = ETrue; |
|
241 } |
|
242 |
|
243 void CMngPlayer::RunL() |
|
244 { |
|
245 ASSERT(!iExecTimer->IsActive()); |
|
246 if (KErrNone != iStatus.Int()) |
|
247 { |
|
248 iPlayerErrorCode = iStatus.Int(); |
|
249 StopDecode(); |
|
250 iState = EStStopped; |
|
251 NotifyObserver(KDecodingStopError, iPlayerErrorCode, TTimeIntervalMicroSeconds32(0)); |
|
252 return; |
|
253 } |
|
254 |
|
255 switch (iState) |
|
256 { |
|
257 case EStJustBorn: |
|
258 ASSERT(EFalse); |
|
259 break; |
|
260 |
|
261 case EStReadingFormat: |
|
262 iState = TPlayerState(iState + 1); |
|
263 delete iMngProcessor; |
|
264 iMngProcessor = NULL; |
|
265 if (iMngHeader == NULL) |
|
266 { |
|
267 User::Leave(KErrCorrupt); |
|
268 } |
|
269 StartPlay(); |
|
270 break; |
|
271 |
|
272 case EStReadyToPlay: |
|
273 ASSERT(EFalse); |
|
274 break; |
|
275 |
|
276 case EStPlaying: |
|
277 OnIteration(); |
|
278 break; |
|
279 |
|
280 case EStStopped: |
|
281 ASSERT(EFalse); |
|
282 break; |
|
283 |
|
284 case EStNeedsRepeat: |
|
285 ASSERT(EFalse); |
|
286 break; |
|
287 } |
|
288 } |
|
289 |
|
290 void CMngPlayer::DoCancel() |
|
291 { |
|
292 TBool timerActive = EFalse; |
|
293 if (NULL != iExecTimer) |
|
294 { |
|
295 timerActive = iExecTimer->IsActive(); |
|
296 iExecTimer->Cancel(); |
|
297 } |
|
298 |
|
299 if (NULL != iMngProcessor) |
|
300 { |
|
301 iMngProcessor->Stop(); |
|
302 } |
|
303 if (!timerActive) |
|
304 { |
|
305 iStatus = KErrCancel; |
|
306 } |
|
307 } |
|
308 |
|
309 TInt CMngPlayer::RunError(TInt aError) |
|
310 { |
|
311 iPlayerErrorCode= aError; |
|
312 iState = EStStopped; |
|
313 NotifyObserver(KDecodingStopError, iPlayerErrorCode, TTimeIntervalMicroSeconds32(0)); |
|
314 return KErrNone; |
|
315 } |
|
316 |
|
317 void CMngPlayer::RunAgain() |
|
318 { |
|
319 SetActive(); |
|
320 TRequestStatus* pReq=&iStatus; |
|
321 User::RequestComplete(pReq, KErrNone); |
|
322 } |
|
323 |
|
324 void CMngPlayer::StartPlay() |
|
325 { |
|
326 if (iState != EStReadyToPlay && iState != EStNeedsRepeat) |
|
327 { |
|
328 NotifyObserver(KNotReadyToDecode, KErrNotReady, TTimeIntervalMicroSeconds32(0)); |
|
329 return; |
|
330 } |
|
331 iNominalDelayBeforeThisFrame = 0; |
|
332 iEndOfFrameNotification = EFalse; |
|
333 iInterframeDelay = 0; |
|
334 iDefaultInterFrmDelay = 0; |
|
335 iNextInterFrameDelay = 0; |
|
336 if (0 != iMngHeader->iTicksPerSecond) |
|
337 { |
|
338 iTickLength = 1000000 / iMngHeader->iTicksPerSecond; |
|
339 if (0 >= iTickLength) |
|
340 { |
|
341 iTickLength = 1; |
|
342 } |
|
343 iInterframeDelay = 1; |
|
344 iDefaultInterFrmDelay = 1; |
|
345 iNextInterFrameDelay = 1; |
|
346 } |
|
347 |
|
348 iCurrentObject = iObjectList.Begin(); |
|
349 |
|
350 iFramingMode=EMngFramNoBgLayerExcpt1stFgLayer; |
|
351 |
|
352 iSubframeLayerNum = 0; |
|
353 iDrawnLayerNum = 0; |
|
354 iDrawnFrameNum = 0; |
|
355 |
|
356 iDefaultClippingBnd.iTl.iX = 0; |
|
357 iDefaultClippingBnd.iTl.iY = 0; |
|
358 iDefaultClippingBnd.iBr.iX = iMngHeader->iFrameWidth; |
|
359 iDefaultClippingBnd.iBr.iY = iMngHeader->iFrameHeight; |
|
360 iFrameBeingRendered = EFalse; |
|
361 |
|
362 iChunkProviders.Clear(); |
|
363 iMngRenderer->Reset(); |
|
364 for (RMngObjectList::TObjectIterator it=iObjectList.Begin(); it != iObjectList.End(); ++it) |
|
365 { |
|
366 iObjectList[it]->Reset(); |
|
367 } |
|
368 |
|
369 iState = EStPlaying; |
|
370 RunAgain(); |
|
371 } |
|
372 |
|
373 void CMngPlayer::SetTerminationCtrlL(CMngTermination* aTermination) |
|
374 { |
|
375 if (NULL != iTerminationCtrl) |
|
376 { |
|
377 delete aTermination; |
|
378 User::Leave(KErrCorrupt); |
|
379 } |
|
380 iTerminationCtrl = aTermination; |
|
381 } |
|
382 |
|
383 void CMngPlayer::AppendObjectL(CMngObject*& aObject) |
|
384 { |
|
385 aObject->SetObjectLabel(iObjectList.Count()+1); |
|
386 TInt err=iObjectList.Append(aObject); |
|
387 CMngObject* temp=aObject; |
|
388 aObject = NULL; |
|
389 if (KErrNone != err) |
|
390 { |
|
391 delete temp; |
|
392 User::Leave(err); |
|
393 } |
|
394 temp->OnAddToPlayerL(*this); |
|
395 } |
|
396 |
|
397 void CMngPlayer::OnEndOfSubFrame() |
|
398 { |
|
399 if (iChangeInterFrmDelay == EMngFramChangeUpcomingSubFrameOnly) |
|
400 { |
|
401 if(iObjectList[iCurrentObject+1]->IsSubFrame()) |
|
402 { |
|
403 iNeedsChange = EFalse; |
|
404 iInterframeDelay = iNextInterFrameDelay; |
|
405 } |
|
406 iNextInterFrameDelay = iDefaultInterFrmDelay; |
|
407 } |
|
408 iChangeInterFrmDelay = EMngFramDoNotChange; |
|
409 |
|
410 if (iChangeClippingBoundaries == EMngFramChangeUpcomingSubFrameOnly) |
|
411 { |
|
412 iCurrentClippingBnd = iDefaultClippingBnd; |
|
413 iMngRenderer->SetBgClipRect(iCurrentClippingBnd); |
|
414 } |
|
415 |
|
416 if (iChangeClippingBoundaries == EMngFramChangeAndResetDefault) |
|
417 { |
|
418 iDefaultClippingBnd = iCurrentClippingBnd; |
|
419 iMngRenderer->SetBgClipRect(iCurrentClippingBnd); |
|
420 iMngRenderer->ClearOutputRect(); |
|
421 } |
|
422 |
|
423 iChangeClippingBoundaries = EMngFramDoNotChange; |
|
424 |
|
425 if (!iFrameBeingRendered) |
|
426 { |
|
427 iInterframeDelay = iNextInterFrameDelay; |
|
428 } |
|
429 |
|
430 iSubframeLayerNum = 0; |
|
431 } |
|
432 |
|
433 void CMngPlayer::OnNewLayer() |
|
434 { |
|
435 if (iFramingMode==EMngFramBgLayerForEachFgLayer || iDrawnLayerNum==0 || |
|
436 (iFramingMode==EMngFramBgLayerFor1stFgLayer && iSubframeLayerNum == 0)) |
|
437 { |
|
438 iMngRenderer->ClearOutputRect(); |
|
439 } |
|
440 ++iDrawnLayerNum; |
|
441 ++iSubframeLayerNum; |
|
442 iFrameBeingRendered = ETrue; |
|
443 } |
|
444 |
|
445 void CMngPlayer::OnEndOfFrame(TBool aAlwaysNotify, TBool aIsLastFrame) |
|
446 { |
|
447 const TInt KTimerThreshold =1000; |
|
448 ++iDrawnFrameNum; |
|
449 TUint NotifyCode=(aIsLastFrame? KLastFrameReady : KFrameReady); |
|
450 |
|
451 if (iFrameNumberToTerminate >= 0 && iFrameNumberToTerminate==iDrawnFrameNum) |
|
452 { |
|
453 NotifyCode = (KLastFrameReady|KFinishedKeepOutputFlag); |
|
454 } |
|
455 |
|
456 const TInt TicksDelay=(iDrawnFrameNum==1 && i1stFrameInterframeDelay>-1 ? i1stFrameInterframeDelay : iInterframeDelay); |
|
457 |
|
458 if ( (NotifyCode & KLastFrameReady)==KLastFrameReady) |
|
459 { |
|
460 StopDecode(); |
|
461 } |
|
462 |
|
463 TInt delayValue=Ticks2TimeInterval(TicksDelay).Int(); |
|
464 i1stFrameInterframeDelay =-1; |
|
465 |
|
466 if (iPerformFrameDelayInternally) |
|
467 { |
|
468 TTime CurrentTime; |
|
469 CurrentTime.HomeTime(); |
|
470 |
|
471 const TInt KDelayNeeded =delayValue; |
|
472 const TInt KMsDifference=I64HIGH(CurrentTime.MicroSecondsFrom(iEndOfPreviuosFrame).Int64()) ? KDelayNeeded +1 : |
|
473 I64LOW( CurrentTime.MicroSecondsFrom(iEndOfPreviuosFrame).Int64() ); |
|
474 |
|
475 delayValue=KDelayNeeded - KMsDifference > KTimerThreshold ? KDelayNeeded - KMsDifference - KTimerThreshold : 0; |
|
476 LOG4("Needed %u Got %u Val %u", KDelayNeeded, KMsDifference, delayValue); |
|
477 } |
|
478 |
|
479 iEndOfFrameNotification = ETrue; |
|
480 if (iInterframeDelay != 0 || aAlwaysNotify ) // as per spec do not send zero-delay updates |
|
481 { |
|
482 NotifyObserver(NotifyCode, KErrNone, TTimeIntervalMicroSeconds32(delayValue)); |
|
483 } |
|
484 iEndOfPreviuosFrame.HomeTime(); |
|
485 |
|
486 iFrameBeingRendered = EFalse; |
|
487 if(iNeedsChange) |
|
488 { |
|
489 iInterframeDelay = iNextInterFrameDelay; |
|
490 iNeedsChange = ETrue; |
|
491 } |
|
492 } |
|
493 |
|
494 inline |
|
495 void CMngPlayer::OnIteration() |
|
496 { |
|
497 if (iIsPaused) |
|
498 { |
|
499 return; |
|
500 } |
|
501 TBool CallAgain=EFalse; |
|
502 do |
|
503 { |
|
504 TRAP(iPlayerErrorCode, CallAgain=DoIterationL()); |
|
505 } while (iPlayerErrorCode==KErrNone && CallAgain && !iIsPaused); |
|
506 |
|
507 if (KErrNone != iPlayerErrorCode) |
|
508 { |
|
509 StopDecode(); |
|
510 iState=EStStopped; |
|
511 NotifyObserver(KDecodingStopError, iPlayerErrorCode, TTimeIntervalMicroSeconds32(0)); |
|
512 } |
|
513 } |
|
514 |
|
515 TBool CMngPlayer::DoIterationL() |
|
516 { |
|
517 CMngObject* pObject=NULL; |
|
518 |
|
519 if (iCurrentObject==iObjectList.End() ) |
|
520 { |
|
521 if (!iLoopStack.IsEmpty()) |
|
522 { |
|
523 User::Leave(KErrCorrupt); |
|
524 } |
|
525 pObject = iTerminationCtrl; |
|
526 } |
|
527 else |
|
528 { |
|
529 pObject = iObjectList[iCurrentObject]; |
|
530 } |
|
531 |
|
532 TMngExecuteResult res; |
|
533 |
|
534 if (NULL != pObject) |
|
535 { |
|
536 if (pObject->IsSubFrame()) |
|
537 { |
|
538 pObject->ExecuteL(*this, res); |
|
539 } |
|
540 if (pObject->IsLayer() || (pObject->IsSubFrame() && |
|
541 (iFramingMode==EMngFramBgLayerForEachFgLayer || iFramingMode==EMngFramBgLayerFor1stFgLayer) )) |
|
542 { |
|
543 OnNewLayer(); |
|
544 } |
|
545 if (!pObject->IsSubFrame()) |
|
546 { |
|
547 pObject->ExecuteL(*this, res); |
|
548 } |
|
549 } |
|
550 else |
|
551 { |
|
552 ASSERT(iCurrentObject==iObjectList.End()); |
|
553 res.iCommand = ECmdTerminate; |
|
554 } |
|
555 |
|
556 CMngObject* pNextObject = NULL; |
|
557 TBool MoreToRun=EFalse; |
|
558 switch (res.iCommand) |
|
559 { |
|
560 case ECmdJumpToObject: |
|
561 { |
|
562 RMngObjectList::TObjectIterator it=iObjectList.Find(res.iObjectLabel); |
|
563 ASSERT( it != iObjectList.End() ); |
|
564 iCurrentObject = it; |
|
565 RunAgain(); |
|
566 } |
|
567 break; |
|
568 case ECmdProcessNext: |
|
569 { |
|
570 if (res.iCommand==ECmdProcessNext) |
|
571 { |
|
572 if ((iCurrentObject+1) != iObjectList.End()) |
|
573 { |
|
574 pNextObject = iObjectList[iCurrentObject+1]; |
|
575 } |
|
576 else |
|
577 { |
|
578 pNextObject = iTerminationCtrl; |
|
579 } |
|
580 } |
|
581 |
|
582 if (NULL != pNextObject) |
|
583 { |
|
584 const TInt SubFrameLayerNum=iSubframeLayerNum; |
|
585 if (pNextObject->IsSubFrame() || |
|
586 (iFramingMode==EMngFramNoBgLayerExcpt1stFgLayer && pObject->IsLayer())) |
|
587 { |
|
588 if(pNextObject->IsSubFrame()) |
|
589 { |
|
590 pNextObject->ExecuteL(*this, res); |
|
591 } |
|
592 |
|
593 OnEndOfSubFrame(); |
|
594 } |
|
595 |
|
596 switch (iFramingMode) |
|
597 { |
|
598 case EMngFramNoBgLayerExcpt1stFgLayer: |
|
599 if (iDrawnLayerNum && iFrameBeingRendered && |
|
600 (pNextObject->IsLayer() || pNextObject->IsSubFrame()) |
|
601 ) |
|
602 { |
|
603 OnEndOfFrame(); |
|
604 } |
|
605 break; |
|
606 case EMngFramNoBgLayerExcpt1stImage: |
|
607 if (iFrameBeingRendered && pNextObject->IsSubFrame()) |
|
608 { |
|
609 OnEndOfFrame(); |
|
610 } |
|
611 break; |
|
612 case EMngFramBgLayerForEachFgLayer: |
|
613 if (iFrameBeingRendered && (pNextObject->IsSubFrame()|| |
|
614 (SubFrameLayerNum>1 && pNextObject->IsLayer() ))) |
|
615 { |
|
616 OnEndOfFrame(); |
|
617 } |
|
618 break; |
|
619 case EMngFramBgLayerFor1stFgLayer: |
|
620 if (pNextObject->IsSubFrame() && iDrawnLayerNum) |
|
621 { |
|
622 OnEndOfFrame(); |
|
623 } |
|
624 break; |
|
625 default: |
|
626 ASSERT(EFalse); |
|
627 } |
|
628 } |
|
629 else |
|
630 { |
|
631 OnEndOfFrame(ETrue, ETrue); |
|
632 } |
|
633 |
|
634 ++iCurrentObject; |
|
635 if (! iExecTimer->IsActive()) |
|
636 { |
|
637 MoreToRun = ( pNextObject!=NULL && !pNextObject->IsLayer() ); |
|
638 if (!MoreToRun) |
|
639 { |
|
640 RunAgain(); |
|
641 } |
|
642 } |
|
643 } |
|
644 break; |
|
645 case ECmdTerminate: |
|
646 if (iFrameBeingRendered) |
|
647 { |
|
648 OnEndOfFrame(ETrue, ETrue); |
|
649 iNotifyEvent |=KFinishedKeepOutputFlag; |
|
650 } |
|
651 else |
|
652 { |
|
653 StopDecode(); |
|
654 if(iMngSubframesNoLoops) |
|
655 { |
|
656 NotifyObserver(KFinishedKeepOutput, KErrNone, Ticks2TimeInterval(res.iDelayInTicks)); //Subframes with No Loops |
|
657 } |
|
658 else |
|
659 { |
|
660 NotifyObserver(KFinishedKeepOutput, KErrNone, TTimeIntervalMicroSeconds32(0)); |
|
661 } |
|
662 } |
|
663 |
|
664 break; |
|
665 case ECmdTerminateClearOutput: |
|
666 if (iFrameBeingRendered) |
|
667 { |
|
668 OnEndOfFrame(ETrue, ETrue); |
|
669 iNotifyEvent |= KFinishedEraseOutputFlag; |
|
670 } |
|
671 else |
|
672 { |
|
673 StopDecode(); |
|
674 NotifyObserver(KFinishedClearOutput, KErrNone, TTimeIntervalMicroSeconds32(0)); |
|
675 } |
|
676 break; |
|
677 case ECmdTerminateAfter1stFrame: |
|
678 case ECmdStartFromBeginning: |
|
679 { |
|
680 if (iFrameBeingRendered) |
|
681 { |
|
682 iState = EStNeedsRepeat; |
|
683 OnEndOfFrame(ETrue); |
|
684 i1stFrameInterframeDelay = iInterframeDelay + res.iDelayInTicks; |
|
685 } |
|
686 else |
|
687 { |
|
688 iState = EStReadyToPlay; |
|
689 i1stFrameInterframeDelay = iInterframeDelay + res.iDelayInTicks; |
|
690 StartPlay(); |
|
691 } |
|
692 } |
|
693 break; |
|
694 default: |
|
695 ASSERT(EFalse); |
|
696 } |
|
697 return MoreToRun; |
|
698 } |
|
699 |
|
700 |
|
701 CDelayTimer* CDelayTimer::NewL(CMngPlayer& aPlayer) |
|
702 { |
|
703 CDelayTimer* self=new (ELeave) CDelayTimer(aPlayer); |
|
704 CleanupStack::PushL(self); |
|
705 self->ConstructL(); |
|
706 CleanupStack::Pop(self); |
|
707 return self; |
|
708 } |
|
709 |
|
710 void CDelayTimer::RunL() |
|
711 { |
|
712 iPlayer.NotifyObserverGate(); |
|
713 } |
|
714 |
|
715 void CDelayTimer::RunNow() |
|
716 { |
|
717 SetActive(); |
|
718 iStatus = KRequestPending; |
|
719 TRequestStatus* p=&iStatus; |
|
720 User::RequestComplete(p, KErrNone); |
|
721 } |
|
722 |
|
723 void CMngPlayer::NotifyObserver(TObserverNotifyEvent aEvent, TInt aErrorCode, TTimeIntervalMicroSeconds32 aNotifyDelay) |
|
724 { |
|
725 if (iExecTimer->IsActive() || iOutstandingNotify) |
|
726 { |
|
727 MngPanic(EPanicObserverIsBusy); |
|
728 } |
|
729 ASSERT(iIsPaused==EFalse); |
|
730 iNominalDelayBeforeThisFrame = aNotifyDelay; |
|
731 iNotifyEvent = aEvent; |
|
732 iObserverNotifyArg = aErrorCode; |
|
733 #ifdef _DEBUG |
|
734 iNotifyStart.HomeTime(); |
|
735 #endif |
|
736 if (iPerformFrameDelayInternally && aNotifyDelay.Int() > 10000) |
|
737 { |
|
738 iExecTimer->After(aNotifyDelay); |
|
739 } |
|
740 else |
|
741 { |
|
742 iExecTimer->RunNow(); |
|
743 } |
|
744 } |
|
745 |
|
746 void CMngPlayer::NotifyObserverGate() |
|
747 { |
|
748 #ifdef _DEBUG |
|
749 TTime Now; |
|
750 Now.HomeTime(); |
|
751 LOG3("Notified after %d Net %d", I64LOW(Now.MicroSecondsFrom(iNotifyStart).Int64()), I64LOW(Now.MicroSecondsFrom(iLastNotify).Int64()) ); |
|
752 iLastNotify = Now; |
|
753 #endif |
|
754 if (iIsPaused) |
|
755 { |
|
756 iOutstandingNotify = ETrue; |
|
757 return; |
|
758 } |
|
759 iObserver.OnDecodeEvent(iNotifyEvent, iObserverNotifyArg); |
|
760 if (iEndOfFrameNotification) |
|
761 { |
|
762 iEndOfPreviuosFrame.HomeTime(); |
|
763 } |
|
764 iEndOfFrameNotification = EFalse; |
|
765 |
|
766 if (iState == EStPlaying) |
|
767 { |
|
768 RunAgain(); |
|
769 } |
|
770 else if (iState == EStNeedsRepeat) |
|
771 { |
|
772 StartPlay(); |
|
773 } |
|
774 } |
|
775 |
|
776 void CMngPlayer::SetLayerClipping(TMngFramChangeNextFrameOption aOption, const TRect& aClipRect, TBool aIsAdditive) |
|
777 { |
|
778 iChangeClippingBoundaries = aOption; |
|
779 if (aIsAdditive) |
|
780 { |
|
781 iCurrentClippingBnd.iTl.iX += aClipRect.iTl.iX; |
|
782 iCurrentClippingBnd.iTl.iY += aClipRect.iTl.iY; |
|
783 iCurrentClippingBnd.iBr.iX += aClipRect.iBr.iX; |
|
784 iCurrentClippingBnd.iBr.iY += aClipRect.iBr.iY; |
|
785 } |
|
786 else |
|
787 { |
|
788 iCurrentClippingBnd = aClipRect; |
|
789 } |
|
790 if (EMngFramChangeAndResetDefault == aOption) |
|
791 { |
|
792 iDefaultClippingBnd = iCurrentClippingBnd; |
|
793 } |
|
794 iMngRenderer->SetBgClipRect(iCurrentClippingBnd); |
|
795 } |
|
796 |
|
797 void CMngPlayer::SetInterFrameDelay(TMngFramChangeNextFrameOption aOption, TInt aTicks) |
|
798 { |
|
799 iChangeInterFrmDelay= aOption; |
|
800 if (aOption != EMngFramDoNotChange) |
|
801 { |
|
802 iNextInterFrameDelay = aTicks; |
|
803 } |
|
804 if (EMngFramChangeAndResetDefault == aOption) |
|
805 { |
|
806 iDefaultInterFrmDelay = aTicks; |
|
807 } |
|
808 } |
|
809 |
|
810 void CMngPlayer::SetMngHeader(TMhdrChunk*& aHeaderChunk) |
|
811 { |
|
812 if (aHeaderChunk) |
|
813 { |
|
814 delete iMngHeader; |
|
815 iMngHeader = aHeaderChunk; |
|
816 aHeaderChunk= NULL; |
|
817 } |
|
818 } |
|
819 |
|
820 void CMngPlayer::SetPixelFilter(MPixelFilter* aPixelFilter) |
|
821 { |
|
822 iMngRenderer->SetRgbFilter(aPixelFilter); |
|
823 } |
|
824 |
|
825 MImageStreamDecoderFactory& CMngPlayer::DecoderFactory() |
|
826 { |
|
827 return *iDecoderFactory; |
|
828 } |
|
829 |
|
830 void CMngPlayer::AddUniqueChunkProviderL(const TChunkId& aChunkId, MUniqueChunkDataProvider& aProvider) |
|
831 { |
|
832 TInt Size; |
|
833 const TUint8* Dummy; |
|
834 aProvider.GetChunkData(aChunkId.iChunkIdChr, Dummy, Size); |
|
835 if (Size > 0) |
|
836 { |
|
837 User::LeaveIfError( iChunkProviders.Add(TProviderEntry(aChunkId, aProvider)) ); |
|
838 } |
|
839 else |
|
840 { |
|
841 iChunkProviders.RemoveProvider(aChunkId); |
|
842 } |
|
843 } |
|
844 // from the MUniqueChunkDataProvider // |
|
845 TInt CMngPlayer::GetChunkData(const TText8* aChunkId, const TUint8*& aDataPtr, TInt& aSizeInBites) |
|
846 { |
|
847 aDataPtr = NULL; |
|
848 aSizeInBites= 0; |
|
849 MUniqueChunkDataProvider* Provider = iChunkProviders.Find(TChunkId::FromPtr(aChunkId)); |
|
850 return (Provider == NULL ? KErrNotFound : Provider->GetChunkData(aChunkId, aDataPtr, aSizeInBites) ); |
|
851 } |
|
852 |
|
853 |
|
854 RMngObjectList::TObjectIterator RMngObjectList::Find(TMngObjLabel aLabel) |
|
855 { |
|
856 for (TInt i=Count()-1; i > -1; --i) |
|
857 { |
|
858 if (aLabel == (*this)[i]->ObjectLabel() ) |
|
859 { |
|
860 return TObjectIterator(i); |
|
861 } |
|
862 } |
|
863 return End(); |
|
864 } |
|
865 |
|
866 void RMngObjectList::Destroy() |
|
867 { |
|
868 for (TInt i=Count()-1; i>-1; --i) |
|
869 { |
|
870 delete (*this)[i]; |
|
871 } |
|
872 Close(); |
|
873 } |
|
874 |
|
875 /*static*/ |
|
876 TInt RChunkProviders::OrderFunc(const TProviderEntry& aLeft, const TProviderEntry& aRight) |
|
877 { |
|
878 return aLeft.iId.iChunkIdInt - aRight.iId.iChunkIdInt; |
|
879 } |
|
880 |
|
881 TInt RChunkProviders::Add(const TProviderEntry& aItem) |
|
882 { |
|
883 TInt res=KErrNone; |
|
884 TInt idx = FindInOrder(aItem, TMyOrder(OrderFunc) ); |
|
885 if (idx>=0) |
|
886 { |
|
887 (*this)[idx] = aItem; |
|
888 } |
|
889 else |
|
890 { |
|
891 res=InsertInOrder(aItem, TMyOrder(RChunkProviders::OrderFunc) ); |
|
892 } |
|
893 return res; |
|
894 } |
|
895 |
|
896 void RChunkProviders::RemoveProvider(const TChunkId& aId) |
|
897 { |
|
898 TProviderEntry item; |
|
899 item.iId = aId; |
|
900 TInt idx = FindInOrder(item, TMyOrder(OrderFunc) ); |
|
901 ASSERT(idx >= 0); |
|
902 Remove(idx); |
|
903 } |
|
904 |
|
905 MUniqueChunkDataProvider* RChunkProviders::Find(const TChunkId& aId) |
|
906 { |
|
907 TProviderEntry item; |
|
908 item.iId = aId; |
|
909 TInt idx = FindInOrder(item, TMyOrder(OrderFunc) ); |
|
910 return (idx >= 0 ? (*this)[idx].iProvider : NULL); |
|
911 } |
|
912 |
|
913 void RChunkProviders::Clear() |
|
914 { |
|
915 Reset(); |
|
916 } |