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 unsigned char firstNibble;
00149 if (!getNibble(configStr, firstNibble)) return False;
00150
00151 unsigned char secondNibble = 0;
00152 if (!getNibble(configStr, secondNibble) && configStr[0] != '\0') {
00153
00154 return False;
00155 }
00156
00157 resultByte = (firstNibble<<4)|secondNibble;
00158 return True;
00159 }
00160
00161 Boolean
00162 parseStreamMuxConfigStr(char const* configStr,
00163
00164 Boolean& audioMuxVersion,
00165 Boolean& allStreamsSameTimeFraming,
00166 unsigned char& numSubFrames,
00167 unsigned char& numProgram,
00168 unsigned char& numLayer,
00169 unsigned char*& audioSpecificConfig,
00170 unsigned& audioSpecificConfigSize) {
00171
00172 audioMuxVersion = 0;
00173 allStreamsSameTimeFraming = 1;
00174 numSubFrames = numProgram = numLayer = 0;
00175 audioSpecificConfig = NULL;
00176 audioSpecificConfigSize = 0;
00177
00178 do {
00179 if (configStr == NULL) break;
00180
00181 unsigned char nextByte;
00182
00183 if (!getByte(configStr, nextByte)) break;
00184 audioMuxVersion = (nextByte&0x80)>>7;
00185 if (audioMuxVersion != 0) break;
00186
00187 allStreamsSameTimeFraming = (nextByte&0x40)>>6;
00188 numSubFrames = (nextByte&0x3F);
00189
00190 if (!getByte(configStr, nextByte)) break;
00191 numProgram = (nextByte&0xF0)>>4;
00192
00193 numLayer = (nextByte&0x0E)>>1;
00194
00195
00196
00197 unsigned char remainingBit = nextByte&1;
00198
00199 unsigned ascSize = (strlen(configStr)+1)/2 + 1;
00200 audioSpecificConfig = new unsigned char[ascSize];
00201
00202 Boolean parseSuccess;
00203 unsigned i = 0;
00204 do {
00205 nextByte = 0;
00206 parseSuccess = getByte(configStr, nextByte);
00207 audioSpecificConfig[i++] = (remainingBit<<7)|((nextByte&0xFE)>>1);
00208 remainingBit = nextByte&1;
00209 } while (parseSuccess);
00210 if (i != ascSize) break;
00211
00212 audioSpecificConfigSize = ascSize;
00213 return True;
00214 } while (0);
00215
00216 delete[] audioSpecificConfig;
00217 return False;
00218 }
00219
00220 unsigned char* parseStreamMuxConfigStr(char const* configStr,
00221
00222 unsigned& audioSpecificConfigSize) {
00223 Boolean audioMuxVersion, allStreamsSameTimeFraming;
00224 unsigned char numSubFrames, numProgram, numLayer;
00225 unsigned char* audioSpecificConfig;
00226
00227 if (!parseStreamMuxConfigStr(configStr,
00228 audioMuxVersion, allStreamsSameTimeFraming,
00229 numSubFrames, numProgram, numLayer,
00230 audioSpecificConfig, audioSpecificConfigSize)) {
00231 audioSpecificConfigSize = 0;
00232 return NULL;
00233 }
00234
00235 return audioSpecificConfig;
00236 }
00237
00238 unsigned char* parseGeneralConfigStr(char const* configStr,
00239
00240 unsigned& configSize) {
00241 unsigned char* config = NULL;
00242 do {
00243 if (configStr == NULL) break;
00244 configSize = (strlen(configStr)+1)/2 + 1;
00245
00246 config = new unsigned char[configSize];
00247 if (config == NULL) break;
00248
00249 Boolean parseSuccess;
00250 unsigned i = 0;
00251 do {
00252 parseSuccess = getByte(configStr, config[i++]);
00253 } while (parseSuccess);
00254 if (i != configSize) break;
00255
00256
00257 return config;
00258 } while (0);
00259
00260 configSize = 0;
00261 delete[] config;
00262 return NULL;
00263 }
00264