summaryrefslogtreecommitdiff
path: root/dxr3pesframe.c
diff options
context:
space:
mode:
authoraustriancoder <austriancoder>2004-08-05 23:05:21 +0000
committeraustriancoder <austriancoder>2004-08-05 23:05:21 +0000
commitc47666d42f7972e1b51f9de61ce0fa27c72f3127 (patch)
treee34a87e37901b7f892fb6f330ccb15bcba30039b /dxr3pesframe.c
downloadvdr-plugin-dxr3-c47666d42f7972e1b51f9de61ce0fa27c72f3127.tar.gz
vdr-plugin-dxr3-c47666d42f7972e1b51f9de61ce0fa27c72f3127.tar.bz2
initial import
Diffstat (limited to 'dxr3pesframe.c')
-rw-r--r--dxr3pesframe.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/dxr3pesframe.c b/dxr3pesframe.c
new file mode 100644
index 0000000..c86002e
--- /dev/null
+++ b/dxr3pesframe.c
@@ -0,0 +1,226 @@
+#include "dxr3pesframe.h"
+#include "dxr3log.h"
+#include <linux/em8300.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+// ==================================
+bool cDxr3PesFrame::ExtractNextFrame(const uint8_t* pBuf, uint32_t length) throw (ePesFrameError)
+{
+ cDxr3SafeArray<uint8_t> pesArray((uint8_t*)pBuf, length);
+ uint32_t pos = 0;
+ m_pNextStart = pBuf;
+ m_remainingLength = length;
+
+ InitData();
+
+ try
+ {
+ if (length > 9)
+ {
+ for (; pos + 9 < length && !IsPesHeader(pesArray.SubArray(pos, 4)); pos++);
+ m_pPesStart = pBuf + pos;
+
+ if ((pesArray[pos + 6] & 0xC0) == 0x80 /*|| (pesArray[pos + 6] & 0xC0) == 0x00*/)
+ {
+ if (pos + 9 + pesArray[pos + 8] < length)
+ {
+ m_pEsStart = pBuf + pos + 9 + pesArray[pos + 8];
+ if ((((int)pesArray[pos + 4]) * (int)256 + (int)pesArray[pos + 5]) > 0)
+ {
+ m_esLength = ((int)pesArray[pos + 4]) * (int)256 + (int)pesArray[pos + 5] + (int)6 - (9 + (int)pesArray[pos + 8]);
+ if (pos + 9 + pesArray[pos + 8] + m_esLength <= length)
+ {
+ m_bValid = true;
+ m_pNextStart = m_pEsStart + m_esLength;
+ m_remainingLength = pBuf + length - (m_pEsStart + m_esLength);
+ 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_esLength));
+ if (m_videoFrameType != UNKNOWN_FRAME && retval) m_offset = retval + pos + 9 + pesArray[pos + 8];
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ uint32_t fpos = pos + 6;
+ m_esLength = ((int)pesArray[pos + 4]) * (int)256 + (int)pesArray[pos + 5];
+ if (length >= pos + 6 + m_esLength)
+ {
+ 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;
+ }
+
+ if (m_esLength) m_esLength = m_esLength - (fpos - pos - 6);
+ m_pEsStart = pBuf + fpos;
+ m_pNextStart = m_pEsStart + m_esLength;
+ m_remainingLength = pBuf + length - (m_pEsStart + m_esLength);
+ m_bValid = true;
+ if (m_pesDataType == PES_VIDEO_DATA)
+ {
+ int retval = ExtractVideoData(pesArray.SubArray(fpos, m_esLength));
+ if (m_videoFrameType != UNKNOWN_FRAME && retval) m_offset = 0;
+ }
+ }
+ }
+ }
+ }
+ catch (cDxr3SafeArray<uint8_t>::eSafeArrayException ex)
+ {
+ m_bValid = false;
+ cLog::Instance() << "*** PES_GENERAL_ERROR ****\n";
+ throw(PES_GENERAL_ERROR);
+ }
+
+ return m_bValid;
+
+}
+
+// ==================================
+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)
+ {
+ // extract 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 = ASPECTRATIO_4_3;
+ break;
+
+ case 0x30:
+ m_staticAspectRatio = m_aspectRatio = ASPECTRATIO_16_9;
+ break;
+
+ default:
+ break;
+ }
+ m_staticHorizontalSize = m_horizontalSize = (esFrame[i + 5] & 0xF0) >> 4 | esFrame[i + 4] << 4;
+ }
+ }
+ }
+ 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;
+}
+
+// ==================================
+bool cDxr3PesFrame::IsPesHeader(cDxr3SafeArray<uint8_t> header) throw (cDxr3SafeArray<uint8_t>::eSafeArrayException)
+{
+ bool ret = false;
+
+ if (!header[0] && !header[1] && header[2] == 0x01 )
+ {
+ ret = true;
+ switch (header[3])
+ {
+ case 0xC0 ... 0xDF: // audio stream
+ m_pesDataType = PES_AUDIO_DATA;
+ break;
+
+ case 0xE0 ... 0xEF: // video stream
+ m_pesDataType = PES_VIDEO_DATA;
+ break;
+
+ case 0xBD: // private stream 1
+ m_pesDataType = PES_PRIVATE_DATA;
+ break;
+
+ case 0xBA:
+ ret = false;
+ break;
+
+ case 0xBE: // padding stream
+ ret = false;
+ break;
+
+ 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_streamId = header[3];
+ }
+
+ return ret;
+}
+
+// ==================================
+uint32_t cDxr3PesFrame::m_staticAspectRatio = EM8300_ASPECTRATIO_4_3;
+uint32_t cDxr3PesFrame::m_staticHorizontalSize = 720;
+const uint32_t cDxr3PesFrame::MAX_PES_HEADER_SIZE = 184;
+