📄 qcelpaudiortpsource.cpp
字号:
}///////// QCELPDeinterleavingBuffer /////////// (used to implement QCELPDeinterleaver)#define QCELP_MAX_FRAME_SIZE 35#define QCELP_MAX_INTERLEAVE_L 5#define QCELP_MAX_FRAMES_PER_PACKET 10#define QCELP_MAX_INTERLEAVE_GROUP_SIZE \ ((QCELP_MAX_INTERLEAVE_L+1)*QCELP_MAX_FRAMES_PER_PACKET)class QCELPDeinterleavingBuffer {public: QCELPDeinterleavingBuffer(); virtual ~QCELPDeinterleavingBuffer(); void deliverIncomingFrame(unsigned frameSize, unsigned char interleaveL, unsigned char interleaveN, unsigned char frameIndex, unsigned short packetSeqNum, struct timeval presentationTime); Boolean retrieveFrame(unsigned char* to, unsigned maxSize, unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes, struct timeval& resultPresentationTime); unsigned char* inputBuffer() { return fInputBuffer; } unsigned inputBufferSize() const { return QCELP_MAX_FRAME_SIZE; }private: class FrameDescriptor { public: FrameDescriptor(); virtual ~FrameDescriptor(); unsigned frameSize; unsigned char* frameData; struct timeval presentationTime; }; // Use two banks of descriptors - one for incoming, one for outgoing FrameDescriptor fFrames[QCELP_MAX_INTERLEAVE_GROUP_SIZE][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;};////////// QCELPDeinterleaver implementation /////////QCELPDeinterleaver*QCELPDeinterleaver::createNew(UsageEnvironment& env, RawQCELPRTPSource* inputSource) { return new QCELPDeinterleaver(env, inputSource);}QCELPDeinterleaver::QCELPDeinterleaver(UsageEnvironment& env, RawQCELPRTPSource* inputSource) : FramedFilter(env, inputSource), fNeedAFrame(False) { fDeinterleavingBuffer = new QCELPDeinterleavingBuffer();}QCELPDeinterleaver::~QCELPDeinterleaver() { delete fDeinterleavingBuffer;}static unsigned const uSecsPerFrame = 20000; // 20 msvoid QCELPDeinterleaver::doGetNextFrame() { // First, try getting a frame from the deinterleaving buffer: if (fDeinterleavingBuffer->retrieveFrame(fTo, fMaxSize, fFrameSize, fNumTruncatedBytes, 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 QCELPDeinterleaver::afterGettingFrame(void* clientData, unsigned frameSize, unsigned /*numTruncatedBytes*/, struct timeval presentationTime, unsigned /*durationInMicroseconds*/) { QCELPDeinterleaver* deinterleaver = (QCELPDeinterleaver*)clientData; deinterleaver->afterGettingFrame1(frameSize, presentationTime);}void QCELPDeinterleaver::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) { RawQCELPRTPSource* source = (RawQCELPRTPSource*)fInputSource; // First, put the frame into our deinterleaving buffer: fDeinterleavingBuffer ->deliverIncomingFrame(frameSize, source->interleaveL(), source->interleaveN(), source->frameIndex(), source->curPacketRTPSeqNum(), presentationTime); // Then, try delivering a frame to the client (if he wants one): if (fNeedAFrame) doGetNextFrame();}////////// QCELPDeinterleavingBuffer implementation /////////QCELPDeinterleavingBuffer::QCELPDeinterleavingBuffer() : fIncomingBankId(0), fIncomingBinMax(0), fOutgoingBinMax(0), fNextOutgoingBin(0), fHaveSeenPackets(False) { fInputBuffer = new unsigned char[QCELP_MAX_FRAME_SIZE];}QCELPDeinterleavingBuffer::~QCELPDeinterleavingBuffer() { delete[] fInputBuffer;}void QCELPDeinterleavingBuffer::deliverIncomingFrame(unsigned frameSize, unsigned char interleaveL, unsigned char interleaveN, unsigned char frameIndex, unsigned short packetSeqNum, struct timeval presentationTime) { // First perform a sanity check on the parameters: // (This is overkill, as the source should have already done this.) if (frameSize > QCELP_MAX_FRAME_SIZE || interleaveL > QCELP_MAX_INTERLEAVE_L || interleaveN > interleaveL || frameIndex == 0 || frameIndex > QCELP_MAX_FRAMES_PER_PACKET) {#ifdef DEBUG fprintf(stderr, "QCELPDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, interleaveL, interleaveN, frameIndex);#endif exit(1); } // The input "presentationTime" was that of the first frame in this // packet. Update it for the current frame: unsigned uSecIncrement = (frameIndex-1)*(interleaveL+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)) { // We've moved to a new interleave group fHaveSeenPackets = True; fLastPacketSeqNumForGroup = packetSeqNum + interleaveL - interleaveN; // 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 = interleaveN + (frameIndex-1)*(interleaveL+1); FrameDescriptor& inBin = fFrames[binNumber][fIncomingBankId]; unsigned char* curBuffer = inBin.frameData; inBin.frameData = fInputBuffer; inBin.frameSize = frameSize; inBin.presentationTime = presentationTime; if (curBuffer == NULL) curBuffer = new unsigned char[QCELP_MAX_FRAME_SIZE]; fInputBuffer = curBuffer; if (binNumber >= fIncomingBinMax) { fIncomingBinMax = binNumber + 1; }}Boolean QCELPDeinterleavingBuffer::retrieveFrame(unsigned char* to, unsigned maxSize, unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes, struct timeval& resultPresentationTime) { if (fNextOutgoingBin >= fOutgoingBinMax) return False; // none left FrameDescriptor& outBin = fFrames[fNextOutgoingBin][fIncomingBankId^1]; unsigned char* fromPtr; 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 an 'erasure' frame: unsigned char erasure = 14; if (fromSize == 0) { fromPtr = &erasure; fromSize = 1; // 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: fromPtr = outBin.frameData; resultPresentationTime = outBin.presentationTime; } fLastRetrievedPresentationTime = resultPresentationTime; if (fromSize > maxSize) { resultNumTruncatedBytes = fromSize - maxSize; resultFrameSize = maxSize; } else { resultNumTruncatedBytes = 0; resultFrameSize = fromSize; } memmove(to, fromPtr, resultFrameSize); ++fNextOutgoingBin; return True;}QCELPDeinterleavingBuffer::FrameDescriptor::FrameDescriptor() : frameSize(0), frameData(NULL) {}QCELPDeinterleavingBuffer::FrameDescriptor::~FrameDescriptor() { delete[] frameData;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -