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

📄 mp3adu.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	packetIsLost = (our_random()%10 == 0); // simulate 10% packet loss #####      }      if (packetIsLost) {	// Read and discard the next input frame (that would be part of	// a lost packet):	Segment dummySegment;	unsigned numBytesRead;	struct timeval presentationTime;	// (this works only if the source can be read synchronously)	fInputSource->syncGetNextFrame(dummySegment.buf,				       sizeof dummySegment.buf, numBytesRead,				       presentationTime);      } else {	break; // from while (1)      }    }#endif    fAreEnqueueingADU = True;    fSegments->enqueueNewSegment(fInputSource, this);  } else {    // Return a frame now:    generateFrameFromHeadADU();        // sets fFrameSize, fPresentationTime, and fDurationInMicroseconds    // Call our own 'after getting' function.  Because we're not a 'leaf'    // source, we can call this directly, without risking infinite recursion.    afterGetting(this);  }}Boolean MP3FromADUSource::needToGetAnADU() {  // Check whether we need to first enqueue a new ADU before we  // can generate a frame for our head ADU.  Boolean needToEnqueue = True;  if (!fSegments->isEmpty()) {    unsigned index = fSegments->headIndex();    Segment* seg = &(fSegments->headSegment());    int const endOfHeadFrame = (int) seg->dataHere();    unsigned frameOffset = 0;        while (1) {      int endOfData = frameOffset - seg->backpointer + seg->aduSize;      if (endOfData >= endOfHeadFrame) {	// We already have enough data to generate a frame	needToEnqueue = False;	break;      }            frameOffset += seg->dataHere();      index = SegmentQueue::nextIndex(index);      if (index == fSegments->nextFreeIndex()) break;      seg = &(fSegments->s[index]);    }  }    return needToEnqueue;}void MP3FromADUSource::insertDummyADUsIfNecessary() {  if (fSegments->isEmpty()) return; // shouldn't happen  // The tail segment (ADU) is assumed to have been recently  // enqueued.  If its backpointer would overlap the data  // of the previous ADU, then we need to insert one or more  // empty, 'dummy' ADUs ahead of it.  (This situation should occur  // only if an intermediate ADU was lost.)    unsigned tailIndex    = SegmentQueue::prevIndex(fSegments->nextFreeIndex());  Segment* tailSeg = &(fSegments->s[tailIndex]);    while (1) {    unsigned prevADUend; // relative to the start of the new ADU    if (fSegments->headIndex() != tailIndex) {      // there is a previous segment      unsigned prevIndex = SegmentQueue::prevIndex(tailIndex);      Segment& prevSegment = fSegments->s[prevIndex];      prevADUend = prevSegment.dataHere() + prevSegment.backpointer;      if (prevSegment.aduSize > prevADUend) {	// shouldn't happen if the previous ADU was well-formed	prevADUend = 0;      } else {	prevADUend -= prevSegment.aduSize;      }    } else {      prevADUend = 0;    }        if (tailSeg->backpointer > prevADUend) {      // We need to insert a dummy ADU in front of the tail#ifdef DEBUG      fprintf(stderr, "a->m:need to insert a dummy ADU (%d, %d, %d) [%d, %d]\n", tailSeg->backpointer, prevADUend, tailSeg->dataHere(), fSegments->headIndex(), fSegments->nextFreeIndex());#endif      tailIndex = fSegments->nextFreeIndex();      if (!fSegments->insertDummyBeforeTail(prevADUend)) return;      tailSeg = &(fSegments->s[tailIndex]);    } else {      break; // no more dummy ADUs need to be inserted    }  }}Boolean MP3FromADUSource::generateFrameFromHeadADU() {    // Output a frame for the head ADU:    if (fSegments->isEmpty()) return False;    unsigned index = fSegments->headIndex();    Segment* seg = &(fSegments->headSegment());#ifdef DEBUG    fprintf(stderr, "a->m:outputting frame for %d<-%d (fs %d, dh %d), (descriptorSize: %d)\n", seg->aduSize, seg->backpointer, seg->frameSize, seg->dataHere(), seg->descriptorSize);#endif    unsigned char* toPtr = fTo;        // output header and side info:    fFrameSize = seg->frameSize;    fPresentationTime = seg->presentationTime;    fDurationInMicroseconds = seg->durationInMicroseconds;    memmove(toPtr, seg->dataStart(), seg->headerSize + seg->sideInfoSize);    toPtr += seg->headerSize + seg->sideInfoSize;        // zero out the rest of the frame, in case ADU data doesn't fill it all in    unsigned bytesToZero = seg->dataHere();     for (unsigned i = 0; i < bytesToZero; ++i) {      toPtr[i] = '\0';    }        // Fill in the frame with appropriate ADU data from this and    // subsequent ADUs:    unsigned frameOffset = 0;    unsigned toOffset = 0;    unsigned const endOfHeadFrame = seg->dataHere();    while (toOffset < endOfHeadFrame) {      int startOfData = frameOffset - seg->backpointer;      if (startOfData > (int)endOfHeadFrame) break; // no more ADUs needed            int endOfData = startOfData + seg->aduSize;      if (endOfData > (int)endOfHeadFrame) {	endOfData = endOfHeadFrame;      }            unsigned fromOffset;      if (startOfData <= (int)toOffset) {	fromOffset = toOffset - startOfData;	startOfData = toOffset;	if (endOfData < startOfData) endOfData = startOfData;      } else {	fromOffset = 0;		// we may need some padding bytes beforehand	unsigned bytesToZero = startOfData - toOffset;#ifdef DEBUG	if (bytesToZero > 0) fprintf(stderr, "a->m:outputting %d zero bytes (%d, %d, %d, %d)\n", bytesToZero, startOfData, toOffset, frameOffset, seg->backpointer);#endif	toOffset += bytesToZero;      }            unsigned char* fromPtr	= &seg->dataStart()[seg->headerSize + seg->sideInfoSize + fromOffset];      unsigned bytesUsedHere = endOfData - startOfData;#ifdef DEBUG      if (bytesUsedHere > 0) fprintf(stderr, "a->m:outputting %d bytes from %d<-%d\n", bytesUsedHere, seg->aduSize, seg->backpointer);#endif      memmove(toPtr + toOffset, fromPtr, bytesUsedHere);      toOffset += bytesUsedHere;            frameOffset += seg->dataHere();      index = SegmentQueue::nextIndex(index);      if (index == fSegments->nextFreeIndex()) break;      seg = &(fSegments->s[index]);    }        fSegments->dequeue();    return True;}////////// Segment //////////unsigned Segment::dataHere() {  int result = frameSize - (headerSize + sideInfoSize);  if (result < 0) {    return 0;  }  return (unsigned)result;} ////////// SegmentQueue //////////void SegmentQueue::enqueueNewSegment(FramedSource* inputSource,				     FramedSource* usingSource) {  if (isFull()) {    usingSource->envir() << "SegmentQueue::enqueueNewSegment() overflow\n";    FramedSource::handleClosure(usingSource);    return;  }    fUsingSource = usingSource;    Segment& seg = nextFreeSegment();  inputSource->getNextFrame(seg.buf, sizeof seg.buf,			    sqAfterGettingSegment, this,			    FramedSource::handleClosure, usingSource);}void SegmentQueue::sqAfterGettingSegment(void* clientData,					 unsigned numBytesRead,					 unsigned /*numTruncatedBytes*/,					 struct timeval presentationTime,					 unsigned durationInMicroseconds) {  SegmentQueue* segQueue = (SegmentQueue*)clientData;  Segment& seg = segQueue->nextFreeSegment();  seg.presentationTime = presentationTime;  seg.durationInMicroseconds = durationInMicroseconds;  if (segQueue->sqAfterGettingCommon(seg, numBytesRead)) {#ifdef DEBUG    char const* direction = segQueue->fDirectionIsToADU ? "m->a" : "a->m";    fprintf(stderr, "%s:read frame %d<-%d, fs:%d, sis:%d, dh:%d, (descriptor size: %d)\n", direction, seg.aduSize, seg.backpointer, seg.frameSize, seg.sideInfoSize, seg.dataHere(), seg.descriptorSize);#endif  }  // Continue our original calling source where it left off:  segQueue->fUsingSource->doGetNextFrame();}// Common code called after a new segment is enqueuedBoolean SegmentQueue::sqAfterGettingCommon(Segment& seg,					   unsigned numBytesRead) {   unsigned char* fromPtr = seg.buf;  if (fIncludeADUdescriptors) {    // The newly-read data is assumed to be an ADU with a descriptor    // in front    (void)ADUdescriptor::getRemainingFrameSize(fromPtr);    seg.descriptorSize = (unsigned)(fromPtr-seg.buf);  } else {    seg.descriptorSize = 0;  }  // parse the MP3-specific info in the frame to get the ADU params  unsigned hdr;  MP3SideInfo sideInfo;  if (!GetADUInfoFromMP3Frame(fromPtr, numBytesRead,			      hdr, seg.frameSize,			      sideInfo, seg.sideInfoSize,			      seg.backpointer, seg.aduSize)) {    return False;  }    // If we've just read an ADU (rather than a regular MP3 frame), then use the  // entire "numBytesRead" data for the 'aduSize', so that we include any  // 'ancillary data' that may be present at the end of the ADU:  if (!fDirectionIsToADU) {    unsigned newADUSize      = numBytesRead - seg.descriptorSize - 4/*header size*/ - seg.sideInfoSize;    if (newADUSize > seg.aduSize) seg.aduSize = newADUSize;  }  fTotalDataSize += seg.dataHere();  fNextFreeIndex = nextIndex(fNextFreeIndex);  return True;}Boolean SegmentQueue::dequeue() {  if (isEmpty()) {    fUsingSource->envir() << "SegmentQueue::dequeue(): underflow!\n";    return False;  }  Segment& seg = s[headIndex()];  fTotalDataSize -= seg.dataHere();  fHeadIndex = nextIndex(fHeadIndex);  return True;}Boolean SegmentQueue::insertDummyBeforeTail(unsigned backpointer) {  if (isEmptyOrFull()) return False;  // Copy the current tail segment to its new position, then modify the  // old tail segment to be a 'dummy' ADU  unsigned newTailIndex = nextFreeIndex();  Segment& newTailSeg = s[newTailIndex];  unsigned oldTailIndex = prevIndex(newTailIndex);  Segment& oldTailSeg = s[oldTailIndex];  newTailSeg = oldTailSeg; // structure copy  // Begin by setting (replacing) the ADU descriptor of the dummy ADU:  unsigned char* ptr = oldTailSeg.buf;  if (fIncludeADUdescriptors) {    unsigned remainingFrameSize      = oldTailSeg.headerSize + oldTailSeg.sideInfoSize + 0 /* 0-size ADU */;    unsigned currentDescriptorSize = oldTailSeg.descriptorSize;    if (currentDescriptorSize == 2) {      ADUdescriptor::generateTwoByteDescriptor(ptr, remainingFrameSize);    } else {      (void)ADUdescriptor::generateDescriptor(ptr, remainingFrameSize);    }  }  // Then zero out the side info of the dummy frame:  if (!ZeroOutMP3SideInfo(ptr, oldTailSeg.frameSize,			  backpointer)) return False;  unsigned dummyNumBytesRead    = oldTailSeg.descriptorSize + 4/*header size*/ + oldTailSeg.sideInfoSize;  return sqAfterGettingCommon(oldTailSeg, dummyNumBytesRead);}

⌨️ 快捷键说明

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