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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: h263pyld.cpp,v 1.5.2.1 2004/07/09 01:56:41 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "h263pyld.h"
  50. #include "debug.h"
  51. #include "ihxpckts.h"
  52. #include <string.h>
  53. #include "rfc2190hlpr.h"
  54. #include "rfc2429hlpr.h"
  55. #include "bitstream.h"
  56. #include "bitpack.h"
  57. #define D_H263 0 // D_INFO
  58. CH263PayloadFormat::CH263PayloadFormat() :
  59.     m_lRefCount(0),
  60.     m_pCCF(0),
  61.     m_state(NeedPSC),
  62.     m_ulFrameSize(0),
  63.     m_ulTimestamp(0),
  64.     m_pDepackHlpr(0)
  65. {
  66. #ifdef DEBUG
  67.     debug_level() |= D_H263;
  68. #endif /* DEBUG */
  69. }
  70. CH263PayloadFormat::~CH263PayloadFormat()
  71. {
  72.     HX_RELEASE(m_pCCF);
  73.     FlushInput();
  74.     FlushOutput();
  75.     delete m_pDepackHlpr;
  76.     m_pDepackHlpr = 0;
  77. }
  78. /*
  79.  * IUnknown methods
  80.  */
  81. STDMETHODIMP CH263PayloadFormat::QueryInterface(REFIID riid,
  82.    void** ppvObj)
  83. {
  84.     HX_RESULT res = HXR_NOINTERFACE;
  85.     *ppvObj = NULL;
  86.     if (IsEqualIID(riid, IID_IUnknown))
  87.     {
  88. AddRef();
  89. *ppvObj = this;
  90. res = HXR_OK;
  91.     }
  92.     else if (IsEqualIID(riid, IID_IHXPayloadFormatObject))
  93.     {
  94. AddRef();
  95. *ppvObj = (IHXPayloadFormatObject*)this;
  96. res = HXR_OK;
  97.     }
  98.     return res;
  99. }
  100. STDMETHODIMP_(ULONG32) CH263PayloadFormat::AddRef()
  101. {
  102.     return InterlockedIncrement(&m_lRefCount);
  103. }
  104. STDMETHODIMP_(ULONG32) CH263PayloadFormat::Release()
  105. {
  106.     if (InterlockedDecrement(&m_lRefCount) > 0)
  107.     {
  108.         return m_lRefCount;
  109.     }
  110.     delete this;
  111.     return 0;
  112. }
  113. /*
  114.  * IHXPayloadFormatObject methods
  115.  */
  116. STDMETHODIMP CH263PayloadFormat::Init(THIS_
  117.       IUnknown* pContext,
  118.       BOOL bPacketize)
  119. {
  120.     DPRINTF(D_H263, ("CH263PayloadFormat::Init(%p, %d)n",
  121.      pContext, bPacketize));
  122.     HX_RESULT res = HXR_UNEXPECTED;
  123.     if (!bPacketize)
  124.     {
  125. // Currently we only support depacketization
  126. res = pContext->QueryInterface(IID_IHXCommonClassFactory,
  127.        (void**)&m_pCCF);
  128.     }
  129.     return res;
  130. }
  131. STDMETHODIMP CH263PayloadFormat::Close()
  132. {
  133.     DPRINTF(D_H263, ("CH263PayloadFormat::Close()n"));
  134.     Flush();
  135.     return HXR_OK;
  136. }
  137. STDMETHODIMP CH263PayloadFormat::Reset()
  138. {
  139.     // Called on Seeks
  140.     DPRINTF(D_H263, ("CH263PayloadFormat::Reset()n"));
  141.     FlushInput();
  142.     FlushOutput();
  143.     m_state = NeedPSC;
  144.     return HXR_OK;
  145. }
  146. STDMETHODIMP CH263PayloadFormat::SetStreamHeader(IHXValues* pHeader)
  147. {
  148.     DPRINTF(D_H263, ("CH263PayloadFormat::SetStreamHeader()n"));
  149.     return HXR_OK;
  150. }
  151. STDMETHODIMP CH263PayloadFormat::GetStreamHeader(REF(IHXValues*) pHeader)
  152. {
  153.     DPRINTF(D_H263, ("CH263PayloadFormat::GetStreamHeader()n"));
  154.     return HXR_OK;
  155. }
  156. STDMETHODIMP CH263PayloadFormat::SetPacket(IHXPacket* pPacket)
  157. {
  158.     DPRINTF(D_H263, ("CH263PayloadFormat::SetPacket()n"));
  159.     HX_RESULT res = HXR_UNEXPECTED;
  160.     if (!pPacket->IsLost())
  161.     {
  162. IHXBuffer* pBuf = pPacket->GetBuffer();
  163. const UINT8* pData = 0;
  164. ULONG32 ulDataSize = 0;
  165. BOOL bP = FALSE;
  166. res = HXR_OK;
  167. if (!m_pDepackHlpr)
  168.     res = CreateHelper(pBuf->GetBuffer(), pBuf->GetSize());
  169. if (SUCCEEDED(res) &&
  170.     SUCCEEDED(res = m_pDepackHlpr->OnPacket(pBuf->GetBuffer(),
  171.     pBuf->GetSize())))
  172. {
  173.     BOOL bDone = FALSE;
  174.     BOOL bPacketAdded = FALSE;
  175.     /* Cache values since ProcessPacket() uses
  176.      * m_pDepackHlpr and can change it's state.
  177.      */
  178.     UINT32 ulDataSize = m_pDepackHlpr->DataSize();
  179.     BOOL bIsPictureStart = m_pDepackHlpr->IsPictureStart();
  180.     while(!bDone && SUCCEEDED(res))
  181.     {
  182. switch(m_state) {
  183. case NeedPSC:
  184.     // See if this packet has a PSC
  185.     if (bIsPictureStart)
  186.     {
  187. m_ulFrameSize = 0; // Make sure the frame size is 0
  188. // Add the packet to the input queue
  189. res = AddPacket(ulDataSize, pPacket);
  190. // Signal that we added this packet
  191. bPacketAdded = TRUE;
  192. // Cache the timestamp for this frame
  193. m_ulTimestamp = pPacket->GetTime();
  194. // Change state
  195. m_state = GotPSC;
  196.     }
  197.     else
  198.     {
  199. // Signal that we are done handling this packet
  200. bDone = TRUE;
  201.     }
  202.     break;
  203. case GotPSC:
  204.     if (pPacket->GetTime() == m_ulTimestamp)
  205.     {
  206. // See if the packet has been added yet
  207. if (!bPacketAdded)
  208. {
  209.     DPRINTF (D_H263,("Multi-packetn"));
  210.     // Add the packet to the input queue
  211.     res = AddPacket(ulDataSize, pPacket);
  212.     // Signal that we added this packet
  213.     bPacketAdded = TRUE;
  214. }
  215. // Check for the marker bit. The marker bit
  216. // is always mapped to odd ASM rule numbers
  217. if ((pPacket->GetASMRuleNumber() & 0x1) == 1)
  218.     m_state = GotFrame;
  219. else
  220.     bDone = TRUE;
  221.     }
  222.     else
  223.     {
  224. // This appears to be a different frame.
  225. // Goto the GotFrame state so that we
  226. // process the current frame
  227. m_state = GotFrame;
  228.     }
  229.     break;
  230. case GotFrame:
  231.     if (!m_inputQueue.IsEmpty())
  232.     {
  233. // Process the packets in the input queue
  234. res = ProcessPackets();
  235.     }
  236.     // Change to the NeedPSC state
  237.     m_state = NeedPSC;
  238.     if (bPacketAdded)
  239. bDone = TRUE;
  240. };
  241.     }
  242. }
  243. if (!SUCCEEDED(res))
  244. {
  245.     /* Something unexpected happened.
  246.      * Flush everything.
  247.      */
  248.     FlushInput();
  249. }
  250. HX_RELEASE(pBuf);
  251.     }
  252.     else
  253.     {
  254. FlushInput();
  255. res = HXR_OK;
  256.     }
  257.     return res;
  258. }
  259. STDMETHODIMP CH263PayloadFormat::GetPacket(REF(IHXPacket*) pPacket)
  260. {
  261.     DPRINTF(D_H263, ("CH263PayloadFormat::GetPacket()n"));
  262.     HX_RESULT res = HXR_FAILED;
  263.     if (!m_outputQueue.IsEmpty())
  264.     {
  265. pPacket = (IHXPacket*)m_outputQueue.RemoveHead();
  266. res = HXR_OK;
  267.     }
  268.     DPRINTF(D_H263, ("CH263PayloadFormat::GetPacket() : %08xn", res));
  269.     return res;
  270. }
  271. STDMETHODIMP CH263PayloadFormat::Flush()
  272. {
  273.     // Called at the end of the clip
  274.     DPRINTF(D_H263, ("CH263PayloadFormat::Flush()n"));
  275.     FlushInput();
  276.     return HXR_OK;
  277. }
  278. static HX_RESULT GetH263FrameSize(int fmt, HXxSize &FrameDim)
  279. {
  280.     HX_RESULT res = HXR_NO_DATA;
  281.     if (fmt == 1)
  282.     {
  283. FrameDim.cx = 128;
  284. FrameDim.cy = 96;
  285. res = HXR_OK;
  286.     }
  287.     else if ((fmt >= 2) && (fmt < 6))
  288.     {
  289. FrameDim.cx = 176;
  290. FrameDim.cy = 144;
  291. for(;fmt > 2; fmt--)
  292. {
  293.     FrameDim.cx <<= 1;
  294.     FrameDim.cy <<= 1;
  295. }
  296. res = HXR_OK;
  297.     }
  298.     else
  299. HX_ASSERT(FALSE);
  300.     return res;
  301. }
  302. static HX_RESULT HandleH263Plus(Bitstream& bs, HXxSize &FrameDim)
  303. {
  304.     HX_RESULT res = HXR_UNEXPECTED;
  305.     if (bs.GetBits(3) == 1) // UFEP
  306.     {
  307. int fmt = bs.GetBits(3); // OPPTYPE (bits 1-3)
  308. if (fmt != 0x6)
  309.     res = GetH263FrameSize(fmt, FrameDim);
  310. else
  311. {
  312.     // This frame has custom dimensions
  313.     bs.GetBits(11) ; // OPPTYPE (bits 4-14)
  314.     if (bs.GetBits(4) == 0x8) // OPPTYPE (bits 15-18)
  315.     {
  316. bs.GetBits(6); // MPPTYPE (bits 1-6)
  317. if (bs.GetBits(3) == 0x1) // MPPTYPE (bits 7-9)
  318. {
  319.     if (bs.GetBits(1)) // CPM
  320. bs.GetBits(2); // PSBI
  321.     bs.GetBits(4); // CPFMT (bits 1-4)
  322.     int pwi = (bs.GetBits(9) + 1) * 4;
  323.     if (bs.GetBits(1)) // CPFMT (bit 14)
  324.     {
  325. int phi = (bs.GetBits(9)) * 4;
  326. if ((phi >= 1) && (phi <= 288))
  327. {
  328.     FrameDim.cx = pwi;
  329.     FrameDim.cy = phi;
  330.     res = HXR_OK;
  331. }
  332.     }
  333. }
  334.     }
  335. }
  336.     }
  337.     return res;
  338. }
  339. HX_RESULT CH263PayloadFormat::GetFrameDimensions(IHXBuffer* pBuffer,
  340.  HXxSize &FrameDim)
  341. {
  342.     DPRINTF(D_H263, ("CH263PayloadFormat::GetFrameDimensions()n"));
  343.     HX_RESULT res = HXR_UNEXPECTED;
  344.     Bitstream bs;
  345.     if (pBuffer->GetSize() >= 5)
  346.     {
  347. bs.SetBuffer(pBuffer->GetBuffer());
  348. if (bs.GetBits(22) == 0x20) // Check PSC
  349. {
  350.     bs.GetBits(8); // Skip TR
  351.     if (bs.GetBits(2) == 0x02) // PTYPE(bits 1 & 2)
  352.     {
  353. bs.GetBits(3); // PTYPE(bits 3-5)
  354. int fmt = bs.GetBits(3); // Get Format
  355. if (fmt != 0x7)
  356. {
  357.     res = GetH263FrameSize(fmt, FrameDim);
  358. }
  359. else if (pBuffer->GetSize() >= 13)
  360. {
  361.     // This has an extended PTYPE
  362.     res = HandleH263Plus(bs, FrameDim);
  363. }
  364.     }
  365. }
  366.     }
  367.     DPRINTF(D_H263, ("CH263PayloadFormat::GetFrameDimensions() : %dn", res));
  368.     return res;
  369. }
  370. HX_RESULT CH263PayloadFormat::ProcessPackets()
  371. {
  372.     HX_RESULT res = HXR_UNEXPECTED;
  373.     if (m_pCCF)
  374.     {
  375. IHXBuffer* pBuf = 0;
  376. IHXRTPPacket* pOutRTPPkt = 0;
  377. ULONG32 ulFrameBytes = (m_ulFrameSize + 7) >> 3;
  378. if (!m_pDepackHlpr)
  379.     res = CreateHelper(pBuf->GetBuffer(), pBuf->GetSize());
  380. else
  381.     res = HXR_OK;
  382. if (SUCCEEDED(res) &&
  383.     SUCCEEDED((res = m_pCCF->CreateInstance(IID_IHXBuffer,
  384.     (void**)(&pBuf)))) &&
  385.     SUCCEEDED((res = pBuf->SetSize(ulFrameBytes))) &&
  386.     SUCCEEDED((res = m_pCCF->CreateInstance(IID_IHXRTPPacket,
  387.     (void**)(&pOutRTPPkt)))))
  388. {
  389.     BitPacker bp(pBuf->GetBuffer(), pBuf->GetSize());
  390.     LISTPOSITION pos = m_inputQueue.GetHeadPosition();
  391.     while((pos != 0) && SUCCEEDED(res))
  392.     {
  393. IHXPacket* pPacket = (IHXPacket*)m_inputQueue.GetNext(pos);
  394. IHXBuffer* pPktBuf = pPacket->GetBuffer();
  395. res = m_pDepackHlpr->OnPacket(pPktBuf->GetBuffer(),
  396.       pPktBuf->GetSize());
  397. if (SUCCEEDED(res))
  398.     res = m_pDepackHlpr->CopyPayload(bp);
  399. ULONG32 used = bp.BytesUsed();
  400. HX_ASSERT(used <= ulFrameBytes);
  401. // Release the packet buffer
  402. HX_RELEASE(pPktBuf);
  403.     }
  404.     if (SUCCEEDED(res))
  405.     {
  406. IHXPacket* pFirstPkt = (IHXPacket*)m_inputQueue.GetHead();
  407. IHXRTPPacket* pRTPPkt = 0;
  408. if (SUCCEEDED(pFirstPkt->QueryInterface(IID_IHXRTPPacket,
  409. (void**)&pRTPPkt)))
  410. {
  411.     res = pOutRTPPkt->SetRTP(pBuf,
  412.      pRTPPkt->GetTime(),
  413.      pRTPPkt->GetRTPTime(),
  414.      pRTPPkt->GetStreamNumber(),
  415.      pRTPPkt->GetASMFlags(),
  416.      pRTPPkt->GetASMRuleNumber());
  417. }
  418. else
  419. {
  420.     res = pOutRTPPkt->Set(pBuf,
  421.   pFirstPkt->GetTime(),
  422.   pFirstPkt->GetStreamNumber(),
  423.   pFirstPkt->GetASMFlags(),
  424.   pFirstPkt->GetASMRuleNumber());
  425. }
  426. IHXPacket* pOutPkt = 0;
  427. res = pOutRTPPkt->QueryInterface(IID_IHXPacket,
  428.  (void**)&pOutPkt);
  429. if (SUCCEEDED(res))
  430.     m_outputQueue.AddTail(pOutPkt);
  431. HX_RELEASE(pRTPPkt);
  432.     }
  433. }
  434. HX_RELEASE(pBuf);
  435. HX_RELEASE(pOutRTPPkt);
  436.     }
  437.     FlushInput();
  438.     return res;
  439. }
  440. HX_RESULT CH263PayloadFormat::AddPacket(ULONG32 ulDataSize, IHXPacket* pPacket)
  441. {
  442.     HX_RESULT res = HXR_OUTOFMEMORY;
  443.     if (m_inputQueue.AddTail(pPacket))
  444.     {
  445. m_ulFrameSize += ulDataSize;
  446. pPacket->AddRef();
  447. res = HXR_OK;
  448.     }
  449.     return res;
  450. }
  451. void CH263PayloadFormat::FlushInput()
  452. {
  453.     LISTPOSITION pos = m_inputQueue.GetHeadPosition();
  454.     while(pos != 0)
  455.     {
  456. IHXPacket* pPacket = (IHXPacket*)m_inputQueue.GetNext(pos);
  457. HX_RELEASE(pPacket);
  458.     }
  459.     m_inputQueue.RemoveAll();
  460.     m_ulFrameSize = 0;
  461.     m_state = NeedPSC;
  462. }
  463. void CH263PayloadFormat::FlushOutput()
  464. {
  465.     LISTPOSITION pos = m_outputQueue.GetHeadPosition();
  466.     while(pos != 0)
  467.     {
  468. IHXPacket* pPacket = (IHXPacket*)m_outputQueue.GetNext(pos);
  469. HX_RELEASE(pPacket);
  470.     }
  471.     m_outputQueue.RemoveAll();
  472. }
  473. HX_RESULT CH263PayloadFormat::CreateHelper(const UINT8* pBuf,
  474.                                            ULONG32 ulBufSize)
  475. {
  476.     HX_RESULT res = HXR_UNEXPECTED;
  477. #if defined(HELIX_FEATURE_H263_RFC2429)
  478.     // Try the RFC2429 helper first
  479.     if (FAILED(res))
  480.     {
  481.         HX_DELETE(m_pDepackHlpr);
  482.         m_pDepackHlpr = new CRFC2429Helper();
  483.         if (m_pDepackHlpr)
  484.         {
  485.             res = m_pDepackHlpr->OnPacket(pBuf, ulBufSize);
  486.         }
  487.     }
  488. #endif
  489. #if defined(HELIX_FEATURE_H263_RFC2190)
  490.     // If the RFC2429 helper didn't succeed, then
  491.     // try the RFC2190 helper next.
  492.     if (FAILED(res))
  493.     {
  494.         HX_DELETE(m_pDepackHlpr);
  495.         m_pDepackHlpr = new CRFC2190Helper();
  496.         if (m_pDepackHlpr)
  497.         {
  498.             res = m_pDepackHlpr->OnPacket(pBuf, ulBufSize);
  499.         }
  500.     }
  501. #endif
  502.     return res;
  503. }