summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dxr3pesframe.c278
-rw-r--r--dxr3pesframe.h15
2 files changed, 70 insertions, 223 deletions
diff --git a/dxr3pesframe.c b/dxr3pesframe.c
index bde2dcd..6077de0 100644
--- a/dxr3pesframe.c
+++ b/dxr3pesframe.c
@@ -2,6 +2,7 @@
* dxr3pesframe.c
*
* Copyright (C) 2002-2004 Kai Möller
+ * Copyright (C) 2009 Christian Gmeiner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -29,240 +30,99 @@
#include <vdr/tools.h>
// ==================================
-bool cDxr3PesFrame::parse(const uint8_t* pBuf, uint32_t length)
- throw (ePesFrameError)
+bool cDxr3PesFrame::parse(const uint8_t *pes, uint32_t length)
{
- cDxr3SafeArray<uint8_t> pesArray((uint8_t*)pBuf, length);
- uint32_t pos = 0;
- m_pNextStart = pBuf;
- m_remainingLength = length;
+ // look if at the beginning there is the pes packet start indicator
+ if (pes[0] != 0 || pes[1] != 0 || pes[2] != 1) {
+ esyslog("[cDxr3PesFrame]: no start indicator found...");
+ return false;
+ }
- InitData();
+ m_bValid = true;
- try
- {
- if (length > 9)
- {
- for (; pos + 9 < length && !IsPesHeader(pesArray.SubArray(pos, 4)); pos++);
- if (pos + 9 >= length)
- {
- // Corrupt stream?
- m_remainingLength = 0;
- return m_bValid;
- }
- m_pPesStart = pBuf + pos;
+ // handle stream id
+ switch (pes[3]) {
+ case 0xBD: // private stream 1
+ m_pesDataType = PES_PRIVATE_DATA;
- if ((pesArray[pos + 6] & 0xC0) == 0x80
- /*|| (pesArray[pos + 6] & 0xC0) == 0x00*/)
- {
- if (pos + 9 + pesArray[pos + 8] < length)
- {
- m_payload = pBuf + pos + 9 + pesArray[pos + 8];
- if ((((int)pesArray[pos + 4]) * (int)256 + (int)pesArray[pos + 5]) > 0)
- {
- m_payloadLength = ((int)pesArray[pos + 4]) *
- (int)256 + (int)pesArray[pos + 5] + (int)6 -
- (9 + (int)pesArray[pos + 8]);
- if (pos + 9 + pesArray[pos + 8] + m_payloadLength <= length)
- {
- m_bValid = true;
- m_pNextStart = m_payload + m_payloadLength;
- m_remainingLength = pBuf + length - (m_payload + m_payloadLength);
- if (pesArray[pos + 6] >> 6 == 2 &&
- pesArray[pos + 7] >> 7 != 0)
- {
- ExtractPts(pesArray.SubArray(pos + 9, 5));
- }
- if (m_pesDataType == PES_VIDEO_DATA)
- {
- int retval = ExtractVideoData(pesArray.SubArray(pos + 9 + pesArray[pos + 8], m_payloadLength));
- if (m_videoFrameType != UNKNOWN_FRAME && retval)
- m_offset = retval + pos + 9 + pesArray[pos + 8];
- }
- }
- }
- }
- }
- else
- {
- uint32_t fpos = pos + 6;
- m_payloadLength = ((int)pesArray[pos + 4]) * (int)256 + (int)pesArray[pos + 5];
- if (length >= pos + 6 + m_payloadLength)
- {
- while (pesArray[fpos] == 0xff)
- ++fpos; // skip stuffing bytes
- if ((pesArray[fpos] & 0xC0) == 0x40)
- fpos += 2; // skip std buffer scale and size
- if ((pesArray[fpos] & 0xF0) == 0x20)
- {
- // pts only
- ExtractPts(pesArray.SubArray(fpos, 5));
- fpos += 5;
- }
- else if ((pesArray[fpos] & 0xF0) == 0x30)
- {
- // pts and dts
- ExtractPts(pesArray.SubArray(fpos, 5));
- fpos += 10;
- }
- else
- {
- ++fpos;
- }
+ case 0xC0 ... 0xDF: // audio stream
+ m_pesDataType = PES_AUDIO_DATA;
+ break;
- if (m_payloadLength) m_payloadLength = m_payloadLength - (fpos - pos - 6);
- m_payload = pBuf + fpos;
- m_pNextStart = m_payload + m_payloadLength;
- m_remainingLength = pBuf + length - (m_payload + m_payloadLength);
- m_bValid = true;
- if (m_pesDataType == PES_VIDEO_DATA)
- {
- int retval = ExtractVideoData(pesArray.SubArray(fpos, m_payloadLength));
- if (m_videoFrameType != UNKNOWN_FRAME && retval)
- m_offset = 0;
- }
- }
- }
- }
- }
- catch (cDxr3SafeArray<uint8_t>::eSafeArrayException ex)
- {
- m_bValid = false;
- esyslog("dxr3: general PES error");
- throw(PES_GENERAL_ERROR);
+ case 0xE0 ... 0xEF: // video stream
+ m_pesDataType = PES_VIDEO_DATA;
+ break;
+
+ default:
+ return false;
}
- return m_bValid;
-}
+ // read pes header len
+ uint8_t pesHeaderDataLength = pes[8];
-// ==================================
-int cDxr3PesFrame::ExtractVideoData(cDxr3SafeArray<uint8_t> esFrame)
- throw (cDxr3SafeArray<uint8_t>::eSafeArrayException)
-{
- int retval = 0;
- for (uint32_t i = 0; esFrame.GetLength() > (uint32_t) 8 && i < esFrame.GetLength() - 8; i++)
- {
- if (esFrame[i] == 0 && esFrame[i + 1] == 0 && esFrame[i + 2] == 1)
- {
- // start code
- if ((esFrame[i + 3] & 0xFF) == 0x00)
- {
- // frame type
- if (m_offset == 0)
- retval = i;
- switch ((esFrame[i + 5] >> 3) & 0x7)
- {
- case 0x1:
- m_videoFrameType = I_FRAME;
- break;
- case 0x2:
- m_videoFrameType = P_FRAME;
- break;
- case 0x3:
- m_videoFrameType = B_FRAME;
- break;
- default:
- m_videoFrameType = UNKNOWN_FRAME;
- break;
- }
- }
- else if ((esFrame[i + 3] & 0xFF) == 0xB3)
- {
- // aspect ratio
- switch ((esFrame[i + 7]) & 0xF0)
- {
- case 0x20:
- m_staticAspectRatio = m_aspectRatio =
- EM8300_ASPECTRATIO_4_3;
- break;
- case 0x30:
- m_staticAspectRatio = m_aspectRatio =
- EM8300_ASPECTRATIO_16_9;
- break;
- default:
- break;
- }
- m_staticHorizontalSize = m_horizontalSize =
- (esFrame[i + 5] & 0xF0) >> 4 | esFrame[i + 4] << 4;
- m_staticVerticalSize = m_verticalSize =
- ((esFrame[i + 5] & 0x0F) << 8) | (esFrame[i + 6]);
- }
- }
+ // look if there is a pts
+ if (pes[7] & (1 << 7)) {
+ // read pts
+ uint64_t pts = (((int64_t)pes[ 9]) & 0x0e) << 29;
+ pts |= ( (int64_t)pes[10]) << 22;
+ pts |= (((int64_t)pes[11]) & 0xfe) << 14;
+ pts |= ( (int64_t)pes[12]) << 7;
+ pts |= (((int64_t)pes[13]) & 0xfe) >> 1;
+
+ m_pts = pts >> 1;
}
- return retval;
-}
-// ==================================
-void cDxr3PesFrame::ExtractPts(cDxr3SafeArray<uint8_t> ptsData)
- throw (cDxr3SafeArray<uint8_t>::eSafeArrayException)
-{
- m_pts = ((ptsData[0] >> 1) & 0x07) << 29;
- m_pts |= ptsData[1] << 21;
- m_pts |= (ptsData[2] >> 1) << 14;
- m_pts |= ptsData[3] << 6;
- m_pts |= ptsData[4] >> 2;
-}
+ // set pointer to start of payload
+ int payloadStart = 9 + pesHeaderDataLength;
+ m_payload = &pes[payloadStart];
+ m_payloadLength = length - payloadStart;
-// ==================================
-bool cDxr3PesFrame::IsPesHeader(cDxr3SafeArray<uint8_t> header)
- throw (cDxr3SafeArray<uint8_t>::eSafeArrayException)
-{
- bool ret = false;
+ if (m_pesDataType == PES_VIDEO_DATA) {
- if (!header[0] && !header[1] && header[2] == 0x01 )
- {
- ret = true;
- switch (header[3])
- {
- case 0xC0 ... 0xDF: // audio stream
- m_pesDataType = PES_AUDIO_DATA;
- break;
+ // we can get some informations about the video payload
+ // of this pes frame. For more informations have a look
+ // at http://dvd.sourceforge.net/dvdinfo/mpeghdrs.htm
- case 0xE0 ... 0xEF: // video stream
- m_pesDataType = PES_VIDEO_DATA;
- break;
+ const uint8_t *video = &pes[payloadStart];
- case 0xBD: // private stream 1
- m_pesDataType = PES_PRIVATE_DATA;
- break;
+ // look if there is the start code prefix (0000 0000 0000 0000 0000 0001)
+ if (video[0] != 0 || video[1] != 0 || video[2] != 1) {
+ return true;
+ }
- case 0xBA:
- ret = false;
- break;
+ // check stream id
+ if (video[3] == 0xb3) {
- case 0xBE: // padding stream
- ret = false;
- break;
+ // in the sequence header we get informations about horizontal
+ // and vertical size of the video and the current aspect ratio.
- case 0xBC: // program stream map
- case 0xBF: // private stream 2
- case 0xF0: // ECM stream
- case 0xF1: // EMM stream
- case 0xF2: // DSMCC stream
- case 0xF3: // 13522 stream
- case 0xF4: // H.22.1 type A
- case 0xF5: // H.22.1 type B
- case 0xF6: // H.22.1 type C
- case 0xF7: // H.22.1 type D
- case 0xF8: // H.22.1 type E
- case 0xF9: // ancillary stream
- case 0xFA ... 0xFE: // reserved data stream
- case 0xFF: // program stream directory
- break;
- default:
- ret = false;
- break;
- }
+ m_horizontalSize = (video[5] & 0xf0) >> 4 | video[4] << 4;
+ m_verticalSize = (video[5] & 0x0f) << 8 | video[6];
+
+ switch ((video[7]) & 0xf0) {
+ case 0x20:
+ m_aspectRatio = EM8300_ASPECTRATIO_4_3;
+ break;
+
+ case 0x30:
+ m_aspectRatio = EM8300_ASPECTRATIO_16_9;
+ break;
+ }
+
+ m_staticHorizontalSize = m_horizontalSize;
+ m_staticVerticalSize = m_verticalSize;
+ m_staticAspectRatio = m_aspectRatio;
+ }
}
- return ret;
+ return true;
}
+
// ==================================
uint32_t cDxr3PesFrame::m_staticAspectRatio = EM8300_ASPECTRATIO_4_3;
uint32_t cDxr3PesFrame::m_staticHorizontalSize = 720;
uint32_t cDxr3PesFrame::m_staticVerticalSize = 576;
-const uint32_t cDxr3PesFrame::MAX_PES_HEADER_SIZE = 184;
// Local variables:
// mode: c++
diff --git a/dxr3pesframe.h b/dxr3pesframe.h
index 869b06b..345f184 100644
--- a/dxr3pesframe.h
+++ b/dxr3pesframe.h
@@ -118,8 +118,7 @@ public:
virtual ~cDxr3PesFrame() {}
- bool parse(const uint8_t* pBuf, uint32_t length)
- throw (ePesFrameError);
+ bool parse(const uint8_t *pes, uint32_t length);
ePesDataType GetPesDataType() const
{
@@ -145,11 +144,6 @@ public:
return m_payloadLength;
}
- const uint8_t* GetNextStart() const
- {
- return m_pNextStart;
- }
-
uint32_t GetPts() const
{
assert(m_bValid);
@@ -196,13 +190,6 @@ public:
}
protected:
- bool IsPesHeader(cDxr3SafeArray<uint8_t> header)
- throw (cDxr3SafeArray<uint8_t>::eSafeArrayException);
- void ExtractPts(cDxr3SafeArray<uint8_t> ptsData)
- throw (cDxr3SafeArray<uint8_t>::eSafeArrayException);
- int ExtractVideoData(cDxr3SafeArray<uint8_t> esFrame)
- throw (cDxr3SafeArray<uint8_t>::eSafeArrayException);
-
void InitData()
{
m_pesDataType = PES_UNKNOWN_DATA;