| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/modules/utility/source/file_player_impl.h" | |
| 12 #include "webrtc/system_wrappers/include/logging.h" | |
| 13 | |
| 14 namespace webrtc { | |
| 15 FilePlayer* FilePlayer::CreateFilePlayer(uint32_t instanceID, | |
| 16 FileFormats fileFormat) { | |
| 17 switch (fileFormat) { | |
| 18 case kFileFormatWavFile: | |
| 19 case kFileFormatCompressedFile: | |
| 20 case kFileFormatPreencodedFile: | |
| 21 case kFileFormatPcm16kHzFile: | |
| 22 case kFileFormatPcm8kHzFile: | |
| 23 case kFileFormatPcm32kHzFile: | |
| 24 // audio formats | |
| 25 return new FilePlayerImpl(instanceID, fileFormat); | |
| 26 default: | |
| 27 assert(false); | |
| 28 return NULL; | |
| 29 } | |
| 30 } | |
| 31 | |
| 32 void FilePlayer::DestroyFilePlayer(FilePlayer* player) { | |
| 33 delete player; | |
| 34 } | |
| 35 | |
| 36 FilePlayerImpl::FilePlayerImpl(const uint32_t instanceID, | |
| 37 const FileFormats fileFormat) | |
| 38 : _instanceID(instanceID), | |
| 39 _fileFormat(fileFormat), | |
| 40 _fileModule(*MediaFile::CreateMediaFile(instanceID)), | |
| 41 _decodedLengthInMS(0), | |
| 42 _audioDecoder(instanceID), | |
| 43 _codec(), | |
| 44 _numberOf10MsPerFrame(0), | |
| 45 _numberOf10MsInDecoder(0), | |
| 46 _resampler(), | |
| 47 _scaling(1.0) { | |
| 48 _codec.plfreq = 0; | |
| 49 } | |
| 50 | |
| 51 FilePlayerImpl::~FilePlayerImpl() { | |
| 52 MediaFile::DestroyMediaFile(&_fileModule); | |
| 53 } | |
| 54 | |
| 55 int32_t FilePlayerImpl::Frequency() const { | |
| 56 if (_codec.plfreq == 0) { | |
| 57 return -1; | |
| 58 } | |
| 59 // Make sure that sample rate is 8,16 or 32 kHz. E.g. WAVE files may have | |
| 60 // other sampling rates. | |
| 61 if (_codec.plfreq == 11000) { | |
| 62 return 16000; | |
| 63 } else if (_codec.plfreq == 22000) { | |
| 64 return 32000; | |
| 65 } else if (_codec.plfreq == 44000) { | |
| 66 return 32000; | |
| 67 } else if (_codec.plfreq == 48000) { | |
| 68 return 32000; | |
| 69 } else { | |
| 70 return _codec.plfreq; | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 int32_t FilePlayerImpl::AudioCodec(CodecInst& audioCodec) const { | |
| 75 audioCodec = _codec; | |
| 76 return 0; | |
| 77 } | |
| 78 | |
| 79 int32_t FilePlayerImpl::Get10msAudioFromFile(int16_t* outBuffer, | |
| 80 size_t& lengthInSamples, | |
| 81 int frequencyInHz) { | |
| 82 if (_codec.plfreq == 0) { | |
| 83 LOG(LS_WARNING) << "Get10msAudioFromFile() playing not started!" | |
| 84 << " codec freq = " << _codec.plfreq | |
| 85 << ", wanted freq = " << frequencyInHz; | |
| 86 return -1; | |
| 87 } | |
| 88 | |
| 89 AudioFrame unresampledAudioFrame; | |
| 90 if (STR_CASE_CMP(_codec.plname, "L16") == 0) { | |
| 91 unresampledAudioFrame.sample_rate_hz_ = _codec.plfreq; | |
| 92 | |
| 93 // L16 is un-encoded data. Just pull 10 ms. | |
| 94 size_t lengthInBytes = sizeof(unresampledAudioFrame.data_); | |
| 95 if (_fileModule.PlayoutAudioData((int8_t*)unresampledAudioFrame.data_, | |
| 96 lengthInBytes) == -1) { | |
| 97 // End of file reached. | |
| 98 return -1; | |
| 99 } | |
| 100 if (lengthInBytes == 0) { | |
| 101 lengthInSamples = 0; | |
| 102 return 0; | |
| 103 } | |
| 104 // One sample is two bytes. | |
| 105 unresampledAudioFrame.samples_per_channel_ = lengthInBytes >> 1; | |
| 106 | |
| 107 } else { | |
| 108 // Decode will generate 10 ms of audio data. PlayoutAudioData(..) | |
| 109 // expects a full frame. If the frame size is larger than 10 ms, | |
| 110 // PlayoutAudioData(..) data should be called proportionally less often. | |
| 111 int16_t encodedBuffer[MAX_AUDIO_BUFFER_IN_SAMPLES]; | |
| 112 size_t encodedLengthInBytes = 0; | |
| 113 if (++_numberOf10MsInDecoder >= _numberOf10MsPerFrame) { | |
| 114 _numberOf10MsInDecoder = 0; | |
| 115 size_t bytesFromFile = sizeof(encodedBuffer); | |
| 116 if (_fileModule.PlayoutAudioData((int8_t*)encodedBuffer, bytesFromFile) == | |
| 117 -1) { | |
| 118 // End of file reached. | |
| 119 return -1; | |
| 120 } | |
| 121 encodedLengthInBytes = bytesFromFile; | |
| 122 } | |
| 123 if (_audioDecoder.Decode(unresampledAudioFrame, frequencyInHz, | |
| 124 (int8_t*)encodedBuffer, | |
| 125 encodedLengthInBytes) == -1) { | |
| 126 return -1; | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 size_t outLen = 0; | |
| 131 if (_resampler.ResetIfNeeded(unresampledAudioFrame.sample_rate_hz_, | |
| 132 frequencyInHz, 1)) { | |
| 133 LOG(LS_WARNING) << "Get10msAudioFromFile() unexpected codec."; | |
| 134 | |
| 135 // New sampling frequency. Update state. | |
| 136 outLen = static_cast<size_t>(frequencyInHz / 100); | |
| 137 memset(outBuffer, 0, outLen * sizeof(int16_t)); | |
| 138 return 0; | |
| 139 } | |
| 140 _resampler.Push(unresampledAudioFrame.data_, | |
| 141 unresampledAudioFrame.samples_per_channel_, outBuffer, | |
| 142 MAX_AUDIO_BUFFER_IN_SAMPLES, outLen); | |
| 143 | |
| 144 lengthInSamples = outLen; | |
| 145 | |
| 146 if (_scaling != 1.0) { | |
| 147 for (size_t i = 0; i < outLen; i++) { | |
| 148 outBuffer[i] = (int16_t)(outBuffer[i] * _scaling); | |
| 149 } | |
| 150 } | |
| 151 _decodedLengthInMS += 10; | |
| 152 return 0; | |
| 153 } | |
| 154 | |
| 155 int32_t FilePlayerImpl::RegisterModuleFileCallback(FileCallback* callback) { | |
| 156 return _fileModule.SetModuleFileCallback(callback); | |
| 157 } | |
| 158 | |
| 159 int32_t FilePlayerImpl::SetAudioScaling(float scaleFactor) { | |
| 160 if ((scaleFactor >= 0) && (scaleFactor <= 2.0)) { | |
| 161 _scaling = scaleFactor; | |
| 162 return 0; | |
| 163 } | |
| 164 LOG(LS_WARNING) << "SetAudioScaling() non-allowed scale factor."; | |
| 165 return -1; | |
| 166 } | |
| 167 | |
| 168 int32_t FilePlayerImpl::StartPlayingFile(const char* fileName, | |
| 169 bool loop, | |
| 170 uint32_t startPosition, | |
| 171 float volumeScaling, | |
| 172 uint32_t notification, | |
| 173 uint32_t stopPosition, | |
| 174 const CodecInst* codecInst) { | |
| 175 if (_fileFormat == kFileFormatPcm16kHzFile || | |
| 176 _fileFormat == kFileFormatPcm8kHzFile || | |
| 177 _fileFormat == kFileFormatPcm32kHzFile) { | |
| 178 CodecInst codecInstL16; | |
| 179 strncpy(codecInstL16.plname, "L16", 32); | |
| 180 codecInstL16.pltype = 93; | |
| 181 codecInstL16.channels = 1; | |
| 182 | |
| 183 if (_fileFormat == kFileFormatPcm8kHzFile) { | |
| 184 codecInstL16.rate = 128000; | |
| 185 codecInstL16.plfreq = 8000; | |
| 186 codecInstL16.pacsize = 80; | |
| 187 | |
| 188 } else if (_fileFormat == kFileFormatPcm16kHzFile) { | |
| 189 codecInstL16.rate = 256000; | |
| 190 codecInstL16.plfreq = 16000; | |
| 191 codecInstL16.pacsize = 160; | |
| 192 | |
| 193 } else if (_fileFormat == kFileFormatPcm32kHzFile) { | |
| 194 codecInstL16.rate = 512000; | |
| 195 codecInstL16.plfreq = 32000; | |
| 196 codecInstL16.pacsize = 160; | |
| 197 } else { | |
| 198 LOG(LS_ERROR) << "StartPlayingFile() sample frequency not " | |
| 199 << "supported for PCM format."; | |
| 200 return -1; | |
| 201 } | |
| 202 | |
| 203 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop, | |
| 204 _fileFormat, &codecInstL16, | |
| 205 startPosition, stopPosition) == -1) { | |
| 206 LOG(LS_WARNING) << "StartPlayingFile() failed to initialize " | |
| 207 << "pcm file " << fileName; | |
| 208 return -1; | |
| 209 } | |
| 210 SetAudioScaling(volumeScaling); | |
| 211 } else if (_fileFormat == kFileFormatPreencodedFile) { | |
| 212 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop, | |
| 213 _fileFormat, codecInst) == -1) { | |
| 214 LOG(LS_WARNING) << "StartPlayingFile() failed to initialize " | |
| 215 << "pre-encoded file " << fileName; | |
| 216 return -1; | |
| 217 } | |
| 218 } else { | |
| 219 CodecInst* no_inst = NULL; | |
| 220 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop, | |
| 221 _fileFormat, no_inst, startPosition, | |
| 222 stopPosition) == -1) { | |
| 223 LOG(LS_WARNING) << "StartPlayingFile() failed to initialize file " | |
| 224 << fileName; | |
| 225 return -1; | |
| 226 } | |
| 227 SetAudioScaling(volumeScaling); | |
| 228 } | |
| 229 if (SetUpAudioDecoder() == -1) { | |
| 230 StopPlayingFile(); | |
| 231 return -1; | |
| 232 } | |
| 233 return 0; | |
| 234 } | |
| 235 | |
| 236 int32_t FilePlayerImpl::StartPlayingFile(InStream& sourceStream, | |
| 237 uint32_t startPosition, | |
| 238 float volumeScaling, | |
| 239 uint32_t notification, | |
| 240 uint32_t stopPosition, | |
| 241 const CodecInst* codecInst) { | |
| 242 if (_fileFormat == kFileFormatPcm16kHzFile || | |
| 243 _fileFormat == kFileFormatPcm32kHzFile || | |
| 244 _fileFormat == kFileFormatPcm8kHzFile) { | |
| 245 CodecInst codecInstL16; | |
| 246 strncpy(codecInstL16.plname, "L16", 32); | |
| 247 codecInstL16.pltype = 93; | |
| 248 codecInstL16.channels = 1; | |
| 249 | |
| 250 if (_fileFormat == kFileFormatPcm8kHzFile) { | |
| 251 codecInstL16.rate = 128000; | |
| 252 codecInstL16.plfreq = 8000; | |
| 253 codecInstL16.pacsize = 80; | |
| 254 | |
| 255 } else if (_fileFormat == kFileFormatPcm16kHzFile) { | |
| 256 codecInstL16.rate = 256000; | |
| 257 codecInstL16.plfreq = 16000; | |
| 258 codecInstL16.pacsize = 160; | |
| 259 | |
| 260 } else if (_fileFormat == kFileFormatPcm32kHzFile) { | |
| 261 codecInstL16.rate = 512000; | |
| 262 codecInstL16.plfreq = 32000; | |
| 263 codecInstL16.pacsize = 160; | |
| 264 } else { | |
| 265 LOG(LS_ERROR) << "StartPlayingFile() sample frequency not " | |
| 266 << "supported for PCM format."; | |
| 267 return -1; | |
| 268 } | |
| 269 if (_fileModule.StartPlayingAudioStream( | |
| 270 sourceStream, notification, _fileFormat, &codecInstL16, | |
| 271 startPosition, stopPosition) == -1) { | |
| 272 LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream " | |
| 273 << "playout."; | |
| 274 return -1; | |
| 275 } | |
| 276 | |
| 277 } else if (_fileFormat == kFileFormatPreencodedFile) { | |
| 278 if (_fileModule.StartPlayingAudioStream(sourceStream, notification, | |
| 279 _fileFormat, codecInst) == -1) { | |
| 280 LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream " | |
| 281 << "playout."; | |
| 282 return -1; | |
| 283 } | |
| 284 } else { | |
| 285 CodecInst* no_inst = NULL; | |
| 286 if (_fileModule.StartPlayingAudioStream(sourceStream, notification, | |
| 287 _fileFormat, no_inst, startPosition, | |
| 288 stopPosition) == -1) { | |
| 289 LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream " | |
| 290 << "playout."; | |
| 291 return -1; | |
| 292 } | |
| 293 } | |
| 294 SetAudioScaling(volumeScaling); | |
| 295 | |
| 296 if (SetUpAudioDecoder() == -1) { | |
| 297 StopPlayingFile(); | |
| 298 return -1; | |
| 299 } | |
| 300 return 0; | |
| 301 } | |
| 302 | |
| 303 int32_t FilePlayerImpl::StopPlayingFile() { | |
| 304 memset(&_codec, 0, sizeof(CodecInst)); | |
| 305 _numberOf10MsPerFrame = 0; | |
| 306 _numberOf10MsInDecoder = 0; | |
| 307 return _fileModule.StopPlaying(); | |
| 308 } | |
| 309 | |
| 310 bool FilePlayerImpl::IsPlayingFile() const { | |
| 311 return _fileModule.IsPlaying(); | |
| 312 } | |
| 313 | |
| 314 int32_t FilePlayerImpl::GetPlayoutPosition(uint32_t& durationMs) { | |
| 315 return _fileModule.PlayoutPositionMs(durationMs); | |
| 316 } | |
| 317 | |
| 318 int32_t FilePlayerImpl::SetUpAudioDecoder() { | |
| 319 if ((_fileModule.codec_info(_codec) == -1)) { | |
| 320 LOG(LS_WARNING) << "Failed to retrieve codec info of file data."; | |
| 321 return -1; | |
| 322 } | |
| 323 if (STR_CASE_CMP(_codec.plname, "L16") != 0 && | |
| 324 _audioDecoder.SetDecodeCodec(_codec) == -1) { | |
| 325 LOG(LS_WARNING) << "SetUpAudioDecoder() codec " << _codec.plname | |
| 326 << " not supported."; | |
| 327 return -1; | |
| 328 } | |
| 329 _numberOf10MsPerFrame = _codec.pacsize / (_codec.plfreq / 100); | |
| 330 _numberOf10MsInDecoder = 0; | |
| 331 return 0; | |
| 332 } | |
| 333 } // namespace webrtc | |
| OLD | NEW |