📄 qcelpaudiortpsource.cpp
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**********/// "liveMedia"// Copyright (c) 1996-2004 Live Networks, Inc. All rights reserved.// Qualcomm "PureVoice" (aka. "QCELP") Audio RTP Sources// Implementation#include "QCELPAudioRTPSource.hh"#include "MultiFramedRTPSource.hh"#include "FramedFilter.hh"#include <string.h>#include <stdlib.h>// This source is implemented internally by two separate sources:// (i) a RTP source for the raw (interleaved) QCELP frames, and// (ii) a deinterleaving filter that reads from this.// Define these two new classes here:class RawQCELPRTPSource: public MultiFramedRTPSource {public: static RawQCELPRTPSource* createNew(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat, unsigned rtpTimestampFrequency); unsigned char interleaveL() const { return fInterleaveL; } unsigned char interleaveN() const { return fInterleaveN; } unsigned char& frameIndex() { return fFrameIndex; } // index within pktprivate: RawQCELPRTPSource(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat, unsigned rtpTimestampFrequency); // called only by createNew() virtual ~RawQCELPRTPSource();private: // redefined virtual functions: virtual Boolean processSpecialHeader(BufferedPacket* packet, unsigned& resultSpecialHeaderSize); virtual char const* MIMEtype() const; virtual Boolean hasBeenSynchronizedUsingRTCP();private: unsigned char fInterleaveL, fInterleaveN, fFrameIndex; unsigned fNumSuccessiveSyncedPackets;};class QCELPDeinterleaver: public FramedFilter {public: static QCELPDeinterleaver* createNew(UsageEnvironment& env, RawQCELPRTPSource* inputSource);private: QCELPDeinterleaver(UsageEnvironment& env, RawQCELPRTPSource* inputSource); // called only by "createNew()" virtual ~QCELPDeinterleaver(); static void afterGettingFrame(void* clientData, unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds); void afterGettingFrame1(unsigned frameSize, struct timeval presentationTime); private: // Redefined virtual functions: void doGetNextFrame();private: class QCELPDeinterleavingBuffer* fDeinterleavingBuffer; Boolean fNeedAFrame;};////////// QCELPAudioRTPSource implementation //////////FramedSource*QCELPAudioRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs, RTPSource*& resultRTPSource, unsigned char rtpPayloadFormat, unsigned rtpTimestampFrequency) { RawQCELPRTPSource* rawRTPSource; resultRTPSource = rawRTPSource = RawQCELPRTPSource::createNew(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency); if (resultRTPSource == NULL) return NULL; QCELPDeinterleaver* deinterleaver = QCELPDeinterleaver::createNew(env, rawRTPSource); if (deinterleaver == NULL) { Medium::close(resultRTPSource); resultRTPSource = NULL; } return deinterleaver;}////////// QCELPBufferedPacket and QCELPBufferedPacketFactory //////////// A subclass of BufferedPacket, used to separate out QCELP frames.class QCELPBufferedPacket: public BufferedPacket {public: QCELPBufferedPacket(RawQCELPRTPSource& ourSource); virtual ~QCELPBufferedPacket();private: // redefined virtual functions virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize);private: RawQCELPRTPSource& fOurSource;};class QCELPBufferedPacketFactory: public BufferedPacketFactory {private: // redefined virtual functions virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);};///////// RawQCELPRTPSource implementation ////////RawQCELPRTPSource*RawQCELPRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat, unsigned rtpTimestampFrequency) { return new RawQCELPRTPSource(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency);}RawQCELPRTPSource::RawQCELPRTPSource(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat, unsigned rtpTimestampFrequency) : MultiFramedRTPSource(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, new QCELPBufferedPacketFactory), fInterleaveL(0), fInterleaveN(0), fFrameIndex(0), fNumSuccessiveSyncedPackets(0) {}RawQCELPRTPSource::~RawQCELPRTPSource() {}Boolean RawQCELPRTPSource::processSpecialHeader(BufferedPacket* packet, unsigned& resultSpecialHeaderSize) { unsigned char* headerStart = packet->data(); unsigned packetSize = packet->dataSize(); // First, check whether this packet's RTP timestamp is synchronized: if (RTPSource::hasBeenSynchronizedUsingRTCP()) { ++fNumSuccessiveSyncedPackets; } else { fNumSuccessiveSyncedPackets = 0; } // There's a 1-byte header indicating the interleave parameters if (packetSize < 1) return False; // Get the interleaving parameters from the 1-byte header, // and check them for validity: unsigned char const firstByte = headerStart[0]; unsigned char const interleaveL = (firstByte&0x38)>>3; unsigned char const interleaveN = firstByte&0x07;#ifdef DEBUG fprintf(stderr, "packetSize: %d, interleaveL: %d, interleaveN: %d\n", packetSize, interleaveL, interleaveN);#endif if (interleaveL > 5 || interleaveN > interleaveL) return False; //invalid fInterleaveL = interleaveL; fInterleaveN = interleaveN; fFrameIndex = 0; // initially resultSpecialHeaderSize = 1; return True;} char const* RawQCELPRTPSource::MIMEtype() const { return "audio/QCELP";}Boolean RawQCELPRTPSource::hasBeenSynchronizedUsingRTCP() { // Don't report ourselves as being synchronized until we've received // at least a complete interleave cycle of synchronized packets. // This ensures that the receiver is currently getting a frame from // a packet that was synchronized. if (fNumSuccessiveSyncedPackets > (unsigned)(fInterleaveL+1)) { fNumSuccessiveSyncedPackets = fInterleaveL+2; // prevents overflow return True; } return False;}///// QCELPBufferedPacket and QCELPBufferedPacketFactory implementationQCELPBufferedPacket::QCELPBufferedPacket(RawQCELPRTPSource& ourSource) : fOurSource(ourSource) {}QCELPBufferedPacket::~QCELPBufferedPacket() {}unsigned QCELPBufferedPacket:: nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) { // The size of the QCELP frame is determined by the first byte: if (dataSize == 0) return 0; // sanity check unsigned char const firstByte = framePtr[0]; unsigned frameSize; switch (firstByte) { case 0: { frameSize = 1; break; } case 1: { frameSize = 4; break; } case 2: { frameSize = 8; break; } case 3: { frameSize = 17; break; } case 4: { frameSize = 35; break; } default: { frameSize = 0; break; } }#ifdef DEBUG fprintf(stderr, "QCELPBufferedPacket::nextEnclosedFrameSize(): frameSize: %d, dataSize: %d\n", frameSize, dataSize);#endif if (dataSize < frameSize) return 0; ++fOurSource.frameIndex(); return frameSize;}BufferedPacket* QCELPBufferedPacketFactory::createNewPacket(MultiFramedRTPSource* ourSource) { return new QCELPBufferedPacket((RawQCELPRTPSource&)(*ourSource));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -