upnpsharing/upnpdlnaprofiler/src/upnpresresolver.cpp
branchnew development branch with rendering state machine and other goodies
changeset 38 5360b7ddc251
parent 0 7f85d04be362
--- a/upnpsharing/upnpdlnaprofiler/src/upnpresresolver.cpp	Fri Sep 17 08:31:21 2010 +0300
+++ b/upnpsharing/upnpdlnaprofiler/src/upnpresresolver.cpp	Mon Nov 01 12:37:49 2010 +0200
@@ -1,440 +1,511 @@
-/*
-* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description:      Implementation file of CUpnpResResolver class. 
-*                CUpnpResResolver is a class used for resolving res field 
-*                attributes for a given file.
-*
-*/
-
-
-
-
-
-
-// system includes
-#include <f32file.h> // RFile
-#include <apgcli.h> // RApaLsSession
-#include <upnpdlnaprotocolinfo.h> // CUpnpDlnaProtocolInfo
-#include <imageconversion.h> // CImageDecoder
-#include <caf/caftypes.h> // ContentAccess
-#include <3gplibrary/mp4lib.h> // MP4ParseRequestAudioDescription
-#include <escapeutils.h> // EscapeUtils::ConvertFromUnicodeToUtf8L
-
-// user includes
-#include "upnpresresolver.h"
-#include "upnpdlnaprofiler.h"
-#include "upnpresparameters.h"
-
-_LIT( KComponentLogfile, "dlnaprofiler.txt");
-#include "upnplog.h"
-
-// constants
-_LIT8( KHttpGet8, "http-get" );
-_LIT8( KStar8, "*" );
-
-const TInt KMicrosecondsInSecond = 1000000;
-const TInt KMilliSecondsInSecond = 1000;
-
-// ======== LOCAL FUNCTIONS ========
-// NONE
-
-// ======== MEMBER FUNCTIONS ========
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver C++ constructor
-// --------------------------------------------------------------------------
-//
-CUpnpResResolver::CUpnpResResolver() : iDuration(0)
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver constructor" );
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::ConstructL
-// --------------------------------------------------------------------------
-//
-void CUpnpResResolver::ConstructL()
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::ConstructL" );
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::NewL
-// --------------------------------------------------------------------------
-//
-EXPORT_C CUpnpResResolver* CUpnpResResolver::NewL()
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::NewL" );
-    CUpnpResResolver* self = CUpnpResResolver::NewLC();
-    CleanupStack::Pop( self );
-    return self;
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::NewLC
-// --------------------------------------------------------------------------
-//
-EXPORT_C CUpnpResResolver* CUpnpResResolver::NewLC()
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::NewLC" );
-    CUpnpResResolver* self = new( ELeave ) CUpnpResResolver;
-    CleanupStack::PushL( self );
-    self->ConstructL();
-    return self;
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver destructor
-// --------------------------------------------------------------------------
-//
-CUpnpResResolver::~CUpnpResResolver()
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver destructor" );
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::GetResParametersL
-// --------------------------------------------------------------------------
-//
-EXPORT_C CUpnpResParameters* CUpnpResResolver::GetResParametersL( 
-                                                    const TDesC& aFilename ) 
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetResParametersL" );
-    // check that aFileName is reasonable
-    if ( aFilename.Length() <= 0 ) 
-        {
-        User::Leave( KErrArgument );
-        }
-    
-    // Create object that will be returned.
-    CUpnpResParameters* retval = CUpnpResParameters::NewLC();
-
-    // try to open file specified by aFileName
-    RFs fsSession;
-    User::LeaveIfError( fsSession.Connect() ); // connect session
-    CleanupClosePushL( fsSession );
-    // without calling ShareProtected() RApaLsSession::RecognizeData 
-    // does not work (leaves with KErrBadHandle).
-    fsSession.ShareProtected();
-
-    RFile file;
-    User::LeaveIfError( file.Open( fsSession, 
-                                   aFilename, 
-                                   EFileShareReadersOrWriters|EFileRead ) );
-    CleanupClosePushL( file );
-    
-    // Obtain mimetype of the file
-    HBufC8* mimetype = GetMimetypeL( file );
-    CleanupStack::PushL( mimetype );
-    retval->SetMimetypeL( *mimetype );
-
-    // Obtain file size
-    TInt filesize = GetFileSizeL( file );
-    retval->SetFileSize( filesize );
-
-    // Obtain duration for video&audio files and resolution for images.
-    TSize imageResolution( KErrNotFound, KErrNotFound );
-    if ( mimetype->Left( KMimeStartLength ).Compare( KVideo() ) == 0 ) 
-        {
-        GetVideoDurationL( file );
-        retval->SetDurationInSeconds( iDuration.Int64() );
-        }
-    else if ( mimetype->Left( KMimeStartLength ).Compare( KAudio() ) == 0 ) 
-        {
-        GetAudioDurationL( aFilename );
-        retval->SetDurationInSeconds( 
-                                iDuration.Int64() / KMicrosecondsInSecond );
-        }
-    else if ( mimetype->Left( KMimeStartLength ).Compare( KImage() ) == 0 ) 
-        {
-        TRAPD( err, imageResolution = GetImageResolutionL( file, 
-                                                           *mimetype ) );
-        if ( !err ) 
-            {
-            retval->SetResolution( imageResolution );
-            }
-        }
-
-    // Construct CUpnpDlnaProtocolInfo object.
-    CUpnpDlnaProtocolInfo* protocolInfo = CUpnpDlnaProtocolInfo::NewL(); 
-    CleanupStack::PushL( protocolInfo ); 
-    protocolInfo->SetFirstFieldL( KHttpGet8() ); 
-    protocolInfo->SetSecondFieldL( KStar8() ); 
-    protocolInfo->SetThirdFieldL( *mimetype ); 
-        
-    // Obtain DLNA Profile ID
-    CUpnpDlnaProfiler* profiler = CUpnpDlnaProfiler::NewLC();
-    HBufC* PnParameter = NULL;
-    TRAPD( profileErr, 
-           PnParameter = profiler->ProfileForFileL( aFilename,
-                                                    file,
-                                                    *retval ) );
-    CleanupStack::PopAndDestroy( profiler );
-    
-    if ( PnParameter && !profileErr ) 
-        {
-        // Set DLNA Profile name (PN parameter)
-        CleanupStack::PushL( PnParameter );
-        HBufC8* profileName8bit = 
-            EscapeUtils::ConvertFromUnicodeToUtf8L( *PnParameter );
-        CleanupStack::PushL( profileName8bit );
-        protocolInfo->SetPnParameterL( *profileName8bit );
-        CleanupStack::PopAndDestroy( profileName8bit );
-
-        // OP parameter is always the same in our CDS.
-        protocolInfo->SetOpParameterL( 
-                                   UpnpDlnaProtocolInfo::KDEFAULT_DLNA_OP ); 
-
-        // Set Flags according to file type.
-        if ( mimetype->Left( KMimeStartLength ).Compare( KVideo() ) == 0 ) 
-            {
-            protocolInfo->SetFlagsParameterL( 
-                           UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_AV );
-            }
-        else if 
-           ( mimetype->Left( KMimeStartLength ).Compare( KAudio() ) == 0 ) 
-            {
-            protocolInfo->SetFlagsParameterL( 
-                           UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_AUDIO );
-            }
-        else if 
-           ( mimetype->Left( KMimeStartLength ).Compare( KImage() ) == 0 ) 
-            {
-            protocolInfo->SetFlagsParameterL( 
-                           UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_IMAGE );
-            }
-                            
-        CleanupStack::PopAndDestroy( PnParameter );
-        }
-
-    retval->SetProtocolInfoL( protocolInfo->ProtocolInfoL() );
-
-    // clean up
-    CleanupStack::PopAndDestroy( protocolInfo );
-    CleanupStack::PopAndDestroy( mimetype );
-    CleanupStack::PopAndDestroy( &file );
-    CleanupStack::PopAndDestroy( &fsSession );
-    CleanupStack::Pop( retval );
-    return retval;
-
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::GetMimetypeL
-// --------------------------------------------------------------------------
-//
-HBufC8* CUpnpResResolver::GetMimetypeL( RFile& aFile ) 
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetMimetypeL" );
-    HBufC8* retval = NULL;
-    // Create an AppArc server session for mime type recognition 
-    RApaLsSession sess;
-    User::LeaveIfError( sess.Connect() );
-    CleanupClosePushL( sess );
-
-    // Try to get mime type from AppArc server
-    TDataRecognitionResult mimeResult;
-    User::LeaveIfError( sess.RecognizeData( aFile, mimeResult ) );
-    
-    // close session handle
-    CleanupStack::PopAndDestroy( &sess );
-
-    // Data recognition done. Check results.
-    retval = mimeResult.iDataType.Des8().AllocL();
-    return retval;
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::GetVideoDurationL
-// --------------------------------------------------------------------------
-//
-void CUpnpResResolver::GetVideoDurationL( RFile& aFile )  
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetVideoDurationL" );
-    mp4_u32 videolength = 0;  
-    mp4_double framerate = 0; 
-    mp4_u32 videotype = 0;    
-    mp4_u32 videowidth = 0;   
-    mp4_u32 videoheight = 0;  
-    mp4_u32 timescale = 0; 
-
-    MP4Handle myMp4Handle;
-    
-    // try open mp4 file handle
-    MP4Err openerr = MP4ParseOpenFileHandle( &myMp4Handle, &aFile );
-    switch ( openerr )
-        {
-        case MP4_OK :
-        	{
-        	// obtain necessary information from file
-            MP4Err requesterr = MP4ParseRequestVideoDescription( 
-                                                myMp4Handle, 
-                                                &videolength,   
-                                                &framerate,     
-                                                &videotype,     
-                                                &videowidth,    
-                                                &videoheight,   
-                                                &timescale );
-               
-            // close mp4 file handle
-            MP4Err closeerr = MP4ParseClose( myMp4Handle );
-            if ( closeerr || requesterr ) 
-                {
-                User::Leave( KErrGeneral );
-                }
-        	}
-        	break;
-        case MP4_ERROR :
-        	{
-        	User::Leave( KErrGeneral );
-        	}
-        	break;
-        case MP4_OUT_OF_MEMORY :
-        	{
-        	User::Leave( KErrNoMemory );
-        	}
-        	break;
-        case MP4_FILE_ERROR :
-        	{
-        	User::Leave( KErrAccessDenied );
-        	}
-        	break;
-        default :
-            User::Leave( KErrGeneral );
-            break;
-        }
-    // videolength in milliseconds
-    iDuration = videolength/KMilliSecondsInSecond;
-    }
-    
-// --------------------------------------------------------------------------
-// CUpnpResResolver::GetAudioDurationL
-// --------------------------------------------------------------------------
-//
-void CUpnpResResolver::GetAudioDurationL( const TDesC& aFilename ) 
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetAudioDurationL" );
-
-    // create audioplayer if it does not exist
-    if ( !iAudioplayer ) 
-        {
-        iAudioplayer = CMdaAudioPlayerUtility::NewL( *this );
-        }
-
-    // Create iWait if it does not exist. Create it here rather than after 
-    // OpenL-call so that there will be no problems if somehow OpenFileL 
-    // calls MapcInitComplete-callback before iWait is created and started.
-    if ( !iWait ) 
-        {
-        iWait = new( ELeave ) CActiveSchedulerWait;
-        }
-
-    // Open file specified in aFilename. This is an asynchronic operation. 
-    // Calls MapcInitComplete callback after completed.
-    iAudioplayer->OpenFileL( aFilename );
-    
-    // start CActiveSchedulerWait which is completed in MapcInitComplete
-    iWait->Start();
-
-    // clean up
-    delete iAudioplayer;
-    iAudioplayer = NULL;
-    
-    delete iWait;
-    iWait = NULL;
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::GetFileSizeL
-// --------------------------------------------------------------------------
-//
-TInt CUpnpResResolver::GetFileSizeL( RFile& aFile ) 
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetFileSizeL" );
-    TInt retval = KErrNone;
-    User::LeaveIfError( aFile.Size( retval ) );
-    return retval;
-    }
-
-
-// --------------------------------------------------------------------------
-// CUpnpResResolver::GetImageResolutionL
-// --------------------------------------------------------------------------
-//  
-TSize CUpnpResResolver::GetImageResolutionL( RFile& aFile, 
-                                             const TDesC8& aMimetype )
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetImageResolutionL" );
-    CImageDecoder* imageDecoder = NULL;
-    TRAPD( createError, imageDecoder = CImageDecoder::FileNewL(
-                                                    aFile,
-                                                    aMimetype, 
-                                                    ContentAccess::EPeek ) );
-
-    if ( createError ) 
-        {
-        __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetImageResolutionL \
-CreateError" );
-        User::Leave( createError );
-        }
-                                                              
-    CleanupStack::PushL( imageDecoder );
-    TSize imageResolution = imageDecoder->FrameInfo().iOverallSizeInPixels;
-    CleanupStack::PopAndDestroy( imageDecoder );
-    
-    return imageResolution;
-    }
-    
-// --------------------------------------------------------------------------
-// From class MMdaAudioPlayerCallback.
-// MapcPlayComplete callback (not used)
-// --------------------------------------------------------------------------
-//
-void CUpnpResResolver::MapcPlayComplete( TInt /*aError*/ ) 
-    {
-    //this callback is not needed
-    }
-
-// --------------------------------------------------------------------------
-// From class MMdaAudioPlayerCallback.
-// MapcInitComplete callback is called after a call to 
-// CMdaAudioConvertUtility::OpenL has completed.
-// --------------------------------------------------------------------------
-//
-void CUpnpResResolver::MapcInitComplete( 
-                                TInt aError, 
-                                const TTimeIntervalMicroSeconds& aDuration ) 
-    {
-    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::MapcInitComplete" );
- 
-    // if opening was successful, save duration to member variable
-    if( KErrNone == aError )
-        {
-        iDuration = aDuration;
-        }
-
-    // continue execution in GetAudioDurationL-method by stopping 
-    // ActiveSchedulerWait
-    iWait->AsyncStop();
-    }
-
-// end of file
+/*
+* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:      Implementation file of CUpnpResResolver class. 
+*                CUpnpResResolver is a class used for resolving res field 
+*                attributes for a given file.
+*
+*/
+
+
+
+
+
+
+// system includes
+#include <f32file.h> // RFile
+#include <apgcli.h> // RApaLsSession
+#include <upnpdlnaprotocolinfo.h> // CUpnpDlnaProtocolInfo
+#include <imageconversion.h> // CImageDecoder
+#include <caf/caftypes.h> // ContentAccess
+#include <3gplibrary/mp4lib.h>  // MP4ParseRequestAudioDescription
+#include <escapeutils.h> // EscapeUtils::ConvertFromUnicodeToUtf8L
+
+// user includes
+#include "upnpresresolver.h"
+#include "upnpdlnaprofiler.h"
+#include "upnpresparameters.h"
+
+_LIT( KComponentLogfile, "dlnaprofiler.txt");
+#include "upnplog.h"
+
+// constants
+_LIT8( KHttpGet8, "http-get" );
+_LIT8( KStar8, "*" );
+
+const TInt KMicrosecondsInSecond = 1000000;
+const TInt KMilliSecondsInSecond = 1000;
+
+// ======== LOCAL FUNCTIONS ========
+// NONE
+
+// ======== MEMBER FUNCTIONS ========
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver C++ constructor
+// --------------------------------------------------------------------------
+//
+CUpnpResResolver::CUpnpResResolver() : iDuration(0)
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver constructor" );
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::ConstructL
+// --------------------------------------------------------------------------
+//
+void CUpnpResResolver::ConstructL()
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::ConstructL" );
+    
+    // open semaphore
+    User::LeaveIfError( iSemaphore.CreateLocal( 0 ) );
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::NewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CUpnpResResolver* CUpnpResResolver::NewL()
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::NewL" );
+    CUpnpResResolver* self = CUpnpResResolver::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::NewLC
+// --------------------------------------------------------------------------
+//
+EXPORT_C CUpnpResResolver* CUpnpResResolver::NewLC()
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::NewLC" );
+    CUpnpResResolver* self = new( ELeave ) CUpnpResResolver;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver destructor
+// --------------------------------------------------------------------------
+//
+CUpnpResResolver::~CUpnpResResolver()
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver destructor" );
+    
+    iSemaphore.Close();
+    delete iAVFile;
+    }
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::GetResParametersL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CUpnpResParameters* CUpnpResResolver::GetResParametersL(
+    const TDesC& aFilename ) 
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetResParametersL" );
+    // check that aFileName is reasonable
+    if ( aFilename.Length() <= 0 ) 
+        {
+        User::Leave( KErrArgument );
+        }
+    
+    // Create object that will be returned.
+    CUpnpResParameters* retval = CUpnpResParameters::NewLC();
+
+    // try to open file specified by aFileName
+    RFs fsSession;
+    User::LeaveIfError( fsSession.Connect() ); // connect session
+    CleanupClosePushL( fsSession );
+    // without calling ShareProtected() RApaLsSession::RecognizeData 
+    // does not work (leaves with KErrBadHandle).
+    fsSession.ShareProtected();
+
+    RFile file;
+    User::LeaveIfError( file.Open( fsSession, 
+                                   aFilename, 
+                                   EFileShareReadersOrWriters|EFileRead ) );
+    CleanupClosePushL( file );
+    
+    // Obtain mimetype of the file
+    HBufC8* mimetype = GetMimetypeL( file );
+    CleanupStack::PushL( mimetype );
+    retval->SetMimetypeL( *mimetype );
+
+    // Obtain file size
+    TInt filesize = GetFileSizeL( file );
+    retval->SetFileSize( filesize );
+
+    // Obtain duration for video&audio files and resolution for images.
+    TSize imageResolution( KErrNotFound, KErrNotFound );
+    if ( mimetype->Left( KMimeStartLength ).Compare( KVideo() ) == 0 ) 
+        {
+        GetVideoDurationL( file );
+        retval->SetDurationInSeconds( iDuration.Int64() );
+        }
+    else if ( mimetype->Left( KMimeStartLength ).Compare( KAudio() ) == 0 ) 
+        {
+        GetAudioDurationL( aFilename );
+        retval->SetDurationInSeconds( 
+                                iDuration.Int64() / KMicrosecondsInSecond );
+        }
+    else if ( mimetype->Left( KMimeStartLength ).Compare( KImage() ) == 0 ) 
+        {
+        TRAPD( err, imageResolution = GetImageResolutionL( file, 
+                                                           *mimetype ) );
+        if ( !err ) 
+            {
+            retval->SetResolution( imageResolution );
+            }
+        }
+
+    // Construct CUpnpDlnaProtocolInfo object.
+    CUpnpDlnaProtocolInfo* protocolInfo = CUpnpDlnaProtocolInfo::NewL(); 
+    CleanupStack::PushL( protocolInfo ); 
+    protocolInfo->SetFirstFieldL( KHttpGet8() ); 
+    protocolInfo->SetSecondFieldL( KStar8() ); 
+    protocolInfo->SetThirdFieldL( *mimetype ); 
+        
+    // Obtain DLNA Profile ID
+    CUpnpDlnaProfiler* profiler = CUpnpDlnaProfiler::NewLC();
+    HBufC* PnParameter = NULL;
+    TRAPD( profileErr, 
+           PnParameter = profiler->ProfileForFileL( aFilename,
+                                                    file,
+                                                    *retval ) );
+    CleanupStack::PopAndDestroy( profiler );
+    
+    if ( PnParameter && !profileErr ) 
+        {
+        // Set DLNA Profile name (PN parameter)
+        CleanupStack::PushL( PnParameter );
+        HBufC8* profileName8bit = 
+            EscapeUtils::ConvertFromUnicodeToUtf8L( *PnParameter );
+        CleanupStack::PushL( profileName8bit );
+        protocolInfo->SetPnParameterL( *profileName8bit );
+        CleanupStack::PopAndDestroy( profileName8bit );
+
+        // OP parameter is always the same in our CDS.
+        protocolInfo->SetOpParameterL( 
+                                   UpnpDlnaProtocolInfo::KDEFAULT_DLNA_OP ); 
+
+        // Set Flags according to file type.
+        if ( mimetype->Left( KMimeStartLength ).Compare( KVideo() ) == 0 ) 
+            {
+            protocolInfo->SetFlagsParameterL( 
+                           UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_AV );
+            }
+        else if 
+           ( mimetype->Left( KMimeStartLength ).Compare( KAudio() ) == 0 ) 
+            {
+            protocolInfo->SetFlagsParameterL( 
+                           UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_AUDIO );
+            }
+        else if 
+           ( mimetype->Left( KMimeStartLength ).Compare( KImage() ) == 0 ) 
+            {
+            protocolInfo->SetFlagsParameterL( 
+                           UpnpDlnaProtocolInfo::KDEFAULT_DLNA_FLAGS_IMAGE );
+            }
+                            
+        CleanupStack::PopAndDestroy( PnParameter );
+        }
+
+    retval->SetProtocolInfoL( protocolInfo->ProtocolInfoL() );
+
+    // clean up
+    CleanupStack::PopAndDestroy( protocolInfo );
+    CleanupStack::PopAndDestroy( mimetype );
+    CleanupStack::PopAndDestroy( &file );
+    CleanupStack::PopAndDestroy( &fsSession );
+    CleanupStack::Pop( retval );
+    return retval;
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::GetMimetypeL
+// --------------------------------------------------------------------------
+//
+HBufC8* CUpnpResResolver::GetMimetypeL( RFile& aFile ) 
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetMimetypeL" );
+    HBufC8* retval = NULL;
+    // Create an AppArc server session for mime type recognition 
+    RApaLsSession sess;
+    User::LeaveIfError( sess.Connect() );
+    CleanupClosePushL( sess );
+
+    // Try to get mime type from AppArc server
+    TDataRecognitionResult mimeResult;
+    User::LeaveIfError( sess.RecognizeData( aFile, mimeResult ) );
+    
+    // close session handle
+    CleanupStack::PopAndDestroy( &sess );
+   
+    if( mimeResult.iDataType.Des8().Length() == 0 )
+        {
+        User::Leave( KErrGeneral );
+        }
+    
+    // Data recognition done. Check results.
+    retval = mimeResult.iDataType.Des8().AllocL();
+    return retval;
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::GetVideoDurationL
+// --------------------------------------------------------------------------
+//
+void CUpnpResResolver::GetVideoDurationL( RFile& aFile )  
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetVideoDurationL" );
+    mp4_u32 videolength = 0;  
+    mp4_double framerate = 0; 
+    mp4_u32 videotype = 0;    
+    mp4_u32 videowidth = 0;   
+    mp4_u32 videoheight = 0;  
+    mp4_u32 timescale = 0; 
+
+    MP4Handle myMp4Handle;
+    
+    // try open mp4 file handle
+    MP4Err openerr = MP4ParseOpenFileHandle( &myMp4Handle, &aFile );
+    switch ( openerr )
+        {
+        case MP4_OK :
+        	{
+        	// obtain necessary information from file
+            MP4Err requesterr = MP4ParseRequestVideoDescription( 
+                                                myMp4Handle, 
+                                                &videolength,   
+                                                &framerate,     
+                                                &videotype,     
+                                                &videowidth,    
+                                                &videoheight,   
+                                                &timescale );
+               
+            // close mp4 file handle
+            MP4Err closeerr = MP4ParseClose( myMp4Handle );
+            if ( closeerr || requesterr ) 
+                {
+                User::Leave( KErrGeneral );
+                }
+        	}
+        	break;
+        case MP4_ERROR :
+        	{
+        	User::Leave( KErrGeneral );
+        	}
+        	break;
+        case MP4_OUT_OF_MEMORY :
+        	{
+        	User::Leave( KErrNoMemory );
+        	}
+        	break;
+        case MP4_FILE_ERROR :
+        	{
+        	User::Leave( KErrAccessDenied );
+        	}
+        	break;
+        default :
+            User::Leave( KErrGeneral );
+            break;
+        }
+    // videolength in milliseconds
+    iDuration = videolength/KMilliSecondsInSecond;
+    }
+    
+// --------------------------------------------------------------------------
+// CUpnpResResolver::GetAudioDurationL
+// --------------------------------------------------------------------------
+//
+void CUpnpResResolver::GetAudioDurationL( const TDesC& aFilename ) 
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetAudioDurationL" );
+
+    TInt err = KErrNone;
+
+    // store current av file
+    HBufC* avFile = aFilename.AllocL();
+    delete iAVFile;
+    iAVFile = avFile;
+    
+    // create audio resolving thread
+    RThread thread;
+    User::LeaveIfError( thread.Create(
+        KNullDesC, ThreadFunction, KDefaultStackSize, &User::Allocator(), this ) );
+    
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetAudioDurationL: Created audio resolving thread" );
+    
+    // start thread and wait until it has finished
+    thread.Resume();
+    iSemaphore.Wait();
+    
+    // check return value and close thread
+    err = thread.ExitReason();
+    thread.Close();
+    
+    __LOG1( "[UPnPDlnaProfiler] CUpnpResResolver::GetAudioDurationL: Finished audio resolving thread with code (%d)", err );
+
+    // leave if could not resolve audio duration
+    User::LeaveIfError( err );
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::GetFileSizeL
+// --------------------------------------------------------------------------
+//
+TInt CUpnpResResolver::GetFileSizeL( RFile& aFile ) 
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetFileSizeL" );
+    TInt retval = KErrNone;
+    User::LeaveIfError( aFile.Size( retval ) );
+    return retval;
+    }
+
+
+// --------------------------------------------------------------------------
+// CUpnpResResolver::GetImageResolutionL
+// --------------------------------------------------------------------------
+//  
+TSize CUpnpResResolver::GetImageResolutionL( RFile& aFile,
+    const TDesC8& aMimetype )
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetImageResolutionL" );
+    CImageDecoder* imageDecoder = NULL;
+    TRAPD( createError, imageDecoder = CImageDecoder::FileNewL(
+                                                    aFile,
+                                                    aMimetype, 
+                                                    ContentAccess::EPeek ) );
+
+    if ( createError ) 
+        {
+        __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::GetImageResolutionL \
+CreateError" );
+        User::Leave( createError );
+        }
+                                                              
+    CleanupStack::PushL( imageDecoder );
+    TSize imageResolution = imageDecoder->FrameInfo().iOverallSizeInPixels;
+    CleanupStack::PopAndDestroy( imageDecoder );
+    
+    return imageResolution;
+    }
+    
+// --------------------------------------------------------------------------
+// From class MMdaAudioPlayerCallback.
+// MapcPlayComplete callback (not used)
+// --------------------------------------------------------------------------
+//
+void CUpnpResResolver::MapcPlayComplete( TInt /*aError*/ ) 
+    {
+    // not used.
+    }
+
+// --------------------------------------------------------------------------
+// From class MMdaAudioPlayerCallback.
+// MapcInitComplete callback is called after a call to 
+// CMdaAudioConvertUtility::OpenL has completed.
+// --------------------------------------------------------------------------
+//
+void CUpnpResResolver::MapcInitComplete( TInt aError,
+    const TTimeIntervalMicroSeconds& aDuration ) 
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::MapcInitComplete" );
+ 
+    // if opening was successful, save duration to member variable
+    if( KErrNone == aError )
+        {
+        iDuration = aDuration;
+        }
+    
+    // stop scheduler for audio resolving thread
+    CActiveScheduler::Stop();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpResResolver::ThreadFunction
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpResResolver::ThreadFunction( TAny* aSelf )
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::ThreadFunction" );
+    
+    TInt err = KErrNone;
+    
+    CUpnpResResolver* self = static_cast<CUpnpResResolver*>( aSelf );
+    
+    // create cleanup stack
+    CTrapCleanup* cleanupStack = CTrapCleanup::New();
+    if( cleanupStack )
+        {
+        // execute thread function
+        TRAP( err, self->ResolveAudioDurationL() );
+        
+        // cleanup
+        delete cleanupStack;
+        }
+
+    // reset scheduler for this thread
+    CActiveScheduler::Install( NULL );
+    
+    // signal main thread so that it can continue
+    self->iSemaphore.Signal();
+    
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpResResolver::ResolveAudioDurationL
+// -----------------------------------------------------------------------------
+//
+void CUpnpResResolver::ResolveAudioDurationL()
+    {
+    __LOG( "[UPnPDlnaProfiler] CUpnpResResolver::ResolveAudioDurationL" );
+    
+    CActiveScheduler* scheduler = new( ELeave ) CActiveScheduler;
+    if( scheduler )
+        {        
+        CleanupStack::PushL( scheduler );
+        
+        // install the new scheduler in use for this thread
+        CActiveScheduler::Install( scheduler );
+        
+        // create audio player utility
+        CMdaAudioPlayerUtility* audioPlayerUtility =
+            CMdaAudioPlayerUtility::NewL( *this );
+        CleanupStack::PushL( audioPlayerUtility );
+        
+        // open file and wait until the audio clip initialization is ready
+        audioPlayerUtility->OpenFileL( *iAVFile );
+        
+        // start scheduler
+        CActiveScheduler::Start();
+        
+        // cleanup
+        CleanupStack::PopAndDestroy( audioPlayerUtility );
+        CleanupStack::PopAndDestroy( scheduler );
+        }
+    }
+
+// end of file