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

📄 mpeg2indexfromtransportstream.cpp

📁 H.264 RTSP 串流(live 555)視窗版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  u_int16_t section_length = ((pkt[2]&0x0F)<<8) | pkt[3];  if ((unsigned)(4+section_length) < size) size = (4+section_length);  // Then, skip any descriptors following the "program_info_length":  if (size < 22) return; // not enough data  unsigned program_info_length = ((pkt[11]&0x0F)<<8) | pkt[12];  pkt += 13; size -= 13;  if (size < program_info_length) return; // not enough data  pkt += program_info_length; size -= program_info_length;  // Look at each ("stream_type","elementary_PID") pair, looking for a video stream  // ("stream_type" == 1 or 2):  while (size >= 9) {    u_int8_t stream_type = pkt[0];    u_int16_t elementary_PID = ((pkt[1]&0x1F)<<8) | pkt[2];    if (stream_type == 1 || stream_type == 2) {      fVideo_PID = elementary_PID;      return;    }    u_int16_t ES_info_length = ((pkt[3]&0x0F)<<8) | pkt[4];    pkt += 5; size -= 5;    if (size < ES_info_length) return; // not enough data    pkt += ES_info_length; size -= ES_info_length;  }}Boolean MPEG2IFrameIndexFromTransportStream::deliverIndexRecord() {  IndexRecord* head = fHeadIndexRecord;  if (head == NULL) return False;  // Check whether the head record has been parsed yet:  if (head->recordType() == RECORD_UNPARSED) return False;  // Remove the head record (the one whose data we'll be delivering):  IndexRecord* next = head->next();  head->unlink();  if (next == head) {    fHeadIndexRecord = fTailIndexRecord = NULL;  } else {    fHeadIndexRecord = next;  }  if (head->recordType() == RECORD_JUNK) {    // Don't actually deliver the data to the client:    delete head;    return True;  }  // Deliver data from the head record:#ifdef DEBUG  envir() << "delivering: " << *head << "\n";#endif  if (fMaxSize < 11) {    fFrameSize = 0;  } else {    fTo[0] = (u_int8_t)(head->recordType());    fTo[1] = head->startOffset();    fTo[2] = head->size();    // Deliver the PCR, as 24 bits (integer part; little endian) + 8 bits (fractional part)    float pcr = head->pcr();    unsigned pcr_int = (unsigned)pcr;    u_int8_t pcr_frac = (u_int8_t)(256*(pcr-pcr_int));    fTo[3] = (unsigned char)(pcr_int);    fTo[4] = (unsigned char)(pcr_int>>8);    fTo[5] = (unsigned char)(pcr_int>>16);    fTo[6] = (unsigned char)(pcr_frac);    // Deliver the transport packet number (in little-endian order):    unsigned long tpn = head->transportPacketNumber();    fTo[7] = (unsigned char)(tpn);    fTo[8] = (unsigned char)(tpn>>8);    fTo[9] = (unsigned char)(tpn>>16);    fTo[10] = (unsigned char)(tpn>>24);    fFrameSize = 11;  }  // Free the (former) head record (as we're now done with it):  delete head;  // Complete delivery to the client:  afterGetting(this);  return True;}Boolean MPEG2IFrameIndexFromTransportStream::parseFrame() {  // At this point, we have a queue of >=0 (unparsed) index records, representing  // the data in the parse buffer from "fParseBufferFrameStart"  // to "fParseBufferDataEnd".  We now parse through this data, looking for  // a complete 'frame' (where a 'frame', in this case, means  // a Video Sequence Header, GOP Header, Picture Header, or Slice).  // Inspect the frame's initial 4-byte code, to make sure it starts with a system code:  if (fParseBufferDataEnd-fParseBufferFrameStart < 4) return False; // not enough data  unsigned numInitialBadBytes = 0;  unsigned char const* p = &fParseBuffer[fParseBufferFrameStart];  if (!(p[0] == 0 && p[1] == 0 && p[2] == 1)) {    // There's no system code at the beginning.  Parse until we find one:    if (fParseBufferParseEnd == fParseBufferFrameStart + 4) {      // Start parsing from the beginning of the frame data:      fParseBufferParseEnd = fParseBufferFrameStart;    }    unsigned char nextCode;    if (!parseToNextCode(nextCode)) return False;    numInitialBadBytes = fParseBufferParseEnd - fParseBufferFrameStart;    //fprintf(stderr, "#####numInitialBadBytes: 0x%x\n", numInitialBadBytes);    fParseBufferFrameStart = fParseBufferParseEnd;    fParseBufferParseEnd += 4; // skip over the code that we just saw    p = &fParseBuffer[fParseBufferFrameStart];  }  unsigned char curCode = p[3];  RecordType curRecordType;  unsigned char nextCode;  switch (curCode) {  case VIDEO_SEQUENCE_START_CODE:  case VISUAL_OBJECT_SEQUENCE_START_CODE: {    curRecordType = RECORD_VSH;    while (1) {      if (!parseToNextCode(nextCode)) return False;      if (nextCode == GROUP_START_CODE || /*nextCode == GROUP_VOP_START_CODE ||*/	  nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;      fParseBufferParseEnd += 4; // skip over the code that we just saw    }    break;  }  case GROUP_START_CODE:    /*case GROUP_VOP_START_CODE:*/ {    curRecordType = RECORD_GOP;    while (1) {      if (!parseToNextCode(nextCode)) return False;      if (nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;      fParseBufferParseEnd += 4; // skip over the code that we just saw    }    break;  }  default: { // picture (including slices)    curRecordType = RECORD_PIC_NON_IFRAME; // may get changed to IFRAME later    while (1) {      if (!parseToNextCode(nextCode)) return False;      if (nextCode == VIDEO_SEQUENCE_START_CODE || nextCode == VISUAL_OBJECT_SEQUENCE_START_CODE ||	  nextCode == GROUP_START_CODE || nextCode == GROUP_VOP_START_CODE ||	  nextCode == PICTURE_START_CODE || nextCode == VOP_START_CODE) break;      fParseBufferParseEnd += 4; // skip over the code that we just saw    }    break;  }  }  if (curRecordType == RECORD_PIC_NON_IFRAME) {    if (curCode == VOP_START_CODE) { // MPEG-4      //fprintf(stderr, "#####parseFrame()1(4): 0x%x, 0x%x\n", curCode, fParseBuffer[fParseBufferFrameStart+4]&0xC0);      if ((fParseBuffer[fParseBufferFrameStart+4]&0xC0) == 0) {	// This is actually an I-frame.  Note it as such:	curRecordType = RECORD_PIC_IFRAME;      }    } else { // MPEG-1 or 2      //fprintf(stderr, "#####parseFrame()1(!4): 0x%x, 0x%x\n", curCode, fParseBuffer[fParseBufferFrameStart+5]&0x38);      if ((fParseBuffer[fParseBufferFrameStart+5]&0x38) == 0x08) {	// This is actually an I-frame.  Note it as such:	curRecordType = RECORD_PIC_IFRAME;      }    }  }  // There is now a parsed 'frame', from "fParseBufferFrameStart"  // to "fParseBufferParseEnd". Tag the corresponding index records to note this:  unsigned frameSize = fParseBufferParseEnd - fParseBufferFrameStart + numInitialBadBytes;#ifdef DEBUG  envir() << "parsed " << recordTypeStr[curRecordType] << "; length "	  << frameSize << "\n";#endif  for (IndexRecord* r = fHeadIndexRecord; ; r = r->next()) {    if (numInitialBadBytes >= r->size()) {      r->recordType() = RECORD_JUNK;      numInitialBadBytes -= r->size();    } else {      r->recordType() = curRecordType;    }    if (r == fHeadIndexRecord) r->setFirstFlag();    // indicates that this is the first record for this frame    if (r->size() > frameSize) {      // This record contains extra data that's not part of the frame.      // Shorten this record, and move the extra data to a new record      // that comes afterwards:      u_int8_t newOffset = r->startOffset() + frameSize;      u_int8_t newSize = r->size() - frameSize;      r->size() = frameSize;#ifdef DEBUG      envir() << "tagged record (modified): " << *r << "\n";#endif      IndexRecord* newRecord	= new IndexRecord(newOffset, newSize, r->transportPacketNumber(), r->pcr());      newRecord->addAfter(r);      if (fTailIndexRecord == r) fTailIndexRecord = newRecord;#ifdef DEBUG      envir() << "added extra record: " << *newRecord << "\n";#endif    } else {#ifdef DEBUG      envir() << "tagged record: " << *r << "\n";#endif    }    frameSize -= r->size();    if (frameSize == 0) break;    if (r == fTailIndexRecord) { // this shouldn't happen      envir() << "!!!!!Internal consistency error!!!!!\n";      return False;    }  }  // Finally, update our parse state (to skip over the now-parsed data):  fParseBufferFrameStart = fParseBufferParseEnd;  fParseBufferParseEnd += 4; // to skip over the next code (that we found)  return True;}Boolean MPEG2IFrameIndexFromTransportStream::parseToNextCode(unsigned char& nextCode) {  unsigned char const* p = &fParseBuffer[fParseBufferParseEnd];  unsigned char const* end = &fParseBuffer[fParseBufferDataEnd];  while (p <= end-4) {    if (p[2] > 1) p += 3; // common case (optimized)    else if (p[2] == 0) ++p;    else if (p[0] == 0 && p[1] == 0) { // && p[2] == 1      // We found a code here:      nextCode = p[3];      fParseBufferParseEnd = p - &fParseBuffer[0]; // where we've gotten to      return True;    } else p += 3;  }  fParseBufferParseEnd = p - &fParseBuffer[0]; // where we've gotten to  return False; // no luck this time}void MPEG2IFrameIndexFromTransportStream::compactParseBuffer() {#ifdef DEBUG  envir() << "Compacting parse buffer: [" << fParseBufferFrameStart	  << "," << fParseBufferParseEnd << "," << fParseBufferDataEnd << "]";#endif  memmove(&fParseBuffer[0], &fParseBuffer[fParseBufferFrameStart],	  fParseBufferDataEnd - fParseBufferFrameStart);  fParseBufferDataEnd -= fParseBufferFrameStart;  fParseBufferParseEnd -= fParseBufferFrameStart;  fParseBufferFrameStart = 0;#ifdef DEBUG  envir() << "-> [" << fParseBufferFrameStart	  << "," << fParseBufferParseEnd << "," << fParseBufferDataEnd << "]\n";#endif}void MPEG2IFrameIndexFromTransportStream::addToTail(IndexRecord* newIndexRecord) {#ifdef DEBUG  envir() << "adding new: " << *newIndexRecord << "\n";#endif  if (fTailIndexRecord == NULL) {    fHeadIndexRecord = fTailIndexRecord = newIndexRecord;  } else {    newIndexRecord->addAfter(fTailIndexRecord);    fTailIndexRecord = newIndexRecord;  }}////////// IndexRecord implementation //////////IndexRecord::IndexRecord(u_int8_t startOffset, u_int8_t size,			 unsigned long transportPacketNumber, float pcr)  : fNext(this), fPrev(this), fRecordType(RECORD_UNPARSED),    fStartOffset(startOffset), fSize(size),    fPCR(pcr), fTransportPacketNumber(transportPacketNumber) {}IndexRecord::~IndexRecord() {  IndexRecord* nextRecord = next();  unlink();  if (nextRecord != this) delete nextRecord;}void IndexRecord::addAfter(IndexRecord* prev) {  fNext = prev->fNext;  fPrev = prev;  prev->fNext->fPrev = this;  prev->fNext = this;}void IndexRecord::unlink() {  fNext->fPrev = fPrev;  fPrev->fNext = fNext;  fNext = fPrev = this;}

⌨️ 快捷键说明

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