00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "WAVAudioFileServerMediaSubsession.hh"
00023 #include "WAVAudioFileSource.hh"
00024 #include "uLawAudioFilter.hh"
00025 #include "SimpleRTPSink.hh"
00026
00027 WAVAudioFileServerMediaSubsession* WAVAudioFileServerMediaSubsession
00028 ::createNew(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource,
00029 Boolean convertToULaw) {
00030 return new WAVAudioFileServerMediaSubsession(env, fileName,
00031 reuseFirstSource, convertToULaw);
00032 }
00033
00034 WAVAudioFileServerMediaSubsession
00035 ::WAVAudioFileServerMediaSubsession(UsageEnvironment& env, char const* fileName,
00036 Boolean reuseFirstSource, Boolean convertToULaw)
00037 : FileServerMediaSubsession(env, fileName, reuseFirstSource),
00038 fConvertToULaw(convertToULaw) {
00039 }
00040
00041 WAVAudioFileServerMediaSubsession
00042 ::~WAVAudioFileServerMediaSubsession() {
00043 }
00044
00045 void WAVAudioFileServerMediaSubsession
00046 ::seekStreamSource(FramedSource* inputSource, double& seekNPT, double streamDuration, u_int64_t& numBytes) {
00047 WAVAudioFileSource* wavSource;
00048 if (fBitsPerSample == 16) {
00049
00050 wavSource = (WAVAudioFileSource*)(((FramedFilter*)inputSource)->inputSource());
00051 } else {
00052
00053 wavSource = (WAVAudioFileSource*)inputSource;
00054 }
00055
00056 unsigned seekSampleNumber = (unsigned)(seekNPT*fSamplingFrequency);
00057 unsigned seekByteNumber = (seekSampleNumber*fNumChannels*fBitsPerSample)/8;
00058
00059 unsigned numDurationSamples = (unsigned)(streamDuration*fSamplingFrequency);
00060 unsigned numDurationBytes = (numDurationSamples*fNumChannels*fBitsPerSample)/8;
00061 numBytes = (u_int64_t)numDurationBytes;
00062
00063 wavSource->seekToPCMByte(seekByteNumber, numDurationBytes);
00064 }
00065
00066 void WAVAudioFileServerMediaSubsession
00067 ::setStreamSourceScale(FramedSource* inputSource, float scale) {
00068 int iScale = (int)scale;
00069 WAVAudioFileSource* wavSource;
00070 if (fBitsPerSample == 16) {
00071
00072 wavSource = (WAVAudioFileSource*)(((FramedFilter*)inputSource)->inputSource());
00073 } else {
00074
00075 wavSource = (WAVAudioFileSource*)inputSource;
00076 }
00077
00078 wavSource->setScaleFactor(iScale);
00079 }
00080
00081 FramedSource* WAVAudioFileServerMediaSubsession
00082 ::createNewStreamSource(unsigned , unsigned& estBitrate) {
00083 FramedSource* resultSource = NULL;
00084 do {
00085 WAVAudioFileSource* wavSource
00086 = WAVAudioFileSource::createNew(envir(), fFileName);
00087 if (wavSource == NULL) break;
00088
00089
00090
00091 fAudioFormat = wavSource->getAudioFormat();
00092 fBitsPerSample = wavSource->bitsPerSample();
00093 if (!(fBitsPerSample == 4 || fBitsPerSample == 8 || fBitsPerSample == 16)) {
00094 envir() << "The input file contains " << fBitsPerSample << " bit-per-sample audio, which we don't handle\n";
00095 break;
00096 }
00097 fSamplingFrequency = wavSource->samplingFrequency();
00098 fNumChannels = wavSource->numChannels();
00099 unsigned bitsPerSecond
00100 = fSamplingFrequency*fBitsPerSample*fNumChannels;
00101
00102 fFileDuration = (float)((8.0*wavSource->numPCMBytes())
00103 /(fSamplingFrequency*fNumChannels*fBitsPerSample));
00104
00105
00106 if (fBitsPerSample == 16) {
00107
00108 if (fConvertToULaw) {
00109
00110
00111 resultSource
00112 = uLawFromPCMAudioSource::createNew(envir(), wavSource, 1);
00113 bitsPerSecond /= 2;
00114 } else {
00115
00116 resultSource = EndianSwap16::createNew(envir(), wavSource);
00117 }
00118 } else {
00119
00120 resultSource = wavSource;
00121 }
00122
00123 estBitrate = (bitsPerSecond+500)/1000;
00124 return resultSource;
00125 } while (0);
00126
00127
00128 Medium::close(resultSource);
00129 return NULL;
00130 }
00131
00132 RTPSink* WAVAudioFileServerMediaSubsession
00133 ::createNewRTPSink(Groupsock* rtpGroupsock,
00134 unsigned char rtpPayloadTypeIfDynamic,
00135 FramedSource* ) {
00136 do {
00137 char const* mimeType;
00138 unsigned char payloadFormatCode;
00139 if (fAudioFormat == WA_PCM) {
00140 if (fBitsPerSample == 16) {
00141 if (fConvertToULaw) {
00142 mimeType = "PCMU";
00143 if (fSamplingFrequency == 8000 && fNumChannels == 1) {
00144 payloadFormatCode = 0;
00145 } else {
00146 payloadFormatCode = rtpPayloadTypeIfDynamic;
00147 }
00148 } else {
00149 mimeType = "L16";
00150 if (fSamplingFrequency == 44100 && fNumChannels == 2) {
00151 payloadFormatCode = 10;
00152 } else if (fSamplingFrequency == 44100 && fNumChannels == 1) {
00153 payloadFormatCode = 11;
00154 } else {
00155 payloadFormatCode = rtpPayloadTypeIfDynamic;
00156 }
00157 }
00158 } else {
00159 mimeType = "L8";
00160 payloadFormatCode = rtpPayloadTypeIfDynamic;
00161 }
00162 } else if (fAudioFormat == WA_PCMU) {
00163 mimeType = "PCMU";
00164 if (fSamplingFrequency == 8000 && fNumChannels == 1) {
00165 payloadFormatCode = 0;
00166 } else {
00167 payloadFormatCode = rtpPayloadTypeIfDynamic;
00168 }
00169 } else if (fAudioFormat == WA_PCMA) {
00170 mimeType = "PCMA";
00171 if (fSamplingFrequency == 8000 && fNumChannels == 1) {
00172 payloadFormatCode = 8;
00173 } else {
00174 payloadFormatCode = rtpPayloadTypeIfDynamic;
00175 }
00176 } else if (fAudioFormat == WA_IMA_ADPCM) {
00177 mimeType = "DVI4";
00178 payloadFormatCode = rtpPayloadTypeIfDynamic;
00179
00180 if (fNumChannels == 1) {
00181 if (fSamplingFrequency == 8000) {
00182 payloadFormatCode = 5;
00183 } else if (fSamplingFrequency == 16000) {
00184 payloadFormatCode = 6;
00185 } else if (fSamplingFrequency == 11025) {
00186 payloadFormatCode = 16;
00187 } else if (fSamplingFrequency == 22050) {
00188 payloadFormatCode = 17;
00189 }
00190 }
00191 } else {
00192 break;
00193 }
00194
00195 return SimpleRTPSink::createNew(envir(), rtpGroupsock,
00196 payloadFormatCode, fSamplingFrequency,
00197 "audio", mimeType, fNumChannels);
00198 } while (0);
00199
00200
00201 return NULL;
00202 }
00203
00204 void WAVAudioFileServerMediaSubsession::testScaleFactor(float& scale) {
00205 if (fFileDuration <= 0.0) {
00206
00207
00208 scale = 1;
00209 } else {
00210
00211 int iScale = scale < 0.0 ? (int)(scale - 0.5) : (int)(scale + 0.5);
00212 if (iScale == 0) iScale = 1;
00213 scale = (float)iScale;
00214 }
00215 }
00216
00217 float WAVAudioFileServerMediaSubsession::duration() const {
00218 return fFileDuration;
00219 }