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