amrff.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:33k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #include "hxcom.h"
  37. #include "hxplugn.h"
  38. #include "ihxpckts.h"
  39. #include "hxformt.h"
  40. #include "hxccf.h"
  41. #include "hxfiles.h"
  42. #include "hxengin.h"
  43. #include "baseobj.h"
  44. #include "pckunpck.h"
  45. #include "hxver.h"
  46. #include "hxamrpack.h"
  47. #include "amr_frame_info.h"
  48. #include "amr_frame_hdr.h"
  49. #include "amrffmlog.h"
  50. #include "amrff.h"
  51. #include "amrff.ver"
  52. #include "hxheap.h"
  53. #ifdef _DEBUG
  54. #undef HX_THIS_FILE
  55. static const char HX_THIS_FILE[] = __FILE__;
  56. #endif
  57. const char* const CAMRFileFormat::m_pszDescription        = "Helix AMR File Format Plugin";
  58. const char* const CAMRFileFormat::m_pszCopyright          = HXVER_COPYRIGHT;
  59. const char* const CAMRFileFormat::m_pszMoreInfoURL        = HXVER_MOREINFO;
  60. const char* const CAMRFileFormat::m_ppszFileMimeTypes[]   = {"audio/amr", "audio/awb", NULL};
  61. const char* const CAMRFileFormat::m_ppszFileExtensions[]  = {"amr", "awb", NULL};
  62. const char* const CAMRFileFormat::m_ppszFileOpenNames[]   = {"AMR Files (*.amr,*.awb)", NULL};
  63. const char* const CAMRFileFormat::m_ppszStreamMimeTypes[] = {"audio/amr",
  64.                                                              "audio/awb",
  65.                                                              "audio/X-RN-3GPP-AMR",
  66.                                                              "audio/X-RN-3GPP-AMR-WB",
  67.                                                              NULL};
  68. const BYTE        CAMRFileFormat::m_pMagicSingle[6]       = {0x23,0x21,0x41,0x4d,0x52,0x0a};
  69. const BYTE        CAMRFileFormat::m_pMagicSingleWB[9]     = {0x23,0x21,0x41,0x4d,0x52,0x2d,0x57,0x42,0x0a};
  70. const BYTE        CAMRFileFormat::m_pMagicMulti[12]       = {0x23,0x21,0x41,0x4d,0x52,0x5F,0x4D,0x43,0x31,
  71.                                                              0x2E,0x30,0x0a};
  72. const BYTE        CAMRFileFormat::m_pMagicMultiWB[15]     = {0x23,0x21,0x41,0x4d,0x52,0x2d,0x57,0x42,0x5F,
  73.                                                              0x4D,0x43,0x31,0x2E,0x30,0x0a};
  74. const BYTE        CAMRFileFormat::m_ucNumChannelsMap[16]  = {0,2,3,4,4,5,6,0,0,0,0,0,0,0,0,0};
  75. //#define DEBUG_TEST_FRAME_SCAN
  76. CAMRFileFormat::CAMRFileFormat()
  77. {
  78.     MLOG_LEAK("CON CAMRFileFormat this=0x%08xn", this);
  79.     m_lRefCount           = 0;
  80.     m_pContext            = NULL;
  81.     m_pCommonClassFactory = NULL;
  82.     m_pFileObject         = NULL;
  83.     m_pFormatResponse     = NULL;
  84.     m_pFileStat           = NULL;
  85.     m_eState              = StateReady;
  86.     m_ulHeaderSize        = 0;
  87.     m_ulBytesPerFrame     = 0;
  88.     m_ulFileSize          = 0;
  89.     m_ulNumChannels       = 0;
  90.     m_ulNextFileOffset    = 0;
  91.     m_ulNextTimeStamp     = 0;
  92.     m_pPayloadFormat      = NULL;
  93.     m_bWideBand           = FALSE;
  94.     m_bScanForFrameBegin  = FALSE;
  95. }
  96. CAMRFileFormat::~CAMRFileFormat()
  97. {
  98.     MLOG_LEAK("DES CAMRFileFormat this=0x%08xn", this);
  99.     Close();
  100. }
  101. STDMETHODIMP CAMRFileFormat::QueryInterface(REFIID riid, void** ppvObj)
  102. {
  103.     HX_RESULT retVal = HXR_OK;
  104.     if (ppvObj)
  105.     {
  106.         // NULL out by default
  107.         *ppvObj = NULL;
  108.         // Switch based on IID
  109.         if (IsEqualIID(riid, IID_IUnknown))
  110.         {
  111.             AddRef();
  112.             *ppvObj = (IUnknown*) (IHXPlugin*) this;
  113.         }
  114.         else if (IsEqualIID(riid, IID_IHXPlugin))
  115.         {
  116.             AddRef();
  117.             *ppvObj = (IHXPlugin*) this;
  118.         }
  119.         else if (IsEqualIID(riid, IID_IHXFileFormatObject))
  120.         {
  121.             AddRef();
  122.             *ppvObj = (IHXFileFormatObject*) this;
  123.         }
  124.         else if (IsEqualIID(riid, IID_IHXFileResponse))
  125.         {
  126.             AddRef();
  127.             *ppvObj = (IHXFileResponse*) this;
  128.         }
  129.         else if (IsEqualIID(riid, IID_IHXFileStatResponse))
  130.         {
  131.             AddRef();
  132.             *ppvObj = (IHXFileStatResponse*) this;
  133.         }
  134.         else if (IsEqualIID(riid, IID_IHXInterruptSafe))
  135.         {
  136.             AddRef();
  137.             *ppvObj = (IHXInterruptSafe*) this;
  138.         }
  139.         else
  140.         {
  141.             retVal = HXR_NOINTERFACE;
  142.         }
  143.     }
  144.     else
  145.     {
  146.         retVal = HXR_FAIL;
  147.     }
  148.     return retVal;
  149. }
  150. STDMETHODIMP_(ULONG32) CAMRFileFormat::AddRef()
  151. {
  152.     return InterlockedIncrement(&m_lRefCount);
  153. }
  154. STDMETHODIMP_(ULONG32) CAMRFileFormat::Release()
  155. {
  156.     if (InterlockedDecrement(&m_lRefCount) > 0)
  157.     {
  158.         return m_lRefCount;
  159.     }
  160.     delete this;
  161.     return 0;
  162. }
  163. STDMETHODIMP CAMRFileFormat::InitPlugin(IUnknown* pContext)
  164. {
  165.     HX_RESULT retVal = HXR_FAIL;
  166.     if (pContext)
  167.     {
  168.         // Save the context
  169.         HX_RELEASE(m_pContext);
  170.         m_pContext = pContext;
  171.         m_pContext->AddRef();
  172.         // Get the commom class factory
  173.         HX_RELEASE(m_pCommonClassFactory);
  174.         retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  175.                                             (void**) &m_pCommonClassFactory);
  176.     }
  177.     return retVal;
  178. }
  179. STDMETHODIMP CAMRFileFormat::GetPluginInfo(REF(BOOL)        rbLoadMultiple,
  180.                                            REF(const char*) rpszDescription,
  181.                                            REF(const char*) rpszCopyright,
  182.                                            REF(const char*) rpszMoreInfoURL,
  183.                                            REF(ULONG32)     rulVersionNumber)
  184. {
  185.     rbLoadMultiple   = TRUE;   // Must be true for file formats.
  186.     rpszDescription  = (const char*) m_pszDescription;
  187.     rpszCopyright    = (const char*) m_pszCopyright;
  188.     rpszMoreInfoURL  = (const char*) m_pszMoreInfoURL;
  189.     rulVersionNumber = TARVER_ULONG32_VERSION;
  190.     return HXR_OK;
  191. }
  192. STDMETHODIMP CAMRFileFormat::GetFileFormatInfo(REF(const char**) rppszFileMimeTypes,
  193.                                                REF(const char**) rppszFileExtensions,
  194.                                                REF(const char**) rppszFileOpenNames)
  195. {
  196.     rppszFileMimeTypes  = (const char**) m_ppszFileMimeTypes;
  197.     rppszFileExtensions = (const char**) m_ppszFileExtensions;
  198.     rppszFileOpenNames  = (const char**) m_ppszFileOpenNames;
  199.     return HXR_OK;
  200. }
  201. STDMETHODIMP CAMRFileFormat::InitFileFormat(IHXRequest*        pRequest, 
  202.                                             IHXFormatResponse* pFormatResponse,
  203.                                             IHXFileObject*     pFileObject)
  204. {
  205.     HX_RESULT retVal = HXR_UNEXPECTED;
  206.     if (m_eState == StateReady)
  207.     {
  208.         retVal = HXR_FAIL;
  209.         if (pFormatResponse && pFileObject)
  210.         {
  211.             // Save response interface
  212.             HX_RELEASE(m_pFormatResponse);
  213.             m_pFormatResponse = pFormatResponse;
  214.             m_pFormatResponse->AddRef();
  215.             // Save file object
  216.             HX_RELEASE(m_pFileObject);
  217.             m_pFileObject = pFileObject;
  218.             m_pFileObject->AddRef();
  219.             // Get our own IHXFileResponse interface
  220.             IHXFileResponse* pResponse = NULL;
  221.             retVal = QueryInterface(IID_IHXFileResponse, (void**) &pResponse);
  222.             if (pResponse)
  223.             {
  224.                 // Set the state
  225.                 m_eState = StateInitFileFormatInitDonePending;
  226.                 // Init the file object
  227.                 retVal   = m_pFileObject->Init(HX_FILE_READ | HX_FILE_BINARY, pResponse);
  228.             }
  229.             HX_RELEASE(pResponse);
  230.         }
  231.         if (FAILED(retVal) && pFormatResponse)
  232.         {
  233.             pFormatResponse->InitDone(retVal);
  234.         }
  235.     }
  236.     return retVal;
  237. }
  238. STDMETHODIMP CAMRFileFormat::Close()
  239. {
  240.     if (m_pFileObject)
  241.     {
  242.         m_pFileObject->Close();
  243.     }
  244.     HX_RELEASE(m_pContext);
  245.     HX_RELEASE(m_pCommonClassFactory);
  246.     HX_RELEASE(m_pFileObject);
  247.     HX_RELEASE(m_pFormatResponse);
  248.     HX_RELEASE(m_pFileStat);
  249.     HX_DELETE(m_pPayloadFormat);
  250.     m_eState            = StateReady;
  251.     m_ulFileSize        = 0;
  252.     m_ulNumChannels     = 0;
  253.     m_ulNextFileOffset  = 0;
  254.     m_ulNextTimeStamp   = 0;
  255.     m_bWideBand         = FALSE;
  256.     return HXR_OK;
  257. }
  258. STDMETHODIMP CAMRFileFormat::GetFileHeader()
  259. {
  260.     HX_RESULT retVal = HXR_OK;
  261.     if (m_eState == StateReady)
  262.     {
  263.         // Set our new state
  264.         m_eState = StateFileHeaderSeekDonePending;
  265.         // Seek back to the beginning of the file
  266.         retVal = m_pFileObject->Seek(0, FALSE);
  267.     }
  268.     else
  269.     {
  270.         retVal = HXR_UNEXPECTED;
  271.     }
  272.     return retVal;
  273. }
  274. STDMETHODIMP CAMRFileFormat::GetStreamHeader(UINT16 unStreamNumber)
  275. {
  276.     HX_RESULT retVal = HXR_OK;
  277.     if (m_eState == StateReady)
  278.     {
  279.         // Set the state
  280.         m_eState = StateStreamHeaderSeekDonePending;
  281.         // m_ulNextFileOffset should be set the offset of
  282.         // the first AMR frame in the file
  283.         retVal = m_pFileObject->Seek(m_ulNextFileOffset, FALSE);
  284.     }
  285.     else
  286.     {
  287.         retVal = HXR_UNEXPECTED;
  288.     }
  289.     return retVal;
  290. }
  291. STDMETHODIMP CAMRFileFormat::GetPacket(UINT16 unStreamNumber)
  292. {
  293.     HX_RESULT retVal = HXR_UNEXPECTED;
  294.     if (m_eState == StateReady)
  295.     {
  296.         if (m_pPayloadFormat)
  297.         {
  298.             // Try and get a packet from the payload format object
  299.             IHXPacket* pPacket = NULL;
  300.             retVal = m_pPayloadFormat->GetPacket(pPacket);
  301.             if (SUCCEEDED(retVal))
  302.             {
  303.                 // The payload format object had a packet ready,
  304.                 // so send it. We don't have to change the state
  305.                 retVal = m_pFormatResponse->PacketReady(HXR_OK, pPacket);
  306.             }
  307.             else
  308.             {
  309.                 // Clear the return value. It's not an error
  310.                 // if the payload format object doesn't have any
  311.                 // packets - it just means we need to provide more data.
  312.                 retVal = HXR_OK;
  313.                 // We need to provide the payload format object
  314.                 // some more of the file, so we will seek to the
  315.                 // new file offset.
  316.                 m_eState = StateGetPacketSeekDonePending;
  317.                 // Seek the file
  318.                 retVal = m_pFileObject->Seek(m_ulNextFileOffset, FALSE);
  319.             }
  320.             HX_RELEASE(pPacket);
  321.         }
  322.     }
  323.     return retVal;
  324. }
  325. STDMETHODIMP CAMRFileFormat::Seek(ULONG32 ulOffset)
  326. {
  327.     HX_RESULT retVal = HXR_UNEXPECTED;
  328.     if (m_pFormatResponse && m_pPayloadFormat)
  329.     {
  330.         // Clear out the packets from the payload format object
  331.         m_pPayloadFormat->Reset();
  332.         // First convert the time offset to a file offset,
  333.         // assuming a constant bitrate and therefore a 
  334.         // constant number of bytes per frame. We know that
  335.         // AMR frames always have a duration of 20ms.
  336.         UINT32 ulFrameNum   = ulOffset / 20;
  337.         UINT32 ulFileOffset = ulFrameNum * m_ulBytesPerFrame + m_ulHeaderSize;
  338.         // Compute the next time stamp
  339.         m_ulNextTimeStamp = ulFrameNum * 20;
  340.         // Set the next file offset
  341.         m_ulNextFileOffset = ulFileOffset;
  342.         // In the case of files where the bytes per frame is not constant
  343.         // throughout the file, the following file seek might
  344.         // not land on a frame boundary. Therefore, this flag
  345.         // will tell us that we need to scan the buffer we read
  346.         // for a frame boundary.
  347.         m_bScanForFrameBegin = TRUE;
  348.         // Tell the format response we're ready
  349.         retVal = m_pFormatResponse->SeekDone(HXR_OK);
  350.     }
  351.     return retVal;
  352. }
  353. STDMETHODIMP CAMRFileFormat::InitDone(HX_RESULT status)
  354. {
  355.     HX_RESULT retVal = HXR_OK;
  356.     if (m_eState == StateInitFileFormatInitDonePending)
  357.     {
  358.         // Get the IHXFileStat interface
  359.         HX_RELEASE(m_pFileStat);
  360.         retVal = m_pFileObject->QueryInterface(IID_IHXFileStat, (void**) &m_pFileStat);
  361.         if (SUCCEEDED(retVal))
  362.         {
  363.             // Get our own IHXFileStatResponse interface
  364.             IHXFileStatResponse* pStatResponse = NULL;
  365.             retVal = QueryInterface(IID_IHXFileStatResponse, (void**) &pStatResponse);
  366.             if (SUCCEEDED(retVal))
  367.             {
  368.                 // Set the state
  369.                 m_eState = StateInitFileFormatStatDonePending;
  370.                 // Call Stat
  371.                 retVal = m_pFileStat->Stat(pStatResponse);
  372.             }
  373.             HX_RELEASE(pStatResponse);
  374.         }
  375.         if (FAILED(retVal))
  376.         {
  377.             // Set the state
  378.             m_eState = StateReady;
  379.             // Call back to the response
  380.             retVal = m_pFormatResponse->InitDone(retVal);
  381.         }
  382.     }
  383.     else
  384.     {
  385.         retVal = HXR_UNEXPECTED;
  386.     }
  387.     return retVal;
  388. }
  389. STDMETHODIMP CAMRFileFormat::SeekDone(HX_RESULT status)
  390. {
  391.     HX_RESULT retVal = HXR_OK;
  392.     if (m_eState == StateFileHeaderSeekDonePending)
  393.     {
  394.         if (SUCCEEDED(status))
  395.         {
  396.             // Set the new state
  397.             m_eState = StateFileHeaderReadDonePending;
  398.             // Now read AMR_HEADER_READ_SIZE bytes
  399.             retVal = m_pFileObject->Read(AMR_HEADER_READ_SIZE);
  400.         }
  401.         else
  402.         {
  403.             // Go back to the StateReady state
  404.             m_eState = StateReady;
  405.             // Fail out to the response interface
  406.             retVal = m_pFormatResponse->FileHeaderReady(status, NULL);
  407.         }
  408.     }
  409.     else if (m_eState == StateStreamHeaderSeekDonePending)
  410.     {
  411.         if (SUCCEEDED(status))
  412.         {
  413.             // Set the new state
  414.             m_eState = StateStreamHeaderReadDonePending;
  415.             // Now read AMR_READ_SIZE bytes
  416.             retVal = m_pFileObject->Read(AMR_READ_SIZE);
  417.         }
  418.         else
  419.         {
  420.             // Go back to StateReady state
  421.             m_eState = StateReady;
  422.             // Fail out to response interface
  423.             retVal = m_pFormatResponse->StreamHeaderReady(status, NULL);
  424.         }
  425.     }
  426.     else if (m_eState == StateGetPacketSeekDonePending)
  427.     {
  428.         if (SUCCEEDED(status))
  429.         {
  430.             // Set the new state
  431.             m_eState = StateGetPacketReadDonePending;
  432.             // Read AMR_READ_SIZE more bytes
  433.             retVal = m_pFileObject->Read(AMR_READ_SIZE);
  434.         }
  435.         else
  436.         {
  437.             // Go back to ready
  438.             m_eState = StateReady;
  439.             // Issue a StreamDone()
  440.             retVal = m_pFormatResponse->StreamDone(0);
  441.         }
  442.     }
  443.     else
  444.     {
  445.         retVal = HXR_UNEXPECTED;
  446.     }
  447.     return retVal;
  448. }
  449. STDMETHODIMP CAMRFileFormat::ReadDone(HX_RESULT status, IHXBuffer* pBuffer)
  450. {
  451.     HX_RESULT retVal = HXR_OK;
  452.     if (m_eState == StateFileHeaderReadDonePending)
  453.     {
  454.         // Assume the worst
  455.         retVal = HXR_FAIL;
  456.         // Process the first few bytes of the file
  457.         if (SUCCEEDED(status) && pBuffer)
  458.         {
  459.             // Check the first five bytes to identify
  460.             // this as an AMR file
  461.             BYTE* pBuf = (BYTE*) pBuffer->GetBuffer();
  462.             if (pBuf)
  463.             {
  464.                 // Test the magic number
  465.                 if (!memcmp(pBuf, m_pMagicSingle, sizeof(m_pMagicSingle)))
  466.                 {
  467.                     m_bWideBand        = FALSE;
  468.                     m_ulNumChannels    = 1;
  469.                     m_ulHeaderSize = sizeof(m_pMagicSingle);
  470.                     retVal             = HXR_OK;
  471.                 }
  472.                 else if (!memcmp(pBuf, m_pMagicSingleWB, sizeof(m_pMagicSingleWB)))
  473.                 {
  474.                     m_bWideBand        = TRUE;
  475.                     m_ulNumChannels    = 1;
  476.                     m_ulHeaderSize = sizeof(m_pMagicSingleWB);
  477.                     retVal             = HXR_OK;
  478.                 }
  479.                 else if (!memcmp(pBuf, m_pMagicMulti, sizeof(m_pMagicMulti)))
  480.                 {
  481.                     m_bWideBand        = FALSE;
  482.                     m_ulNumChannels    = m_ucNumChannelsMap[pBuf[sizeof(m_pMagicMulti) + 3] & 0x0F];
  483.                     m_ulHeaderSize = sizeof(m_pMagicMulti) + 4;
  484.                     if (m_ulNumChannels != 0)
  485.                     {
  486.                         retVal = HXR_OK;
  487.                     }
  488.                 }
  489.                 else if (!memcmp(pBuf, m_pMagicMultiWB, sizeof(m_pMagicMultiWB)))
  490.                 {
  491.                     m_bWideBand        = TRUE;
  492.                     m_ulNumChannels    = m_ucNumChannelsMap[pBuf[sizeof(m_pMagicMultiWB) + 3] & 0x0F];
  493.                     m_ulHeaderSize = sizeof(m_pMagicMultiWB) + 4;
  494.                     if (m_ulNumChannels != 0)
  495.                     {
  496.                         retVal = HXR_OK;
  497.                     }
  498.                 }
  499.                 else
  500.                 {
  501.                     // This is not an AMR file
  502.                     retVal = HXR_FAIL;
  503.                 }
  504.                 if (SUCCEEDED(retVal))
  505.                 {
  506.                     // Set the next file offset to right after
  507.                     // the file header
  508.                     m_ulNextFileOffset = m_ulHeaderSize;
  509.                     // Create an IHXValues
  510.                     IHXValues* pHdr = NULL;
  511.                     retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void**) &pHdr);
  512.                     if (SUCCEEDED(retVal))
  513.                     {
  514.                         // Set the StreamCount property
  515.                         pHdr->SetPropertyULONG32("StreamCount", 1);
  516.                         // Set the new state
  517.                         m_eState = StateReady;
  518.                         // Send the file header
  519.                         retVal = m_pFormatResponse->FileHeaderReady(HXR_OK, pHdr);
  520.                     }
  521.                     HX_RELEASE(pHdr);
  522.                 }
  523.             }
  524.         }
  525.         if (FAILED(retVal))
  526.         {
  527.             // Go back to the StateFileFormatInitialized state
  528.             m_eState = StateReady;
  529.             // Fail out to the response interface
  530.             retVal = m_pFormatResponse->FileHeaderReady(retVal, NULL);
  531.         }
  532.     }
  533.     else if (m_eState == StateStreamHeaderReadDonePending)
  534.     {
  535.         retVal = status;
  536.         if (SUCCEEDED(retVal))
  537.         {
  538.             // Create our CHXAMRPayloadFormat object
  539.             retVal = HXR_OUTOFMEMORY;
  540.             HX_DELETE(m_pPayloadFormat);
  541.             m_pPayloadFormat = new CHXAMRPayloadFormatPacketizer();
  542.             if (m_pPayloadFormat)
  543.             {
  544.                 // Init the payload format
  545.                 retVal = m_pPayloadFormat->Init(m_pContext, TRUE);
  546.                 if (SUCCEEDED(retVal))
  547.                 {
  548.                     // Create an IHXValues
  549.                     IHXValues* pHdr = NULL;
  550.                     retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues, (void**) &pHdr);
  551.                     if (SUCCEEDED(retVal))
  552.                     {
  553.                         // Set the MimeType
  554.                         INT32 lIndx = (m_bWideBand ? 3 : 2);
  555.                         SetCStringProperty(pHdr, "MimeType", m_ppszStreamMimeTypes[lIndx], m_pContext);
  556.                         // Compute the average bitrate
  557.                         UINT32 ulAvgBitRate = 0;
  558.                         GetStreamInfo(pBuffer, 0, ulAvgBitRate, m_ulBytesPerFrame);
  559.                         // Set the ASM rule book
  560.                         char szASMRuleBook[64]; /* Flawfinder: ignore */
  561.                         sprintf(szASMRuleBook, "AverageBandwidth=%lu,Priority=5;", ulAvgBitRate); /* Flawfinder: ignore */
  562.                         SetCStringProperty(pHdr, "ASMRuleBook", szASMRuleBook, m_pContext);
  563.                         // Compute the duration
  564.                         UINT32 ulDur = 1000;
  565.                         if (ulAvgBitRate != 0)
  566.                         {
  567.                             ulDur = m_ulFileSize * 8000 / ulAvgBitRate;
  568.                         }
  569.                         // Set some properties
  570.                         pHdr->SetPropertyULONG32("StreamNumber",  0);
  571.                         pHdr->SetPropertyULONG32("MaxBitRate",    ulAvgBitRate);
  572.                         pHdr->SetPropertyULONG32("AvgBitRate",    ulAvgBitRate);
  573.                         pHdr->SetPropertyULONG32("MaxPacketSize", AMR_IDEAL_PACKET_SIZE);
  574.                         pHdr->SetPropertyULONG32("AvgPacketSize", AMR_IDEAL_PACKET_SIZE);
  575.                         pHdr->SetPropertyULONG32("MinPacketSize", AMR_IDEAL_PACKET_SIZE);
  576.                         pHdr->SetPropertyULONG32("StartTime",     0);
  577.                         pHdr->SetPropertyULONG32("Duration",      ulDur);
  578.                         // Pass this stream header into the payload format object
  579.                         retVal = m_pPayloadFormat->SetStreamHeader(pHdr);
  580.                         if (SUCCEEDED(retVal))
  581.                         {
  582.                             // Create a raw file packet
  583.                             IHXPacket* pPacket = NULL;
  584.                             retVal = MakeRawFilePacket(pBuffer, m_ulNextTimeStamp, pPacket);
  585.                             if (SUCCEEDED(retVal))
  586.                             {
  587.                                 // Add this packet to the payload object
  588.                                 retVal = m_pPayloadFormat->SetPacket(pPacket);
  589.                                 if (SUCCEEDED(retVal))
  590.                                 {
  591.                                     // Update the next file offset
  592.                                     m_ulNextFileOffset += m_pPayloadFormat->GetPacketBytesConsumed();
  593.                                     // Update the next time stamp
  594.                                     m_ulNextTimeStamp  += m_pPayloadFormat->GetDurationConsumed();
  595.                                     // Set the state
  596.                                     m_eState = StateReady;
  597.                                     // Send the stream header
  598.                                     retVal = m_pFormatResponse->StreamHeaderReady(HXR_OK, pHdr);
  599.                                 }
  600.                             }
  601.                             HX_RELEASE(pPacket);
  602.                         }
  603.                     }
  604.                     HX_RELEASE(pHdr);
  605.                 }
  606.             }
  607.         }
  608.         if (FAILED(retVal))
  609.         {
  610.             // Return to StateReady
  611.             m_eState = StateReady;
  612.             // Fail out to response interface
  613.             retVal = m_pFormatResponse->StreamHeaderReady(retVal, NULL);
  614.         }
  615.     }
  616.     else if (m_eState == StateGetPacketReadDonePending)
  617.     {
  618.         retVal = status;
  619.         if (SUCCEEDED(retVal))
  620.         {
  621.             // Do we need to scan this buffer for a frame begin?
  622.             IHXBuffer* pNewBuffer = NULL;
  623.             UINT32     ulNewBufferOffset = 0;
  624.             if (m_bScanForFrameBegin)
  625.             {
  626. #ifdef DEBUG_TEST_FRAME_SCAN
  627.                 // Force the first fifth of the buffer to be invalid
  628.                 memset(pBuffer->GetBuffer(), 0x83, pBuffer->GetSize() / 5);
  629. #endif
  630.                 // Scan the buffer
  631.                 UINT32 ulOffset = 0;
  632.                 BYTE   bRet = CAMRFrameInfo::FindFrameBegin((m_bWideBand ? WideBand : NarrowBand),
  633.                                                             pBuffer->GetBuffer(),
  634.                                                             pBuffer->GetSize(),
  635.                                                             AMR_MIN_CONSEC_FRAMES,
  636.                                                             ulOffset);
  637.                 if (bRet)
  638.                 {
  639.                     // If the offset is at the beginning
  640.                     // of the buffer, then we don't have to
  641.                     // do anything. If the offset is NOT at the
  642.                     // beginning, then we need to create a new
  643.                     // buffer and copy the old one into it.
  644.                     if (ulOffset > 0 && ulOffset < pBuffer->GetSize())
  645.                     {
  646.                         // We have a valid offset
  647.                         retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
  648.                                                                        (void**) &pNewBuffer);
  649.                         if (SUCCEEDED(retVal))
  650.                         {
  651.                             retVal = pNewBuffer->Set(pBuffer->GetBuffer() + ulOffset,
  652.                                                      pBuffer->GetSize()   - ulOffset);
  653.                             if (SUCCEEDED(retVal))
  654.                             {
  655.                                 ulNewBufferOffset = ulOffset;
  656.                             }
  657.                         }
  658.                     }
  659.                     else if (ulOffset != 0)
  660.                     {
  661.                         // Huh? the offset was outside the buffer? Surrender!
  662.                         retVal = HXR_FAIL;
  663.                     }
  664.                 }
  665.                 else
  666.                 {
  667.                     // Yikes! We didn't find a frame in this
  668.                     // buffer at all? We surrender!
  669.                     retVal = HXR_FAIL;
  670.                 }
  671.                 // Clear the flag
  672.                 m_bScanForFrameBegin = FALSE;
  673.             }
  674.             if (SUCCEEDED(retVal))
  675.             {
  676.                 // Create a raw file packet
  677.                 IHXPacket* pRawPacket = NULL;
  678.                 retVal = MakeRawFilePacket((pNewBuffer ? pNewBuffer : pBuffer),
  679.                                            m_ulNextTimeStamp, pRawPacket);
  680.                 if (SUCCEEDED(retVal))
  681.                 {
  682.                     // If the buffer was less than we read, then we are 
  683.                     // probably at the end of the file. Therefore, we want
  684.                     // to process ALL of this buffer, regardless of the
  685.                     // minimum packet size. So we need to tell the payload
  686.                     // format object to Flush().
  687.                     if (pBuffer->GetSize() < AMR_READ_SIZE)
  688.                     {
  689.                         m_pPayloadFormat->Flush();
  690.                     }
  691.                     // Add this packet to the payload object
  692.                     retVal = m_pPayloadFormat->SetPacket(pRawPacket);
  693.                     if (SUCCEEDED(retVal))
  694.                     {
  695.                         // Update the next file offset
  696.                         m_ulNextFileOffset += m_pPayloadFormat->GetPacketBytesConsumed() + ulNewBufferOffset;
  697.                         // Update the next time stamp
  698.                         m_ulNextTimeStamp  += m_pPayloadFormat->GetDurationConsumed();
  699.                         // Did we get here from a GetPacket() or a seek
  700.                         // Now try and get a packet from the payload format object
  701.                         IHXPacket* pPacket = NULL;
  702.                         retVal = m_pPayloadFormat->GetPacket(pPacket);
  703.                         if (SUCCEEDED(retVal))
  704.                         {
  705.                             // Set the state
  706.                             m_eState = StateReady;
  707.                             // We have a packet to give, so give it
  708.                             retVal = m_pFormatResponse->PacketReady(retVal, pPacket);
  709.                         }
  710.                         HX_RELEASE(pPacket);
  711.                     }
  712.                 }
  713.                 HX_RELEASE(pRawPacket);
  714.             }
  715.             HX_RELEASE(pNewBuffer);
  716.         }
  717.         if (FAILED(retVal))
  718.         {
  719.             // We either got here because of something bad, or because
  720.             // we simply got to the end of the file and couldn't read
  721.             // any more. Either way, we issue a StreamDone().
  722.             //
  723.             // Go back to ready
  724.             m_eState = StateReady;
  725.             // Issue a StreamDone
  726.             retVal = m_pFormatResponse->StreamDone(0);
  727.         }
  728.     }
  729.     else
  730.     {
  731.         retVal = HXR_UNEXPECTED;
  732.     }
  733.     return retVal;
  734. }
  735. STDMETHODIMP CAMRFileFormat::WriteDone(HX_RESULT status)
  736. {
  737.     HX_RESULT retVal = HXR_OK;
  738.     return retVal;
  739. }
  740. STDMETHODIMP CAMRFileFormat::CloseDone(HX_RESULT status)
  741. {
  742.     HX_RESULT retVal = HXR_OK;
  743.     return retVal;
  744. }
  745. STDMETHODIMP CAMRFileFormat::StatDone(HX_RESULT status, UINT32 ulSize, UINT32 ulCreationTime,
  746.                                       UINT32 ulAccessTime, UINT32 ulModificationTime, UINT32 ulMode)
  747. {
  748.     HX_RESULT retVal = HXR_UNEXPECTED;
  749.     if (m_eState == StateInitFileFormatStatDonePending)
  750.     {
  751.         // Did we succeed?
  752.         if (SUCCEEDED(status))
  753.         {
  754.             // Save the file size
  755.             m_ulFileSize = ulSize;
  756.             // Now we are done with the stat interface
  757.             HX_RELEASE(m_pFileStat);
  758.         }
  759.         // Set the state
  760.         m_eState = StateReady;
  761.         // Call back to response
  762.         retVal = m_pFormatResponse->InitDone(status);
  763.     }
  764.     return retVal;
  765. }
  766. HX_RESULT STDAPICALLTYPE CAMRFileFormat::HXCreateInstance(IUnknown** ppIUnknown)
  767. {
  768.     HX_RESULT retVal = HXR_FAIL;
  769.     if (ppIUnknown)
  770.     {
  771.         // Set default
  772.         *ppIUnknown = NULL;
  773.         // Create the object
  774.         CAMRFileFormat *pObj = new CAMRFileFormat();
  775.         if (pObj)
  776.         {
  777.             // QI for IUnknown
  778.             retVal = pObj->QueryInterface(IID_IUnknown, (void**) ppIUnknown);
  779.         }
  780.         if (FAILED(retVal))
  781.         {
  782.             HX_DELETE(pObj);
  783.         }
  784.     }
  785.     return retVal;
  786. }
  787. HX_RESULT STDAPICALLTYPE CAMRFileFormat::CanUnload2(void)
  788. {
  789.     return ((CHXBaseCountingObject::ObjectsActive() > 0) ? HXR_FAIL : HXR_OK);
  790. }
  791. HX_RESULT CAMRFileFormat::GetStreamInfo(IHXBuffer*  pBuffer,
  792.                                         UINT32      ulOffset,
  793.                                         REF(UINT32) rulAvgBitRate,
  794.                                         REF(UINT32) rulBytesPerFrame)
  795. {
  796.     HX_RESULT retVal = HXR_OK;
  797.     if (pBuffer && ulOffset < pBuffer->GetSize())
  798.     {
  799.         BYTE*     pBuf      = pBuffer->GetBuffer() + ulOffset;
  800.         BYTE*     pBufLimit = pBuffer->GetBuffer() + pBuffer->GetSize();
  801.         UINT32    ulByteSum = 0;
  802.         UINT32    ulMSSum   = 0;
  803.         UINT32    ulNumFr   = 0;
  804.         CAMRFrameHdr cHdr((m_bWideBand ? WideBand : NarrowBand));
  805.         while (1)
  806.         {
  807.             if (pBuf + cHdr.HdrBytes() >= pBufLimit)
  808.             {
  809.                 break;
  810.             }
  811.             cHdr.Unpack(pBuf);
  812.             if(pBuf + cHdr.DataBytes() >= pBufLimit)
  813.             {
  814.                 break;
  815.             }
  816.             pBuf += cHdr.DataBytes();
  817.             ulByteSum += cHdr.DataBytes() + cHdr.HdrBytes();
  818.             ulMSSum   += CAMRFrameInfo::FrameDuration();
  819.             ulNumFr++;
  820.         }
  821.         if (ulNumFr) rulBytesPerFrame = ulByteSum / ulNumFr;
  822.         if (ulMSSum) rulAvgBitRate = ulByteSum * 8000 / ulMSSum;
  823.     }
  824.     else
  825.     {
  826.         retVal = HXR_FAIL;
  827.     }
  828.     return retVal;
  829. }
  830. HX_RESULT CAMRFileFormat::MakeRawFilePacket(IHXBuffer* pBuffer, UINT32 ulTimeStamp,
  831.                                             REF(IHXPacket*) rpPacket)
  832. {
  833.     HX_RESULT retVal = HXR_FAIL;
  834.     if (pBuffer && m_pCommonClassFactory)
  835.     {
  836.         IHXPacket* pPacket = NULL;
  837.         retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXPacket, (void**) &pPacket);
  838.         if (SUCCEEDED(retVal))
  839.         {
  840.             retVal = pPacket->Set(pBuffer, ulTimeStamp, 0, HX_ASM_SWITCH_ON, 0);
  841.             if (SUCCEEDED(retVal))
  842.             {
  843.                 HX_RELEASE(rpPacket);
  844.                 rpPacket = pPacket;
  845.                 rpPacket->AddRef();
  846.             }
  847.         }
  848.         HX_RELEASE(pPacket);
  849.     }
  850.     return retVal;
  851. }