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

📄 amraudiortpsource.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**********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.// AMR Audio RTP Sources (RFC 3267)// Implementation#include "AMRAudioRTPSource.hh"#include "MultiFramedRTPSource.hh"#include "BitVector.hh"#include <string.h>#include <stdlib.h>// This source is implemented internally by two separate sources:// (i) a RTP source for the raw (and possibly interleaved) AMR frames, and// (ii) a deinterleaving filter that reads from this.// Define these two new classes here:class RawAMRRTPSource: public MultiFramedRTPSource {public:  static RawAMRRTPSource*  createNew(UsageEnvironment& env,	    Groupsock* RTPgs, unsigned char rtpPayloadFormat,	    Boolean isWideband, Boolean isOctetAligned,	    Boolean isInterleaved, Boolean CRCsArePresent);  Boolean isWideband() const { return fIsWideband; }  unsigned char ILL() const { return fILL; }  unsigned char ILP() const { return fILP; }  unsigned TOCSize() const { return fTOCSize; } // total # of frames in the last pkt  unsigned char* TOC() const { return fTOC; } // FT+Q value for each TOC entry  unsigned& frameIndex() { return fFrameIndex; } // index of frame-block within pktprivate:  RawAMRRTPSource(UsageEnvironment& env, Groupsock* RTPgs,		  unsigned char rtpPayloadFormat,		  Boolean isWideband, Boolean isOctetAligned,		  Boolean isInterleaved, Boolean CRCsArePresent);      // called only by createNew()  virtual ~RawAMRRTPSource();private:  // redefined virtual functions:  virtual Boolean processSpecialHeader(BufferedPacket* packet,                                       unsigned& resultSpecialHeaderSize);  virtual char const* MIMEtype() const;   virtual Boolean hasBeenSynchronizedUsingRTCP();private:  Boolean fIsWideband, fIsOctetAligned, fIsInterleaved, fCRCsArePresent;  unsigned char fILL, fILP;  unsigned fTOCSize;  unsigned char* fTOC;  unsigned fFrameIndex, fNumSuccessiveSyncedPackets;};class AMRDeinterleaver: public AMRAudioSource {public:  static AMRDeinterleaver*  createNew(UsageEnvironment& env,	    Boolean isWideband, unsigned numChannels, unsigned maxInterleaveGroupSize,	    RawAMRRTPSource* inputSource);private:  AMRDeinterleaver(UsageEnvironment& env,		   Boolean isWideband, unsigned numChannels,		   unsigned maxInterleaveGroupSize, RawAMRRTPSource* inputSource);      // called only by "createNew()"   virtual ~AMRDeinterleaver();  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:  FramedSource* fInputSource;  class AMRDeinterleavingBuffer* fDeinterleavingBuffer;  Boolean fNeedAFrame;};////////// AMRAudioRTPSource implementation //////////#define MAX_NUM_CHANNELS 20 // far larger than ever expected...#define MAX_INTERLEAVING_GROUP_SIZE 1000 // far larger than ever expected...AMRAudioSource*AMRAudioRTPSource::createNew(UsageEnvironment& env,			     Groupsock* RTPgs,			     RTPSource*& resultRTPSource,			     unsigned char rtpPayloadFormat,			     Boolean isWideband,			     unsigned numChannels,			     Boolean isOctetAligned,			     unsigned interleaving,			     Boolean robustSortingOrder,			     Boolean CRCsArePresent) {  // Perform sanity checks on the input parameters:  if (robustSortingOrder) {    env << "AMRAudioRTPSource::createNew(): 'Robust sorting order' was specified, but we don't yet support this!\n";    return NULL;  } else if (numChannels > MAX_NUM_CHANNELS) {    env << "AMRAudioRTPSource::createNew(): The \"number of channels\" parameter ("	<< numChannels << ") is much too large!\n";    return NULL;  } else if (interleaving > MAX_INTERLEAVING_GROUP_SIZE) {    env << "AMRAudioRTPSource::createNew(): The \"interleaving\" parameter ("	<< interleaving << ") is much too large!\n";    return NULL;  }  // 'Bandwidth-efficient mode' precludes some other options:  if (!isOctetAligned) {    if (interleaving > 0 || robustSortingOrder || CRCsArePresent) {      env << "AMRAudioRTPSource::createNew(): 'Bandwidth-efficient mode' was specified, along with interleaving, 'robust sorting order', and/or CRCs, so we assume 'octet-aligned mode' instead.\n";      isOctetAligned = True;    }  }   Boolean isInterleaved;  unsigned maxInterleaveGroupSize; // in frames (not frame-blocks)  if (interleaving > 0) {    isInterleaved = True;    maxInterleaveGroupSize = interleaving*numChannels;  } else {    isInterleaved = False;    maxInterleaveGroupSize = numChannels;  }  RawAMRRTPSource* rawRTPSource;  resultRTPSource = rawRTPSource    = RawAMRRTPSource::createNew(env, RTPgs, rtpPayloadFormat,				 isWideband, isOctetAligned,				 isInterleaved, CRCsArePresent);  if (resultRTPSource == NULL) return NULL;  AMRDeinterleaver* deinterleaver    = AMRDeinterleaver::createNew(env, isWideband, numChannels,				  maxInterleaveGroupSize, rawRTPSource);  if (deinterleaver == NULL) {    Medium::close(resultRTPSource);    resultRTPSource = NULL;  }  return deinterleaver;}////////// AMRBufferedPacket and AMRBufferedPacketFactory //////////// A subclass of BufferedPacket, used to separate out AMR frames.class AMRBufferedPacket: public BufferedPacket {public:  AMRBufferedPacket(RawAMRRTPSource& ourSource);  virtual ~AMRBufferedPacket();private: // redefined virtual functions  virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,					 unsigned dataSize);private:  RawAMRRTPSource& fOurSource;};class AMRBufferedPacketFactory: public BufferedPacketFactory {private: // redefined virtual functions  virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);};///////// RawAMRRTPSource implementation ////////RawAMRRTPSource*RawAMRRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,			   unsigned char rtpPayloadFormat,			   Boolean isWideband, Boolean isOctetAligned,			   Boolean isInterleaved, Boolean CRCsArePresent) {  return new RawAMRRTPSource(env, RTPgs, rtpPayloadFormat,			     isWideband, isOctetAligned,			     isInterleaved, CRCsArePresent);}RawAMRRTPSource::RawAMRRTPSource(UsageEnvironment& env,		  Groupsock* RTPgs, unsigned char rtpPayloadFormat,		  Boolean isWideband, Boolean isOctetAligned,		  Boolean isInterleaved, Boolean CRCsArePresent)  : MultiFramedRTPSource(env, RTPgs, rtpPayloadFormat,			 isWideband ? 16000 : 8000,                         new AMRBufferedPacketFactory),  fIsWideband(isWideband), fIsOctetAligned(isOctetAligned),  fIsInterleaved(isInterleaved), fCRCsArePresent(CRCsArePresent),  fILL(0), fILP(0), fTOCSize(0), fTOC(NULL), fFrameIndex(0),  fNumSuccessiveSyncedPackets(0) {}RawAMRRTPSource::~RawAMRRTPSource() {  delete[] fTOC;}#define FT_SPEECH_LOST 14#define FT_NO_DATA 15static void unpackBandwidthEfficientData(BufferedPacket* packet,					 Boolean isWideband); // forwardBoolean RawAMRRTPSource::processSpecialHeader(BufferedPacket* packet,		       unsigned& resultSpecialHeaderSize) {  // If the data is 'bandwidth-efficient', first unpack it so that it's  // 'octet-aligned':  if (!fIsOctetAligned) unpackBandwidthEfficientData(packet, fIsWideband);  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 at least a 1-byte header, containing the CMR:  if (packetSize < 1) return False;  resultSpecialHeaderSize = 1;  if (fIsInterleaved) {    // There's an extra byte, containing the interleave parameters:    if (packetSize < 2) return False;    // Get the interleaving parameters, and check them for validity:    unsigned char const secondByte = headerStart[1];    fILL = (secondByte&0xF0)>>4;    fILP = secondByte&0x0F;    if (fILP > fILL) return False; // invalid    ++resultSpecialHeaderSize;  }#ifdef DEBUG  fprintf(stderr, "packetSize: %d, ILL: %d, ILP: %d\n", packetSize, fILL, fILP);#endif  fFrameIndex = 0; // initially  // Next, there's a "Payload Table of Contents" (one byte per entry):  unsigned numFramesPresent = 0, numNonEmptyFramesPresent = 0;  unsigned tocStartIndex = resultSpecialHeaderSize;  Boolean F;  do {    if (resultSpecialHeaderSize >= packetSize) return False;    unsigned char const tocByte = headerStart[resultSpecialHeaderSize++];    F = (tocByte&0x80) != 0;    unsigned char const FT = (tocByte&0x78) >> 3;#ifdef DEBUG    unsigned char Q = (tocByte&0x04)>>2;    fprintf(stderr, "\tTOC entry: F %d, FT %d, Q %d\n", F, FT, Q);#endif    ++numFramesPresent;    if (FT != FT_SPEECH_LOST && FT != FT_NO_DATA) ++numNonEmptyFramesPresent;  } while (F);#ifdef DEBUG  fprintf(stderr, "TOC contains %d entries (%d non-empty)\n", numFramesPresent, numNonEmptyFramesPresent);#endif  // Now that we know the size of the TOC, fill in our copy:  if (numFramesPresent > fTOCSize) {    delete[] fTOC;    fTOC = new unsigned char[numFramesPresent];  }  fTOCSize = numFramesPresent;  for (unsigned i = 0; i < fTOCSize; ++i) {    unsigned char const tocByte = headerStart[tocStartIndex + i];    fTOC[i] = tocByte&0x7C; // clear everything except the F and Q fields  }  if (fCRCsArePresent) {    // 'numNonEmptyFramesPresent' CRC bytes will follow.    // Note: we currently don't check the CRCs for validity #####    resultSpecialHeaderSize += numNonEmptyFramesPresent;#ifdef DEBUG    fprintf(stderr, "Ignoring %d following CRC bytes\n", numNonEmptyFramesPresent);#endif    if (resultSpecialHeaderSize > packetSize) return False;  }#ifdef DEBUG  fprintf(stderr, "Total special header size: %d\n", resultSpecialHeaderSize);#endif  return True;} char const* RawAMRRTPSource::MIMEtype() const {  return fIsWideband ? "audio/AMR-WB" : "audio/AMR-WB";}Boolean RawAMRRTPSource::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)(fILL+1)) {    fNumSuccessiveSyncedPackets = fILL + 2; // prevents overflow    return True;  }  return False;}///// AMRBufferedPacket and AMRBufferedPacketFactory implementationAMRBufferedPacket::AMRBufferedPacket(RawAMRRTPSource& ourSource)  : fOurSource(ourSource) {}AMRBufferedPacket::~AMRBufferedPacket() {}// The mapping from the "FT" field to frame size.// Values of 65535 are invalid.#define FT_INVALID 65535static unsigned short frameBytesFromFT[16] = {  12, 13, 15, 17,  19, 20, 26, 31,  5, FT_INVALID, FT_INVALID, FT_INVALID,  FT_INVALID, FT_INVALID, FT_INVALID, 0};static unsigned short frameBytesFromFTWideband[16] = {  17, 23, 32, 36,  40, 46, 50, 58,  60, 5, FT_INVALID, FT_INVALID,  FT_INVALID, FT_INVALID, 0, 0};unsigned AMRBufferedPacket::  nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) {  if (dataSize == 0) return 0; // sanity check  // The size of the AMR frame is determined by the corresponding 'FT' value  // in the packet's Table of Contents.  unsigned const tocIndex = fOurSource.frameIndex();  if (tocIndex >= fOurSource.TOCSize()) return 0; // sanity check  unsigned char const tocByte = fOurSource.TOC()[tocIndex];  unsigned char const FT = (tocByte&0x78) >> 3;  // ASSERT: FT < 16  unsigned short frameSize    = fOurSource.isWideband() ? frameBytesFromFTWideband[FT] : frameBytesFromFT[FT];  if (frameSize == FT_INVALID) {

⌨️ 快捷键说明

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