[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