os/mm/mmplugins/mmfwplugins/src/Plugin/Controller/Video/AviPlayController/aviplaycontroller.cpp
First public contribution.
1 // Copyright (c) 2006-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include "aviplaycontroller.h"
19 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
20 #include "srtreader.h"
21 #include "mmfdevsubtitle.h"
22 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
23 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
24 #include <mmf/common/mmfvideoenums.h>
27 const TInt KTestBufferSize = 0x10000;
28 _LIT8(KXvidDecoderMimeType,"video/mp4v-es");
29 _LIT8(KAviVideoCodec,"XVID");
31 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
32 _LIT(KSrtExtension, "srt");
33 _LIT(KSrtDecoder, "srtdecoder");
34 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
37 //Table that maps given samplerate with the MMF samplerate
38 const TSampleRateTable KRateLookup[]=
40 {96000,EMMFSampleRate96000Hz},
41 {88200,EMMFSampleRate88200Hz},
42 {48000,EMMFSampleRate48000Hz},
43 {44100,EMMFSampleRate44100Hz},
44 {32000,EMMFSampleRate32000Hz},
45 {22050,EMMFSampleRate22050Hz},
46 {16000,EMMFSampleRate16000Hz},
47 {11025,EMMFSampleRate11025Hz},
48 {8000, EMMFSampleRate8000Hz}
52 //This method generates a panic internal to this dll.
53 void CAviPlayController::Panic(TInt aPanicCode)
55 _LIT(KAviPlayControllerPanicCategory, "AviPlayController");
56 User::Panic(KAviPlayControllerPanicCategory, aPanicCode);
60 //This function creates an object of CAviPlayController.
61 CAviPlayController* CAviPlayController::NewL()
63 CAviPlayController* self = new(ELeave)CAviPlayController();
64 CleanupStack::PushL(self);
66 CleanupStack::Pop(self);
71 //Default Constructor of CAviPlayController
72 CAviPlayController::CAviPlayController() :
73 iVideoSurfaceSupport(NULL)
79 //Destructor of CAviPlayController.
80 CAviPlayController::~CAviPlayController()
82 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
85 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
87 iDisplayRegion.Close();
88 iDerivedClipRegion.Close();
95 RFbsSession::Disconnect();
98 //This constructs the custom command parsers of CAviPlayController.
99 void CAviPlayController::ConstructL()
101 CMMFVideoPlayControllerCustomCommandParser* vidPlayConParser = CMMFVideoPlayControllerCustomCommandParser::NewL(*this);
102 CleanupStack::PushL(vidPlayConParser);
103 AddCustomCommandParserL(*vidPlayConParser);
104 CleanupStack::Pop(vidPlayConParser);
106 CMMFVideoControllerCustomCommandParser* vidConParser = CMMFVideoControllerCustomCommandParser::NewL(*this);
107 CleanupStack::PushL(vidConParser);
108 AddCustomCommandParserL(*vidConParser);
109 CleanupStack::Pop(vidConParser);
111 CMMFAudioPlayDeviceCustomCommandParser* audPlayDevParser = CMMFAudioPlayDeviceCustomCommandParser::NewL(*this);
112 CleanupStack::PushL(audPlayDevParser);
113 AddCustomCommandParserL(*audPlayDevParser);
114 CleanupStack::Pop(audPlayDevParser);
116 CMMFResourceNotificationCustomCommandParser* notiParser = CMMFResourceNotificationCustomCommandParser::NewL(*this);
117 CleanupStack::PushL(notiParser);
118 AddCustomCommandParserL(*notiParser);
119 CleanupStack::Pop(notiParser);//audio resource Notification Parser
121 CMMFVideoSetInitScreenCustomCommandParser* vidScrDevParser = CMMFVideoSetInitScreenCustomCommandParser::NewL(*this);
122 CleanupStack::PushL(vidScrDevParser);
123 AddCustomCommandParserL(*vidScrDevParser);
124 CleanupStack::Pop(vidScrDevParser);
126 CMMFVideoPlayControllerExtCustomCommandParser* vidPlayExtParser = CMMFVideoPlayControllerExtCustomCommandParser::NewL(*this);
127 CleanupStack::PushL(vidPlayExtParser);
128 AddCustomCommandParserL(*vidPlayExtParser);
129 CleanupStack::Pop(vidPlayExtParser);
131 #ifdef SYMBIAN_BUILD_GCE
132 CMMFVideoPlaySurfaceSupportCustomCommandParser* vidPlaySurfaceSupParser = CMMFVideoPlaySurfaceSupportCustomCommandParser::NewL(*this);
133 CleanupStack::PushL(vidPlaySurfaceSupParser);
134 AddCustomCommandParserL(*vidPlaySurfaceSupParser);
135 CleanupStack::Pop(vidPlaySurfaceSupParser);
136 #endif // SYMBIAN_BUILD_GCE
138 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
139 CMMFVideoPlaySubtitleSupportCustomCommandParser * vidPlaySubtitleSupParser = CMMFVideoPlaySubtitleSupportCustomCommandParser::NewL(*this);
140 CleanupStack::PushL(vidPlaySubtitleSupParser);
141 AddCustomCommandParserL(*vidPlaySubtitleSupParser);
142 CleanupStack::Pop(vidPlaySubtitleSupParser);
143 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
145 iEventHandler = new(ELeave) CSourceSinkEventHandler(*this);
146 iAudioEnabled = EFalse;
147 User::LeaveIfError(RFbsSession::Connect());
151 //Adds a data source to the controller
152 void CAviPlayController::AddDataSourceL(MDataSource& aDataSource)
154 if (iState != EStopped)
156 User::Leave(KErrNotReady);
160 User::Leave(KErrAlreadyExists);
162 if (aDataSource.DataSourceType()==KUidMmfFileSource)
164 iClip = static_cast<CMMFFile*>(&aDataSource);
165 iAviReader = CAviReader::NewL(*iClip,*this);
166 User::LeaveIfError(iClip->SourceThreadLogon(*iEventHandler));
167 iAviReader->AudioEnabled(iAudioEnabled);
171 User::Leave(KErrNotSupported);
173 TMMFEvent controllerEvent;
174 controllerEvent.iEventType = KMMFEventCategoryVideoOpenComplete;
175 controllerEvent.iErrorCode = KErrNone;
176 DoSendEventToClient(controllerEvent);
180 //Adds a data sink to the controller
181 void CAviPlayController::AddDataSinkL(MDataSink& aDataSink)
183 if (iState != EStopped)
185 User::Leave(KErrNotReady);
189 User::Leave(KErrAlreadyExists);
191 if (aDataSink.DataSinkType()!=KUidMmfAudioOutput)
193 User::Leave(KErrNotSupported);
195 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(&aDataSink);
196 User::LeaveIfError(audioOutput->SinkThreadLogon(*iEventHandler));
197 iDevSound = &(audioOutput->SoundDevice());
198 iDevSound->SetPrioritySettings(iPrioritySettings);
199 if (IsSecureDrmModeL())
201 User::LeaveIfError(iDevSound->SetClientThreadInfo(ClientThreadIdL()));
206 TRAPD(err, iScreenDev = CFbsScreenDevice::NewL(iScreenNumber,EColor16MA));
207 if (err == KErrNotSupported)
209 TRAP(err, iScreenDev = CFbsScreenDevice::NewL(iScreenNumber,EColor16M));
211 if (err == KErrNotSupported)
213 TRAP(err, iScreenDev = CFbsScreenDevice::NewL(iScreenNumber,EColor64K));
215 if (err == KErrNotSupported)
217 TRAP(err, iScreenDev = CFbsScreenDevice::NewL(iScreenNumber,EColor4K));
219 if (err == KErrNotSupported)
221 TRAP(err, iScreenDev = CFbsScreenDevice::NewL(iScreenNumber,EColor256));
223 if (err == KErrNotSupported)
225 TRAP(err, iScreenDev = CFbsScreenDevice::NewL(iScreenNumber,EColor16MAP));
228 User::LeaveIfError(err);
231 User::LeaveIfError(iScreenDev->CreateContext(iScreenGc));
232 iScreenGc->SetPenColor(KRgbBlack);
233 iScreenGc->SetBrushColor(KRgbWhite);
234 iScreenGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
235 delete iDevVideoPlay;
236 iDevVideoPlay = NULL;
237 iDevVideoPlay = CMMFDevVideoPlay::NewL(*this);
238 iVideoDecoderInitialized = EFalse;
242 //Removes the data source from the controller
243 void CAviPlayController::RemoveDataSourceL(MDataSource& aDataSource)
245 if (iState != EStopped)
247 User::Leave(KErrNotReady);
251 User::Leave(KErrNotReady);
253 if (iClip != &aDataSource)
255 User::Leave(KErrArgument);
266 //Removes the data sink from the controller
267 void CAviPlayController::RemoveDataSinkL(MDataSink& aDataSink)
269 if ((!iDevSound) || (iState!= EStopped))
271 User::Leave(KErrNotReady);
273 if (aDataSink.DataSinkType() != KUidMmfAudioOutput)
275 User::Leave(KErrNotSupported);
277 MMMFAudioOutput* audioOutput = static_cast<MMMFAudioOutput*>(&aDataSink);
278 CMMFDevSound& devSound = audioOutput->SoundDevice();
279 if (iDevSound != &devSound)
281 User::Leave(KErrArgument);
287 delete iDevVideoPlay;
288 iDevVideoPlay = NULL;
294 //Resets the controller
295 void CAviPlayController::ResetL()
299 delete iDevVideoPlay;
300 iDevVideoPlay = NULL;
309 //Primes the controller
310 void CAviPlayController::PrimeL(TMMFMessage& aMessage)
312 if (iState != EStopped)
314 User::Leave( KErrNotReady );
318 User::Leave(KErrNotReady);
324 User::Leave(KErrNotReady);
327 __ASSERT_ALWAYS((!iMessage),Panic(EBadCall));
328 iMessage = CMMFMessageHolder::NewL(aMessage);
329 TRAPD(err,StartPrimeL());
332 SendErrorToClient(err);
337 void CAviPlayController::PrimeL()
343 //Primes the controller
344 void CAviPlayController::StartPrimeL()
346 CheckAviReaderPresentL();
347 CheckDevVideoPresentL();
348 iAviReader->AudioEnabled(iAudioEnabled);
349 iClip->SourcePrimeL();
350 // Initialise Devsound
353 iDevSound->InitializeL(*this, EMMFStatePlaying);
355 if(!iVideoDecoderInitialized)
357 if (!iVideoSurfaceSupport)
359 if (LocateDecoderL(EFalse))
361 // Set the video destination as Screen.This will leave if the
362 // plug-in does not support DSA.
363 iDevVideoPlay->SetVideoDestScreenL(ETrue);
364 // Initialize devvideoPlay
365 iDevVideoPlay->Initialize();
369 // Inform client if we couldn't find a suitable decoder.
370 SendErrorToClient(KErrNotFound);
375 // Decoder already located, done in UseSurfaces
376 iDevVideoPlay->Initialize();
383 iDevVideoInitialized = ETrue;
389 iMessage->Complete(KErrNone);
399 TBool CAviPlayController::LocateDecoderL(TBool aUseSurfaces)
402 RArray<TUid> foundDecodersArray;
403 CleanupClosePushL(foundDecodersArray);
404 iDevVideoPlay->FindDecodersL(KXvidDecoderMimeType,
405 0, // post-processing
406 // support is not needed
409 TBool suitableDecoderFound = EFalse;
410 if(foundDecodersArray.Count() > 0)
412 TUncompressedVideoFormat reqOutFormat;
413 // Prefer RGB over YUV in case of graphics surfaces.
416 reqOutFormat.iDataFormat = ERgbRawData;
417 reqOutFormat.iRgbFormat = ERgb32bit888;
421 reqOutFormat.iDataFormat = ERgbFbsBitmap;
422 reqOutFormat.iRgbFormat = EFbsBitmapColor16M;
425 // Here, we pick a decoder that can handle the output format
427 suitableDecoderFound =
428 SelectFirstSuitableDecoderL(foundDecodersArray, reqOutFormat, aUseSurfaces);
431 CleanupStack::PopAndDestroy(&foundDecodersArray);
432 return suitableDecoderFound;
436 // Selection of a suitable decoder based on the output format required
438 TBool CAviPlayController::SelectFirstSuitableDecoderL(
439 const RArray<TUid>& aDecodersArray,
440 const TUncompressedVideoFormat& aRequiredOutputFormat,
441 #ifdef SYMBIAN_BUILD_GCE
444 TBool /* aUseSurfaces */
445 #endif // SYMBIAN_BUILD_GCE
448 RArray<TUncompressedVideoFormat> outputFormatsArray;
449 CleanupClosePushL(outputFormatsArray);
450 TBool suitableDecoderFound = EFalse;
451 TInt numDecoders = aDecodersArray.Count();
452 for (TInt i = 0; !suitableDecoderFound && i < numDecoders; i++)
454 iDecoderDeviceId = iDevVideoPlay->SelectDecoderL(aDecodersArray[i]);
456 #ifdef SYMBIAN_BUILD_GCE
459 // try to access the interface for video surfaces in dev video
460 iVideoSurfaceSupport = static_cast<MMMFVideoSurfaceSupport*>(iDevVideoPlay->CustomInterface(iDecoderDeviceId, KUidMMFVideoSurfaceSupport));
462 if (!iVideoSurfaceSupport)
467 #endif // SYMBIAN_BUILD_GCE
469 iDevVideoPlay->GetOutputFormatListL(iDecoderDeviceId,
471 if (outputFormatsArray.Find(aRequiredOutputFormat) !=
474 iDevVideoPlay->SetOutputFormatL(iDecoderDeviceId,
475 aRequiredOutputFormat);
477 #ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT
478 CVideoDecoderInfo* pCVideoDecoderInfo =
479 iDevVideoPlay->VideoDecoderInfoLC(aDecodersArray[i]);
480 RArray<TInt> supportedScreensArray;
481 CleanupClosePushL(supportedScreensArray);
482 pCVideoDecoderInfo->GetSupportedScreensL(supportedScreensArray);
483 // If supportedScreensArray.Count() is zero, it implies that
484 // decoder does not support any specific screens and it should be
485 // able to support any screen. Continue to initialize DevVideoPlay.
487 if(supportedScreensArray.Count() > 0)
489 // The decoder supports specific screens. Check if it supports
490 // the screen number set by the client.
491 err = supportedScreensArray.Find(iScreenNumber);
493 // If err is KErrNotFound, it implies that the decoder does not
494 // support the given screen and hence not suitable for the client.
495 // check if the next decoder in the list is suitable.
496 if(KErrNotFound != err)
498 // Suitable decoder is found.
499 iDevVideoInitialized = EFalse;
500 suitableDecoderFound = ETrue;
502 // supportedScreensArray, pCVideoDecoderInfo
503 CleanupStack::PopAndDestroy(2, pCVideoDecoderInfo);
505 iDevVideoInitialized = EFalse;
506 suitableDecoderFound = ETrue;
509 outputFormatsArray.Reset();
511 CleanupStack::PopAndDestroy(&outputFormatsArray);
513 return suitableDecoderFound;
517 //Starts playing and transfers the data from data source to data sink.
518 void CAviPlayController::PlayL()
520 if (iState != EPrimed )
522 User::Leave(KErrNotReady);
524 iClip->SourcePlayL();
526 if (iVideoSurfaceSupport == NULL)
528 iDevVideoPlay->StartDirectScreenAccessL(iScreenRect,*iScreenDev,iDerivedClipRegion);
531 iDevVideoPlay->Start();
534 iDevSound->PlayInitL();
535 iState = EAudioReadyToPlay;
542 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
546 iDevSubtitle->SetVideoPositionL(0);
547 iDevSubtitle->Start();
548 iDevSubtitleStarted = ETrue;
550 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
554 //Pause playing and the data transfer from data source to data sink.
555 void CAviPlayController::PauseL()
557 User::Leave(KErrNotSupported);
561 //Stops playing and the data transfer from data source to data sink.
562 void CAviPlayController::StopL()
564 if (iState == EStopped)
572 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
574 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
580 //Returns the current playing position from devvideoplay.
581 TTimeIntervalMicroSeconds CAviPlayController::PositionL() const
583 if (iState == EStopped)
587 CheckDevVideoPresentL();
588 return iDevVideoPlay->PlaybackPosition();
592 //Set the position to play from.
593 void CAviPlayController::SetPositionL(const TTimeIntervalMicroSeconds& /*aPosition*/)
595 //This will leave with KErrNotsupported as there is no support for seeking
596 //position in an .avi file.
597 User::Leave(KErrNotSupported);
601 //Returns the duration of the clip.
602 TTimeIntervalMicroSeconds CAviPlayController::DurationL() const
604 CheckAviReaderPresentL();
605 return iAviReader->Duration();
609 //Handles a custom command.
610 void CAviPlayController::CustomCommand(TMMFMessage& aMessage)
612 aMessage.Complete(KErrNotSupported);
616 //Sets the priority settings for devsound.
617 void CAviPlayController::SetPrioritySettings(const TMMFPrioritySettings& aPrioritySettings)
619 iPrioritySettings = aPrioritySettings;
622 iDevSound->SetPrioritySettings(aPrioritySettings);
627 //Gets the number of meta entries in the clip.
628 void CAviPlayController::GetNumberOfMetaDataEntriesL(TInt& /*aNumberOfEntries*/)
630 //Support to get meta data is not present.so this will leave with KErrNotSupported.
631 User::Leave(KErrNotSupported);
636 //Gets a meta entry at a specified index.
637 CMMFMetaDataEntry* CAviPlayController::GetMetaDataEntryL(TInt /*aIndex*/)
639 //Support to get meta data is not present.so this will leave with KErrNotSupported.
640 User::Leave(KErrNotSupported);
644 //----------------------------------------------- //
645 // MMMFVideoPlayControllerCustomCommandImplementor //
646 //-----------------------------------------------//
649 //Sets the screen clip region
650 void CAviPlayController::MvpcUpdateDisplayRegionL(const TRegion& aRegion)
652 // Only update display region if not using graphics surfaces
653 if (!iVideoSurfaceSupport)
655 iDisplayRegion.Copy(aRegion);
661 //Gets the previously requested frame
662 void CAviPlayController::MvpcGetFrameL(MMMFVideoFrameMessage& aMessage)
664 CFbsBitmap& bitmap = aMessage.GetBitmap();
665 TRAPD(err, CopyFrameL(bitmap));
666 aMessage.FrameReady(err);
670 //Copies the previously requested frame
671 void CAviPlayController::CopyFrameL(CFbsBitmap& aBitmap)
673 CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
674 CleanupStack::PushL(bitmap);
675 User::LeaveIfError(aBitmap.Resize(bitmap->SizeInPixels()));
676 CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(&aBitmap);
677 CleanupStack::PushL(bitmapDevice);
678 CFbsBitGc* gc = NULL;
679 User::LeaveIfError(bitmapDevice->CreateContext(gc));
680 gc->DrawBitmap(TPoint(0,0), bitmap);
683 CleanupStack::PopAndDestroy(2,bitmap);//for bitmapdevice and bitmap.
687 //Gets if audio is enabled during playing.
688 void CAviPlayController::MvpcGetAudioEnabledL(TBool& aEnabled)
690 CheckAviReaderPresentL();
691 iAviReader->AudioEnabled(iAudioEnabled);
692 aEnabled = iAudioEnabled;
696 //Sets the display window on the screen.
697 void CAviPlayController::MvpcSetDisplayWindowL(const TRect& aWindowRect, const TRect& aClipRect)
699 if (iVideoSurfaceSupport != NULL)
701 User::Leave(KErrNotSupported);
704 iScreenRect= aWindowRect;
705 iClipRect = aClipRect;
711 //Aborts or resumes direct screen access depends on the DSA event received
712 void CAviPlayController::MvpcDirectScreenAccessEventL(const TMMFDSAEvent aDSAEvent)
714 if (iVideoSurfaceSupport != NULL)
716 User::Leave(KErrNotSupported);
719 CheckDevVideoPresentL();
720 if (aDSAEvent == EAbortDSA)
722 if(iState == EPlaying)
724 iDevVideoPlay->AbortDirectScreenAccess();
727 else if (aDSAEvent == EResumeDSA)
729 if((iState == EPrimed)||(iState == EPlaying))
731 iDevVideoPlay->StartDirectScreenAccessL(iScreenRect,*iScreenDev,iDerivedClipRegion);
736 //Plays videoclip within the playwindow set
737 void CAviPlayController::MvpcPlayL(const TTimeIntervalMicroSeconds& /*aBegin*/,const TTimeIntervalMicroSeconds& /*aEnd*/)
739 //This will leave with KErrNotSupported as there is no provision to
740 // seek the position in an .avi file.
741 User::Leave(KErrNotSupported);
745 //Redraws the current frame
746 void CAviPlayController::MvpcRefreshFrameL()
748 CheckDevVideoPresentL();
749 iDevVideoPlay->Redraw();
753 //Gets the progress of loading video clip
754 void CAviPlayController::MvpcGetLoadingProgressL(TInt& /*aPercentage*/)
756 //This will leave with KErrNotSuuported as there is no support
757 User::Leave(KErrNotSupported);
761 //Prepares the controller for recording.
762 void CAviPlayController::MvpcPrepare()
764 TMMFEvent controllerEvent;
765 controllerEvent.iEventType = KMMFEventCategoryVideoPrepareComplete;
766 controllerEvent.iErrorCode = KErrNone;
767 DoSendEventToClient(controllerEvent);
771 //Rotates the video file on the screen with the rotation angle given.
772 void CAviPlayController::MvpcSetRotationL(TVideoRotation aRotation)
774 //this will leave with KErrNotSupported as the Xvid Hwdevice does not support post processing.
775 iRotation = aRotation;
776 User::Leave(KErrNotSupported);
780 //Gets the rotation applied to the video file.
781 void CAviPlayController::MvpcGetRotationL(TVideoRotation& aRotation)
783 //this will leave with KErrNotSupported as the Xvid Hwdevice does not support post processing.
784 aRotation = iRotation;
785 User::Leave(KErrNotSupported);
789 //Scales the the video file on the screen with the scaling parameters given.
790 void CAviPlayController::MvpcSetScaleFactorL(TReal32 aWidthPercentage, TReal32 aHeightPercentage, TBool aAntiAliasFiltering)
792 //this will leave with KErrNotSupported as the Xvid Hwdevice does not support post processing.
793 iWidthPercentage = aWidthPercentage;
794 iHeightPercentage = aHeightPercentage;
795 iAntiAliasFiltering = aAntiAliasFiltering;
796 User::Leave(KErrNotSupported);
800 //Gets the scale factor applied for the video file.
801 void CAviPlayController::MvpcGetScaleFactorL(TReal32& aWidthPercentage, TReal32& aHeightPercentage, TBool& aAntiAliasFiltering)
803 //this will leave with KErrNotSupported as the Xvid Hwdevice does not support post processing.
804 aWidthPercentage = iWidthPercentage;
805 aHeightPercentage = iHeightPercentage;
806 aAntiAliasFiltering = iAntiAliasFiltering;
807 User::Leave(KErrNotSupported);
811 //Sets the crop options for the image.
812 void CAviPlayController::MvpcSetCropRegionL(const TRect& aCropRegion)
814 //this will leave with KErrNotSupported as the Xvid Hwdevice does not support post processing.
815 iCropRect = aCropRegion;
816 User::Leave(KErrNotSupported);
820 //Gets the crop options of the image.
821 void CAviPlayController::MvpcGetCropRegionL(TRect& aCropRegion)
823 //this will leave with KErrNotSupported as the Xvid Hwdevice does not support post processing.
824 aCropRegion = iCropRect;
825 User::Leave(KErrNotSupported);
829 //Sets the video frame rate for recording.
830 void CAviPlayController::MvcSetFrameRateL(TReal32 /*aFramesPerSecond*/)
832 //There are no apis available at devvideo level to do this.
833 //so, this will leave with KErrNotSupported.
834 User::Leave(KErrNotSupported);
838 //Gets the video frame rate applied for playing
839 void CAviPlayController::MvcGetFrameRateL(TReal32& aFramesPerSecond)
841 CheckAviReaderPresentL();
842 iAviReader->FrameRate(aFramesPerSecond);
846 //Gets the audio codec used for playing.
847 void CAviPlayController::MvcGetAudioCodecL(TFourCC& aCodec)
851 aCodec = KMMFFourCCCodePCM16;
852 CheckAviReaderPresentL();
853 iAviReader->AudioCodec(aCodec);
857 User::Leave(KErrNotSupported);
862 //Gets the video codec used for playing.
863 void CAviPlayController::MvcGetVideoMimeTypeL(TDes8& aMimeType)
865 CheckAviReaderPresentL();
866 aMimeType = KAviVideoCodec;
867 iAviReader->VideoMimeType(aMimeType);
871 //Gets the video bit rate used for playing.
872 void CAviPlayController::MvcGetVideoBitRateL(TInt& /*aBitRate*/)
874 //There are no devvideo api's to do this.
875 //so, leave with KErrNotSuported.
876 User::Leave(KErrNotSupported);
880 //Gets the audio bit rate used for playing.
881 void CAviPlayController::MvcGetAudioBitRateL(TInt& aBitRate)
883 CheckAviReaderPresentL();
886 aBitRate = (iAviReader->BitsPerSample() * iAviReader->SampleRate()* iAviReader->Channels());
890 User::Leave(KErrNotSupported);
895 //Returns the video framesize of the file.
896 void CAviPlayController::MvcGetVideoFrameSizeL(TSize& aSize)
898 CheckAviReaderPresentL();
899 iAviReader->VideoFrameSize(aSize);
904 //Sets the volume during playing.
905 void CAviPlayController::MapdSetVolumeL(TInt aVolume)
909 CheckDevSoundPresentL();
910 TInt maxVolume = iDevSound->MaxVolume();
911 iDevSound->SetVolume(aVolume);
915 User::Leave(KErrNotSupported);
920 //Gets the maximum audio volume for playing.
921 void CAviPlayController::MapdGetMaxVolumeL(TInt& aMaxVolume)
925 CheckDevSoundPresentL();
926 aMaxVolume = iDevSound->MaxVolume();
930 User::Leave(KErrNotSupported);
935 //Gets the volume for playing
936 void CAviPlayController::MapdGetVolumeL(TInt& aVolume)
940 CheckDevSoundPresentL();
941 aVolume = iDevSound->Volume();
945 User::Leave(KErrNotSupported);
950 //Gets the volume ramp for playing
951 void CAviPlayController::MapdSetVolumeRampL(const TTimeIntervalMicroSeconds& aRampDuration)
955 CheckDevSoundPresentL();
956 iDevSound->SetVolumeRamp(aRampDuration);
960 User::Leave(KErrNotSupported);
965 //Set the audio balance for playing.
966 void CAviPlayController::MapdSetBalanceL(TInt aBalance)
970 CheckDevSoundPresentL();
971 if (aBalance < KMMFBalanceMaxLeft)
973 aBalance = KMMFBalanceMaxLeft;
975 else if (aBalance > KMMFBalanceMaxRight)
977 aBalance = KMMFBalanceMaxRight;
979 TInt left = (100 * (aBalance-KMMFBalanceMaxRight)) / (KMMFBalanceMaxLeft-KMMFBalanceMaxRight);
980 TInt right = 100 - left;
981 iDevSound->SetPlayBalanceL(left, right);
985 User::Leave(KErrNotSupported);
990 //Get the audio balance applied for playing
991 void CAviPlayController::MapdGetBalanceL(TInt& aBalance)
995 CheckDevSoundPresentL();
996 TInt left = 50; // arbitrary values
998 iDevSound->GetPlayBalanceL(left, right);
999 if ((left > 0) && (right > 0))
1001 aBalance = (left * (KMMFBalanceMaxLeft-KMMFBalanceMaxRight))/100 + KMMFBalanceMaxRight;
1003 else if ((left == 0) && (right == 0))
1007 else if ((left == 0) && (right > 0))
1011 else if ((left > 0) && (right == 0))
1018 User::Leave(KErrNotSupported);
1023 //Checks if valid devsound object is present.
1024 void CAviPlayController::CheckDevSoundPresentL()
1028 User::Leave(KErrNotReady);
1033 //Checks if valid devvideoplay object present
1034 void CAviPlayController::CheckDevVideoPresentL() const
1036 if (iDevVideoPlay && iVideoFatalError)
1038 // A fatal error occured. This will recreate the DevVideo instance and
1039 // also will clear iVideoFatalError flag. We use the cast operator here
1040 // as we need to modify member data.
1041 const_cast<CAviPlayController*>(this)->RecreateDevVideoAfterFatalErrorL();
1045 User::Leave(KErrNotReady);
1050 //Checks if valid avireader object present.
1051 void CAviPlayController::CheckAviReaderPresentL() const
1055 User::Leave(KErrNotReady);
1060 //New empty buffers are available for decoding.Fill the video buffer
1061 //with video data and send it for decoding.
1062 void CAviPlayController:: MdvpoNewBuffers()
1064 TVideoInputBuffer* newBuffer = NULL;
1066 ASSERT(iDevVideoPlay);
1067 if (!iAviReader->IsVideoInputEnd())
1069 // get a buffer of a minimum size from DevVideoPlay.
1070 TRAPD(error, newBuffer = iDevVideoPlay->GetBufferL(KTestBufferSize));
1073 //Lack of free buffers are not considered as an error.Hence return.
1077 TRAP(error, iAviReader->FillVideoBufferL(newBuffer));
1078 if (error != KErrNone)
1080 SendErrorToClient(error);
1083 if(iAviReader->IsVideoInputEnd())
1085 TRAPD(error,iDevVideoPlay->WriteCodedDataL(newBuffer));
1086 if (error!= KErrNone)
1088 SendErrorToClient(error);
1091 iDevVideoPlay->InputEnd();
1097 //Fatal error occured while decoding video.Send the error to client.
1098 void CAviPlayController::MdvpoFatalError(TInt aError)
1100 // No need to stop Video as this call back already implies a video problem,
1101 // therefore it is supposed to be stopped (trying to stop it twice will
1102 // cause a panic in devvideo).
1103 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
1105 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
1106 TRAP_IGNORE(StopAudioL(); StopAviReaderL());
1107 // At this point we have to recreate the DevVideo instance. Since it is not
1108 // safe to delete the instance inside this error call back, we use a flag
1109 // so the next time we need to use DevVideo it will be recreated.
1110 iVideoFatalError = ETrue;
1111 iDevVideoInitialized = EFalse;
1112 iVideoDecoderInitialized = EFalse;
1114 SendErrorToClient(aError);
1118 //Notifies the client that there are one or more new pictures are available.
1119 void CAviPlayController::MdvpoNewPictures()
1121 // dispose of the picture
1122 TVideoPicture* thePicture= NULL;
1123 ASSERT(iDevVideoPlay);
1124 TRAPD(err, thePicture = iDevVideoPlay->NextPictureL());
1125 if (err == KErrNone && thePicture != NULL)
1127 iDevVideoPlay->ReturnPicture(thePicture);
1132 //Initialization complete for devvideoplay.If audio is not enabled
1133 //set state to EPrimed.
1134 void CAviPlayController::MdvpoInitComplete(TInt aError)
1136 if (aError != KErrNone)
1138 SendErrorToClient(aError);
1141 iDevVideoInitialized = ETrue;
1142 // if audio is enabled we need to wait for both the audio and video initializations
1143 //before completing client's prime message.
1144 CheckForInitComplete();
1148 //End of the video data in the file.
1149 void CAviPlayController::MdvpoStreamEnd()
1151 TRAP_IGNORE(StopL());
1152 SendErrorToClient(KErrNone);
1156 //Intended for future use.Will panic if called.
1157 void CAviPlayController:: MdvpoReturnPicture(TVideoPicture* /*aPicture*/)
1163 //Intended for future use.Will panic if called.
1164 void CAviPlayController::MdvpoSupplementalInformation(const TDesC8 &/*aData*/, const TTimeIntervalMicroSeconds &/*aTimestamp*/, const TPictureId &/*aPictureId*/)
1170 //Intended for future use.Will panic if called.
1171 void CAviPlayController:: MdvpoPictureLoss()
1177 //Intended for future use.Will panic if called.
1178 void CAviPlayController::MdvpoPictureLoss(const TArray< TPictureId > &/*aPictures*/)
1184 //Intended for future use.Will panic if called.
1185 void CAviPlayController:: MdvpoSliceLoss(TUint /*aFirstMacroblock*/, TUint /*aNumMacroblocks*/, const TPictureId &/*aPicture*/)
1191 //Intended for future use.Will panic if called.
1192 void CAviPlayController::MdvpoReferencePictureSelection(const TDesC8 &/*aSelectionData*/)
1198 //Intended for future use.Will panic if called.
1199 void CAviPlayController::MdvpoTimedSnapshotComplete(TInt /*aError*/, TPictureData */*aPictureData*/, const TTimeIntervalMicroSeconds &/*aPresentationTimestamp*/, const TPictureId &/*aPictureId*/)
1204 //Sets the initial screen number for the video display
1205 void CAviPlayController::MvsdSetInitScreenNumber(TInt aScreenNumber)
1207 iScreenNumber = aScreenNumber;
1210 #ifdef SYMBIAN_BUILD_GCE
1211 void CAviPlayController::MvpssUseSurfacesL()
1213 // UseSurfaces must happen before initialize
1214 if (!iDevVideoPlay || iVideoDecoderInitialized)
1216 User::Leave(KErrNotReady);
1219 // Calling UseSurfaces multiple times is allowed
1221 if (iVideoSurfaceSupport == NULL)
1223 if (LocateDecoderL(ETrue) && iVideoSurfaceSupport != NULL)
1225 iVideoSurfaceSupport->MmvssSetObserver(*this);
1226 iVideoSurfaceSupport->MmvssUseSurfaces();
1230 // iVideoSurfaceSupport will be updated in LocateDecoderL
1231 if (iVideoSurfaceSupport == NULL)
1233 User::Leave(KErrNotSupported);
1237 void CAviPlayController::MvpssGetSurfaceParametersL(TSurfaceId& aSurfaceId, TRect& aCropRect,
1238 TVideoAspectRatio& aPixelAspectRatio)
1240 if (iVideoSurfaceSupport == NULL)
1242 User::Leave(KErrNotSupported);
1245 iVideoSurfaceSupport->MmvssGetSurfaceParametersL(aSurfaceId, aCropRect, aPixelAspectRatio);
1248 void CAviPlayController::MvpssSurfaceRemovedL(const TSurfaceId& aSurfaceId)
1250 if (iVideoSurfaceSupport == NULL)
1252 User::Leave(KErrNotSupported);
1255 iVideoSurfaceSupport->MmvssSurfaceRemovedL(aSurfaceId);
1258 void CAviPlayController::MmvsoSurfaceCreated()
1260 DoSendEventToClient(TMMFEvent(KMMFEventCategoryVideoSurfaceCreated, KErrNone));
1263 void CAviPlayController::MmvsoSurfaceParametersChanged()
1265 DoSendEventToClient(TMMFEvent(KMMFEventCategoryVideoSurfaceParametersChanged, KErrNone));
1268 void CAviPlayController::MmvsoRemoveSurface()
1270 DoSendEventToClient(TMMFEvent(KMMFEventCategoryVideoRemoveSurface, KErrNone));
1272 #endif // SYMBIAN_BUILD_GCE
1274 //Devsound initialization is completed.Configure devsound capabilities.
1275 void CAviPlayController::InitializeComplete(TInt aError)
1277 TInt error = aError;
1278 if (error == KErrNone)
1281 TMMFCapabilities devSoundCaps = iDevSound->Capabilities();
1282 TMMFCapabilities caps;
1284 TInt rate = iAviReader->SampleRate();
1285 TBool found = EFalse;
1286 for( TInt index =0; index < KNumSampleRates; index++)
1288 if(rate == KRateLookup[index].iRate)
1290 caps.iRate = KRateLookup[index].iRateEnum;
1296 error = KErrNotFound;
1298 if(error == KErrNone)
1300 caps.iChannels = iAviReader->Channels();
1301 if (caps.iChannels == 1)
1303 caps.iChannels = EMMFMono;
1305 else if (caps.iChannels == 2)
1307 caps.iChannels = EMMFStereo;
1311 error = KErrNotFound;
1314 if(error == KErrNone)
1316 caps.iEncoding = EMMFSoundEncoding16BitPCM;
1317 TRAP(error,iDevSound->SetConfigL(caps));
1318 if(error == KErrNone)
1320 iDevSoundInitialized = ETrue;
1321 CheckForInitComplete();
1327 SendErrorToClient(error);
1332 //Intended for future use.Will panic if called.
1333 void CAviPlayController::ToneFinished(TInt /*aError*/)
1339 //This is called when an empty audio buffer is available.Fill the buffer with audio data.
1340 void CAviPlayController::BufferToBeFilled(CMMFBuffer* aBuffer)
1342 if (iState == EAudioReadyToPlay)
1347 TRAPD(err, iAviReader->FillAudioBufferL(aBuffer));
1348 //if error,send the error to client
1351 SendErrorToClient(err);
1355 //This is called when an audio play completion is successfully played or otherwise
1356 void CAviPlayController::PlayError(TInt aError)
1360 // Ignore overflow when the end of audio is reached.
1361 if(aError == KErrUnderflow && iAviReader->IsAudioInputEnd())
1363 // audio has reached the end of the file
1367 // Controller will be stopped and play complete message sent when the video stream
1368 // has ended, unless there is an error.
1369 if (aError != KErrNone)
1371 TRAP_IGNORE(StopL());
1372 SendErrorToClient(aError);
1376 //Will panic if called.Should not be called during playing
1377 void CAviPlayController::BufferToBeEmptied(CMMFBuffer* /*aBuffer*/)
1383 //Will panic if called.Should not be called during playing
1384 void CAviPlayController::RecordError(TInt /*aError*/)
1390 //Will panic if called.Should not be called during playing
1391 void CAviPlayController::ConvertError(TInt /*aError*/)
1397 //Will panic if called.Should not be called during playing
1398 void CAviPlayController::DeviceMessage(TUid /*aMessageType*/, const TDesC8& /*aMsg*/)
1404 //Sends an event to client.
1405 void CAviPlayController::SendEventToClient(const TMMFEvent& aEvent)
1407 DoSendEventToClient(aEvent);
1411 //This function is called when an empty audio buffer filled with audio data.
1412 //This can now be sent to devsound for decoding.
1413 void CAviPlayController::AudioBufferFilled()
1416 iDevSound->PlayData();
1420 //This function is called when an empty video buffer is filled with video data.
1421 //This can now be sent for decoding.If there is no data then inform devvideo
1422 //about end of video stream.
1423 void CAviPlayController::VideoBufferFilled(TVideoInputBuffer* aBuffer)
1425 ASSERT(iDevVideoPlay);
1427 TRAPD(error,iDevVideoPlay->WriteCodedDataL(aBuffer));
1428 if(error != KErrNone)
1430 SendErrorToClient(error);
1433 if(iAviReader->IsVideoInputEnd())
1435 iDevVideoPlay->InputEnd();
1441 //This function is used when both audio and video are enabled for playing.
1442 //The State is set to EPrimed when initialization is completed on both DevSound and DevVideo
1443 void CAviPlayController::CheckForInitComplete()
1447 if ((iDevVideoInitialized) &&(iDevSoundInitialized))
1452 iMessage->Complete(KErrNone);
1464 iMessage->Complete(KErrNone);
1469 iVideoDecoderInitialized = ETrue;
1472 //Sends the error message to the client.
1473 void CAviPlayController::SendErrorToClient(TInt aError)
1477 iMessage->Complete(aError);
1483 TMMFEvent controllerEvent;
1484 controllerEvent.iEventType = KMMFEventCategoryPlaybackComplete;
1485 controllerEvent.iErrorCode = aError;
1486 DoSendEventToClient(controllerEvent);
1490 CAviPlayController::CMMFMessageHolder* CAviPlayController::CMMFMessageHolder::NewL(TMMFMessage& aMessage)
1492 return new(ELeave) CMMFMessageHolder(aMessage);
1495 void CAviPlayController::CMMFMessageHolder::Complete(TInt aError)
1497 iMessage.Complete(aError);
1500 CAviPlayController::CMMFMessageHolder::CMMFMessageHolder(TMMFMessage& aMessage): CBase(), iMessage(aMessage)
1505 CAviPlayController::CSourceSinkEventHandler::CSourceSinkEventHandler(CAviPlayController& aParent):iParent(aParent)
1509 CAviPlayController::CSourceSinkEventHandler::~CSourceSinkEventHandler()
1513 TInt CAviPlayController::CSourceSinkEventHandler::SendEventToClient(const TMMFEvent& aEvent)
1515 iParent.SendEventToClient(aEvent);
1519 void CAviPlayController::MarnRegisterAsClientL(TUid aEventType, const TDesC8& aNotificationRegistrationData)
1521 //If file is open, check if audio is enabled
1524 iAviReader->AudioEnabled(iAudioEnabled);
1527 User::Leave(KErrArgument);
1530 //[ precondition that we have a sink]
1531 CheckDevSoundPresentL();
1533 //[register the notification ]
1534 TInt err = iDevSound->RegisterAsClient(aEventType, aNotificationRegistrationData);
1535 User::LeaveIfError(err);
1538 void CAviPlayController::MarnCancelRegisterAsClientL(TUid aEventType)
1540 //[ precondition that we have a sink]
1541 CheckDevSoundPresentL();
1543 //[cancel the notification ]
1544 TInt err = iDevSound->CancelRegisterAsClient(aEventType);
1545 User::LeaveIfError(err);
1548 void CAviPlayController::MarnGetResourceNotificationDataL(TUid aEventType, TDes8& aNotificationData)
1550 //[ precondition that we have a sink]
1551 CheckDevSoundPresentL();
1553 //[get the notification data]
1554 TMMFTimeIntervalMicroSecondsPckg pckg;
1555 TInt err = iDevSound->GetResourceNotificationData(aEventType, pckg);
1556 User::LeaveIfError(err);
1558 // aNotificationData is a package buffer returned as TMMFTimeIntervalMicroSecondsPckg.
1559 // The contents should be converted to an integer and interpreted as samples played,
1560 // but not as a microsecond value.
1561 // As the client expects a position (in microseconds from the beginning
1562 // of the clip) we need to convert the data depending on the sample rate.
1563 // Potential issue if using the number of samples played with VBR sampling.
1565 TMMFCapabilities caps = iDevSound->Config();
1566 for( TInt i = 0; i < KNumSampleRates; i++)
1568 if(caps.iRate == KRateLookup[i].iRateEnum)
1570 rate = KRateLookup[i].iRate;
1576 // Convert the given number of samples using the sample rate
1577 const TInt KMicroSecsInOneSec = 1000000;
1578 TTimeIntervalMicroSeconds value = pckg();
1579 value = TTimeIntervalMicroSeconds(value.Int64() * ((TReal)KMicroSecsInOneSec / rate));
1584 User::Leave(KErrArgument);
1586 aNotificationData = pckg;
1589 void CAviPlayController::MarnWillResumePlayL()
1591 //[ precondition that we have a sink]
1592 CheckDevSoundPresentL();
1594 //[wait for the client to resume ]
1595 TInt err = iDevSound->WillResumePlay();
1596 User::LeaveIfError(err);
1600 void CAviPlayController::StopVideoL()
1602 // If already stopped, do nothing
1603 if (iState == EStopped)
1608 CheckDevVideoPresentL();
1609 // AbortDirectScreenAccess and Stop can only be used if DevVideoPlay has
1610 // been already initialized. If CheckDevVideoPresentL has just recreated
1611 // the DevVideoPlay instance, no need to make these calls on DevVideoPlay.
1612 if (iDevVideoInitialized)
1614 if (iVideoSurfaceSupport == NULL)
1616 iDevVideoPlay->AbortDirectScreenAccess();
1619 iDevVideoPlay->Stop();
1624 // Stops audio (if enabled).
1625 void CAviPlayController::StopAudioL()
1627 // If already stopped, do nothing
1628 if (iState == EStopped || !iAudioEnabled)
1633 CheckDevSoundPresentL();
1635 iDevSoundInitialized = EFalse;
1638 // Stops the data transfer from data source to data sink.
1639 void CAviPlayController::StopAviReaderL()
1641 // If already stopped, do nothing
1642 if (iState == EStopped)
1648 CheckAviReaderPresentL();
1649 iAviReader->ResetL();
1652 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
1653 // Stops DevSubtitle
1654 void CAviPlayController::StopSubtitles()
1656 if (iDevSubtitle && iDevSubtitleStarted)
1658 // stop subtitles if it was enabled
1659 iDevSubtitle->Stop();
1660 iDevSubtitleStarted = EFalse;
1663 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
1665 // This non-const method is used to encapsulate non-const actions that need to
1666 // take place within a const method so there's no need to change the constness
1667 // definition of the caller method.
1668 void CAviPlayController::RecreateDevVideoAfterFatalErrorL()
1670 iVideoFatalError = EFalse;
1671 delete iDevVideoPlay;
1672 iDevVideoPlay = NULL;
1673 iDevVideoPlay = CMMFDevVideoPlay::NewL(*this);
1674 iDevVideoInitialized = EFalse;
1678 MMMFVideoPlayControllerExtCustomCommandImplementor
1681 // Sets play velocity. that will be effective on next play
1682 void CAviPlayController::MvpecSetPlayVelocityL(TInt )
1684 User::Leave(KErrNotSupported);
1687 // returns play velocity
1688 TInt CAviPlayController::MvpecPlayVelocityL()
1690 return 100; // return default play velocity.
1693 //steps to the frame, relative to current frame
1694 void CAviPlayController::MvpecStepFrameL(TInt )
1696 User::Leave(KErrNotSupported);
1699 // return paly capabilities.
1700 void CAviPlayController::MvpecGetPlayRateCapabilitiesL(TVideoPlayRateCapabilities& aCapabilities)
1702 // none of the capabilities are supported.
1703 aCapabilities.iPlayBackward = EFalse;
1704 aCapabilities.iPlayForward = EFalse;
1705 aCapabilities.iStepBackward = EFalse;
1706 aCapabilities.iStepForward = EFalse;
1709 // enables or disables video.
1710 void CAviPlayController::MvpecSetVideoEnabledL(TBool )
1712 User::Leave(KErrNotSupported);
1715 // reutrns video enabled status.
1716 TBool CAviPlayController::MvpecVideoEnabledL()
1718 // by default video is enabled.
1722 //enables or disables video.
1723 void CAviPlayController::MvpecSetAudioEnabledL(TBool )
1725 User::Leave(KErrNotSupported);
1728 // Scales video display as per the input parameters.
1729 void CAviPlayController::MvpecSetAutoScaleL(TAutoScaleType , TInt , TInt )
1731 User::Leave(KErrNotSupported);
1734 // Called when either iDisplayRegion or iClipRect are changed. The derived
1735 // clip region is the intersection of these. This method can be called
1736 // during playback, so the new region is passed immediately to DevVideo.
1737 void CAviPlayController::UpdateClipRegion()
1739 iDerivedClipRegion.Copy(iDisplayRegion);
1740 iDerivedClipRegion.ClipRect(iClipRect);
1742 if(iDevVideoInitialized)
1744 // This isn't necessary in all cases, for instance there may be a
1745 // direct screen access start/stop, which would also set the clipping
1746 // region. This is added for completeness.
1747 iDevVideoPlay->SetScreenClipRegion(iDerivedClipRegion);
1752 iScreenGc->SetClippingRegion(iDerivedClipRegion);
1756 #ifdef SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
1757 // MMMFVideoPlaySubtitleSupportCustomCommandImplementor
1758 void CAviPlayController::MvpsusGetCrpParametersL(TInt aWindowId, TWsGraphicId& aId, TRect& aCrpRect)
1762 User::Leave(KErrNotReady);
1764 iDevSubtitle->GetCrpParametersL(aWindowId, aId, aCrpRect);
1767 void CAviPlayController::MvpsusAddSubtitleConfigL(const TMMFSubtitleWindowConfig& aConfig)
1771 User::Leave(KErrNotReady);
1773 iDevSubtitle->AddSubtitleConfigL(aConfig);
1775 // Add successful, increment configuration count.
1776 iSubtitleConfigCount++;
1778 if (iState == EPlaying && !iDevSubtitleStarted)
1780 // video is playing but dev subtitle hasn't started, i.e. subtitle enabled during play
1781 iDevSubtitle->SetVideoPositionL(iDevVideoPlay->PlaybackPosition());
1782 iDevSubtitle->Start();
1783 iDevSubtitleStarted = ETrue;
1786 // add subtitle config was successful
1787 DoSendEventToClient(TMMFEvent(KMMFEventCategoryVideoSubtitleCrpReady, aConfig.iWindowId));
1790 void CAviPlayController::MvpsusRemoveSubtitleConfigL(TInt aWindowId)
1794 User::Leave(KErrNotReady);
1796 iDevSubtitle->RemoveSubtitleConfigL(aWindowId);
1798 // Remove successful, decrement configuration count.
1799 iSubtitleConfigCount--;
1801 if (iSubtitleConfigCount == 0)
1807 void CAviPlayController::MvpsusUpdateSubtitleConfigL(const TMMFSubtitleWindowConfig& aConfig)
1811 User::Leave(KErrNotReady);
1813 iDevSubtitle->UpdateSubtitleConfigL(aConfig);
1815 // update subtitle config was successful
1816 DoSendEventToClient(TMMFEvent(KMMFEventCategoryVideoSubtitleCrpReady, aConfig.iWindowId));
1819 void CAviPlayController::MvpsusGetSubtitlesAvailableL(TBool& aAvailable)
1821 aAvailable = EFalse;
1822 // first check if file source is added
1831 // Create and destroy a temporary SRT Reader object.
1832 CSrtReader* tempReader = NULL;
1833 TRAPD(err, tempReader = CreateSubtitleSourceL());
1836 // Subtitles are available if and only if CreateSubtitleSourceL had no errors.
1837 aAvailable = (err == KErrNone);
1839 // If CreateSubtitleSourceL left with KErrNotFound then we do not leave; just report
1840 // subtitles as not available.
1841 if (err != KErrNotFound && err != KErrNone)
1849 // create srt reader, return subtitle file name if a file clip has been added, leave if out of memory
1850 CSrtReader* CAviPlayController::CreateSubtitleSourceL()
1852 const TDesC& filedrive = iClip->FileDrive();
1853 const TDesC& filepath = iClip->FilePath();
1854 const TDesC& filename = iClip->FileName();
1856 TFileName srtFileName;
1858 // Check that the srt file's filename length is not longer than the maximum filename length. This
1859 // can arise only when the extension "srt" is longer than the clip's file extension and the rest of
1860 // the name is very long.
1861 // The 1 is added to account for the period "." before the extension.
1862 if (filedrive.Length() + filepath.Length() + filename.Length() + KSrtExtension().Length() + 1 > srtFileName.MaxLength())
1864 // File cannot exist on the filesystem
1865 User::Leave(KErrNotFound);
1868 srtFileName.Format(_L("%S%S%S.%S"), &filedrive, &filepath, &filename, &KSrtExtension);
1870 CSrtReader* reader = CSrtReader::NewL(srtFileName);
1875 void CAviPlayController::MvpsusDisableSubtitlesL()
1877 // disable subtitles if subtitles was enabled
1881 delete iDevSubtitle;
1882 iDevSubtitle = NULL;
1889 void CAviPlayController::MvpsusEnableSubtitlesL()
1893 User::Leave(KErrNotReady);
1897 User::Leave(KErrInUse);
1899 CSrtReader* reader = CreateSubtitleSourceL();
1900 CleanupStack::PushL(reader);
1901 CMMFDevSubtitle* devSubtitle = CMMFDevSubtitle::NewLC(*reader);
1902 devSubtitle->SelectDecoderL(KSrtDecoder);
1904 // subtitle was enabled sucessfully
1905 // assign reader and devSubtitle to class and pop them from cleanup stack
1906 CleanupStack::Pop(2, reader);
1907 iDevSubtitle = devSubtitle;
1908 iSrtReader = reader;
1911 void CAviPlayController::MvpsusGetSubtitleLanguageL(TLanguage& aLanguage)
1915 User::Leave(KErrNotReady);
1917 aLanguage = iDevSubtitle->SubtitleLanguageL();
1920 void CAviPlayController::MvpsusGetSupportedSubtitleLanguagesL(RArray<TLanguage>& aLanguages)
1924 User::Leave(KErrNotReady);
1926 iDevSubtitle->GetSupportedSubtitleLanguagesL(aLanguages);
1929 void CAviPlayController::MvpsusSetSubtitleLanguageL(TLanguage aLanguage)
1933 User::Leave(KErrNotReady);
1935 iDevSubtitle->SetSubtitleLanguageL(aLanguage);
1938 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT