recog_util.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:10k
源码类别:

Symbian

开发平台:

Visual C++

  1. /*============================================================================*
  2.  *
  3.  * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
  4.  *
  5.  *
  6.  * Recognition helpers for recognizing file datatype given buffer and filename
  7.  * 
  8.  *============================================================================*/
  9.  
  10. #include <e32svr.h>
  11. #include <apmrec.h>
  12. #include <apmstd.h>
  13. #include "mpa_frame_header.h"
  14. #include "hxassert.h"
  15. #include "hxsym_mimetypes.h"
  16. #include "recog_util.h"
  17. namespace RecogUtil
  18. {
  19. //
  20. // constants
  21. //
  22. // magic numbers
  23. _LIT8(KMagicRMF, ".RMF");
  24. _LIT8(KMagic3GPP, "ftyp3gp");
  25. _LIT8(KMagicMPEG4, "moov");
  26. _LIT8(KMagicAMR, "#!AMR");
  27. _LIT8(KMagicSDP, "v=");
  28. enum RecognitionLevel
  29. {
  30.     ECertain=CApaDataRecognizerType::ECertain,
  31.     EProbable=CApaDataRecognizerType::EProbable,
  32.     EPossible=CApaDataRecognizerType::EPossible,
  33.     EUnlikely=CApaDataRecognizerType::EUnlikely,
  34.     ENotRecognized=CApaDataRecognizerType::ENotRecognized
  35. };
  36. void IncRecogLevel(RecognitionLevel& level)
  37. {
  38.     switch( level)
  39.     {
  40.     case ECertain:
  41.         // highest level already
  42.         break;
  43.     case EProbable:
  44.         level = ECertain;
  45.         break;
  46.     case EPossible:
  47.         level = EProbable;
  48.         break;
  49.     case EUnlikely:
  50.     case ENotRecognized:
  51.         level = EPossible;
  52.         break;
  53.     default:
  54.         HX_ASSERT(false); 
  55.         break;
  56.     }
  57. }
  58. TBool FindScheme(const TDesC& aScheme, const TDesC& aUrl)
  59. {
  60.     TInt colonPos = aUrl.Locate(':');
  61.     TInt schemePos = KErrNotFound;
  62.     schemePos = aUrl.FindF(aScheme);
  63.     TBool found = (schemePos >= 0 && aScheme.Length() == colonPos);
  64.     return found;
  65. }
  66. TInt IsRMFile(const TDesC& aName, const TDesC8& aBuffer)
  67. {
  68.     TInt confidence = ENotRecognized;
  69.     const TDesC8& magic = KMagicRMF;
  70.     TBool validMagic=ETrue;
  71.     TInt i;
  72.     for (i=0; i<aBuffer.Length() && i<4; i++)
  73.     {
  74. if (aBuffer[i] != magic[i])
  75. {
  76.     validMagic = EFalse;
  77.     break;
  78. }
  79.     }
  80.     if (validMagic)
  81.     {
  82. confidence = ECertain;
  83.     }
  84.     return confidence;
  85. }
  86. TInt IsAMRFile(const TDesC& aName, const TDesC8& aBuffer)
  87. {
  88.     TInt confidence = ENotRecognized;
  89.     const TDesC8& magic = KMagicAMR;
  90.     TBool validMagic=ETrue;
  91.     TInt i;
  92.     for (i=0; i<aBuffer.Length() && i<KMagicAMR().Length(); i++)
  93.     {
  94. if (aBuffer[i] != magic[i])
  95. {
  96.     validMagic = EFalse;
  97.     break;
  98. }
  99.     }
  100.     if (validMagic)
  101.     {
  102. confidence = ECertain;
  103.     }
  104.     return confidence;
  105. }
  106. TInt IsSMILFile(const TDesC& aName, const TDesC8& aBuffer)
  107. {
  108.     //
  109.     //<?xml version="1.0"?>
  110.     //<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  111.     //<body>
  112.     //</body>
  113.     //</smil
  114.     //
  115.     bool bHasExt = false;
  116.     TInt confidence = ENotRecognized;
  117.     // check for .smi or .smil extension
  118.     TInt idxDot = aName.LocateReverse('.');
  119.     if(idxDot != KErrNotFound)
  120.     {
  121.         _LIT(KSmilExtShort, ".smi");
  122.         _LIT(KSmilExtLong, ".smil");
  123.         TPtrC ptrExt = aName.Mid(idxDot);
  124.         if( !ptrExt.CompareF(KSmilExtShort) || !ptrExt.CompareF(KSmilExtLong) )
  125.         {
  126.             // has extension, therefore probably a smil file 
  127.             bHasExt = true;
  128.             confidence = EProbable;
  129.         }
  130.     }
  131.     // both of these are required smil tags
  132.     _LIT8(KXmlSMILTag, "<smil");
  133.     _LIT8(KXmlBODYTag, "<body");
  134.     
  135.     if (aBuffer.FindF(KXmlSMILTag) != KErrNotFound)
  136.     {
  137.         if(bHasExt)
  138.         {
  139.             // has smil tag as well as extension, therefore certainly a smil file
  140.             confidence = ECertain;
  141.         }
  142.         else
  143.         {
  144.             // has smil tag but no extension, therefore possibly a smil file
  145.     confidence = EPossible;
  146.             if(aBuffer.FindF(KXmlBODYTag) != KErrNotFound)
  147.             {
  148.                 // body tag as well, therefore probably a smil file
  149.                 confidence = EProbable;
  150.             }
  151.         }
  152.     }
  153.     return confidence;
  154. }
  155.                                         
  156. TInt IsRAMFile(const TDesC& aName, const TDesC8& aBuffer)
  157. {
  158.     TBool nameRecognized=EFalse;
  159.     TInt confidence = ENotRecognized;
  160.     
  161.     if ((aBuffer.FindF(_L8("rtsp://")) != KErrNotFound ||
  162.  aBuffer.FindF(_L8("file://")) != KErrNotFound ||
  163.  aBuffer.FindF(_L8("http://")) != KErrNotFound) &&
  164. aBuffer.FindF(_L8("<html>")) == KErrNotFound)
  165.     {
  166. confidence = EPossible;
  167.     }
  168.     if (aName.Length()>4)
  169.     {
  170.         _LIT(KRamExt, ".ram");
  171. if (aName.Right(4).CompareF(KRamExt)==0)
  172.         {
  173.     nameRecognized=ETrue;
  174.         }
  175.     }
  176.     if (confidence == EPossible && nameRecognized)
  177.     {
  178. confidence = ECertain;
  179.     }
  180.     return confidence;
  181. }
  182. RecognitionLevel TestForMP3FrameHeaders(const TDesC8& buffer)
  183. {
  184.     TInt idxEnd = buffer.Length() - MPA_FRAME_HDR_SZ;
  185.     for(TInt idx = 0; idx < idxEnd; ++idx)
  186.     {
  187.         const unsigned char* pBuf = buffer.Ptr() + idx;
  188.         
  189.         // try and parse mp3 frame at this location
  190.         MPAFrameHeader frame;   
  191.         if( frame.Unpack(pBuf) && (MPA_LAYER3 == frame.m_layer) )
  192.         {
  193.             // looks like a valid frame so far; now move on past frame (header + data)
  194.             pBuf += frame.m_frameSize;
  195.             if(pBuf < buffer.Ptr() + idxEnd)
  196.             {
  197.                 // look for second frame header with matching attributes
  198.                 MPAFrameHeader frame2;
  199.                 if( frame2.Unpack(pBuf)
  200.                     && (frame2.m_version == frame.m_version)
  201.                     && (frame2.m_layer == frame.m_layer) 
  202.                     && (frame2.m_sampleRate == frame.m_sampleRate) )
  203.                 {
  204.                     // highly likely this is mp3
  205.                     return EProbable;
  206.                 }
  207.             }
  208.             else
  209.             {
  210.                 // good chance this is mp3 (frame size exceeds the buffer we get)
  211.                 return EPossible;
  212.             }
  213.         }
  214.         
  215.     }
  216.     return ENotRecognized;
  217. }
  218. TInt IsMP3File(const TDesC& aName, const TDesC8& aBuffer)
  219. {
  220.     RecognitionLevel confidence = ENotRecognized;
  221.     //RDebug::Print(_L("looking at '%S'"), &aName);
  222.     _LIT8(KMagicID3, "ID3");
  223.     _LIT(KMP3Ext, ".mp3");
  224.     // look for mp3 extension
  225.     bool bHasExtension = (0 == aName.Right(4).CompareF(KMP3Ext));
  226.     // look for start of ID3v2 header
  227.     bool bHasID3 = (0 == aBuffer.Left(3).Compare(KMagicID3));
  228.     
  229.     if(bHasID3)
  230.     {
  231.         // other MPA types as well as AAC may have an ID3 header; the header
  232.         // can be quite long so we often can't find frame headers because the
  233.         // buffer is too small
  234.         confidence = EPossible;
  235.     }
  236.     else
  237.     {
  238.         confidence = TestForMP3FrameHeaders(aBuffer);
  239.     }
  240.     if(bHasExtension)
  241.     {
  242.         IncRecogLevel(confidence);
  243.     }
  244.     return confidence;
  245. }
  246. TInt Is3GPPFile(const TDesC& aName, const TDesC8& aBuffer)
  247. {
  248.     _LIT8(KFtyp3gpp, "3gp"); // 3gp4 and 3gp5
  249.     TInt confidence = IsISOMediaFile(aName, aBuffer, KFtyp3gpp);
  250.     if( ENotRecognized != confidence )
  251.     {
  252.         TInt index = aBuffer.Find(KFtyp3gpp);
  253.         HX_ASSERT(index != KErrNotFound);
  254.         if(index != KErrNotFound)
  255.         {
  256.             // look at character after '3gp'
  257.             index += KFtyp3gpp().Length();
  258.             HX_ASSERT(index  < aBuffer.Length());
  259.     if (aBuffer[index] != '4' && aBuffer[index] != '5')
  260.             {
  261.                 // we only recognize 3gp4 and 3gp5
  262.         confidence = ENotRecognized;
  263.             }
  264.         }
  265.     }
  266.     return confidence;
  267. }
  268. TInt IsMPEG4File(const TDesC& aName, const TDesC8& aBuffer)
  269. {
  270.     _LIT8(KFtypMP4, "mp4"); // mp41 and others
  271.     
  272.     return IsISOMediaFile(aName, aBuffer, KFtypMP4);
  273. }
  274. TInt IsMPEG4Audio(const TDesC& aName, const TDesC8& aBuffer)
  275. {
  276.     TInt confidence = ENotRecognized;
  277.     _LIT8(KSampleEntryMPEG4Video, "mp4v");
  278.     _LIT8(KSampleEntryH263Video, "s263");
  279.     if (aBuffer.Find(KSampleEntryH263Video) != KErrNotFound &&
  280. aBuffer.Find(KSampleEntryMPEG4Video) != KErrNotFound)
  281. confidence = EProbable;
  282.     return confidence;
  283. }
  284. TInt IsSDPFile(const TDesC& aName, const TDesC8& aBuffer)
  285. {
  286.     TInt confidence = ENotRecognized;
  287.     const TDesC8& magic = KMagicSDP;
  288.     TBool validMagic=ETrue;
  289.     TInt i;
  290.     for (i=0; i<aBuffer.Length() &&  i<KMagicSDP().Length(); i++)
  291.     {
  292. if (aBuffer[i] != magic[i])
  293. {
  294.     validMagic = EFalse;
  295.     break;
  296. }
  297.     }
  298.     if (validMagic)
  299. confidence = ECertain;
  300.     return confidence;
  301. }
  302. inline
  303. TUint32 UnpackUint32(const TUint8* buf)
  304. {
  305.     return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
  306. }
  307. TInt IsISOMediaFile(const TDesC& aName, const TDesC8& aBuffer, const TDesC8& brand)
  308. {
  309.     _LIT8(KAtomFTYP, "ftyp");
  310.     HX_ASSERT(brand.Length() <= 4);
  311.     TInt confidence = ENotRecognized; 
  312.     TInt idx = aBuffer.Find(KAtomFTYP);
  313.     if( idx >= 4)
  314.     {
  315.         // back up to size field; preceeds object identifier
  316.         idx -= 4;
  317.        
  318.         // get size of potential atom(box) data
  319.         TInt cbAtomData = UnpackUint32(aBuffer.Ptr() + idx) - 8;
  320.         // index past size + 'ftype' to beginning of atom data
  321.         idx += 8;
  322.         TInt cbLeft = aBuffer.Length() - idx;
  323.         if( cbLeft > cbAtomData )
  324.         {
  325.             // likely case since ftyp atom is small and buffer is large; we'll only look at potential ftyp atom
  326.             cbLeft = cbAtomData;
  327.         }
  328.         // now look for matching brand (3gp?, isom, mp4?, etc.)
  329.         enum
  330.         {
  331.             getFirst,
  332.             getOthers
  333.         } state = getFirst;
  334.         // look at 4-byte objects (every field is four bytes in ftyp atom/box)
  335.         for(TInt idxLast = idx + cbLeft - 4; idx <= idxLast; idx += 4)
  336.         {
  337.             TPtrC8 ptr = aBuffer.Mid(idx, brand.Length());
  338.             if(0 == ptr.Compare(brand))
  339.             {
  340.                 // found matching brand 
  341.                 confidence = ECertain;
  342.                 break;
  343.             }
  344.             if( getFirst == state )
  345.             {
  346.                 // skip past minor version and continue searching for compatible brands
  347.                 idx += 4;
  348.                 state = getOthers;
  349.             }
  350.         }
  351.         
  352.     }
  353.     return confidence;
  354. }
  355. } // ns RecogUtil