[Android-port-dev] Re: [datatype-dev] CR: Extend CHXFileRecognizer for Android project

[Android-port-dev] Re: [datatype-dev] CR: Extend CHXFileRecognizer for Android project

Sheldon Fu sfu at real.com
Mon Mar 2 12:11:25 PST 2009


I believe the correct logic should b "if (ID3 at the beginning) skip it; 
check MP3 header at current location;".

fxd

Qiang Luo wrote:
> I have changed the mp3 format detection to check mp3 frame header 
> first per Eric's review.  This has been checked in to head and 
> hxclient_3_1_0_atlas branch.
>
> Thanks Eric and Sheldon for the reviews.
>
> Qiang
>
>> Delivered-To: qluo at real.com
>> Reply-To: ehyche at real.com
>> From: "Eric Hyche" <ehyche at real.com>
>> To: "'Qiang Luo'" <qluo at real.com>, "'Greg Wright'" <gwright at real.com>,
>>       "'Tony Seaward'" <tseaward at helixcommunity.org>
>> Cc: "'Milko Boic'" <milko at real.com>, "'Sheldon Fu'" <sfu at real.com>
>> Subject: RE: [Client-dev] CR: extend CHXFileRecognizer to cover more  
>> mine-types
>> Date: Mon, 2 Mar 2009 10:21:55 -0500
>> Organization: RealNetworks, Inc.
>> X-Mailer: Microsoft Office Outlook 12.0
>> Thread-Index: AcmZNIVEE72yww2oQ6GMMpdDPKfxoQCFU8xg
>>
>> Qiang,
>>
>> Here are my comments:
>>
>> +HXBOOL
>> +CHXFileRecognizer::IsMP3File(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize)
>> +    {
>> +       // check for ID3 tags
>> +        if (0 == strncmp((const char*)pData, "ID3", 3))
>> +        {
>> +            bResult = TRUE;
>> +        }
>> +       else
>> +       {
>> +           // check for valid frame header
>> +           UINT32 ulHdr;
>> +           UCHAR* pEnd = pData + ulSize - 4;
>> +           do
>> +           {
>> +               ulHdr = LoadMP3Header(pData);
>> +               if (IsValidMP3Header(ulHdr))
>> +               {
>> +                   bResult = TRUE;
>> +                   break;
>> +               }
>> +               pData += 4;
>> +           }
>> +           while(pData < pEnd);
>> +       }
>> +    }
>> +    return bResult;
>> +}
>> +
>>
>> ID3 tags are generally at the end of .mp3 files. Also,
>> ID3 tags can be found in other files, such as .aac or .amr.
>> So the presence of ID3 tags is not a reliable indication
>> of an .mp3 file. Your mp3 header check is the more reliable
>> way.
>>
>> Rest looks good.
>>
>> =======================================
>> Eric Hyche (ehyche at real.com)
>> Principal Engineer
>> RealNetworks, Inc.
>>
>>
>> >-----Original Message-----
>> >From: Qiang Luo [mailto:qluo at real.com]
>> Re-send to the datatype-dev group.  I'm hopping to get some feedback 
>> for the file format detection code.
>>
>> Synopsis:
>> Extend CHXFileRecognizer to cover additional mine-types for Android 
>> project.
>>
>> Summary:
>> In Android project, we are introducing a new protocol scheme, fd://, 
>> claimed by the local file system, to support file descriptor as data 
>> source.  Normally, for the local file source, the client core uses 
>> the file extension to load the file format plugin via 
>> IHXPluginHandler3.  When using descriptor as data source, the content 
>> file name and extension will be unknown.  Therefore, we need to 
>> extend the SDP-only CHXFileRecognizer to cover additional mine-types 
>> for Android project.
>>
>> The client core HXFileSource setup code has the following file 
>> mine-type discovery order:
>>
>> 1) look for "Content-Type" property in the request's response header.
>> 2) QI the file-system's file object for IHXFileMimeMapper interface 
>> and call FindMimeType().
>> 3) get mime-type from url parameters.
>> 4) try the file recognizer  GetMimeType(m_pFileObject,  
>> m_pMimeFinderResponse).
>> 5) try to create a file format plugin enumerator via 
>> IHXPluginHandler3 based on the file extension to load the plugin
>> 6) fail if none of the above attempts succeeds.
>>
>> Adding additional mine-types detection to CHXFileRecognizer would 
>> alter the client core code path.  To minimize the risk to other 
>> projects, I add #if defined() to make the addition Android platform 
>> only.  Even for Android, we defer mime-type detection to 
>> FileRecognizer only when there is no file extension.
>>
>> Note, the detection code must be simple and small in size.  It is 
>> intended to be just robust enough to load the correct file format 
>> plugin.
>>
>> Branch:
>> head, hxclient_3_1_0_atlas
>>
>> File modified:
>> common/system/recognizer.cpp
>> common/system/pub/recognizer.h
>>
>> Affected platform: Android only
>>
>> Risks for non-android projects: low
>>
>> Please review the attached diff.  I'm looking forward to suggestions 
>> to improve the format detection code.
>>
>> Thanks,
>>
>> Qiang
>>
>> Diffs:
>> Index: recognizer.cpp
>> ===================================================================
>> RCS file: /cvsroot/common/system/recognizer.cpp,v
>> retrieving revision 1.12
>> diff -u -r1.12 recognizer.cpp
>> --- recognizer.cpp      7 Feb 2006 19:21:27 -0000       1.12
>> +++ recognizer.cpp      23 Feb 2009 17:51:01 -0000
>> @@ -4,43 +4,418 @@
>>
>>  #include "recognizer.h"
>>
>> +// file mime-types our recognizer might return
>> +#define HX_MIMETYPE_RM             "application/x-pn-realmedia"
>> +#define HX_MIMETYPE_MP3                    "audio/mp3"
>> +#define HX_MIMETYPE_MP4AUDIO       "audio/mp4"
>> +#define HX_MIMETYPE_MP4VIDEO       "video/mp4"
>> +#define HX_MIMETYPE_3GPAUDIO       "audio/3gpp"
>> +#define HX_MIMETYPE_3GPVIDEO       "video/3gpp"
>> +#define HX_MIMETYPE_MPEG           "video/x-mpeg"
>> +#define HX_MIMETYPE_WM             "application/vnd.ms-asf"
>> +#define HX_MIMETYPE_AVI                    
>> "application/x-pn-avi-plugin"
>> +#define HX_MIMETYPE_OGG                    "application/ogg"
>> +#define HX_MIMETYPE_MIDI           "application/x-midi"
>> +#define HX_MIMETYPE_WAVE           "audio/x-wav"
>> +#define HX_MIMETYPE_QT             "application/x-pn-quicktime-stream"
>> +#define HX_MIMETYPE_SDP                    "application/sdp"
>> +
>> +// length of buffer read from file and passed to recognizer
>> +static const int KRecogLength = 512;
>> +
>>  #if !defined (_SYMBIAN)
>>  HX_RESULT CHXFileRecognizer::GetMimeType(const char* pFileName, 
>> IHXBuffer* pBuffer, REF(IHXBuffer*) pMimeType)
>>  {
>> -    if (IsSDPFile(pBuffer))
>> +    HX_RESULT retVal = HXR_FAILED;
>> +    char* pMimeTypeString = NULL;
>> +    char* pFileExtension = NULL;
>> +    UCHAR* pData = NULL;
>> +    UINT32 ulSize = 0;
>> +    HXBOOL bContinue = TRUE;
>> +
>> +    // get file extension
>> +    if (pFileName)
>> +    {
>> +       CHXString strExtension = pFileName;
>> +       INT32 lPeriod = strExtension.ReverseFind('.');
>> +       if (lPeriod >= 0)
>> +       {
>> +           strExtension = 
>> strExtension.Right(strExtension.GetLength() - lPeriod - 1);
>> +           if (strExtension.GetLength() > 0)
>> +           {
>> +               strExtension.MakeLower();
>> +               pFileExtension = (char*)(const char*)strExtension;
>> +           }
>> +       }
>> +    }
>> +
>> +    // data at the begining of the media file
>> +    if (pBuffer)
>> +    {
>> +       ulSize = pBuffer->GetSize();
>> +       pData = pBuffer->GetBuffer();
>> +    }
>> +
>> +    // check SDP
>> +    if (IsSDPFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_SDP;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    //XXXqluo to minimize the risk, the following format check is 
>> for ANDROID platform only
>> +#if defined(ANDROID)
>> +    // skip format checking if the file name has an extension.
>> +    if (bContinue && (pFileExtension || ulSize != KRecogLength))
>> +    {
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // RealMedia
>> +    if (bContinue && IsRMFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_RM;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // 3GPP
>> +    if (bContinue && Is3GPPFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_3GPAUDIO;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // WM
>> +    if (bContinue && IsWMFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_WM;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // AVI
>> +    if (bContinue && IsAVIFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_AVI;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // OGG
>> +    if (bContinue && IsOGGFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_OGG;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // MIDI
>> +    if (bContinue && IsMIDIFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_MIDI;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // WAVE
>> +    if (bContinue && IsWAVEFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_WAVE;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // MP4
>> +    if (bContinue && IsMP4File(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_MP4AUDIO;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // QuickTime
>> +    if (bContinue && IsQuickTimeFile(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_QT;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // MPEG
>> +    if (bContinue && IsMPEGFile(pData, ulSize))
>>      {
>> -       if (HXR_OK == CreateBufferCCF(pMimeType, m_pContext))
>> +       pMimeTypeString = HX_MIMETYPE_MPEG;
>> +       bContinue = FALSE;
>> +    }
>> +
>> +    // MP3
>> +    if (bContinue && IsMP3File(pData, ulSize))
>> +    {
>> +       pMimeTypeString = HX_MIMETYPE_MP3;
>> +       bContinue = FALSE;
>> +    }
>> +#endif // ANDROID
>> +
>> +    if (pMimeTypeString)
>> +    {
>> +       retVal = CreateBufferCCF(pMimeType, m_pContext);
>> +       if (HXR_OK == retVal)
>>         {
>> -            int len = strlen("application/sdp");
>> -           pMimeType->Set((const UCHAR*)"application/sdp", len + 1);
>> +            int len = strlen(pMimeTypeString);
>> +           pMimeType->Set((const UCHAR*)pMimeTypeString, len + 1);
>>             ((char*)pMimeType->GetBuffer())[len] = '\0';
>> -           return HXR_OK;
>>         }
>>      }
>>
>> -    return HXR_FAILED;
>> +    return retVal;
>>  }
>>  #endif
>>
>>  HXBOOL
>> -CHXFileRecognizer::IsSDPFile(IHXBuffer* pBuffer)
>> +CHXFileRecognizer::IsSDPFile(UCHAR* pData, UINT32 ulSize)
>>  {
>>      HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 2)
>> +    {
>> +        if (0 == strncmp((const char*)pData, "v=", 2))
>> +        {
>> +            bResult = TRUE;
>> +        }
>> +    }
>> +    return bResult;
>> +}
>>
>> -    if (pBuffer && pBuffer->GetSize())
>> +HXBOOL
>> +CHXFileRecognizer::IsRMFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    UCHAR pRAMagic[4] = {'.', 'r', 'a', 0xFD};
>> +    if (pData && ulSize > 4)
>>      {
>> -        if (0 == strncmp((const char*)pBuffer->GetBuffer(), "v=", 2))
>> +        if (0 == strncmp((const char*)pData, ".RMF", 4) 
>> ||             // .RMF
>> +           0 == strncmp((const char*)pData, ".RMS", 4) 
>> ||              // .RMS
>> +           0 == memcmp(pData, pRAMagic, 
>> 4))                            // .ra\0xFD
>>          {
>>              bResult = TRUE;
>>          }
>>      }
>> +    return bResult;
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsQuickTimeFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 8)
>> +    {
>> +       // check atom types
>> +       pData += 4;
>> +       if (0 == strncmp((const char*)pData, "moov", 4) ||
>> +           0 == strncmp((const char*)pData, "free", 4) ||
>> +           0 == strncmp((const char*)pData, "skip", 4) ||
>> +           0 == strncmp((const char*)pData, "mdat", 4) ||
>> +           0 == strncmp((const char*)pData, "wide", 4) ||
>> +           0 == strncmp((const char*)pData, "pnot", 4))
>> +       {
>> +           //XXXqluo todo: validate atom.
>> +           bResult = TRUE;
>> +       }
>> +    }
>> +    return bResult;
>> +}
>>
>> +HXBOOL
>> +CHXFileRecognizer::IsWMFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 16)
>> +    {
>> +       // WM header magic
>> +       UCHAR pMagic[16] = {0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 
>> 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C};
>> +       if (memcmp(pData, pMagic, 16) == 0)
>> +       {
>> +           bResult = TRUE;
>> +       }
>> +    }
>>      return bResult;
>>  }
>>
>> -// length of buffer read from file and passed to recognizer
>> -static const int KRecogLength = 512;
>> +HXBOOL
>> +CHXFileRecognizer::IsAVIFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 16)
>> +    {
>> +       UCHAR pMagic1[4] = {'R', 'I', 'F', 
>> 'F'};                        // RIFF
>> +       UCHAR pMagic2[8] = {'A', 'V', 'I', ' ', 'L', 'I', 'S', 
>> 'T'};    // AVI LIST chunk
>> +       if (memcmp(pData, pMagic1, 4) == 0 ||
>> +           memcmp(pData+8, pMagic2, 8) == 0)
>> +       {
>> +           bResult = TRUE;
>> +       }
>> +    }
>> +    return bResult;
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsOGGFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 4)
>> +    {
>> +       UCHAR pMagic[4] = {'O', 'g', 'g', 
>> 'S'};                         // page magic "OggS"
>> +       if (memcmp(pData, pMagic, 4) == 0)
>> +       {
>> +           bResult = TRUE;
>> +       }
>> +    }
>> +    return bResult;
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsMIDIFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 4)
>> +    {
>> +       UCHAR pMagic[4] = {'M', 'T', 'h', 
>> 'd'};                         // MIDI header chunk ID
>> +       if (memcmp(pData, pMagic, 4) == 0)
>> +       {
>> +           bResult = TRUE;
>> +       }
>> +    }
>> +    return bResult;
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsWAVEFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 12)
>> +    {
>> +       UCHAR pMagic1[4] = {'R', 'I', 'F', 
>> 'F'};                        // Chunk ID
>> +       UCHAR pMagic2[4] = {'W', 'A', 'V', 
>> 'E'};                        // Format
>> +       if (memcmp(pData, pMagic1, 4) == 0 ||
>> +           memcmp(pData+8, pMagic2, 4) == 0)
>> +       {
>> +           bResult = TRUE;
>> +       }
>> +    }
>> +    return bResult;
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsMPEGFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize > 4)
>> +    {
>> +       UCHAR pMagic[4] = {0x00, 0x00, 0x01, 
>> 0xb3};                     // MPEG sequence header start code
>> +       if (memcmp(pData, pMagic, 4) == 0)
>> +       {
>> +           bResult = TRUE;
>> +       }
>> +    }
>> +    return bResult;
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsMP3File(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize)
>> +    {
>> +       // check for ID3 tags
>> +        if (0 == strncmp((const char*)pData, "ID3", 3))
>> +        {
>> +            bResult = TRUE;
>> +        }
>> +       else
>> +       {
>> +           // check for valid frame header
>> +           UINT32 ulHdr;
>> +           UCHAR* pEnd = pData + ulSize - 4;
>> +           do
>> +           {
>> +               ulHdr = LoadMP3Header(pData);
>> +               if (IsValidMP3Header(ulHdr))
>> +               {
>> +                   bResult = TRUE;
>> +                   break;
>> +               }
>> +               pData += 4;
>> +           }
>> +           while(pData < pEnd);
>> +       }
>> +    }
>> +    return bResult;
>> +}
>> +
>> +UINT32
>> +CHXFileRecognizer::LoadMP3Header(UCHAR* p)
>> +{
>> +    return (UINT32)(((p[0] & 255) << 24) | ((p[1] & 255) << 16) | 
>> ((p[2] & 255) <<  8) | ((p[3] & 255)));
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsValidMP3Header(UINT32 ulHdr)
>> +{
>> +    return (((getFrameSync(ulHdr)      & 2047)==2047) &&
>> +            ((getVersionIndex(ulHdr)   &    3)!=   1) &&
>> +            ((getLayerIndex(ulHdr)     &    3)!=   0) &&
>> +            ((getBitrateIndex(ulHdr)   &   15)!=   0) &&
>> +            ((getBitrateIndex(ulHdr)   &   15)!=  15) &&
>> +            ((getFrequencyIndex(ulHdr) &    3)!=   3) &&
>> +            ((getEmphasisIndex(ulHdr)  &    3)!=   2)    );
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::Is3GPPFile(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    return IsISOMediaFile(pData, ulSize, "3gp");
>> +}
>>
>> +HXBOOL
>> +CHXFileRecognizer::IsMP4File(UCHAR* pData, UINT32 ulSize)
>> +{
>> +    if (IsISOMediaFile(pData, ulSize, "M4A") ||
>> +       IsISOMediaFile(pData, ulSize, "mp4"))
>> +    {
>> +       return TRUE;
>> +    }
>> +    else
>> +    {
>> +       return FALSE;
>> +    }
>> +}
>> +
>> +HXBOOL
>> +CHXFileRecognizer::IsISOMediaFile(UCHAR* pData, UINT32 ulSize, const 
>> char* pBrand)
>> +{
>> +    HXBOOL bResult = FALSE;
>> +    if (pData && ulSize)
>> +    {
>> +       UCHAR* pEnd = (pData + ulSize - 4);
>> +
>> +       // locate file type box
>> +       pData += 4;
>> +       HXBOOL bFound = FALSE;
>> +       while (pData < pEnd)
>> +       {
>> +           // scan for "ftyp"
>> +           if ((*pData == 'f' && *(pData+1) == 't' && *(pData+2) == 
>> 'y' && *(pData+3) == 'p'))
>> +           {
>> +               bFound = TRUE;
>> +               break;
>> +           }
>> +           pData++;
>> +       }
>> +
>> +       // match for the given type(pBrand)
>> +       if (bFound)
>> +       {
>> +           pData += 4;
>> +           if (0 == strncmp((const char*)pData, pBrand, 
>> strlen(pBrand)))
>> +           {
>> +               bResult = TRUE;
>> +           }
>> +       }
>> +    }
>> +    return bResult;
>> +}
>>
>>  CHXFileRecognizer::CHXFileRecognizer(IUnknown* pContext)
>>      : m_lRefCount(0),
>> Index: pub/recognizer.h
>> ===================================================================
>> RCS file: /cvsroot/common/system/pub/recognizer.h,v
>> retrieving revision 1.5
>> diff -u -r1.5 recognizer.h
>> --- pub/recognizer.h    7 Feb 2006 19:21:27 -0000       1.5
>> +++ pub/recognizer.h    23 Feb 2009 17:51:02 -0000
>> @@ -51,9 +51,30 @@
>>                             IHXBuffer* /* IN */ pBuffer,
>>                             REF(IHXBuffer*) /* OUT*/ pMimeType);
>>
>> -    HXBOOL    IsSDPFile(IHXBuffer* pBuffer);
>> +    HXBOOL  IsSDPFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsRMFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsMP3File(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsISOMediaFile(UCHAR* pData, UINT32 ulSize, const char* 
>> pBrand);
>> +    HXBOOL  IsMP4File(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  Is3GPPFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsWMFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsAVIFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsOGGFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsMIDIFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsWAVEFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsMPEGFile(UCHAR* pData, UINT32 ulSize);
>> +    HXBOOL  IsQuickTimeFile(UCHAR* pData, UINT32 ulSize);
>>      void    DoFileRecognize(void);
>>
>> +    UINT32  LoadMP3Header(UCHAR* pData);
>> +    HXBOOL  IsValidMP3Header(UINT32 ulHdr);
>> +    INT32   getFrameSync(UINT32 ulHdr)     { return 
>> (int)((ulHdr>>21) & 2047); };
>> +    INT32   getVersionIndex(UINT32 ulHdr)   { return 
>> (int)((ulHdr>>19) & 3); };
>> +    INT32   getLayerIndex(UINT32 ulHdr)     { return 
>> (int)((ulHdr>>17) & 3); };
>> +    INT32   getBitrateIndex(UINT32 ulHdr)   { return 
>> (int)((ulHdr>>12) & 15); };
>> +    INT32   getFrequencyIndex(UINT32 ulHdr) { return 
>> (int)((ulHdr>>10) & 3); };
>> +    INT32   getEmphasisIndex(UINT32 ulHdr)  { return (int)(ulHdr & 
>> 3); };
>> +
>>  private:
>>      LONG32 m_lRefCount;
>>      IUnknown* m_pContext;
>>
>>
>> _______________________________________________
>> Datatype-dev mailing list
>> Datatype-dev at helixcommunity.org
>> http://lists.helixcommunity.org/mailman/listinfo/datatype-dev
>
>
>
> _______________________________________________
> Android-port-dev mailing list
> Android-port-dev at lists.helixcommunity.org
> http://lists.helixcommunity.org/mailman/listinfo/android-port-dev
>




More information about the Datatype-dev mailing list
 

Site Map   |   Terms of Use   |   Privacy Policy   |   Contact Us

Copyright © 1995-2007 RealNetworks, Inc. All rights reserved. RealNetworks and Helix are trademarks of RealNetworks.
All other trademarks or registered trademarks are the property of their respective holders.