[prev in list] [next in list] [prev in thread] [next in thread] 

List:       helix-datatype-cvs
Subject:    [Datatype-cvs] mpg/fileformat Umakefil, 1.2, 1.2.256.1 rmpgff.cpp, 1.8.10.2.32.3, 1.8.10.2.32.4 rmpg
From:       jgordon () helixcommunity ! org
Date:       2012-01-19 19:21:38
[Download RAW message or body]

Update of /cvsroot/datatype/mpg/fileformat
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv18260

Modified Files:
      Tag: hxclient_3_6_1_atlas
	Umakefil rmpgff.cpp rmpgff.h xmddemuxer.cpp xmddemuxer.h 
Log Message:
Synopsis
========
Various changes and fixes to MPEG video ES file support

Branches: 361atlas, 310atlas, HEAD
Reviewed By: Qiang


Description
===========
Primarily changes to allow the depacketizer + codec plugin rendering 
format to handle the output from mpgfformat in case of ES files.

1. For ES files for local playback, mpgfformat was using RTP 
packetization (2250) for packet creation, but without e.g. the 
RTP timestamps, etc. This is really silly and inefficient and 
error-prone! And of course also does not work with the newer 
renderer due to requiring a lot more depacketization work.

This is rewritten to just find a full frame and create a simple ES packet.
Including setting the right PTS in the RTP time.

2. Duration and bitrate estimation for ES was buggy and often incorrect. 
This in turn also screws up seeking when they are wrong.

The GOP time_code parsing as well as the end-start duration calculation 
had some bugs. Also the way it was handling finding the last GOP and 
following frames was overly complicated and inefficient. 

Fixed the time_code parsing and calculation and rewrote the parsing to 
start from the end and search backward for a GOP!

Once a duration was determined from GOP, the handling of that duration, 
the bitrate, etc.  was strange and buggy. I basically just rewrote 
that as well.

3. Eliminated the unnecessary alloc and copy from the read buffer to a 
new packet buffer. Just wrap it in a CHXStatic buffer instead.
 
 3. Changed the output mime type to differentiate between MPEG-1 and MPEG-2,
 using the same mime types as the ts plugins, since the packet format is now
 the same. Different mime types allows different codecs (or renderers) for 
 MPEG-1 vs MPEG-2, as well as other cases where we want to identify the codec
 from the stream header.

 Changed the whole mime type setting block in mpgfformat to be more readable 
 and maintainable.

 Added the new mimetypes to mpgrenderer and similarly updating its mimetype 
 parsing for ease of readability and maintenance.

 4. Removed some unreachable code and ifdefd out server RTP packetization 
 on client builds.


 Files Affected
 ==============
 datatype/mpg/common/xmdplugincommon.h
 datatype/mpg/fileformat/Umakefil
 datatype/mpg/fileformat/rmpgff.cpp
 datatype/mpg/fileformat/rmpgff.h
 datatype/mpg/fileformat/xmddemuxer.cpp
 datatype/mpg/fileformat/xmddemuxer.h
 datatype/mpg/renderer/mpgvideo.cpp
 datatype/mpg/renderer/mpgvideo.h



Index: xmddemuxer.cpp
===================================================================
RCS file: /cvsroot/datatype/mpg/fileformat/xmddemuxer.cpp,v
retrieving revision 1.8.18.1
retrieving revision 1.8.18.1.36.1
diff -u -d -r1.8.18.1 -r1.8.18.1.36.1
--- xmddemuxer.cpp	18 Sep 2007 09:35:56 -0000	1.8.18.1
+++ xmddemuxer.cpp	19 Jan 2012 19:21:36 -0000	1.8.18.1.36.1
@@ -42,6 +42,7 @@
 #include "ac3info.h"
 #include "xmddemuxer.h"
 #include "memcpy.h"
+#include "hxassert.h"
 
 #ifdef _MACINTOSH
 #ifndef _MAC_MACHO
@@ -61,6 +62,9 @@
 #define max(x,y) (x)>(y) ? (x) : (y)
 #endif
 
+#define MPEG1_PROFILE_LEVEL_ID  0x48
+#define GOP_TIME_CODE_ROLLOVER  86400000    // 1-day = 86400 seconds
+
 static const double PictureTimes[16] =
 {
     0.0,
@@ -75,42 +79,41 @@
 };
 
 CXmdDemuxer::CXmdDemuxer(UINT8 bMPEG2)
- :  m_bMPEG2(bMPEG2),
-    m_pAudInfo(NULL),
+ :  m_pAudInfo(NULL),
+    m_bMPEG2(bMPEG2),
+    m_bFindAudio(FALSE),
+    m_bFindVideo(FALSE),
+    m_bSendSeqHdr(TRUE),
+    m_bPackHeader(FALSE),
+    m_bVCD(FALSE),
     m_pPack(NULL),
     m_pSeqHdr(NULL),
     m_pVCDBuffer(NULL),
     m_pVCDAlloc(NULL),
     m_ulSeqHdrSize(0),
+    m_ulDataOffset(0),
+    m_ulReadSize(48*1024),
+    m_ulVCDBytes(0),
     m_nVidStreams(0),
     m_nAudStreams(0),
     m_nCurrVidId(0),
     m_nCurrAudId(0),
-    m_bFindAudio(0),
-    m_bFindVideo(0),
-    m_bSendSeqHdr(1),
-    m_bPackHeader(0),
-    m_bVCD(FALSE),
     m_dFrameTime(0.0),
     m_dGopBaseTs(0.0),
     m_dLastPts(0.0),
-    m_ulFirstGopDuration(0),
-    m_ulLastGopDuration(0),
-    m_ulDataOffset(0),
-    m_ulReadSize(48*1024),
-    m_ulVCDBytes(0),
-    m_dGopFrames(0.0),
-    m_dScrBase(0),
     m_dFirstPacketTime(0),
     m_dFirstScr(0),
     m_dFirstTimeStamp(0),
+    m_dScrBase(0),
     m_dScr(0),
+    m_dPtsDelta(0),
     m_llScrOffset(0),
-    m_ulPackRate(0),
-    m_dPtsDelta(0)
+    m_ulPackRate(0)
 {
+
     memset(m_aVidStreams, 0, sizeof(m_aVidStreams));
     memset(m_aAudStreams, 0, sizeof(m_aAudStreams));
+    memset(&m_GOPDurationData, 0, sizeof(m_GOPDurationData));
 
     int i;
     for (i=0; i<16; i++)
@@ -188,7 +191,7 @@
         if (!m_pVCDAlloc)
         {
             m_pVCDAlloc = new UINT8[VCD_BUFFER_SIZE + 31];
-            m_pVCDBuffer = (UINT8*)((UINT32)m_pVCDAlloc + 31 & ~31);
+            m_pVCDBuffer = (UINT8*)((UINT32)(m_pVCDAlloc + 31) & ~31);
         }
 
         pBuffer += m_ulDataOffset;
@@ -264,19 +267,25 @@
             case GROUP_START_CODE:
             {
                 // Grab the first timecode for duration calcs
-                if (dwSize > 8 && !m_ulFirstGopDuration)
+                if (dwSize > 8)
                 {
                     pBuffer += 4;
                     dwSize -= 4;
                     
-                    m_ulFirstGopDuration = ((pBuffer[0] & 0x7C) >> 2) * 360000;
-                    m_ulFirstGopDuration += (((pBuffer[0] & 0x3)<<4) | ((pBuffer[1] \
                & 0xF0)>>4)) * 60000;
-                    m_ulFirstGopDuration += (((pBuffer[1] & 0x7)<<3) | ((pBuffer[2] \
& 0xE0)>>5)) * 1000; +                    m_GOPDurationData.ulStartTimeBase =         \
// hours +                                    ((pBuffer[0] & 0x7C) >> 2) * 3600;
+                    m_GOPDurationData.ulStartTimeBase +=        // minutes
+                                            (((pBuffer[0] & 0x3)<<4) |
+                                            ((pBuffer[1] & 0xF0)>>4)) * 60;
+                    m_GOPDurationData.ulStartTimeBase +=        //seconds
+                                            (((pBuffer[1] & 0x7)<<3) |
+                                            ((pBuffer[2] & 0xE0)>>5));
 
-                    UINT32 ulFrames = ((pBuffer[2] & 0x1F)<<1) | ((pBuffer[3] & \
0x80)>>7); +                    m_GOPDurationData.ulStartTimeBase *= 1000;  // to ms
 
-                    m_ulFirstGopDuration = max(1, m_ulFirstGopDuration);
-                    m_ulFirstGopDuration += (UINT32)(ulFrames * \
(m_dFrameTime/90.0)); +                    m_GOPDurationData.ulStartTimePics =
+                                    ((pBuffer[2] & 0x1F)<<1) |
+                                    ((pBuffer[3] & 0x80)>>7);
 
                     if (pInfo[FILE_STREAM].eType != eHXSystem ||
                         pInfo[AUDIO_STREAM].eType != eHXUnknown)
@@ -312,21 +321,7 @@
                         m_aVidStreams[packet.cStreamId].pSeqHdr = new \
                UINT8[m_ulSeqHdrSize+256];
                         memcpy(m_aVidStreams[packet.cStreamId].pSeqHdr, pBuffer, \
m_ulSeqHdrSize); /* Flawfinder: ignore */  
-                        pBuffer += 4;
-                        dwSize -= 4;
-
-                        lCode = GetStartCode(&pBuffer, dwSize);
-
-                        // There is always extension data following seq hdrs in an \
                MPEG2 file
-                        if (EXT_DATA_START_CODE == lCode)
-                        {
-                            m_aVidStreams[packet.cStreamId].bMPEG2 = 1;
-                            ParseSequenceExtHeader(pBuffer, dwSize, \
                &m_aVidStreams[packet.cStreamId]);
-                        }
-                        else
-                        {
-                            m_aVidStreams[packet.cStreamId].bMPEG2 = 0;
-                        }
+                        
 
                         // Prepare to play the first video stream we find
                         if (pInfo[VIDEO_STREAM].eType == eHXUnknown)
@@ -340,10 +335,18 @@
                             pInfo[VIDEO_STREAM].dFrameTime = \
                m_aVidStreams[packet.cStreamId].dFrameTime;
                             pInfo[VIDEO_STREAM].ulBufSize = \
m_aVidStreams[packet.cStreamId].ulBufSize;  
-                            // Don't reassign -1 to the bitrate if we already went \
                through all 
-                            // the trouble of guessing one.
-                            if (!pInfo[VIDEO_STREAM].ulBitRate || \
                (INT32)m_aVidStreams[packet.cStreamId].ulBitRate > 0)
-                                pInfo[VIDEO_STREAM].ulBitRate = \
m_aVidStreams[packet.cStreamId].ulBitRate; +                            UINT32 ulBR = \
m_aVidStreams[packet.cStreamId].ulBitRate; +                            \
pInfo[VIDEO_STREAM].ulMaxBitRate = ulBR; +
+                            // If we have not got an estimated average bitrate
+                            // or if the estimate is higher than the seq. max
+                            // set the avg. to the max.
+
+                            if ((INT32)pInfo[VIDEO_STREAM].ulBitRate <= 0 ||
+                                ((INT32)ulBR > 0 && ulBR < \
pInfo[VIDEO_STREAM].ulBitRate)) +                            {
+                                pInfo[VIDEO_STREAM].ulBitRate = ulBR;
+                            }
                             
                             if (m_aVidStreams[packet.cStreamId].bMPEG2)
                                 pInfo[VIDEO_STREAM].eVideo = eHXMPEG2;
@@ -475,6 +478,7 @@
                                     pInfo[FILE_STREAM].eAudio = \
pInfo[VIDEO_STREAM].eAudio;  
                                     pInfo[AUDIO_STREAM].ulBitRate = \
m_aAudStreams[packet.cStreamId].ulBitRate; +                                    \
                pInfo[AUDIO_STREAM].ulMaxBitRate = pInfo[AUDIO_STREAM].ulBitRate;
                                     pInfo[AUDIO_STREAM].ulSampleRate = \
m_aAudStreams[packet.cStreamId].ulSampleRate;  pInfo[AUDIO_STREAM].eType = eHXAudio;
                                     pInfo[AUDIO_STREAM].nPacketSize = \
m_aAudStreams[packet.cStreamId].ulFrameSize; @@ -1012,6 +1016,7 @@
                                       tRtpPacket *pRtp,
                                       tStreamInfo *pInfo)
 {
+#ifdef HELIX_FEATURE_PACKETIZER_MPEG_RTP
     UINT8   bCont = 1,
             *pStart = pRead,
             *pLastCode = NULL;
@@ -1106,10 +1111,15 @@
                     pInfo[VIDEO_STREAM].nHeight = \
                m_aVidStreams[m_nCurrVidId].ulHeight;
                     pInfo[VIDEO_STREAM].dFrameTime = \
m_aVidStreams[m_nCurrVidId].dFrameTime;  
-                    // Don't reassign -1 to the bitrate if we already went through \
                all 
-                    // the trouble of guessing one.
-                    if (!pInfo[VIDEO_STREAM].ulBitRate || \
                (INT32)m_aVidStreams[m_nCurrVidId].ulBitRate > 0)
-                        pInfo[VIDEO_STREAM].ulBitRate = \
m_aVidStreams[m_nCurrVidId].ulBitRate; +                    // If we have not got \
estimated average bitrate +                    // or if the estimate is higher than \
the seq. max +                    // set the avg. to the max.
+                    UINT32 ulBR = m_aVidStreams[m_nCurrVidId].ulBitRate;
+                    if (!pInfo[VIDEO_STREAM].ulBitRate ||
+                        ((INT32)ulBR > 0 && ulBR < pInfo[VIDEO_STREAM].ulBitRate))
+                    {
+                        pInfo[VIDEO_STREAM].ulBitRate = ulBR;
+                    }
                 }
                 else if (m_dLastPts)
                     m_dGopBaseTs = m_dLastPts + m_dFrameTime;
@@ -1357,57 +1367,54 @@
     }
 
     return ulBytes;
+#else
+    HX_ASSERT(FALSE);
+    return 0;
+#endif /* HELIX_FEATURE_PACKETIZER_MPEG_RTP */
 }
 
 UINT32 CXmdDemuxer::GetDuration(UINT8 *pBuffer,
                                 UINT32 ulSize,
-                                tStreamInfo *pInfo,
-                                tDurationStats *pStats)
+                                tStreamInfo *pInfo)
 {
     UINT32 ulDuration = 0;
     UINT8 bOldValue = m_bSendSeqHdr;
     m_bSendSeqHdr = 0;
     INT32 lScan = 0;
+    Packet packet;
+    double dTimeStamp = m_dFirstTimeStamp;
 
-    if (eHXVideo == pInfo->eType)
-        ulDuration = GetVbrDuration(pBuffer, ulSize, pStats);
-
-    else
+    do
     {
-        Packet packet;
-        double dTimeStamp = m_dFirstTimeStamp;
+        lScan = Demux(pBuffer, ulSize, &packet);
 
-        do
+        // If no scr was found, use pts for duration
+        if (!packet.lBytes)
         {
-            lScan = Demux(pBuffer, ulSize, &packet);
-    
-            // If no scr was found, use pts for duration
-            if (!packet.lBytes)
-            {
-                if (!ulDuration)
-                    ulDuration = (INT32)(dTimeStamp - m_dFirstTimeStamp);
-            }
+            if (!ulDuration)
+                ulDuration = (INT32)(dTimeStamp - m_dFirstTimeStamp);
+        }
 
-            if (packet.dScr)
-            {
-                if (packet.dScr + m_dScrBase - m_dFirstScr > (INT32)ulDuration)
-                    ulDuration = (INT32)(packet.dScr + m_dScrBase - m_dFirstScr);
-            }
+        if (packet.dScr)
+        {
+            if (packet.dScr + m_dScrBase - m_dFirstScr > (INT32)ulDuration)
+                ulDuration = (INT32)(packet.dScr + m_dScrBase - m_dFirstScr);
+        }
 
-            if (packet.dPts > dTimeStamp)
-                dTimeStamp = packet.dPts;
+        if (packet.dPts > dTimeStamp)
+            dTimeStamp = packet.dPts;
 
-            pBuffer += packet.lBytes + lScan;
-            ulSize -= packet.lBytes + lScan;
-    
-        } while (packet.dScr || (!ulDuration && packet.lBytes));
-    }
+        pBuffer += packet.lBytes + lScan;
+        ulSize -= packet.lBytes + lScan;
 
+    } while (packet.dScr || (!ulDuration && packet.lBytes));
+    
     m_bSendSeqHdr = bOldValue;
 
     return ulDuration;
 }
 
+
 BYTE* CXmdDemuxer::GetSequenceHeader(INT32 nStreamId,
                                      INT32 &nHdrSize)
 {
@@ -1516,7 +1523,8 @@
         pInfo->ulBufSize = 65536;
 
     // Check constrained parameter stuff
-    if (pBuffer[11] & 0x04)
+    pInfo->bConstrained = pBuffer[11] & 0x04 >> 3;
+    if (pInfo->bConstrained)
     {
         //  Have to let this through too!  bisp.mpg has this
         //  But constrain it since it might be random
@@ -1561,6 +1569,29 @@
     // Check for user data and extension data
     INT32 lCode = GetStartCode(&pBuffer, dwSize);
 
+    // check for sequence_extension header
+    if (lCode == EXT_DATA_START_CODE)
+    {
+        if (dwSize < 5)
+        {
+            return 0;
+        }
+        else if ((pBuffer[4] & 0xF0) == 0x10)
+        {
+            if (dwSize < 10)
+            {
+                return 0;
+            }
+            pInfo->bMPEG2 = TRUE;
+
+            ParseSequenceExtHeader(pBuffer, dwSize, pInfo);
+
+            pBuffer += 10;
+            dwSize -= 10;
+            lCode = GetStartCode(&pBuffer, dwSize);
+        }
+
+    }
     while (EXT_DATA_START_CODE == lCode ||
            USER_DATA_CODE == lCode) 
     {
@@ -1584,127 +1615,174 @@
 
         lCode = GetStartCode(&pBuffer, dwSize);
     }
-
+    if (!pInfo->bMPEG2)
+    {
+        pInfo->uyProfileLevel = MPEG1_PROFILE_LEVEL_ID;
+        pInfo->bProgressiveSeq = TRUE;
+        pInfo->bLowDelay = FALSE;
+    }
     return ulSize;
 }
 
-UINT8 CXmdDemuxer::ParseSequenceExtHeader(UINT8 *pBuffer,
-                                          UINT32 dwSize,
-                                          tVideoStream *pInfo)
-                                          //tStreamInfo *pInfo)
+void CXmdDemuxer::ParseSequenceExtHeader(UINT8 *pBuffer,
+                                         UINT32 dwSize,
+                                         tVideoStream *pInfo)
 {
-    // Check for sequence ext id
-    if ((pBuffer[4] & 0xF0) >> 4 != 1)
-        return 0;
+    pInfo->uyProfileLevel = ((pBuffer[4] & 0x0F) << 4) |
+                            ((pBuffer[5] & 0xF0) >> 4);
+    pInfo->bProgressiveSeq = (pBuffer[5] & 0x08);
+    pInfo->bLowDelay = (pBuffer[9] & 0x80);
+    
+    if ((INT32)pInfo->ulBitRate != -1)
+    {
+        pInfo->ulBitRate /= 400;
 
-    pInfo->ulBitRate /= 400;
+        pInfo->ulBitRate |= ((pBuffer[6] & 0x1F)<<25) | ((pBuffer[7] & 0xFE)<<17);
+        pInfo->ulBitRate *= 400;
+    }
+}
 
-    pInfo->ulBitRate |= ((pBuffer[6] & 0x1F)<<25) | ((pBuffer[7] & 0xFE)<<17);
-    pInfo->ulBitRate *= 400;
+inline UINT32
+GetReverseStartCode(UINT8* pStart, UINT8*& pEnd)
+{
+    while (pEnd - 3 > pStart)
+    {
+        if (pEnd[-2] == 1 && pEnd[-3] == 0 && pEnd[-4] == 0)
+        {
+            return 0x0100 | pEnd[-1];
+        }
+        else
+        {
+            --pEnd;
+        }
+    }
+    return NO_START_CODE;
+}
 
-    return 1;
+inline UINT32
+GetGOPTimeCode(UINT8* pBuffer, UINT32& ulFrames)
+{
+    UINT32 ulTimeCode =  ((pBuffer[0] & 0x7C) >> 2) * 3600; // hours
+    ulTimeCode += (((pBuffer[0] & 0x3) << 4) | // minutes
+                  (pBuffer[1] >> 4)) * 60;
+    ulTimeCode += (((pBuffer[1] & 0x7) << 3) | //seconds
+                  ((pBuffer[2] & 0xE0) >> 5));
+    ulTimeCode *= 1000;   // to ms
+
+    ulFrames = ((pBuffer[2] & 0x1F) << 1) | ((pBuffer[3] & 0x80) >> 7);
+
+    return ulTimeCode;
 }
 
-UINT32 CXmdDemuxer::GetVbrDuration(UINT8 *pBuffer,
-                                   UINT32 ulBytes,
-                                   tDurationStats *pStats)
+HXBOOL CXmdDemuxer::GetGOPTime(UINT8 *pBuffer,
+                               UINT32 ulBytes,
+                               tStreamInfo *pInfo,
+                               UINT32& ulMediaTime,
+                               GOPTimeStats*& pStats)
 {
-    UINT32  ulDuration = 0,
-            ulRet = 0;
-    INT32   lCode;
-    UINT32  ulFrames = 0;
+    UINT32 ulTCFrames = 0;
+    UINT32 lCode = NO_START_CODE;
+    HXBOOL bSucceeded = FALSE;
+    UINT8*  pIter = pBuffer + ulBytes;
+    UINT8*  pEnd = pIter;
+    UINT32 ulHalfFrameCount = m_GOPDurationData.ulHalfFrameCount;
 
-    do
-    {
-        lCode = GetStartCode(&pBuffer, ulBytes);
+    ulMediaTime = 0;
+    pStats = &m_GOPDurationData;
 
-        switch (lCode)
+    if (ulBytes >= 8)
+    {
+        // back up 4 bytes to make sure we don't overrun the buffer.
+        // anything starting past that is useless
+        pIter -= 4;
+        do
         {
-            case GROUP_START_CODE:
+            // store the last start position so we know where we left
+            // off if there are no more.
+            pEnd = pIter;
+            lCode = GetReverseStartCode(pBuffer, pIter);
+
+            switch (lCode)
             {
-                if (ulBytes > 8)
+                case GROUP_START_CODE:
                 {
-                    pBuffer += 4;
-                    ulBytes -= 4;
-                    
-                    ulDuration = ((pBuffer[0] & 0x7C) >> 2) * 360000;
-                    ulDuration += (((pBuffer[0] & 0x3)<<4) | ((pBuffer[1] & \
                0xF0)>>4)) * 60000;
-                    ulDuration += (((pBuffer[1] & 0x7)<<3) | ((pBuffer[2] & \
                0xE0)>>5)) * 1000;
-
-                    ulFrames = ((pBuffer[2] & 0x1F)<<1) | ((pBuffer[3] & 0x80)>>7);
-                    ulDuration += (UINT32)(ulFrames * (m_dFrameTime/90.0));
-
-                    if (!m_ulFirstGopDuration)
-                    {
-                        m_ulFirstGopDuration = max(1, ulDuration);
-                        m_ulLastGopDuration = m_ulFirstGopDuration;
-
-                        m_dGopFrames = ulFrames;
-                    }
+                    ulMediaTime = GetGOPTimeCode(pIter, ulTCFrames);
 
-                    if (ulDuration > m_ulLastGopDuration)
-                    {
-                        m_ulLastGopDuration = ulDuration;
-                        m_dGopFrames = 0.0;
+                    pIter -= 4;
+                    pEnd = pIter;
+                    bSucceeded = TRUE;
 
-                        if (pStats)
-                            pStats->ulFramesFound = 0;
-                    }
+                    break;
                 }
-                else
-                    lCode = NO_START_CODE;
 
-                break;
-            }
-            
-            case EXT_DATA_START_CODE:
-                if (ulBytes > 8)
+                case EXT_DATA_START_CODE:
                 {
-                    pBuffer += 4;
-                    ulBytes -= 4;
-
-                    // Look for picture coding extension flag
-                    if ((pBuffer[0] & 0x80) == 0x80)
+                    // Look for picture coding extension identifier
+                    if ((pIter[0] & 0xF0) == 0x80)
                     {
-                        pBuffer += 3;
-                        ulBytes -= 3;
-                        
                         // Look for repeat first field for MPEG2 video
-                        if((pBuffer[0] & 0x02) == 0x02 &&
-                           (pBuffer[1] & 0x80) == 0x80)
-                            m_dGopFrames += .5;
+                        if((pIter[3] & 0x02) == 0x02 &&
+                           (pIter[4] & 0x80) == 0x80)
+                        {
+                            ++ulHalfFrameCount;
+                        }
                     }
+                    pIter -= 4;
+                    break;
                 }
-                else
-                    lCode = NO_START_CODE;
 
-                break;
+                case PICTURE_START_CODE:
+                    ulHalfFrameCount += 2;
+                    pIter -= 4;
+                    break;
 
-            case PICTURE_START_CODE:
-                ++m_dGopFrames;
-                // fall through
-        
-            default:
-                pBuffer += 4;
-                ulBytes -= 4;
-        }
-    
-    } while (lCode != NO_START_CODE);
-    
-    if (m_ulLastGopDuration)
-    {
-        ulRet = m_ulLastGopDuration - m_ulFirstGopDuration;
-        ulRet += (UINT32)(m_dGopFrames * (m_dFrameTime/90.0));
+                case NO_START_CODE:
+                    break;
+
+                default:
+                    pIter -= 4;
+                    break;
+            }
+
+        } while (!bSucceeded && lCode != NO_START_CODE);
     }
 
-    if (pStats)
+    m_GOPDurationData.ulHalfFrameCount = ulHalfFrameCount;
+    m_GOPDurationData.ulBytesProcessed += ulBytes - (UINT32)(pEnd - pBuffer);
+    if (bSucceeded)
     {
-        pStats->ulFirstTimeStamp = m_ulFirstGopDuration;
-        pStats->ulLastTimeStamp = m_ulLastGopDuration;
-        pStats->ulFramesFound = (UINT32)m_dGopFrames;
+        UINT32 ulStartTime = m_GOPDurationData.ulStartTimeBase;
+
+        if (ulMediaTime < ulStartTime)
+        {
+            // handle rollover. Need to deal with the actual time
+            // portions here, without time_code_pictures.
+            ulMediaTime += GOP_TIME_CODE_ROLLOVER;
+        }
+
+        // Now add the time_code_pictures time from the time code
+        ulMediaTime += (UINT32)(ulTCFrames * pInfo->dFrameTime + .5);
+
+        // And add the duration of the frames that were in this GOP.
+        ulMediaTime += ((UINT32)(ulHalfFrameCount * pInfo->dFrameTime) + 1) >> 1;
+
+        // And add the time_code_pictures time from the first
+        // GOP to the start time.
+        ulStartTime += (UINT32)(m_GOPDurationData.ulStartTimePics *
+                        pInfo->dFrameTime + .5);
+
+        // subtract the starting time to get the duration
+        if (ulMediaTime >= ulStartTime)
+        {
+            ulMediaTime -= ulStartTime;
+        }
+        else
+        {
+            ulMediaTime = 0;
+        }
     }
-    
-    return ulRet;
+
+    return bSucceeded;
 }
 
 HXBOOL CXmdDemuxer::IsInitDone(tStreamInfo pInfo[], int nPacketsProcessed)
@@ -1807,7 +1885,6 @@
     return 0;
 }
 
-
 int CXmdDemuxer::ParseSystemHeader(UINT8 *pBuffer,
                                    UINT32 dwSize,
                                    UINT32 &ulMuxRate)

Index: xmddemuxer.h
===================================================================
RCS file: /cvsroot/datatype/mpg/fileformat/xmddemuxer.h,v
retrieving revision 1.3.18.1
retrieving revision 1.3.18.1.36.1
diff -u -d -r1.3.18.1 -r1.3.18.1.36.1
--- xmddemuxer.h	18 Sep 2007 09:35:56 -0000	1.3.18.1
+++ xmddemuxer.h	19 Jan 2012 19:21:36 -0000	1.3.18.1.36.1
@@ -83,27 +83,35 @@
 
 typedef struct
 {
-    UINT32  ulFirstTimeStamp,
-            ulLastTimeStamp,
-            ulFramesFound;
-} tDurationStats;
+    UINT32 ulStartTimeBase;
+    UINT32 ulStartTimePics;
+    UINT32 ulHalfFrameCount;
+    UINT32 ulBytesProcessed;
+} GOPTimeStats;
 
 typedef struct
 {
     INT8        yStreamId;
     
-    UINT32      ulBufSize,
-                ulWidth,
-                ulHeight,
-                ulBitRate,
-                ulFirstPacketTime,
-                ulLastScr;
+    UINT8       uyProfileLevel;
+    UINT32      ulBufSize;
+    UINT32      ulWidth;
+    UINT32      ulHeight;
+    UINT32      ulBitRate;  // max bitrate (from seq header)
+    UINT32      ulFirstPacketTime;
+    UINT32      ulLastScr;
+    UINT16      usNextTempRef;  // next temporal reference w/in GOP
+    INT16       sPendingTempRef;
 
-    HXBOOL        bMPEG2,     // Is the video data mpeg2
-                bVbr;       // Is the muxing vbr
+    UINT8       bMPEG2;     // Is the video data mpeg2
+    UINT8       bVbr;       // Is the muxing vbr
+    UINT8       bLowDelay;  // MPEG-2 low-delay
+    UINT8       bConstrained;
+    UINT8       bProgressiveSeq;
 
     double      dFrameTime;
-
+    double      dPendingFrameTime;
+    
     UCHAR       *pSeqHdr;
     INT32       ulSeqHdrSize;
 
@@ -145,6 +153,10 @@
                  int &nStreamCount,
                  tStreamInfo pInfo[]);
 
+    UINT32  ParseSequenceHeader(UINT8 *pBuffer,
+                                UINT32 dwSize,
+                                tVideoStream *pInfo);
+    
     UINT32  Demux(UINT8 *pBuffer, UINT32 ulBytes, Packet *pPacket);
     UINT32  GetAudioRtpPacket(UINT8 *pRead,
                               UINT32 ulRead,
@@ -157,8 +169,12 @@
     
     UINT32  GetDuration(UINT8 *pBuffer,
                         UINT32 ulBytes,
-                        tStreamInfo *pInfo,
-                        tDurationStats *pStats=NULL);
+                        tStreamInfo *pInfo);
+    HXBOOL  GetGOPTime(UINT8 *pBuffer,
+                       UINT32 ulBytes,
+                       tStreamInfo *pInfo,
+                       UINT32& ulMediaTime,
+                       GOPTimeStats*& pStats);
 
     BYTE*   GetSequenceHeader(INT32 nStreamId, INT32 &nHdrSize);
 
@@ -184,10 +200,6 @@
     UINT8   IsMPEG2()               {return m_bMPEG2;}
 
 protected:
-    UINT32  GetVbrDuration(UINT8 *pBuffer,
-                           UINT32 ulBytes,
-                           tDurationStats *pStats);
-
     HXBOOL    IsInitDone(tStreamInfo pInfo[], int nPacketsProcessed);
 
     UINT8   ParseAudioHeader(UINT8 *&pBuffer,
@@ -195,13 +207,9 @@
                              ePacketSubType eType,
                              tAudioStream *pInfo);
 
-    UINT32  ParseSequenceHeader(UINT8 *pBuffer,
-                                UINT32 dwSize,
-                                tVideoStream *pInfo);
-    
-    UINT8   ParseSequenceExtHeader(UINT8 *pBuffer,
-                                   UINT32 dwSize,
-                                   tVideoStream *pInfo);
+    void   ParseSequenceExtHeader(UINT8 *pBuffer,
+                                  UINT32 dwSize,
+                                  tVideoStream *pInfo);
     
     int     ParseSystemHeader(UINT8 *pBuffer,
                               UINT32 dwSize,
@@ -219,7 +227,7 @@
 
     CAudioInfoBase  *m_pAudInfo;
 
-    HXBOOL    m_bMPEG2,       // Is this MPEG1 or MPEG2 data
+    HXBOOL  m_bMPEG2,       // Is this MPEG1 or MPEG2 data
             m_bFindAudio,   // Need audio data for init
             m_bFindVideo,   // Need video data for init
             m_bSendSeqHdr,  // Send the seq header as the first packet
@@ -236,12 +244,6 @@
             m_ulReadSize,   // Size for file reads
             m_ulVCDBytes;   // Number of bytes in m_pVCDBuffer
 
-    
-    enum    {AUDIO_BUFFER_SIZE  = 4096};
-
-    tVideoStream    m_aVidStreams[16];
-    tAudioStream    m_aAudStreams[32];
-
     int     m_nVidStreams,  // Number of muxed video streams
             m_nAudStreams,  // Number of muxed audio streams
             m_nCurrVidId,   // Stream id to extract
@@ -249,11 +251,7 @@
 
     double  m_dFrameTime,   // Frame time in 90 KHz units
             m_dGopBaseTs,   // 90 KHz pts
-            m_dLastPts,     // Last90 KHz pts
-            m_dGopFrames;
-
-    UINT32  m_ulFirstGopDuration,
-            m_ulLastGopDuration;
+            m_dLastPts;     // Last90 KHz pts
 
     double  m_dFirstPacketTime,     // time of first packet after Reset (ms)
             m_dFirstScr,            // first scr in the stream
@@ -264,6 +262,23 @@
 
     INT32   m_llScrOffset,          // byte offset from last scr
             m_ulPackRate;           // bit rate for this pack
+
+    tVideoStream    m_aVidStreams[16];
+    tAudioStream    m_aAudStreams[32];
+
+    GOPTimeStats m_GOPDurationData;
+
+    enum    {AUDIO_BUFFER_SIZE  = 4096};
 };
 
+inline HXBOOL IsVideoCode(UINT32 lCode)
+{
+    return (HXBOOL)(lCode < 0x1b9);
+}
+
+inline HXBOOL IsSliceCode(UINT32 lCode)
+{
+    return (lCode < 0x1b0) & (lCode > PICTURE_START_CODE) ? TRUE : FALSE;
+}
+
 #endif

Index: Umakefil
===================================================================
RCS file: /cvsroot/datatype/mpg/fileformat/Umakefil,v
retrieving revision 1.2
retrieving revision 1.2.256.1
diff -u -d -r1.2 -r1.2.256.1
--- Umakefil	12 Nov 2004 21:23:43 -0000	1.2
+++ Umakefil	19 Jan 2012 19:21:35 -0000	1.2.256.1
@@ -40,6 +40,9 @@
 
 #project.AddDefines("HELIX_FEATURE_MPGFF_LPCM")
 
+if project.IsDefined("HELIX_FEATURE_SERVER"):
+    project.AddDefines("HELIX_FEATURE_PACKETIZER_MPEG_RTP")
+   
 project.AddModuleIncludes("common/include",
                           "datatype/mpg/common")
 

Index: rmpgff.h
===================================================================
RCS file: /cvsroot/datatype/mpg/fileformat/rmpgff.h,v
retrieving revision 1.3.18.1
retrieving revision 1.3.18.1.32.1
diff -u -d -r1.3.18.1 -r1.3.18.1.32.1
--- rmpgff.h	28 Mar 2008 02:13:58 -0000	1.3.18.1
+++ rmpgff.h	19 Jan 2012 19:21:35 -0000	1.3.18.1.32.1
@@ -50,9 +50,6 @@
 #define MY_FILE_EXTENSIONS     {"mpa", "mpg", "mpeg", "mpv", "mps", "m2v", "m1v", \
"mpe", NULL}  #define MY_FILE_OPEN_NAMES     {"MPEG Files \
(.mpg;.mpeg;.mpv;.m2v;.mps;.m1v;.mpe)", NULL}  
-#define MY_VIDEO_MIME_TYPE     {"video/MPV", "video/mp1s", "video/mp2p", \
                "video/vnd.rn-mpv", "video/vnd.rn-mp1s", "video/vnd.rn-mp2p", NULL}
-#define MY_AUDIO_MIME_TYPE     {"audio/MPA", "audio/mp1s", "audio/mp2p", \
                "audio/vnd.rn-mp3", "audio/vnd.rn-mp1s", "audio/vnd.rn-mp2p", NULL}
-#define MY_AC3_MIME_TYPE       {"audio/AC3", "audio/vnd.rn-mp2pAC3", NULL}
 
 enum { MY_FILE_HEADER_START = 0 };
 enum { MY_FILE_HEADER_LENGTH = 48*1024};
@@ -74,8 +71,6 @@
     SetStreamHeaderSeekPending,
     GetDurationSeekPending,
     GetDurationReadPending,
-    GetVbrDurationSeekPending,
-    GetVbrDurationReadPending,
     GetPacketSeekPending,
     GetPacketReadPending,
     SeekSeekPending
@@ -169,7 +164,7 @@
 private:
     ///////////////////////////////////////////////////////////////////////////
     // Private Class Variables
-    INT32                   m_RefCount;         // Object's reference count
+    INT32                  m_RefCount;         // Object's reference count
     IHXCommonClassFactory* m_pClassFactory;    // Creates common RMA classes
     IHXFileObject*         m_pFileObj;         // Used for file I/O
     IHXFormatResponse*     m_pStatus;          // Reports status to RMA core
@@ -181,8 +176,6 @@
     HX_RESULT               m_StrmHdrResult;
     MyState                 m_State;            // State used for asynch. calls
 
-    CBasePacketizer*        m_aMpg[2];
-
     double                  m_dNextPts,
                             m_dLastPts;         // Last rtp pts
 
@@ -198,7 +191,8 @@
                             m_ulPacketDuration, // Duration of packets sent (in ms)
                             m_ulStartTime;      // Time of first packet sent (in ms)
 
-    HXBOOL                    m_bEOF,
+
+    HXBOOL                  m_bEOF,
                             m_bStreaming,       // Are we in a packet loss enviorn
                             m_bNeedPacket,      // Read did not finish inside \
                GetPacket
                             m_bLicensedM1,      // Is the user licensed for mpeg1
@@ -212,12 +206,18 @@
     UINT16                  m_wStreamCount,     // Number of streams we are sending
                             m_wStreamNo;        // Stream number of last operation
 
+    UCHAR                   m_bRtp,         // Are we using rtp transport
+                            m_bGetHeader;   // Get the other stream header
+    IUnknown                *m_pContext;
+
+    CBasePacketizer*        m_aMpg[2];
+    tStreamInfo             m_aInfo[3];         // V/A/File stream info
+
+
     enum                    {VIDEO_STREAM,
                              AUDIO_STREAM,
                              FILE_STREAM};
 
-    tStreamInfo             m_aInfo[3];         // V/A/File stream info
-
     // Buffered Read
     typedef struct
     {
@@ -236,9 +236,6 @@
 
     tRtpPacket              m_aRtpPackets[2];
 
-    UCHAR                   m_bRtp,         // Are we using rtp transport
-                            m_bGetHeader;   // Get the other stream header        
-    IUnknown                *m_pContext;
 
     ///////////////////////////////////////////////////////////////////////////
     // Private Static Class Variables
@@ -249,9 +246,7 @@
     static const char*     zm_pFileExtensions[];
     static const char*     zm_pFileOpenNames[];
     static const char*     zm_pPacketFormats[];
-    static const char*     zm_pVideoMimeTypes[];
-    static const char*     zm_pAudioMimeTypes[];
-    static const char*     zm_pAc3MimeTypes[];
+
 
 	///////////////////////////////////////////////////////////////////////////
     // Private Class Methods
@@ -267,6 +262,11 @@
                                      tReadBuffer* pDataRead,
                                      UINT16 streamNo);
     
+    HXBOOL      GetSystemDuration(IHXBuffer* pBufferRead);
+    HXBOOL      GetVideoESDuration(IHXBuffer* pBufferRead);
+    void        HandleVideoDuration(UINT32 ulDuration, GOPTimeStats* pStats);
+    HXBOOL      IsVideoBitrateSane(UINT32 ulBitRate);
+
     UCHAR*      GetPacket_p(tReadBuffer* pPacketData,
                             int &nPacketSize,
                             UINT32 &ulScr,
@@ -275,6 +275,11 @@
     UINT32      GetSystemStreamPacket(UCHAR *pRead,
                                       UINT32 ulRead,
                                       Packet *pPacket);
+
+    UINT32      GetVideoESPacket(UCHAR*& pBuffer,
+                                 UINT32 ulSize,
+                                 tVideoStream* pVidStream,
+                                 tRtpPacket* pRTPStream);
     
     UINT16      InitStream_n(IHXBuffer* pDataRead,
                              tStreamInfo pInfo[],

Index: rmpgff.cpp
===================================================================
RCS file: /cvsroot/datatype/mpg/fileformat/rmpgff.cpp,v
retrieving revision 1.8.10.2.32.3
retrieving revision 1.8.10.2.32.4
diff -u -d -r1.8.10.2.32.3 -r1.8.10.2.32.4
--- rmpgff.cpp	10 Nov 2011 01:53:27 -0000	1.8.10.2.32.3
+++ rmpgff.cpp	19 Jan 2012 19:21:35 -0000	1.8.10.2.32.4
@@ -63,6 +63,7 @@
 #include "hxvsrc.h"     // IHXFileViewSource
 #include "hxupgrd.h"    // IHXUpgradeCollection
 #include "hxprefutil.h"
+#include "hxsbuffer.h"
 
 #include "xmddemuxer.h"
 #include "rmpgff.h"     // CRnMpgFmt
@@ -78,6 +79,38 @@
 ENABLE_MULTILOAD_DLLACCESS_PATHS(Rmpgff);
 #endif
 
[...1701 lines suppressed...]
+            // be certain about the PTS without big changes to the
+            // broader structure. I don't think we will run across that
+            // very often if at all with ES files anyway!
+
+            pRTPStream->dPts = (pVidStream->dFrameTime * sRefOffset +
+                                pRTPStream->dScr) * RTP_TS_MULT_FP;
+
+            pVidStream->sPendingTempRef = (INT16)usTemporalRef;
+            pVidStream->dPendingFrameTime = dDuration;
+        }
+
+        return pRead - pFrameBuf;
+    }
+
+    return 0;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Function:    InitStream_n
 // Purpose:     Determine the stream type, prepare our pluigin to handle it.


_______________________________________________
Datatype-cvs mailing list
Datatype-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/datatype-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic