diff options
author | austriancoder <austriancoder> | 2005-08-15 17:28:49 +0000 |
---|---|---|
committer | austriancoder <austriancoder> | 2005-08-15 17:28:49 +0000 |
commit | 290038f3de13b728cab6d3db7729078482903844 (patch) | |
tree | b83287be6ad0602f7f73a91c11b36074e5062be0 /dxr3pesframe.c | |
parent | 8955b4dfa419698ecb853bb8f1cdc1fe96d206d6 (diff) | |
download | vdr-plugin-dxr3-290038f3de13b728cab6d3db7729078482903844.tar.gz vdr-plugin-dxr3-290038f3de13b728cab6d3db7729078482903844.tar.bz2 |
HEAD = 0.2.3 release, because i want to start my coding with this codebase
Diffstat (limited to 'dxr3pesframe.c')
-rw-r--r-- | dxr3pesframe.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/dxr3pesframe.c b/dxr3pesframe.c new file mode 100644 index 0000000..8bf5fe3 --- /dev/null +++ b/dxr3pesframe.c @@ -0,0 +1,273 @@ +/* + * dxr3pesframe.c + * + * Copyright (C) 2002-2004 Kai Möller + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "dxr3pesframe.h" + +#include <linux/em8300.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <vdr/tools.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++); + if (pos + 9 >= length) + { + // Corrupt stream? + m_remainingLength = 0; + return m_bValid; + } + 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; + esyslog("dxr3: general PES error"); + 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; + m_staticVerticalSize = m_verticalSize = ((esFrame[i + 5] & 0x0F) << 8) | (esFrame[i + 6]); + } + } + } + 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; +uint32_t cDxr3PesFrame::m_staticVerticalSize = 576; +const uint32_t cDxr3PesFrame::MAX_PES_HEADER_SIZE = 184; + +// Local variables: +// mode: c++ +// c-file-style: "stroustrup" +// c-file-offsets: ((inline-open . 0)) +// indent-tabs-mode: t +// End: |