upnpavcontroller/upnpavcontrollerhelper/src/upnptranscodehelper.cpp
branchIOP_Improvements
changeset 40 08b5eae9f9ff
equal deleted inserted replaced
39:6369bfd1b60d 40:08b5eae9f9ff
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of UPnP transcode helper
       
    15 *
       
    16 */
       
    17 #include <bautils.h> //hack
       
    18 
       
    19 #include <upnpitem.h>
       
    20 #include <upnpstring.h>
       
    21 #include <upnpdlnaprotocolinfo.h>
       
    22 
       
    23 #include <upnpgstwrapper.h>
       
    24 #include <upnprenderercfg.h>
       
    25 #include <upnprenderercfgparser.h>
       
    26 
       
    27 #include "upnpitemutility.h"
       
    28 #include "upnpavdevice.h"
       
    29 
       
    30 #include "upnptranscodehelper.h"
       
    31 
       
    32 _LIT( KComponentLogfile, "upnptranscodehelper.txt");
       
    33 #include "upnplog.h"
       
    34 
       
    35 #define __FUNC_LOG __LOG8_1( "%s", __PRETTY_FUNCTION__ );
       
    36 
       
    37 _LIT( KRendererCfgFile, "C:\\data\\UpnpCfgs.xml" );
       
    38 
       
    39 _LIT( KTranscodedFlag, "?transcoded=true" );
       
    40 
       
    41 _LIT8( KSymbianDirDelimiter, "\\" );
       
    42 _LIT8( KLinuxDirDelimiter, "/" );
       
    43 _LIT8( KProtocolInfo, "protocolInfo" );
       
    44 _LIT8( KRes, "res" );
       
    45 
       
    46 // These are for Transport Stream muxer checking (from pipeline)
       
    47 _LIT8( KMpegTsMux, "mpegtsmux" );
       
    48 _LIT8( KFFMuxMpegTs, "ffmux_mpegts" );
       
    49 
       
    50 // These are for Transport Stream support checking
       
    51 _LIT8( KTsProtocolInfoIdentifier, "_TS_" );
       
    52 _LIT8( KAllMpegMimeTypes, "video/mpeg:*" );
       
    53 
       
    54 // This is for MP4 support checking 
       
    55 _LIT8( KMp4MimeType, "video/mp4" );
       
    56 
       
    57 // The pipeline is currently hardcoded (except input file)
       
    58 _LIT8( KDefaultPipelineFmt, 
       
    59 "mpegtsmux output-buf-size=0x7FCCC name=mux ! appsink max-buffers=10 name=sinkbuffer filesrc \
       
    60 location=%S ! qtdemux name=demux ! queue max-size-bytes=0xAAAA ! mux. demux. ! \
       
    61 queue max-size-bytes=0xAAAA ! mux.");
       
    62 
       
    63 const TInt KLocationFmtTagLen = 2;
       
    64 
       
    65 CUpnpTranscodeHelper* CUpnpTranscodeHelper::NewL()
       
    66     {
       
    67     __FUNC_LOG;
       
    68     
       
    69     CUpnpTranscodeHelper* self = new ( ELeave ) CUpnpTranscodeHelper();
       
    70     CleanupStack::PushL( self );
       
    71     self->ConstructL();
       
    72     CleanupStack::Pop( self );
       
    73     return self;
       
    74     }
       
    75 
       
    76 CUpnpTranscodeHelper::~CUpnpTranscodeHelper()
       
    77     {
       
    78     __FUNC_LOG;
       
    79     
       
    80     iGstWrapper->RemoveObserver( *this );
       
    81     iGstWrapper->Close();
       
    82     iFs.Close();
       
    83     }
       
    84 
       
    85 void CUpnpTranscodeHelper::PreDefinedCfgL( const CUpnpAVDevice& aRenderer, 
       
    86         CUpnpItem& aUpnpItem, HBufC8*& aPipeline,
       
    87         HBufC8*& aProtocolInfo )
       
    88     {
       
    89     __FUNC_LOG;
       
    90     
       
    91     //fetch mimetype and filename from original resource
       
    92     RUPnPElementsArray resources;
       
    93     CleanupClosePushL( resources );
       
    94     UPnPItemUtility::GetResElements( aUpnpItem, resources );
       
    95     TInt resourcesCount = resources.Count();
       
    96     if ( resourcesCount == 0 )
       
    97         {
       
    98         User::Leave( KErrNotFound );
       
    99         }         
       
   100 
       
   101     const CUpnpAttribute& originalProtocolInfoDesc = 
       
   102              UPnPItemUtility::FindAttributeByNameL( 
       
   103              *resources[0], KProtocolInfo ); 
       
   104     
       
   105     CUpnpDlnaProtocolInfo* originalProtocolInfo = 
       
   106             CUpnpDlnaProtocolInfo::NewL( originalProtocolInfoDesc.Value() );
       
   107     CleanupStack::PushL( originalProtocolInfo );            
       
   108     
       
   109     //create config for renderer
       
   110     CUpnpRendererCfg* config = CUpnpRendererCfg::NewLC( KRendererCfgFile, 
       
   111             aRenderer.ModelName(), originalProtocolInfo->ThirdField() );    
       
   112     
       
   113     CUpnpRendererCfgParser* parser = CUpnpRendererCfgParser::NewLC();   
       
   114         
       
   115     parser->ParseRendererCfgL( *config );
       
   116     
       
   117     HBufC8* srcFileName8 = PathToLinuxSyntaxL( resources[0]->FilePath() );
       
   118     CleanupStack::PushL( srcFileName8 );
       
   119     
       
   120     HBufC8* pipeline = HBufC8::NewLC( config->Pipeline().Length() + 
       
   121             srcFileName8->Length() - KLocationFmtTagLen );    
       
   122     pipeline->Des().AppendFormat( config->Pipeline(), srcFileName8 );
       
   123       
       
   124     HBufC8* protocolInfo = config->ProtocolInfo().AllocL();
       
   125 
       
   126     RFile file;
       
   127     User::LeaveIfError( file.Open(iFs,resources[0]->FilePath(),EFileRead) );
       
   128     CleanupClosePushL(file);
       
   129     TInt size(KErrNotFound);
       
   130     User::LeaveIfError( file.Size(size) );
       
   131     iGstWrapper->SetTranscodedFileSize( config->SizeMultiplier()*size );
       
   132     CleanupStack::PopAndDestroy(&file);
       
   133     
       
   134     CleanupStack::Pop( pipeline );
       
   135     CleanupStack::PopAndDestroy( srcFileName8 );
       
   136     CleanupStack::PopAndDestroy( parser );
       
   137     CleanupStack::PopAndDestroy( config );
       
   138     CleanupStack::PopAndDestroy( originalProtocolInfo );
       
   139     CleanupStack::PopAndDestroy( &resources );
       
   140     
       
   141     aPipeline = pipeline;
       
   142     aProtocolInfo = protocolInfo;
       
   143     }
       
   144 
       
   145 HBufC8* CUpnpTranscodeHelper::PipelineL( CUpnpItem& aUpnpItem, 
       
   146         const CDesC8Array& aRendererProtocolInfos )
       
   147     {
       
   148     __FUNC_LOG;
       
   149     
       
   150     HBufC8* pipeline = NULL;
       
   151     TBool protocolMatch = EFalse;
       
   152     TContainerType srcContainerType = EUnknownContainer;
       
   153     TContainerType destContainerType = EUnknownContainer;
       
   154 
       
   155     //Get resources from the current upnp item
       
   156     RUPnPElementsArray resources;
       
   157     CleanupClosePushL( resources );
       
   158     UPnPItemUtility::GetResElements( aUpnpItem, resources );
       
   159     TInt resourcesCount = resources.Count();
       
   160     if ( resourcesCount == 0 )
       
   161         {
       
   162         User::Leave( KErrNotFound );
       
   163         }    
       
   164 
       
   165     //Check if suitable source container is found from 1st resource
       
   166     const CUpnpAttribute& originalProtocolInfo = 
       
   167             UPnPItemUtility::FindAttributeByNameL( 
       
   168             *resources[0], KProtocolInfo ); 
       
   169             
       
   170     if( originalProtocolInfo.Value().Find( KMp4MimeType ) )
       
   171         {
       
   172         srcContainerType = EMp4Container; 
       
   173         }
       
   174     else
       
   175         {
       
   176         User::Leave( KErrNotSupported );
       
   177         }        
       
   178 
       
   179     //Loop through all protocol infos from renderer and try to find suitable        
       
   180     TInt rendererProtocolInfoCount = aRendererProtocolInfos.Count(); 
       
   181     for( TInt i = 0; i < rendererProtocolInfoCount && !protocolMatch; i++ )
       
   182         {
       
   183         for( TInt j = 0; j < resourcesCount && !protocolMatch; j++ )
       
   184             {
       
   185             const TDesC8& protocolInfo = 
       
   186             UPnPItemUtility::FindAttributeByNameL( 
       
   187                     *resources[j], KProtocolInfo ).Value();        
       
   188 
       
   189             const TDesC8& rendererProtocolInfo = 
       
   190             aRendererProtocolInfos.MdcaPoint(i);
       
   191 
       
   192             if( rendererProtocolInfo.Find( protocolInfo ) != KErrNotFound )
       
   193                 {                                
       
   194                 protocolMatch = ETrue;
       
   195                 //breaks both 'for' loops here    
       
   196                 }
       
   197 
       
   198             //Check if protocol info is supported 
       
   199             if( destContainerType == EUnknownContainer &&
       
   200                 ( rendererProtocolInfo.Find( 
       
   201                       KTsProtocolInfoIdentifier ) != KErrNotFound || 
       
   202                   rendererProtocolInfo.Find(
       
   203                       KAllMpegMimeTypes ) != KErrNotFound ) ) 
       
   204                 {
       
   205                 destContainerType = ETsContainer; 
       
   206                 }
       
   207             //TODO: add here other supported containers (muxers) as well
       
   208 
       
   209             }        
       
   210         }
       
   211 
       
   212     if( !protocolMatch )
       
   213         {               
       
   214         HBufC8* filePath = PathToLinuxSyntaxL( resources[0]->FilePath() );     
       
   215         CleanupStack::PushL( filePath );            
       
   216         pipeline = GeneratePipelineL( *filePath, destContainerType );        
       
   217         CleanupStack::PopAndDestroy( filePath );                
       
   218         }
       
   219 
       
   220     CleanupStack::PopAndDestroy( &resources );
       
   221 
       
   222     return pipeline;
       
   223     }
       
   224 
       
   225 void CUpnpTranscodeHelper::ReplaceResourceL( CUpnpItem& aUpnpItem, 
       
   226                                              const TDesC8& aProtocolInfo )
       
   227     {
       
   228     RUPnPElementsArray& elements = const_cast<RUPnPElementsArray&>(
       
   229                     aUpnpItem.GetElements());
       
   230 
       
   231     for( TInt resIndex(0); resIndex < elements.Count(); ++resIndex )
       
   232         {
       
   233         if( elements[resIndex]->Name() == KRes )
       
   234             {
       
   235             HBufC* tmp = HBufC::NewLC( 
       
   236                     elements[resIndex]->FilePath().Length() +
       
   237                     KTranscodedFlag().Length() );
       
   238             tmp->Des().Append( elements[resIndex]->FilePath() );
       
   239             tmp->Des().Append( KTranscodedFlag() );
       
   240             elements.Remove( resIndex );
       
   241             aUpnpItem.AddResourceL( *tmp, aProtocolInfo );
       
   242             CleanupStack::PopAndDestroy( tmp );
       
   243             break;
       
   244             }
       
   245         }
       
   246     }
       
   247 
       
   248 void CUpnpTranscodeHelper::TranscodeL( const TDesC8& aPipeline )
       
   249     {
       
   250     __FUNC_LOG;
       
   251     
       
   252     //iGstWrapper->StartL( aPipeline ); 
       
   253     iGstWrapper->SetPipelineL( aPipeline );
       
   254     
       
   255     //should we wait here until we get pipeline playing state notification
       
   256     //or error ;)
       
   257     }
       
   258 
       
   259 
       
   260 void CUpnpTranscodeHelper::AddValidResElementL( 
       
   261         CUpnpItem& aUpnpItem, const TDesC8& aPipeline, 
       
   262         const CDesC8Array& aRendererProtocolInfos )
       
   263     {
       
   264     __FUNC_LOG;
       
   265     
       
   266     TBool suitableFound = EFalse;
       
   267     const TDesC8* protocolInfoIdentifier = NULL;
       
   268 
       
   269     //TODO: Add also other supported containers (muxers)
       
   270     if( aPipeline.Find( KMpegTsMux ) != KErrNotFound || 
       
   271         aPipeline.Find( KFFMuxMpegTs ) != KErrNotFound )        
       
   272         {
       
   273         protocolInfoIdentifier = &KTsProtocolInfoIdentifier(); 
       
   274         }
       
   275     else
       
   276         {
       
   277         User::Leave( KErrNotSupported );
       
   278         }
       
   279 
       
   280     TInt rendererProtocolInfoCount = aRendererProtocolInfos.Count();
       
   281 
       
   282     if( rendererProtocolInfoCount == 0 )
       
   283         {
       
   284         User::Leave(KErrNotFound);
       
   285         }
       
   286 
       
   287     //Get resources from the current upnp item
       
   288     RUPnPElementsArray resources;
       
   289     CleanupClosePushL( resources );
       
   290     UPnPItemUtility::GetResElements( aUpnpItem, resources );
       
   291     TInt resourcesCount = resources.Count();
       
   292     if ( resourcesCount == 0 )
       
   293         {
       
   294         User::Leave( KErrNotFound );
       
   295         }  
       
   296     
       
   297     for( TInt i = 0; i < rendererProtocolInfoCount && !suitableFound; i++ )
       
   298         {           
       
   299         TPtrC8 rendererProtocolInfo = aRendererProtocolInfos.MdcaPoint(i);
       
   300         if( rendererProtocolInfo.Find( *protocolInfoIdentifier ) )
       
   301             {
       
   302             //TODO: Add only suitable ones -- now adds all protocol infos
       
   303             //      from renderer, which contains _TS_ sub-string
       
   304             const TDesC& originalFilePath = resources[0]->FilePath();
       
   305             HBufC* transcodedFilePath = HBufC::NewL( 
       
   306                     originalFilePath.Length() + KTranscodedFlag().Length() );
       
   307             CleanupStack::PushL( transcodedFilePath );
       
   308             
       
   309             
       
   310             transcodedFilePath->Des().Append( originalFilePath );
       
   311             transcodedFilePath->Des().Append( KTranscodedFlag );
       
   312         
       
   313             aUpnpItem.AddResourceL( *transcodedFilePath, 
       
   314                     rendererProtocolInfo );
       
   315             
       
   316             CleanupStack::PopAndDestroy( transcodedFilePath );
       
   317             
       
   318             suitableFound = ETrue;
       
   319             }                
       
   320         }
       
   321 
       
   322     CleanupStack::PopAndDestroy( &resources );
       
   323     
       
   324     if( !suitableFound )
       
   325         {
       
   326         User::Leave( KErrNotFound );
       
   327         }    
       
   328     else
       
   329         {
       
   330         // delete orig.
       
   331         RUPnPElementsArray& elements = const_cast<RUPnPElementsArray&>(
       
   332                 aUpnpItem.GetElements());
       
   333 
       
   334         for( TInt resIndex(0); resIndex < elements.Count(); ++resIndex )
       
   335             {
       
   336             if( elements[resIndex]->Name() == KRes )
       
   337                 {
       
   338                 elements.Remove(resIndex);
       
   339                 break;
       
   340                 }
       
   341             }
       
   342         }
       
   343     }
       
   344 
       
   345 CUpnpTranscodeHelper::CUpnpTranscodeHelper()
       
   346     {
       
   347     __FUNC_LOG;    
       
   348     }
       
   349 
       
   350 void CUpnpTranscodeHelper::ConstructL()
       
   351     {
       
   352     __FUNC_LOG;    
       
   353     
       
   354     iGstWrapper = CUpnpGstWrapper::GetInstanceL();    
       
   355     iGstWrapper->SetObserverL( *this );
       
   356     User::LeaveIfError( iFs.Connect() );
       
   357     }
       
   358 
       
   359 HBufC8* CUpnpTranscodeHelper::GeneratePipelineL( 
       
   360         const TDesC8& aOriginalFilePath, 
       
   361         TContainerType aDestContainerType )
       
   362     {    
       
   363     __FUNC_LOG;
       
   364     
       
   365     if( aDestContainerType == EUnknownContainer )
       
   366         {
       
   367         User::Leave( KErrNotSupported );
       
   368         }    
       
   369 
       
   370     HBufC8* pipeline = NULL;     
       
   371     
       
   372     switch( aDestContainerType )
       
   373         {
       
   374         case ETsContainer:
       
   375             {
       
   376             //TODO ??
       
   377             pipeline = HBufC8::NewL( KDefaultPipelineFmt().Length() - 
       
   378                     KLocationFmtTagLen + aOriginalFilePath.Length() );            
       
   379             pipeline->Des().AppendFormat( KDefaultPipelineFmt, 
       
   380                     &aOriginalFilePath );
       
   381             break;
       
   382             }
       
   383         default:
       
   384             {
       
   385             __ASSERT_ALWAYS( 0, User::Invariant() );
       
   386             }
       
   387         }
       
   388     
       
   389     return pipeline; 
       
   390     }
       
   391 
       
   392 HBufC8* CUpnpTranscodeHelper::PathToLinuxSyntaxL( 
       
   393         const TDesC& aOriginalPath )
       
   394     {
       
   395     __FUNC_LOG;
       
   396     
       
   397     HBufC8* newFilePath = UpnpString::FromUnicodeL( aOriginalPath );
       
   398      
       
   399     TInt index = 0;
       
   400     while( index >= 0 )
       
   401         {
       
   402         index = newFilePath->Find( KSymbianDirDelimiter );
       
   403         if( index >= 0 )
       
   404             {
       
   405             newFilePath->Des().Replace( index, 
       
   406                     KSymbianDirDelimiter().Length(), KLinuxDirDelimiter );
       
   407             }
       
   408         }    
       
   409     
       
   410     return newFilePath;
       
   411     }
       
   412 
       
   413 void CUpnpTranscodeHelper::HandleGstEvent( Gst::TEvent aEvent )
       
   414     {
       
   415     __FUNC_LOG;
       
   416     
       
   417     if( aEvent == Gst::EError )
       
   418         {
       
   419         __LOG1( "CUpnpTranscodeHelper::HandleGstEvent ErrorMsg: %S",
       
   420                 iGstWrapper->ErrorMsg() );
       
   421         __ASSERT( EFalse, __FILE__, __LINE__ );
       
   422         }
       
   423     }
       
   424 
       
   425 
       
   426 // end of file