⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg1or2demux.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
void MPEGProgramStreamParser::parsePackHeader() {#ifdef DEBUG  fprintf(stderr, "parsing pack header\n"); fflush(stderr);#endif  unsigned first4Bytes;  while (1) {    first4Bytes = test4Bytes();    // We're supposed to have a pack header here, but check also for    // a system header or a PES packet, just in case:    if (first4Bytes == PACK_START_CODE) {      skipBytes(4);      break;    } else if (first4Bytes == SYSTEM_HEADER_START_CODE) {#ifdef DEBUG      fprintf(stderr, "found system header instead of pack header\n");#endif      setParseState(PARSING_SYSTEM_HEADER);      return;    } else if (isPacketStartCode(first4Bytes)) {#ifdef DEBUG      fprintf(stderr, "found packet start code 0x%02x instead of pack header\n", first4Bytes);#endif      setParseState(PARSING_PES_PACKET);      return;    }    setParseState(PARSING_PACK_HEADER); // ensures we progress over bad data    if ((first4Bytes&0xFF) > 1) { // a system code definitely doesn't start here      skipBytes(4);    } else {      skipBytes(1);    }  }    // The size of the pack header differs depending on whether it's  // MPEG-1 or MPEG-2.  The next byte tells us this:   unsigned char nextByte = get1Byte();  MPEG1or2Demux::SCR& scr = fUsingSource->fLastSeenSCR; // alias  if ((nextByte&0xF0) == 0x20) { // MPEG-1    fUsingSource->fMPEGversion = 1;    scr.highBit =  (nextByte&0x08)>>3;    scr.remainingBits = (nextByte&0x06)<<29;    unsigned next4Bytes = get4Bytes();    scr.remainingBits |= (next4Bytes&0xFFFE0000)>>2;    scr.remainingBits |= (next4Bytes&0x0000FFFE)>>1;    scr.extension = 0;    scr.isValid = True;    skipBits(24);#if defined(DEBUG_TIMESTAMPS) || defined(DEBUG_SCR_TIMESTAMPS)    fprintf(stderr, "pack hdr system_clock_reference_base: 0x%x",	    scr.highBit);    fprintf(stderr, "%08x\n", scr.remainingBits);#endif  } else if ((nextByte&0xC0) == 0x40) { // MPEG-2    fUsingSource->fMPEGversion = 2;    scr.highBit =  (nextByte&0x20)>>5;    scr.remainingBits = (nextByte&0x18)<<27;    scr.remainingBits |= (nextByte&0x03)<<28;    unsigned next4Bytes = get4Bytes();    scr.remainingBits |= (next4Bytes&0xFFF80000)>>4;    scr.remainingBits |= (next4Bytes&0x0003FFF8)>>3;    scr.extension = (next4Bytes&0x00000003)<<7;    next4Bytes = get4Bytes();    scr.extension |= (next4Bytes&0xFE000000)>>25;    scr.isValid = True;    skipBits(5);#if defined(DEBUG_TIMESTAMPS) || defined(DEBUG_SCR_TIMESTAMPS)    fprintf(stderr, "pack hdr system_clock_reference_base: 0x%x",	    scr.highBit);    fprintf(stderr, "%08x\n", scr.remainingBits);    fprintf(stderr, "pack hdr system_clock_reference_extension: 0x%03x\n",	    scr.extension);#endif    unsigned char pack_stuffing_length = getBits(3);    skipBytes(pack_stuffing_length);  } else { // unknown    fUsingSource->envir() << "StreamParser::parsePack() saw strange byte "			  << (void*)nextByte			  << " following pack_start_code\n";  }    // Check for a System Header next:  setParseState(PARSING_SYSTEM_HEADER);}  void MPEGProgramStreamParser::parseSystemHeader() {#ifdef DEBUG  fprintf(stderr, "parsing system header\n"); fflush(stderr);#endif  unsigned next4Bytes = test4Bytes();  if (next4Bytes != SYSTEM_HEADER_START_CODE) {    // The system header was optional.  Look for a PES Packet instead:    setParseState(PARSING_PES_PACKET);    return;  }  #ifdef DEBUG  fprintf(stderr, "saw system_header_start_code\n"); fflush(stderr);#endif  skipBytes(4); // we've already seen the system_header_start_code    unsigned short remaining_header_length = get2Bytes();    // According to the MPEG-1 and MPEG-2 specs, "remaining_header_length" should be  // at least 6 bytes.  Check this now:  if (remaining_header_length < 6) {    fUsingSource->envir() << "StreamParser::parseSystemHeader(): saw strange header_length: "			  << remaining_header_length << " < 6\n";  }  skipBytes(remaining_header_length);    // Check for a PES Packet next:  setParseState(PARSING_PES_PACKET);}#define private_stream_1 0xBD#define private_stream_2 0xBF// A test for stream ids that are exempt from normal PES packet header parsingBoolean MPEGProgramStreamParser::isSpecialStreamId(unsigned char stream_id) const {  if (stream_id == RAW_PES) return True; // hack  if (fUsingSource->fMPEGversion == 1) {    return stream_id == private_stream_2;  } else { // assume MPEG-2    if (stream_id <= private_stream_2) {      return stream_id != private_stream_1;    } else if ((stream_id&0xF0) == 0xF0) {      unsigned char lower4Bits = stream_id&0x0F;      return lower4Bits <= 2 || lower4Bits == 0x8 || lower4Bits == 0xF;    } else {      return False;    }  }}#define READER_NOT_READY 2 unsigned char MPEGProgramStreamParser::parsePESPacket() {#ifdef DEBUG  fprintf(stderr, "parsing PES packet\n"); fflush(stderr);#endif  unsigned next4Bytes = test4Bytes();  if (!isPacketStartCode(next4Bytes)) {    // The PES Packet was optional.  Look for a Pack Header instead:    setParseState(PARSING_PACK_HEADER);    return 0;  }  #ifdef DEBUG  fprintf(stderr, "saw packet_start_code_prefix\n"); fflush(stderr);#endif  skipBytes(3); // we've already seen the packet_start_code_prefix  unsigned char stream_id = get1Byte();#if defined(DEBUG) || defined(DEBUG_TIMESTAMPS)  unsigned char streamNum = stream_id;  char* streamTypeStr;  if ((stream_id&0xE0) == 0xC0) {    streamTypeStr = "audio";    streamNum = stream_id&~0xE0;  } else if ((stream_id&0xF0) == 0xE0) {    streamTypeStr = "video";    streamNum = stream_id&~0xF0;  } else if (stream_id == 0xbc) {    streamTypeStr = "reserved";  } else if (stream_id == 0xbd) {    streamTypeStr = "private_1";  } else if (stream_id == 0xbe) {    streamTypeStr = "padding";  } else if (stream_id == 0xbf) {    streamTypeStr = "private_2";  } else {    streamTypeStr = "unknown";  }#endif#ifdef DEBUG  static unsigned frameCount = 1;  fprintf(stderr, "%d, saw %s stream: 0x%02x\n", frameCount, streamTypeStr, streamNum); fflush(stderr);#endif    unsigned short PES_packet_length = get2Bytes();#ifdef DEBUG  fprintf(stderr, "PES_packet_length: %d\n", PES_packet_length); fflush(stderr);#endif  // Parse over the rest of the header, until we get to the packet data itself.  // This varies depending upon the MPEG version:  if (fUsingSource->fOutput[RAW_PES].isPotentiallyReadable) {    // Hack: We've been asked to return raw PES packets, for every stream:    stream_id = RAW_PES;  }   unsigned savedParserOffset = curOffset();#ifdef DEBUG_TIMESTAMPS  unsigned char pts_highBit = 0;  unsigned pts_remainingBits = 0;  unsigned char dts_highBit = 0;  unsigned dts_remainingBits = 0;#endif  if (fUsingSource->fMPEGversion == 1) {    if (!isSpecialStreamId(stream_id)) {      unsigned char nextByte;      while ((nextByte = get1Byte()) == 0xFF) { // stuffing_byte      }      if ((nextByte&0xC0) == 0x40) { // '01'	skipBytes(1);	nextByte = get1Byte();      }      if ((nextByte&0xF0) == 0x20) { // '0010'#ifdef DEBUG_TIMESTAMPS	pts_highBit =  (nextByte&0x08)>>3;	pts_remainingBits = (nextByte&0x06)<<29;	unsigned next4Bytes = get4Bytes();	pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;	pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;#else	skipBytes(4);#endif      } else if ((nextByte&0xF0) == 0x30) { // '0011'#ifdef DEBUG_TIMESTAMPS	pts_highBit =  (nextByte&0x08)>>3;	pts_remainingBits = (nextByte&0x06)<<29;	unsigned next4Bytes = get4Bytes();	pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;	pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;	nextByte = get1Byte();	dts_highBit =  (nextByte&0x08)>>3;	dts_remainingBits = (nextByte&0x06)<<29;	next4Bytes = get4Bytes();	dts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;	dts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;#else	skipBytes(9);#endif      }    }  } else { // assume MPEG-2    if (!isSpecialStreamId(stream_id)) {      // Fields in the next 3 bytes determine the size of the rest:      unsigned next3Bytes = getBits(24);#ifdef DEBUG_TIMESTAMPS      unsigned char PTS_DTS_flags       = (next3Bytes&0x00C000)>>14;#endif#ifdef undef      unsigned char ESCR_flag           = (next3Bytes&0x002000)>>13;      unsigned char ES_rate_flag        = (next3Bytes&0x001000)>>12;      unsigned char DSM_trick_mode_flag = (next3Bytes&0x000800)>>11;#endif      unsigned char PES_header_data_length = (next3Bytes&0x0000FF);#ifdef DEBUG      fprintf(stderr, "PES_header_data_length: 0x%02x\n", PES_header_data_length); fflush(stderr);#endif#ifdef DEBUG_TIMESTAMPS      if (PTS_DTS_flags == 0x2 && PES_header_data_length >= 5) {	unsigned char nextByte = get1Byte();	pts_highBit =  (nextByte&0x08)>>3;	pts_remainingBits = (nextByte&0x06)<<29;	unsigned next4Bytes = get4Bytes();	pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;	pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;	skipBytes(PES_header_data_length-5);      } else if (PTS_DTS_flags == 0x3 && PES_header_data_length >= 10) {	unsigned char nextByte = get1Byte();	pts_highBit =  (nextByte&0x08)>>3;	pts_remainingBits = (nextByte&0x06)<<29;	unsigned next4Bytes = get4Bytes();	pts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;	pts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;	nextByte = get1Byte();	dts_highBit =  (nextByte&0x08)>>3;	dts_remainingBits = (nextByte&0x06)<<29;	next4Bytes = get4Bytes();	dts_remainingBits |= (next4Bytes&0xFFFE0000)>>2;	dts_remainingBits |= (next4Bytes&0x0000FFFE)>>1;	skipBytes(PES_header_data_length-10);      }#else      skipBytes(PES_header_data_length);#endif    }  }#ifdef DEBUG_TIMESTAMPS  fprintf(stderr, "%s stream, ", streamTypeStr);  fprintf(stderr, "packet presentation_time_stamp: 0x%x", pts_highBit);  fprintf(stderr, "%08x\n", pts_remainingBits);  fprintf(stderr, "\t\tpacket decoding_time_stamp: 0x%x", dts_highBit);  fprintf(stderr, "%08x\n", dts_remainingBits);#endif  // The rest of the packet will be the "PES_packet_data_byte"s  // Make sure that "PES_packet_length" was consistent with where we are now:  unsigned char acquiredStreamIdTag = 0;  unsigned currentParserOffset = curOffset();  unsigned bytesSkipped = currentParserOffset - savedParserOffset;  if (stream_id == RAW_PES) {    restoreSavedParserState(); // so we deliver from the beginning of the PES packet    PES_packet_length += 6; // to include the whole of the PES packet    bytesSkipped = 0;  }  if (PES_packet_length < bytesSkipped) {    fUsingSource->envir() << "StreamParser::parsePESPacket(): saw inconsistent PES_packet_length "			  << PES_packet_length << " < "			  << bytesSkipped << "\n";  } else {    PES_packet_length -= bytesSkipped;#ifdef DEBUG    unsigned next4Bytes = test4Bytes(); #endif    // Check whether our using source is interested in this stream type.    // If so, deliver the frame to him:    MPEG1or2Demux::OutputDescriptor_t& out = fUsingSource->fOutput[stream_id];     if (out.isCurrentlyAwaitingData) {      unsigned numBytesToCopy;      if (PES_packet_length > out.maxSize) {	fUsingSource->envir() << "MPEGProgramStreamParser::parsePESPacket() error: PES_packet_length ("			      << PES_packet_length			      << ") exceeds max frame size asked for ("			      << out.maxSize << ")\n";	numBytesToCopy = out.maxSize;      } else {	numBytesToCopy = PES_packet_length;      }      getBytes(out.to, numBytesToCopy);      out.frameSize = numBytesToCopy;#ifdef DEBUG      fprintf(stderr, "%d, %d bytes of PES_packet_data (out.maxSize: %d); first 4 bytes: 0x%08x\n", frameCount, numBytesToCopy, out.maxSize, next4Bytes); fflush(stderr);#endif      // set out.presentationTime later #####      acquiredStreamIdTag = stream_id;      PES_packet_length -= numBytesToCopy;    } else if (out.isCurrentlyActive) {      // Someone has been reading this stream, but isn't right now.      // We can't deliver this frame until he asks for it, so punt for now.      // The next time he asks for a frame, he'll get it.#ifdef DEBUG      fprintf(stderr, "%d, currently undeliverable PES data; first 4 bytes: 0x%08x - currently undeliverable!\n", frameCount, next4Bytes); fflush(stderr);#endif      restoreSavedParserState(); // so we read from the beginning next time      fUsingSource->fHaveUndeliveredData = True;      throw READER_NOT_READY;    } else if (out.isPotentiallyReadable &&	       out.savedDataTotalSize + PES_packet_length < 1000000 /*limit*/) {      // Someone is interested in this stream, but hasn't begun reading it yet.      // Save this data, so that the reader will get it when he later asks for it.      unsigned char* buf = new unsigned char[PES_packet_length];      getBytes(buf, PES_packet_length);      MPEG1or2Demux::OutputDescriptor::SavedData* savedData	= new MPEG1or2Demux::OutputDescriptor::SavedData(buf, PES_packet_length);      if (out.savedDataHead == NULL) {	out.savedDataHead = out.savedDataTail = savedData;      } else {	out.savedDataTail->next = savedData;	out.savedDataTail = savedData;      }      out.savedDataTotalSize += PES_packet_length;      PES_packet_length = 0;    }    skipBytes(PES_packet_length);  }  // Check for another PES Packet next:  setParseState(PARSING_PES_PACKET);#ifdef DEBUG  ++frameCount;#endif return acquiredStreamIdTag;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -