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

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 "hlxclib/string.h"
  37. #include "types64.h"
  38. #include "xmdtypes.h"
  39. #include "xmddemuxer.h"
  40. #include "hxassert.h"
  41. CDemuxer::CDemuxer(BOOL bMPEG2)
  42.  :  m_bMPEG2(bMPEG2),
  43.     m_pPack(NULL),
  44.     m_llPtsDelta(0)
  45. {
  46. }
  47. CDemuxer::~CDemuxer()
  48. {
  49. }
  50. ///////////////////////////////////////////////////////////////////////////////
  51. // Function:    Demux_ul
  52. // Returns:     The number of bytes processed
  53. ///////////////////////////////////////////////////////////////////////////////
  54. UINT32 CDemuxer::Demux_ul(UINT8 *pBuffer,
  55.                              UINT32 ulBytes,
  56.                              Packet *pPacket)
  57. {
  58.     UINT8       *pTemp = (UINT8*)pBuffer;
  59.     UINT32      ulTemp = ulBytes;
  60.     INT32       lCode = 0;
  61.     memset(pPacket, 0, sizeof(Packet));
  62.     UINT8 bCont = TRUE;
  63.     while (ulTemp >= 4 && bCont)
  64.     {
  65.         lCode = GetStartCode(&pTemp, ulTemp);
  66.         switch (lCode)
  67.         {
  68.             case -1:
  69.                 bCont = FALSE;
  70.                 break;
  71.             case PACK_HEADER:
  72.             {
  73.             m_pPack = pTemp;
  74.                 pTemp+=4;
  75.             ulTemp-=4;
  76.                 // Is this MPEG1 or MPEG2
  77.                 UINT8 yNext = *pTemp & 0xF0;
  78.                 // Check for MPEG1 or MPEG2.
  79.                 // In MPEG2 files, '0100' follows pack_start_code and
  80.                 // in MPEG1 files, '0010' follows pack_start_code.
  81.                 if ((yNext & 0xC0) == 0x40)
  82.                     m_bMPEG2 = TRUE;
  83.                 else
  84.                     m_bMPEG2 = FALSE;
  85.                 break;
  86.             }
  87.             default:
  88.                 // PRIVATE_STREAM_1
  89.                 // VIDEO_PACKET
  90.                 // AUDIO_PACKET
  91.                 if ( PRIVATE_STREAM_1 == lCode ||
  92.                     (lCode & 0x000000F0) == 0xE0 ||
  93.                     (lCode & 0x000000E0) == 0xC0)
  94.                 {
  95.                     if (ProcessPacket(&pTemp, ulTemp, pPacket))
  96.                     {
  97.                         bCont = FALSE;
  98.                     }
  99.                 }
  100.                 else
  101.                 {
  102.                     pTemp+=4;
  103.                 ulTemp-=4;
  104.                 }
  105.                 break;
  106.         }
  107. }
  108.     return (UINT32)(PTR_INT)(pTemp - pBuffer);
  109. }
  110. INT32 CDemuxer::GetStartCode(UINT8 **ppBuffer,
  111.                                 UINT32 &ulBytes)
  112. {
  113.     if ((long)ulBytes < 4)
  114.         return -1;
  115.     UINT8 *pStart = *ppBuffer + 2,
  116.                   *pEnd = *ppBuffer + ulBytes - 1;
  117.     INT32 ulCode = -1;
  118.     
  119.     while (pStart < pEnd)
  120.     {
  121.         // Look for a 1
  122.         pStart = (UINT8*)memchr(pStart, 1, pEnd-pStart);
  123.         if (!pStart)
  124.             return -1;
  125.         // If the previous 2 bytes are 0's assume it is a start code
  126.         if (pStart[-1] || pStart[-2])
  127.             ++pStart;
  128.         else
  129.         {
  130.             ulCode = 0x00000100 + pStart[1];
  131.             pStart -= 2;
  132.             break;
  133.             
  134.         }
  135.     }
  136.     ulBytes -= pStart - *ppBuffer;
  137.     *ppBuffer = pStart;
  138.     return ulCode;
  139. }
  140. UINT8 CDemuxer::ProcessPacket(UINT8 **ppBuffer,
  141.                                    UINT32 &ulBytes,
  142.                                    Packet *pPacket)
  143. {
  144.     if (!m_bMPEG2)
  145.         return ProcessMPEG1Packet(ppBuffer, ulBytes, pPacket);
  146.     UINT32 ulTempBytes = ulBytes;
  147.     pPacket->pHeader = *ppBuffer;
  148.     if (ulBytes < 6)
  149.         return 1;
  150.     // Move beyond the packet start code
  151.     *ppBuffer += 3;
  152.     UINT8 yStream = **ppBuffer;
  153.     *ppBuffer += 1;
  154.    // Extract the packet length (including the PES header)
  155.    int nLength = **ppBuffer << 8;
  156.     *ppBuffer += 1;
  157.     nLength += **ppBuffer;
  158.     if ((UINT32)nLength > ulBytes)
  159.         return 1;
  160.     
  161.     pPacket->lHeaderBytes = nLength + 6;
  162.     // Move beyond the packet length field to the PES header
  163. *ppBuffer += 1;
  164. ulBytes -= 6;
  165. // PES Header
  166. if ((**ppBuffer & 0xC0) == 0x80)
  167. {
  168.         // Check for an encryped pack
  169.         if (**ppBuffer & 0x30)
  170.             HX_ASSERT(FALSE);
  171.         
  172.         // Check for pts and/or dts
  173.         UINT8 yPtsDtsFlags = *(*ppBuffer+1) & 0xC0;
  174.         // Extract the length of the PES extra header
  175. UINT8 cSize = *(*ppBuffer+2);
  176. // Move beyond 3 byte header
  177.         *ppBuffer += 3;
  178. nLength -= 3;
  179. ulBytes -= 3;
  180.         // Extract pts/dts
  181.         if ( ((yPtsDtsFlags & 0xC0) == 0x80) || ((yPtsDtsFlags & 0xC0) == 0xC0) ) 
  182.         { 
  183.             // "0010"                    4 bits
  184.             // presentation_time_stamp   3 bits
  185.             // marker_bit                1 bit 
  186.             // presentation_time_stamp  15 bits  
  187.             // marker_bit                1 bit 
  188.             // presentation_time_stamp  15 bits  
  189.             // marker_bit                1 bit 
  190.             pPacket->cHasPts = 1;
  191.             pPacket->llPts = GetTimeStamp(*ppBuffer) + m_llPtsDelta;
  192.                         
  193.             *ppBuffer +=5;
  194.     nLength -= 5;
  195.             ulBytes -=5;
  196.             cSize -= 5;
  197.             // Extract dts
  198.             if ( (yPtsDtsFlags & 0xC0) == 0xC0 ) 
  199.             { 
  200.                 // " 0001 "                  4 bits
  201.                 // decode_time_stamp         3 bits 
  202.                 // marker_bit                1 bit 
  203.                 // decoding_time_stamp      15 bits  
  204.                 // marker_bit                1 bit 
  205.                 // decoding_time_stamp      15 bits  
  206.                 // marker_bit                1 bit 
  207.             
  208.                 pPacket->cHasDts = 1;
  209.                 pPacket->llDts = GetTimeStamp(*ppBuffer) + m_llPtsDelta;
  210.                 
  211.                 *ppBuffer += 5;
  212.         nLength -= 5;
  213.                 ulBytes -=5;
  214.                 cSize -= 5;
  215.             }
  216.         }
  217.         // Move beyond the remaining PES header
  218. if (cSize)
  219.         {
  220.             *ppBuffer += cSize;
  221.     nLength -= cSize;
  222.     ulBytes -= cSize;
  223.         }
  224. // PrivateStream 1 (AC3/LPCM/DTS/Subpicture)
  225.         if (yStream == 0xbd)
  226.         {
  227.             // Check for AC3 data
  228.     if ((**ppBuffer & 0xF8) == 0x80)
  229.     {
  230.                 // Mark the stream id
  231.                 pPacket->cStreamId = **ppBuffer & 0x07;
  232.         // Store private data
  233.                 pPacket->pPrivateData = *ppBuffer;
  234.                 pPacket->lPrivBytes = 4;
  235.         // Move beyond 4 byte header
  236.                 *ppBuffer += 4;
  237.         nLength -= 4;
  238.         ulBytes -= 4;
  239.     
  240.         // Fill pPacket
  241.         pPacket->pData = *ppBuffer;
  242.                 pPacket->lBytes = nLength;
  243.                 pPacket->ePacket = eAudio;
  244.                 pPacket->eSubtype = eAC3;
  245.                 return 1;
  246.     }
  247.     // LPCM
  248.             else if ((**ppBuffer & 0xF8) == 0xA0)
  249.     {
  250.                 // Mark the stream id
  251.                 pPacket->cStreamId = **ppBuffer & 0x07;                        
  252.         // Store private data
  253.                 pPacket->pPrivateData = *ppBuffer;
  254.                 pPacket->lPrivBytes = 7;
  255.                 // Move beyond  byte header
  256.                 *ppBuffer += 7;
  257.         nLength -= 7;
  258.         ulBytes -= 7;
  259.     
  260.         // Fill pPacket
  261.         pPacket->pData = *ppBuffer;
  262.                 pPacket->lBytes = nLength;
  263.                 pPacket->ePacket = eAudio;
  264.                 pPacket->eSubtype = eLPCM;
  265.                 return 1;
  266.     }
  267.             // DTS
  268.             else if ((**ppBuffer & 0xF8) == 0x88)
  269.     {
  270.                 // Mark the stream id
  271.                 pPacket->cStreamId = **ppBuffer & 0x07;                        
  272.         // Move beyond 4 byte header
  273.                 *ppBuffer += 4;
  274.         nLength -= 4;
  275.         ulBytes -= 4;
  276.     
  277.         // Fill pPacket
  278.         pPacket->pData = *ppBuffer;
  279.                 pPacket->lBytes = nLength;
  280.                 pPacket->ePacket = eAudio;
  281.                 pPacket->eSubtype = eDTS;
  282.                 return 1;
  283.     }
  284.             // Subpicture
  285.             else if ((**ppBuffer & 0xE0) == 0x20)
  286.             {
  287.                 // Mark the stream id
  288.                 pPacket->cStreamId = **ppBuffer & 0x1F;                        
  289.         // Move beyond id header
  290.                 *ppBuffer += 1;
  291.         nLength -= 1;
  292.         ulBytes -= 1;
  293.     
  294.         // Fill pPacket
  295.         pPacket->pData = *ppBuffer;
  296.                 pPacket->lBytes = nLength;
  297.                 pPacket->ePacket = eSubpicture;
  298.                 return 1;
  299.             }
  300.         }
  301.         // Video
  302.         else if ((yStream & 0xF0) == 0xe0)
  303.         {
  304.             // Mark the stream id
  305.             pPacket->cStreamId = yStream & 0x0F;
  306.     // Fill pPacket
  307.     pPacket->pData = *ppBuffer;
  308.             pPacket->lBytes = nLength;
  309.             pPacket->ePacket = eVideo;
  310.             pPacket->eSubtype = eMPEG2;
  311.             return 1;
  312.         }
  313.         // Audio
  314.         else if ((yStream & 0xE0) == 0xc0)
  315.         {
  316.             // Mark the stream id
  317.             pPacket->cStreamId = yStream & 0x1F;
  318.     // Fill pPacket
  319.     pPacket->pData = *ppBuffer;
  320.             pPacket->lBytes = nLength;
  321.             pPacket->ePacket = eAudio;
  322.             pPacket->eSubtype = eMPEG1;
  323.             return 1;
  324.         }
  325. }
  326. // Skip the packet
  327.     *ppBuffer += nLength;
  328.     ulBytes -= nLength;
  329.     return 0;
  330. }
  331. UINT8 CDemuxer::ProcessMPEG1Packet(UINT8 **ppBuffer,
  332.                                       UINT32 &ulBytes,
  333.                                       Packet *pPacket)
  334. {
  335.     UINT8 *pHeader = *ppBuffer;
  336.     UINT32 ulTempBytes = ulBytes;
  337.     if (ulBytes < 6)
  338.         return 1;
  339.     
  340.     // Move beyond the packet start code
  341.     *ppBuffer += 3;
  342.     UINT8 yStream = **ppBuffer;
  343.     *ppBuffer += 1;
  344.    // Extract the packet length (including the PES header)
  345.    int nLength = **ppBuffer << 8;
  346.     *ppBuffer += 1;
  347.     nLength += **ppBuffer;
  348.     INT32   lHeaderBytes = nLength + 6;
  349.     // Move beyond the packet length to data
  350. *ppBuffer += 1;
  351. ulBytes -= 6;
  352.     if ((UINT32)nLength > ulBytes)
  353.         return 1;
  354.     pPacket->pHeader = pHeader;
  355.     pPacket->lHeaderBytes = lHeaderBytes;
  356.     // Remove stuffing bytes
  357.     while (**ppBuffer == 0xFF)
  358. {
  359.         if (!ulBytes)
  360.             return 1;
  361.         *ppBuffer += 1;
  362.         --ulBytes;
  363.         --nLength;
  364. }
  365.     if ( (**ppBuffer & 0xC0) == 0x40 )
  366.     {
  367.         // "01"                    2 bits
  368.         // STD_buffer_scale        1 bit
  369.         // STD_buffer_size        13 bits
  370.         
  371.         if (ulBytes < 2)
  372.             return 1;
  373.         *ppBuffer += 2;
  374. ulBytes -= 2;
  375.         nLength -= 2;
  376.     }
  377.     // Extract PTS and DTS
  378.     UINT8 bNextByte = **ppBuffer;
  379.     if ( ((bNextByte & 0xF0) == 0x20) || ((bNextByte & 0xF0) == 0x30) ) 
  380.     {
  381.         if (ulBytes < 5)
  382.             return 1;
  383.         
  384.         pPacket->cHasPts = 1;
  385.         pPacket->llPts = GetTimeStamp(*ppBuffer) + m_llPtsDelta;
  386.         
  387.         *ppBuffer +=5;
  388. nLength -= 5;
  389.         ulBytes -=5;
  390.         // DTS
  391.         if ( (bNextByte & 0xF0) == 0x30 )
  392.         {
  393.             if (ulBytes < 5)
  394.                 return 1;
  395.             pPacket->cHasDts = 1;
  396.             pPacket->llDts = GetTimeStamp(*ppBuffer) + m_llPtsDelta;
  397.             *ppBuffer += 5;
  398.     nLength -= 5;
  399.             ulBytes -=5;
  400.         }
  401.     }
  402.     else 
  403.     {
  404.         if (!ulBytes)
  405.             return 1;
  406.         // "0000 1111"
  407.         *ppBuffer += 1;
  408.         --ulBytes;
  409.         --nLength;
  410.     }
  411.     
  412.     // Extract video and audio data
  413.     if ((yStream & 0xF0) == 0xe0)
  414.     {
  415.         // Mark the stream id
  416.         pPacket->cStreamId = yStream & 0x0F;
  417. // Fill pPacket
  418. pPacket->pData = *ppBuffer;
  419.         pPacket->lBytes = nLength;
  420.         pPacket->ePacket = eVideo;
  421.         pPacket->eSubtype = eMPEG1;
  422.         return 1;
  423.     }
  424.     // Audio
  425.     else if ((yStream & 0xE0) == 0xc0)
  426.     {
  427.         // Mark the stream id
  428.         pPacket->cStreamId = yStream & 0x1F;
  429. // Fill pPacket
  430. pPacket->pData = *ppBuffer;
  431.         pPacket->lBytes = nLength;
  432.         pPacket->ePacket = eAudio;
  433.         pPacket->eSubtype = eMPEG1;
  434.         return 1;
  435.     }
  436.     return 0;
  437. }
  438. INT64 CDemuxer::GetTimeStamp(UINT8 *pBuffer)
  439. {
  440.     INT64 llPts = 0;
  441.     llPts  = (*pBuffer & 0x0E) << 29;
  442.     llPts |=  *(pBuffer+1)  << 22;
  443.     llPts |= (*(pBuffer+2) & 0xFE) << 14;
  444.     llPts |=  *(pBuffer+3)  << 7;
  445.     llPts |= (*(pBuffer+4) & 0xFE) >> 1;
  446.     return (INT64)(llPts / 90.0 * UNITS_CONVERSION_MS);
  447. }
  448. void CDemuxer::Reset_v()
  449. {
  450.     m_llPtsDelta = 0;
  451.     m_pPack = NULL;
  452. }