diff options
author | austriancoder <austriancoder> | 2004-08-05 23:05:21 +0000 |
---|---|---|
committer | austriancoder <austriancoder> | 2004-08-05 23:05:21 +0000 |
commit | c47666d42f7972e1b51f9de61ce0fa27c72f3127 (patch) | |
tree | e34a87e37901b7f892fb6f330ccb15bcba30039b /dxr3pesframe.c | |
download | vdr-plugin-dxr3-c47666d42f7972e1b51f9de61ce0fa27c72f3127.tar.gz vdr-plugin-dxr3-c47666d42f7972e1b51f9de61ce0fa27c72f3127.tar.bz2 |
initial import
Diffstat (limited to 'dxr3pesframe.c')
-rw-r--r-- | dxr3pesframe.c | 226 |
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; + |