00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MPEG4GenericRTPSource.hh"
00022 #include "BitVector.hh"
00023 #include "MPEG4LATMAudioRTPSource.hh"
00024
00026
00027 class MPEG4GenericBufferedPacket: public BufferedPacket {
00028 public:
00029 MPEG4GenericBufferedPacket(MPEG4GenericRTPSource* ourSource);
00030 virtual ~MPEG4GenericBufferedPacket();
00031
00032 private:
00033 virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00034 unsigned dataSize);
00035 private:
00036 MPEG4GenericRTPSource* fOurSource;
00037 };
00038
00039 class MPEG4GenericBufferedPacketFactory: public BufferedPacketFactory {
00040 private:
00041 virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00042 };
00043
00044
00046 struct AUHeader {
00047 unsigned size;
00048 unsigned index;
00049 };
00050
00051
00053
00054
00055
00056 MPEG4GenericRTPSource*
00057 MPEG4GenericRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00058 unsigned char rtpPayloadFormat,
00059 unsigned rtpTimestampFrequency,
00060 char const* mediumName,
00061 char const* mode,
00062 unsigned sizeLength, unsigned indexLength,
00063 unsigned indexDeltaLength
00064 ) {
00065 return new MPEG4GenericRTPSource(env, RTPgs, rtpPayloadFormat,
00066 rtpTimestampFrequency, mediumName,
00067 mode, sizeLength, indexLength,
00068 indexDeltaLength
00069 );
00070 }
00071
00072 MPEG4GenericRTPSource
00073 ::MPEG4GenericRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00074 unsigned char rtpPayloadFormat,
00075 unsigned rtpTimestampFrequency,
00076 char const* mediumName,
00077 char const* mode,
00078 unsigned sizeLength, unsigned indexLength,
00079 unsigned indexDeltaLength
00080 )
00081 : MultiFramedRTPSource(env, RTPgs,
00082 rtpPayloadFormat, rtpTimestampFrequency,
00083 new MPEG4GenericBufferedPacketFactory),
00084 fSizeLength(sizeLength), fIndexLength(indexLength),
00085 fIndexDeltaLength(indexDeltaLength),
00086 fNumAUHeaders(0), fNextAUHeader(0), fAUHeaders(NULL) {
00087 unsigned mimeTypeLength =
00088 strlen(mediumName) + 14 + 1;
00089 fMIMEType = new char[mimeTypeLength];
00090 if (fMIMEType != NULL) {
00091 sprintf(fMIMEType, "%s/MPEG4-GENERIC", mediumName);
00092 }
00093
00094 fMode = strDup(mode);
00095
00096 if (mode == NULL ||
00097 (strcmp(mode, "aac-hbr") != 0 && strcmp(mode, "generic") != 0)) {
00098 envir() << "MPEG4GenericRTPSource Warning: Unknown or unsupported \"mode\": "
00099 << mode << "\n";
00100 }
00101 }
00102
00103 MPEG4GenericRTPSource::~MPEG4GenericRTPSource() {
00104 delete[] fAUHeaders;
00105 delete[] fMode;
00106 delete[] fMIMEType;
00107 }
00108
00109 Boolean MPEG4GenericRTPSource
00110 ::processSpecialHeader(BufferedPacket* packet,
00111 unsigned& resultSpecialHeaderSize) {
00112 unsigned char* headerStart = packet->data();
00113 unsigned packetSize = packet->dataSize();
00114
00115 fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame;
00116
00117
00118
00119 fCurrentPacketCompletesFrame = packet->rtpMarkerBit();
00120
00121
00122 resultSpecialHeaderSize = 0;
00123 fNumAUHeaders = 0;
00124 fNextAUHeader = 0;
00125 delete[] fAUHeaders; fAUHeaders = NULL;
00126
00127 if (fSizeLength > 0) {
00128
00129
00130 resultSpecialHeaderSize += 2;
00131 if (packetSize < resultSpecialHeaderSize) return False;
00132
00133 unsigned AU_headers_length = (headerStart[0]<<8)|headerStart[1];
00134 unsigned AU_headers_length_bytes = (AU_headers_length+7)/8;
00135 if (packetSize
00136 < resultSpecialHeaderSize + AU_headers_length_bytes) return False;
00137 resultSpecialHeaderSize += AU_headers_length_bytes;
00138
00139
00140 int bitsAvail = AU_headers_length - (fSizeLength + fIndexLength);
00141 if (bitsAvail >= 0 && (fSizeLength + fIndexDeltaLength) > 0) {
00142 fNumAUHeaders = 1 + bitsAvail/(fSizeLength + fIndexDeltaLength);
00143 }
00144 if (fNumAUHeaders > 0) {
00145 fAUHeaders = new AUHeader[fNumAUHeaders];
00146
00147 BitVector bv(&headerStart[2], 0, AU_headers_length);
00148 fAUHeaders[0].size = bv.getBits(fSizeLength);
00149 fAUHeaders[0].index = bv.getBits(fIndexLength);
00150
00151 for (unsigned i = 1; i < fNumAUHeaders; ++i) {
00152 fAUHeaders[i].size = bv.getBits(fSizeLength);
00153 fAUHeaders[i].index = bv.getBits(fIndexDeltaLength);
00154 }
00155 }
00156
00157 }
00158
00159 return True;
00160 }
00161
00162 char const* MPEG4GenericRTPSource::MIMEtype() const {
00163 return fMIMEType;
00164 }
00165
00166
00169
00170 MPEG4GenericBufferedPacket
00171 ::MPEG4GenericBufferedPacket(MPEG4GenericRTPSource* ourSource)
00172 : fOurSource(ourSource) {
00173 }
00174
00175 MPEG4GenericBufferedPacket::~MPEG4GenericBufferedPacket() {
00176 }
00177
00178 unsigned MPEG4GenericBufferedPacket
00179 ::nextEnclosedFrameSize(unsigned char*& , unsigned dataSize) {
00180
00181 AUHeader* auHeader = fOurSource->fAUHeaders;
00182 if (auHeader == NULL) return dataSize;
00183 unsigned numAUHeaders = fOurSource->fNumAUHeaders;
00184
00185 if (fOurSource->fNextAUHeader >= numAUHeaders) {
00186 fOurSource->envir() << "MPEG4GenericBufferedPacket::nextEnclosedFrameSize("
00187 << dataSize << "): data error ("
00188 << auHeader << "," << fOurSource->fNextAUHeader
00189 << "," << numAUHeaders << ")!\n";
00190 return dataSize;
00191 }
00192
00193 auHeader = &auHeader[fOurSource->fNextAUHeader++];
00194 return auHeader->size <= dataSize ? auHeader->size : dataSize;
00195 }
00196
00197 BufferedPacket* MPEG4GenericBufferedPacketFactory
00198 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00199 return new MPEG4GenericBufferedPacket((MPEG4GenericRTPSource*)ourSource);
00200 }
00201
00202
00204
00205 static unsigned const samplingFrequencyFromIndex[16] = {
00206 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
00207 16000, 12000, 11025, 8000, 7350, 0, 0, 0
00208 };
00209
00210 unsigned samplingFrequencyFromAudioSpecificConfig(char const* configStr) {
00211 unsigned char* config = NULL;
00212 unsigned result = 0;
00213
00214 do {
00215
00216 unsigned configSize;
00217 config = parseGeneralConfigStr(configStr, configSize);
00218 if (config == NULL) break;
00219
00220 if (configSize < 2) break;
00221 unsigned char samplingFrequencyIndex = ((config[0]&0x07)<<1) | (config[1]>>7);
00222 if (samplingFrequencyIndex < 15) {
00223 result = samplingFrequencyFromIndex[samplingFrequencyIndex];
00224 break;
00225 }
00226
00227
00228 if (configSize < 5) break;
00229 result = ((config[1]&0x7F)<<17) | (config[2]<<9) | (config[3]<<1) | (config[4]>>7);
00230 } while (0);
00231
00232 delete[] config;
00233 return result;
00234 }