summaryrefslogtreecommitdiffstats
path: root/mpeglib/lib/mpegplay/pesSystemStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mpeglib/lib/mpegplay/pesSystemStream.cpp')
-rw-r--r--mpeglib/lib/mpegplay/pesSystemStream.cpp498
1 files changed, 498 insertions, 0 deletions
diff --git a/mpeglib/lib/mpegplay/pesSystemStream.cpp b/mpeglib/lib/mpegplay/pesSystemStream.cpp
new file mode 100644
index 00000000..10787f21
--- /dev/null
+++ b/mpeglib/lib/mpegplay/pesSystemStream.cpp
@@ -0,0 +1,498 @@
+/*
+ demux pes mpeg stream
+ Copyright (C) 2001 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+
+#include "pesSystemStream.h"
+
+#include <iostream>
+
+using namespace std;
+
+PESSystemStream::PESSystemStream(InputStream* input) {
+ this->input=input;
+}
+
+
+PESSystemStream::~PESSystemStream() {
+}
+
+
+
+int PESSystemStream::getByteDirect() {
+ unsigned char byte;
+ if (input->read((char*)&byte,1) != 1) {
+ return -1;
+ }
+ bytes_read++;
+ return (int)byte;
+}
+
+int PESSystemStream::read(char* pointer,int bytes) {
+ if (input->read(pointer,bytes) != bytes) {
+ return false;
+ }
+ bytes_read+=bytes;
+
+ return true;
+}
+
+int PESSystemStream::processStartCode(unsigned int startCode,
+ MpegSystemHeader* mpegHeader) {
+ int lok=true;
+ bytes_read=4; // startcode
+ mpegHeader->setPacketLen(0);
+ mpegHeader->setPacketID(_PAKET_ID_NUKE);
+
+ // handle default
+ bytes_read=processPacket(startCode,mpegHeader);
+ return bytes_read;
+}
+
+
+/* Returns:
+ 0 - no error, but not video packet we want
+ -1 - error
+ >0 - length of packet
+*/
+int PESSystemStream::processPacket(unsigned int startCode,
+ MpegSystemHeader* mpegHeader) {
+
+ int ioBytes;
+ unsigned short packetLength;
+ int packetDataLength;
+
+ /* Leftovers from previous video packets */
+
+ int packetID=startCode & 0xff;
+ mpegHeader->setPacketID(packetID);
+ int lPacket=startCode & _PACKET_START_CODE_MASK &_PACKET_START_CODE_PREFIX;
+ if ((lPacket == false) || (packetID < 0xbc)) {
+ //printf("unknown startcode,packet or packetID:%8x\n",startCode);
+ return false;
+ }
+
+ if (packetID == _NOT_PACKET_ID) {
+ cout << "(vid_stream->mpegVideoStream)->makeEnd()"<<endl;
+ } else if (packetID==_KILL_BUFFER) {
+ printf("packetID==_KILL_BUFFER\n");
+ }
+
+ if (read((char*)&packetLength, 2) == false) return false;
+ packetLength = htons(packetLength);
+
+ mpegHeader->setPTSFlag(false);
+ mpegHeader->setPacketID(packetID);
+ mpegHeader->setPESPacketLen(packetLength);
+ switch (packetID>>4) {
+ case _PAKET_ID_AUDIO_1>>4:
+ case _PAKET_ID_AUDIO_2>>4:
+ case _PAKET_ID_VIDEO>>4:
+ break;
+ default:
+ switch(packetID) {
+ case _PRIVATE_STREAM_1_ID:
+ break;
+ default:
+ switch (packetID) {
+ case _PRIVATE_STREAM_2_ID:
+ case _PADDING_STREAM_ID:
+ case _RESERVED_STREAM_ID:
+ case _ECM_STREAM_ID:
+ case _EMM_STREAM_ID:
+ case _PROGRAM_STREAM_DIRECTORY_ID:
+ case _DSMCC_STREAM_ID:
+ case _ITUTRECH222TYPEE_STREAM_ID:
+ return bytes_read;
+ }
+ printf("\nUnknown packet type. (%x) at %ld\n",
+ packetID,input->getBytePosition());
+ return bytes_read;
+ }
+ }
+ // this is only processed if audio or video found
+
+ if (mpegHeader->getMPEG2()==false) {
+ packetDataLength = packetLength-processPacketHeader(mpegHeader);
+ } else {
+ int len=processMPEG2PacketHeader(mpegHeader);
+
+ if (len < 0) {
+ return false;
+ }
+ packetDataLength = packetLength-len;
+
+ // now check in private stream for AC3
+ if ( packetID == _PRIVATE_STREAM_1_ID ) {
+ packetDataLength = packetDataLength-processPrivateHeader(mpegHeader);
+ }
+ }
+
+ if (packetDataLength <= 0) {
+ if (mpegHeader->hasPSHeader()) return false;
+ // -> buggy TS stream
+ packetDataLength=0;
+ }
+ mpegHeader->setPESPacketLen(packetDataLength);
+
+ return bytes_read;
+
+}
+
+
+int PESSystemStream::processPrivateHeader(MpegSystemHeader* mpegHeader) {
+ char nukeBuffer[30];
+ int pos=0;
+ int one=getByteDirect();
+ pos++;
+ mpegHeader->setSubStreamID(one);
+ switch(one>>4) {
+ case _SUBSTREAM_AC3_ID>>4:
+ if (read(nukeBuffer,3) == false) return false;
+ mpegHeader->addAvailableLayer(one);
+ cout << "addAvailableLayer:"<<one<<endl;
+ pos+=3;
+ break;
+ case _SUBSTREAM_LPCM_ID>>4:
+ if (read(nukeBuffer,6) == false) return false;
+ pos+=6;
+ break;
+ case _SUBSTREAM_SUBPIC_ID>>4:
+ if (read(nukeBuffer,3) == false) return false;
+ pos+=3;
+ break;
+ default:
+ printf("unknown sub id :%8x\n",one);
+ }
+ return pos;
+
+}
+
+
+int PESSystemStream::processMPEG2PacketHeader(MpegSystemHeader* mpegHeader){
+
+ int stdCnt=0;
+ int pos=0;
+
+ // 1. Byte
+ /*
+ FROM FLASK:
+ int getbits(2);
+ encrypted = getbits(2); // PES_scrambling_control
+ getbits(4);
+ //LIVID
+ u_char original_or_copy : 1;
+ u_char copyright : 1;
+ u_char data_alignment_indicator : 1;
+ u_char pes_priority : 1;
+ u_char pes_scrambling_control : 2;
+ u_char start_code_prefix : 2; // 0x02
+
+ */
+ int first=getByteDirect();
+ stdCnt++;
+ mpegHeader->setOriginalOrCopy(first&(128)>>7);
+ mpegHeader->setCopyRight(first&(64)>>6);
+ mpegHeader->setDataAlignmentIndicator(first&(32)>>5);
+ mpegHeader->setPesPriority(first&(16)>>4);
+ mpegHeader->setEncrypted((first&(8+4))>>2);
+ mpegHeader->setStartCodePrefix(first&(1+2));
+
+
+ // 2. Byte
+ /*
+ PTS_DTS_flags = getbits(2);
+ ESCR_flag = get1bit();
+ ES_rate_flag = get1bit();
+ DSM_trick_mode_flag = get1bit();
+ additional_copy_info_flag = get1bit();
+ PES_CRC_flag = get1bit();
+ PES_extension_flag = get1bit();
+ */
+ int second=getByteDirect();
+ stdCnt++;
+
+ mpegHeader->setPTSDTSFlag((second&(128+64))>>6);
+ mpegHeader->setESCRFlag((second&(32))>>5);
+ mpegHeader->setES_RATE_Flag((second%(16))>>4);
+ mpegHeader->setDMSTRICKFLAG((second&(8))>>3);
+ mpegHeader->setADDITIONAL_COPY_FLAG((second&(4))>>2);
+ mpegHeader->setPES_CRC_FLAG((second&(2))>>1);
+ mpegHeader->setPES_EXT_FLAG(second&(1));
+
+
+ // 3. Byte
+ /*
+ PES_header_data_length = getbits(8);
+ */
+ int third=getByteDirect();
+ stdCnt++;
+ mpegHeader->setPES_HEADER_DATA_LENGTH(third);
+
+
+ //
+ // PARSING MPEG 2 HEADER FLAGS [START]
+ //
+ unsigned char nukeBuffer[300];
+
+ int PTS_DTS_flags=mpegHeader->getPTSDTSFlag();
+ if (PTS_DTS_flags == 0) {
+ mpegHeader->setPTSFlag(false);
+ } else {
+ mpegHeader->setPTSFlag(true);
+ }
+
+ if (PTS_DTS_flags > 0x1) {
+ if (read((char*)nukeBuffer,5) == false) return false;
+ double pts=GET_MPEG2_PTS(nukeBuffer);
+ pts=(pts*300.0)/(double)MPEG2_CLK_REF;
+ mpegHeader->setPTSTimeStamp(pts);
+ pos+=5;
+ }
+ if (PTS_DTS_flags > 0x2) {
+ if (read((char*)nukeBuffer,5) == false) return false;
+ double dts=GET_MPEG2_PTS(nukeBuffer);
+ mpegHeader->setDTSTimeStamp((dts*300.0)/(double)MPEG2_CLK_REF);
+ pos+=5;
+ }
+
+ int ESCRFlag=mpegHeader->getESCRFlag();
+ if (ESCRFlag == 1){
+ cout << "ESCRFlag == 1"<<endl;
+ if (read((char*)nukeBuffer,6) == false) return false;
+ pos+=6;
+ }
+
+ int ES_rate_flag=mpegHeader->getES_RATE_Flag();
+ if (ES_rate_flag == 1){
+ cout << "ES_rate_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,3) == false) return false;
+ pos+=3;
+ }
+
+ int DSM_trick_mode_flag=mpegHeader->getDMSTRICKFLAG();
+ if (DSM_trick_mode_flag == 1){
+ cout << "DSM_trick_mode_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,1) == false) return false;
+ pos++;
+ }
+
+ int additional_copy_info_flag=mpegHeader->getADDITIONAL_COPY_FLAG();
+ if (additional_copy_info_flag == 1) {
+ cout << "additional_copy_info_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,1) == false) return false;
+ pos++;
+ }
+
+ int PES_CRC_flag=mpegHeader->getPES_CRC_FLAG();
+ if (PES_CRC_flag == 1) {
+ cout << "PES_CRC_flag == 1"<<endl;
+ if (read((char*)nukeBuffer,2) == false) return false;
+ pos+=2;
+ }
+
+ //
+ // PES Extension [START]
+ //
+
+ int PES_extension_flag=mpegHeader->getPES_EXT_FLAG();
+ if (PES_extension_flag == 1) {
+ /*
+ FLASK:
+ PES_private_data_flag = get1bit();
+ pack_header_field_flag = get1bit();
+ program_packet_sequence_counter_flag = get1bit();
+ PSTD_buffer_flag = get1bit();
+ getbits(3);
+ PES_extension_flag_2 = get1bit();
+ */
+ int extensionByte=getByteDirect();
+
+ pos++;
+ mpegHeader->setPrivateDataFlag((extensionByte&(128))>>7);
+ mpegHeader->setPackHeaderFieldFlag((extensionByte&(64))>>6);
+ mpegHeader->setSequenceCounterFlag((extensionByte&(32))>>5);
+ mpegHeader->setSTDBufferFlag((extensionByte&(16))>>4);
+ mpegHeader->setPES_EXT_FLAG_2(extensionByte&(1));
+
+ int PES_private_data_flag=mpegHeader->getPrivateDataFlag();
+ if (PES_private_data_flag == 1) {
+ if (read((char*)nukeBuffer,128) == false) return false;
+ pos+=128;
+ }
+
+ int pack_header_field_flag=mpegHeader->getPackHeaderFieldFlag();
+ if (pack_header_field_flag == 1) {
+ printf("pack header field flag value not allowed in program streams\n");
+ return false;
+ }
+
+ int sequence_counter_flag=mpegHeader->getSequenceCounterFlag();
+ if (sequence_counter_flag==1) {
+ cout<<"sequence_counter_flag ==1"<<endl;
+ if (read((char*)nukeBuffer,2) == false) return false;
+ pos+=2;
+ }
+
+ int PSTD_buffer_flag=mpegHeader->getSTDBufferFlag();
+ if (PSTD_buffer_flag==1) {
+ if (read((char*)nukeBuffer,2) == false) return false;
+ pos+=2;
+ }
+
+ int PES_extension_flag_2=mpegHeader->getPES_EXT_FLAG_2();
+ if (PES_extension_flag_2 == 1) {
+ int extension2_byte=getByteDirect();
+ pos++;
+ mpegHeader->setPES_EXT_FIELD_LENGTH(extension2_byte&(254));
+
+
+ int PES_field_length=mpegHeader->getPES_EXT_FIELD_LENGTH();
+ int j;
+ for (j=0;j<PES_field_length ; j++) {
+ cout << "PES_field_length (nuke)"<<endl;
+ getByteDirect();
+ pos++;
+ }
+ }
+ }
+ //
+ // PES Extension [END]
+ //
+
+ // now nuke remaining bytes from PES DATA Length
+ int PES_HEADER_DATA_LENGTH=mpegHeader->getPES_HEADER_DATA_LENGTH();
+ int tmp=PES_HEADER_DATA_LENGTH-pos;
+ if (tmp>0) {
+ if (read((char*)nukeBuffer,tmp) == false) return false;
+ pos+=tmp;
+ }
+
+
+
+
+
+ //
+ // PARSING MPEG 2 HEADER FLAGS [START]
+ //
+
+ int parsed=stdCnt+pos;
+ return parsed;
+
+}
+
+
+int PESSystemStream::processPacketHeader(MpegSystemHeader* mpegHeader) {
+ unsigned char nextByte;
+ int pos;
+ int val;
+ unsigned char scratch[10];
+
+
+ nextByte=getByteDirect();
+
+ mpegHeader->setPTSFlag(false);
+
+ pos = 1;
+ while (nextByte & 0x80) {
+ ++pos;
+ val=getByteDirect();
+ if (val == -1) return false;
+ scratch[0]=val;
+
+ nextByte=scratch[0];
+ }
+ if ((nextByte >> 6) == 0x01) {
+ pos += 2;
+ scratch[1]=getByteDirect();
+ scratch[2]=getByteDirect();
+ nextByte=scratch[2];
+ }
+ if ((nextByte >> 4) == 0x02) {
+ scratch[0] = nextByte;
+ if (read((char*)&scratch[1],4) == false) return false;
+ /* presentation time stamps */
+ unsigned char hiBit;
+ unsigned long low4Bytes;
+ double ptsTimeStamp;
+ double dtsTimeStamp=0.0;
+ readTimeStamp((unsigned char*)scratch,&hiBit,&low4Bytes);
+ makeClockTime(hiBit,low4Bytes,&ptsTimeStamp);
+ mpegHeader->setPTSFlag(true);
+ mpegHeader->setPTSTimeStamp(ptsTimeStamp);
+ mpegHeader->setDTSTimeStamp(dtsTimeStamp);
+
+ pos += 4;
+ }
+ else if ((nextByte >> 4) == 0x03) {
+ scratch[0] = nextByte;
+ if (read((char*)&scratch[1],9) == false) return false;
+ /* presentation and decoding time stamps */
+ unsigned char hiBit;
+ unsigned long low4Bytes;
+ double ptsTimeStamp;
+ double dtsTimeStamp;
+ readTimeStamp((unsigned char*)scratch,&hiBit,&low4Bytes);
+ makeClockTime(hiBit,low4Bytes,&ptsTimeStamp);
+
+ readTimeStamp((unsigned char*)&(scratch[5]),&hiBit,&low4Bytes);
+ makeClockTime(hiBit,low4Bytes,&dtsTimeStamp);
+ mpegHeader->setPTSFlag(true);
+ mpegHeader->setPTSTimeStamp(ptsTimeStamp);
+ mpegHeader->setDTSTimeStamp(dtsTimeStamp);
+
+ pos += 9;
+ }
+ return pos;
+}
+
+
+
+void PESSystemStream::readTimeStamp(unsigned char* inputBuffer,
+ unsigned char* hiBit,
+ unsigned long* low4Bytes) {
+ *hiBit = ((unsigned long)inputBuffer[0] >> 3) & 0x01;
+ *low4Bytes = (((unsigned long)inputBuffer[0] >> 1) & 0x03) << 30;
+ *low4Bytes |= (unsigned long)inputBuffer[1] << 22;
+ *low4Bytes |= ((unsigned long)inputBuffer[2] >> 1) << 15;
+ *low4Bytes |= (unsigned long)inputBuffer[3] << 7;
+ *low4Bytes |= ((unsigned long)inputBuffer[4]) >> 1;
+}
+
+
+void PESSystemStream::readSTD(unsigned char* inputBuffer,
+ MpegSystemHeader* mpegHeader) {
+ int stdBufferScale;
+ unsigned long stdBufferSize;
+ stdBufferScale = ((int)(inputBuffer[0] & 0x20) >> 5);
+ stdBufferSize = ((unsigned long)inputBuffer[0] & 0x1f) << 8;
+ stdBufferSize |= (unsigned long)inputBuffer[1];
+ mpegHeader->setStdBufferScale(stdBufferScale);
+ mpegHeader->setStdBufferSize(stdBufferSize);
+}
+
+
+int PESSystemStream::makeClockTime(unsigned char hiBit,
+ unsigned long low4Bytes,
+ double * clockTime) {
+ if (hiBit != 0 && hiBit != 1) {
+ *clockTime = 0.0;
+ return 1;
+ }
+ *clockTime = (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes;
+ *clockTime /= (double)_STD_SYSTEM_CLOCK_FREQ;
+ return 0;
+}
+
+
+
+