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

📄 amraudiortpsource.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // Strange TOC entry!    fOurSource.envir() << "AMRBufferedPacket::nextEnclosedFrameSize(): invalid FT: " << FT << "\n";    frameSize = 0; // This probably messes up the rest of this packet, but...  }#ifdef DEBUG  fprintf(stderr, "AMRBufferedPacket::nextEnclosedFrameSize(): frame #: %d, FT: %d, isWideband: %d => frameSize: %d (dataSize: %d)\n", tocIndex, FT, fOurSource.isWideband(), frameSize, dataSize);#endif  ++fOurSource.frameIndex();  if (dataSize < frameSize) return 0;  return frameSize;}BufferedPacket* AMRBufferedPacketFactory::createNewPacket(MultiFramedRTPSource* ourSource) {  return new AMRBufferedPacket((RawAMRRTPSource&)(*ourSource));}///////// AMRDeinterleavingBuffer /////////// (used to implement AMRDeinterleaver)#define AMR_MAX_FRAME_SIZE 60class AMRDeinterleavingBuffer {public:  AMRDeinterleavingBuffer(unsigned numChannels, unsigned maxInterleaveGroupSize);  virtual ~AMRDeinterleavingBuffer();  void deliverIncomingFrame(unsigned frameSize, RawAMRRTPSource* source,			    struct timeval presentationTime);  Boolean retrieveFrame(unsigned char* to, unsigned maxSize,			unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes,			u_int8_t& resultFrameHeader,			struct timeval& resultPresentationTime);  unsigned char* inputBuffer() { return fInputBuffer; }  unsigned inputBufferSize() const { return AMR_MAX_FRAME_SIZE; }private:  unsigned char* createNewBuffer();  class FrameDescriptor {  public:    FrameDescriptor();    virtual ~FrameDescriptor();    unsigned frameSize;    unsigned char* frameData;    u_int8_t frameHeader;    struct timeval presentationTime;  };  unsigned fNumChannels, fMaxInterleaveGroupSize;  FrameDescriptor* fFrames[2];  unsigned char fIncomingBankId; // toggles between 0 and 1  unsigned char fIncomingBinMax; // in the incoming bank  unsigned char fOutgoingBinMax; // in the outgoing bank  unsigned char fNextOutgoingBin;  Boolean fHaveSeenPackets;  u_int16_t fLastPacketSeqNumForGroup;  unsigned char* fInputBuffer;  struct timeval fLastRetrievedPresentationTime;};////////// AMRDeinterleaver implementation /////////AMRDeinterleaver* AMRDeinterleaver::createNew(UsageEnvironment& env,	    Boolean isWideband, unsigned numChannels, unsigned maxInterleaveGroupSize,	    RawAMRRTPSource* inputSource) {  return new AMRDeinterleaver(env, isWideband, numChannels, maxInterleaveGroupSize,			      inputSource);}AMRDeinterleaver::AMRDeinterleaver(UsageEnvironment& env,				   Boolean isWideband, unsigned numChannels,				   unsigned maxInterleaveGroupSize,				   RawAMRRTPSource* inputSource)  : AMRAudioSource(env, isWideband, numChannels),    fInputSource(inputSource), fNeedAFrame(False) {  fDeinterleavingBuffer    = new AMRDeinterleavingBuffer(numChannels, maxInterleaveGroupSize);}AMRDeinterleaver::~AMRDeinterleaver() {  delete fDeinterleavingBuffer;  Medium::close(fInputSource);}static unsigned const uSecsPerFrame = 20000; // 20 msvoid AMRDeinterleaver::doGetNextFrame() {  // First, try getting a frame from the deinterleaving buffer:  if (fDeinterleavingBuffer->retrieveFrame(fTo, fMaxSize,					   fFrameSize, fNumTruncatedBytes,					   fLastFrameHeader, fPresentationTime)) {    // Success!    fNeedAFrame = False;    fDurationInMicroseconds = uSecsPerFrame;    // Call our own 'after getting' function.  Because we're not a 'leaf'    // source, we can call this directly, without risking    // infinite recursion    afterGetting(this);    return;  }  // No luck, so ask our source for help:  fNeedAFrame = True;  if (!fInputSource->isCurrentlyAwaitingData()) {    fInputSource->getNextFrame(fDeinterleavingBuffer->inputBuffer(),			       fDeinterleavingBuffer->inputBufferSize(),			       afterGettingFrame, this,			       FramedSource::handleClosure, this);  }}void AMRDeinterleaver::afterGettingFrame(void* clientData, unsigned frameSize,		    unsigned /*numTruncatedBytes*/,		    struct timeval presentationTime,		    unsigned /*durationInMicroseconds*/) {  AMRDeinterleaver* deinterleaver = (AMRDeinterleaver*)clientData;  deinterleaver->afterGettingFrame1(frameSize, presentationTime);}void AMRDeinterleaver::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) {  RawAMRRTPSource* source = (RawAMRRTPSource*)fInputSource;    // First, put the frame into our deinterleaving buffer:  fDeinterleavingBuffer->deliverIncomingFrame(frameSize, source, presentationTime);  // Then, try delivering a frame to the client (if he wants one):  if (fNeedAFrame) doGetNextFrame();}////////// AMRDeinterleavingBuffer implementation /////////AMRDeinterleavingBuffer::AMRDeinterleavingBuffer(unsigned numChannels, unsigned maxInterleaveGroupSize)  : fNumChannels(numChannels), fMaxInterleaveGroupSize(maxInterleaveGroupSize),    fIncomingBankId(0), fIncomingBinMax(0),    fOutgoingBinMax(0), fNextOutgoingBin(0),    fHaveSeenPackets(False) {  // Use two banks of descriptors - one for incoming, one for outgoing  fFrames[0] = new FrameDescriptor[fMaxInterleaveGroupSize];  fFrames[1] = new FrameDescriptor[fMaxInterleaveGroupSize];  fInputBuffer = createNewBuffer();}AMRDeinterleavingBuffer::~AMRDeinterleavingBuffer() {  delete[] fInputBuffer;  delete[] fFrames[0]; delete[] fFrames[1];}void AMRDeinterleavingBuffer::deliverIncomingFrame(unsigned frameSize, RawAMRRTPSource* source,		       struct timeval presentationTime) {  unsigned char const ILL = source->ILL();  unsigned char const ILP = source->ILP();  unsigned frameIndex = source->frameIndex();  unsigned short packetSeqNum = source->curPacketRTPSeqNum();  // First perform a sanity check on the parameters:  // (This is overkill, as the source should have already done this.)  if (ILP > ILL || frameIndex == 0) {#ifdef DEBUG    fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, ILL, ILP, frameIndex);#endif    exit(1);  }  --frameIndex; // because it was incremented by the source when this frame was read   u_int8_t frameHeader;  if (frameIndex >= source->TOCSize()) { // sanity check    frameHeader = FT_NO_DATA<<3;  } else {    frameHeader = source->TOC()[frameIndex];  }  unsigned frameBlockIndex = frameIndex/fNumChannels;  unsigned frameWithinFrameBlock = frameIndex%fNumChannels;  // The input "presentationTime" was that of the first frame-block in this  // packet.  Update it for the current frame:  unsigned uSecIncrement = frameBlockIndex*(ILL+1)*uSecsPerFrame;  presentationTime.tv_usec += uSecIncrement;  presentationTime.tv_sec += presentationTime.tv_usec/1000000;  presentationTime.tv_usec = presentationTime.tv_usec%1000000;  // Next, check whether this packet is part of a new interleave group  if (!fHaveSeenPackets      || seqNumLT(fLastPacketSeqNumForGroup, packetSeqNum + frameBlockIndex)) {    // We've moved to a new interleave group#ifdef DEBUG    fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): new interleave group\n");#endif    fHaveSeenPackets = True;    fLastPacketSeqNumForGroup = packetSeqNum + ILL - ILP;    // Switch the incoming and outgoing banks:    fIncomingBankId ^= 1;    unsigned char tmp = fIncomingBinMax;    fIncomingBinMax = fOutgoingBinMax;    fOutgoingBinMax = tmp;     fNextOutgoingBin = 0;  }  // Now move the incoming frame into the appropriate bin:  unsigned const binNumber    = ((ILP + frameBlockIndex*(ILL+1))*fNumChannels + frameWithinFrameBlock)      % fMaxInterleaveGroupSize; // the % is for sanity#ifdef DEBUG  fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): frameIndex %d (%d,%d) put in bank %d, bin %d (%d): size %d, header 0x%02x, presentationTime %lu.%06ld\n", frameIndex, frameBlockIndex, frameWithinFrameBlock, fIncomingBankId, binNumber, fMaxInterleaveGroupSize, frameSize, frameHeader, presentationTime.tv_sec, presentationTime.tv_usec);#endif  FrameDescriptor& inBin = fFrames[fIncomingBankId][binNumber];  unsigned char* curBuffer = inBin.frameData;  inBin.frameData = fInputBuffer;  inBin.frameSize = frameSize;  inBin.frameHeader = frameHeader;  inBin.presentationTime = presentationTime;  if (curBuffer == NULL) curBuffer = createNewBuffer();  fInputBuffer = curBuffer;  if (binNumber >= fIncomingBinMax) {    fIncomingBinMax = binNumber + 1;  }}Boolean AMRDeinterleavingBuffer::retrieveFrame(unsigned char* to, unsigned maxSize,		unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes,		u_int8_t& resultFrameHeader,		struct timeval& resultPresentationTime) {  if (fNextOutgoingBin >= fOutgoingBinMax) return False; // none left  FrameDescriptor& outBin = fFrames[fIncomingBankId^1][fNextOutgoingBin];  unsigned char* fromPtr = outBin.frameData;  unsigned char fromSize = outBin.frameSize;  outBin.frameSize = 0; // for the next time this bin is used  // Check whether this frame is missing; if so, return a FT_NO_DATA frame:  if (fromSize == 0) {    resultFrameHeader = FT_NO_DATA<<3;    // Compute this erasure frame's presentation time via extrapolation:    resultPresentationTime = fLastRetrievedPresentationTime;    resultPresentationTime.tv_usec += uSecsPerFrame;    if (resultPresentationTime.tv_usec >= 1000000) {      ++resultPresentationTime.tv_sec;      resultPresentationTime.tv_usec -= 1000000;    }  } else {    // Normal case - a frame exists:    resultFrameHeader = outBin.frameHeader;    resultPresentationTime = outBin.presentationTime;  }  fLastRetrievedPresentationTime = resultPresentationTime;  if (fromSize > maxSize) {    resultNumTruncatedBytes = fromSize - maxSize;    resultFrameSize = maxSize;  } else {    resultNumTruncatedBytes = 0;    resultFrameSize = fromSize;  }  memmove(to, fromPtr, resultFrameSize);#ifdef DEBUG  fprintf(stderr, "AMRDeinterleavingBuffer::retrieveFrame(): from bank %d, bin %d: size %d, header 0x%02x, presentationTime %lu.%06ld\n", fIncomingBankId^1, fNextOutgoingBin, resultFrameSize, resultFrameHeader, resultPresentationTime.tv_sec, resultPresentationTime.tv_usec);#endif  ++fNextOutgoingBin;  return True;}unsigned char* AMRDeinterleavingBuffer::createNewBuffer() {  return new unsigned char[inputBufferSize()];}AMRDeinterleavingBuffer::FrameDescriptor::FrameDescriptor()  : frameSize(0), frameData(NULL) {}AMRDeinterleavingBuffer::FrameDescriptor::~FrameDescriptor() {  delete[] frameData;}// Unpack bandwidth-aligned data to octet-aligned:static unsigned short frameBitsFromFT[16] = {  95, 103, 118, 134,  148, 159, 204, 244,  39, 0, 0, 0,  0, 0, 0, 0};static unsigned short frameBitsFromFTWideband[16] = {  132, 177, 253, 285,  317, 365, 397, 461,  477, 40, 0, 0,  0, 0, 0, 0};static void unpackBandwidthEfficientData(BufferedPacket* packet,					 Boolean isWideband) {#ifdef DEBUG  fprintf(stderr, "Unpacking 'bandwidth-efficient' payload (%d bytes):\n", packet->dataSize());  for (unsigned j = 0; j < packet->dataSize(); ++j) {    fprintf(stderr, "%02x:", (packet->data())[j]);  }  fprintf(stderr, "\n");#endif  BitVector fromBV(packet->data(), 0, 8*packet->dataSize());  unsigned const toBufferSize = 2*packet->dataSize(); // conservatively large  unsigned char* toBuffer = new unsigned char[toBufferSize];  unsigned toCount = 0;  // Begin with the payload header:  unsigned CMR = fromBV.getBits(4);  toBuffer[toCount++] = CMR << 4;  // Then, run through and unpack the TOC entries:  while (1) {    unsigned toc = fromBV.getBits(6);    toBuffer[toCount++] = toc << 2;    if ((toc&0x20) == 0) break; // the F bit is 0  }  // Then, using the TOC data, unpack each frame payload:  unsigned const tocSize = toCount - 1;  for (unsigned i = 1; i <= tocSize; ++i) {    unsigned char tocByte = toBuffer[i];    unsigned char const FT = (tocByte&0x78) >> 3;    unsigned short frameSizeBits      = isWideband ? frameBitsFromFTWideband[FT] : frameBitsFromFT[FT];    unsigned short frameSizeBytes = (frameSizeBits+7)/8;    shiftBits(&toBuffer[toCount], 0, // to	      packet->data(), fromBV.curBitIndex(), // from	      frameSizeBits // num bits	      );#ifdef DEBUG    if (frameSizeBits > fromBV.numBitsRemaining()) {      fprintf(stderr, "\tWarning: Unpacking frame %d of %d: want %d bits, but only %d are available!\n", i, tocSize, frameSizeBits, fromBV.numBitsRemaining());    }#endif    fromBV.skipBits(frameSizeBits);    toCount += frameSizeBytes;  }  #ifdef DEBUG  if (fromBV.numBitsRemaining() > 7) {    fprintf(stderr, "\tWarning: %d bits remain unused!\n", fromBV.numBitsRemaining());  }#endif  // Finally, replace the current packet data with the unpacked data:  packet->removePadding(packet->dataSize()); // throws away current packet data  packet->appendData(toBuffer, toCount);  delete[] toBuffer;}

⌨️ 快捷键说明

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