00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MPEG4LATMAudioRTPSource.hh"
00022
00024
00025 class LATMBufferedPacket: public BufferedPacket {
00026 public:
00027 LATMBufferedPacket(Boolean includeLATMDataLengthField);
00028 virtual ~LATMBufferedPacket();
00029
00030 private:
00031 virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00032 unsigned dataSize);
00033
00034 private:
00035 Boolean fIncludeLATMDataLengthField;
00036 };
00037
00038 class LATMBufferedPacketFactory: public BufferedPacketFactory {
00039 private:
00040 virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00041 };
00042
00044
00045 MPEG4LATMAudioRTPSource*
00046 MPEG4LATMAudioRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00047 unsigned char rtpPayloadFormat,
00048 unsigned rtpTimestampFrequency) {
00049 return new MPEG4LATMAudioRTPSource(env, RTPgs, rtpPayloadFormat,
00050 rtpTimestampFrequency);
00051 }
00052
00053 MPEG4LATMAudioRTPSource
00054 ::MPEG4LATMAudioRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00055 unsigned char rtpPayloadFormat,
00056 unsigned rtpTimestampFrequency)
00057 : MultiFramedRTPSource(env, RTPgs,
00058 rtpPayloadFormat, rtpTimestampFrequency,
00059 new LATMBufferedPacketFactory),
00060 fIncludeLATMDataLengthField(True) {
00061 }
00062
00063 MPEG4LATMAudioRTPSource::~MPEG4LATMAudioRTPSource() {
00064 }
00065
00066 void MPEG4LATMAudioRTPSource::omitLATMDataLengthField() {
00067 fIncludeLATMDataLengthField = False;
00068 }
00069
00070 Boolean MPEG4LATMAudioRTPSource
00071 ::processSpecialHeader(BufferedPacket* packet,
00072 unsigned& resultSpecialHeaderSize) {
00073 fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame;
00074
00075
00076
00077 fCurrentPacketCompletesFrame = packet->rtpMarkerBit();
00078
00079
00080 resultSpecialHeaderSize = 0;
00081 return True;
00082 }
00083
00084 char const* MPEG4LATMAudioRTPSource::MIMEtype() const {
00085 return "audio/MP4A-LATM";
00086 }
00087
00088
00090
00091 LATMBufferedPacket::LATMBufferedPacket(Boolean includeLATMDataLengthField)
00092 : fIncludeLATMDataLengthField(includeLATMDataLengthField) {
00093 }
00094
00095 LATMBufferedPacket::~LATMBufferedPacket() {
00096 }
00097
00098 unsigned LATMBufferedPacket
00099 ::nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) {
00100
00101
00102 unsigned resultFrameSize = 0;
00103 unsigned i;
00104 for (i = 0; i < dataSize; ++i) {
00105 resultFrameSize += framePtr[i];
00106 if (framePtr[i] != 0xFF) break;
00107 }
00108 ++i;
00109 if (fIncludeLATMDataLengthField) {
00110 resultFrameSize += i;
00111 } else {
00112 framePtr += i;
00113 dataSize -= i;
00114 }
00115
00116 return (resultFrameSize <= dataSize) ? resultFrameSize : dataSize;
00117 }
00118
00119 BufferedPacket* LATMBufferedPacketFactory
00120 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00121 MPEG4LATMAudioRTPSource* source = (MPEG4LATMAudioRTPSource*)ourSource;
00122 return new LATMBufferedPacket(source->returnedFrameIncludesLATMDataLengthField());
00123 }
00124
00125
00127
00128 static Boolean getNibble(char const*& configStr,
00129 unsigned char& resultNibble) {
00130 char c = configStr[0];
00131 if (c == '\0') return False;
00132
00133 if (c >= '0' && c <= '9') {
00134 resultNibble = c - '0';
00135 } else if (c >= 'A' && c <= 'F') {
00136 resultNibble = 10 + c - 'A';
00137 } else if (c >= 'a' && c <= 'f') {
00138 resultNibble = 10 + c - 'a';
00139 } else {
00140 return False;
00141 }
00142
00143 ++configStr;
00144 return True;
00145 }
00146
00147 static Boolean getByte(char const*& configStr, unsigned char& resultByte) {
00148 resultByte = 0;
00149
00150 unsigned char firstNibble;
00151 if (!getNibble(configStr, firstNibble)) return False;
00152 resultByte = firstNibble<<4;
00153
00154 unsigned char secondNibble = 0;
00155 if (!getNibble(configStr, secondNibble) && configStr[0] != '\0') {
00156
00157 return False;
00158 }
00159 resultByte |= secondNibble;
00160
00161 return True;
00162 }
00163
00164 Boolean
00165 parseStreamMuxConfigStr(char const* configStr,
00166
00167 Boolean& audioMuxVersion,
00168 Boolean& allStreamsSameTimeFraming,
00169 unsigned char& numSubFrames,
00170 unsigned char& numProgram,
00171 unsigned char& numLayer,
00172 unsigned char*& audioSpecificConfig,
00173 unsigned& audioSpecificConfigSize) {
00174
00175 audioMuxVersion = 0;
00176 allStreamsSameTimeFraming = 1;
00177 numSubFrames = numProgram = numLayer = 0;
00178 audioSpecificConfig = NULL;
00179 audioSpecificConfigSize = 0;
00180
00181 do {
00182 if (configStr == NULL) break;
00183
00184 unsigned char nextByte;
00185
00186 if (!getByte(configStr, nextByte)) break;
00187 audioMuxVersion = (nextByte&0x80)>>7;
00188 if (audioMuxVersion != 0) break;
00189
00190 allStreamsSameTimeFraming = (nextByte&0x40)>>6;
00191 numSubFrames = (nextByte&0x3F);
00192
00193 if (!getByte(configStr, nextByte)) break;
00194 numProgram = (nextByte&0xF0)>>4;
00195
00196 numLayer = (nextByte&0x0E)>>1;
00197
00198
00199
00200 unsigned char remainingBit = nextByte&1;
00201
00202 unsigned ascSize = (strlen(configStr)+1)/2 + 1;
00203 audioSpecificConfig = new unsigned char[ascSize];
00204
00205 Boolean parseSuccess;
00206 unsigned i = 0;
00207 do {
00208 nextByte = 0;
00209 parseSuccess = getByte(configStr, nextByte);
00210 audioSpecificConfig[i++] = (remainingBit<<7)|((nextByte&0xFE)>>1);
00211 remainingBit = nextByte&1;
00212 } while (parseSuccess);
00213 if (i != ascSize) break;
00214
00215 audioSpecificConfigSize = ascSize;
00216 return True;
00217 } while (0);
00218
00219 delete[] audioSpecificConfig;
00220 return False;
00221 }
00222
00223 unsigned char* parseStreamMuxConfigStr(char const* configStr,
00224
00225 unsigned& audioSpecificConfigSize) {
00226 Boolean audioMuxVersion, allStreamsSameTimeFraming;
00227 unsigned char numSubFrames, numProgram, numLayer;
00228 unsigned char* audioSpecificConfig;
00229
00230 if (!parseStreamMuxConfigStr(configStr,
00231 audioMuxVersion, allStreamsSameTimeFraming,
00232 numSubFrames, numProgram, numLayer,
00233 audioSpecificConfig, audioSpecificConfigSize)) {
00234 audioSpecificConfigSize = 0;
00235 return NULL;
00236 }
00237
00238 return audioSpecificConfig;
00239 }
00240
00241 unsigned char* parseGeneralConfigStr(char const* configStr,
00242
00243 unsigned& configSize) {
00244 unsigned char* config = NULL;
00245 do {
00246 if (configStr == NULL) break;
00247 configSize = (strlen(configStr)+1)/2;
00248
00249 config = new unsigned char[configSize];
00250 if (config == NULL) break;
00251
00252 unsigned i;
00253 for (i = 0; i < configSize; ++i) {
00254 if (!getByte(configStr, config[i])) break;
00255 }
00256 if (i != configSize) break;
00257
00258 return config;
00259 } while (0);
00260
00261 configSize = 0;
00262 delete[] config;
00263 return NULL;
00264 }