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/interface/logging.h" 13 14 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 15 #include "frame_scaler.h" 16 #include "tick_util.h" 17 #include "video_coder.h" 18 #endif 19 20 namespace webrtc { 21 FilePlayer* FilePlayer::CreateFilePlayer(uint32_t instanceID, 22 FileFormats fileFormat) 23 { 24 switch(fileFormat) 25 { 26 case kFileFormatWavFile: 27 case kFileFormatCompressedFile: 28 case kFileFormatPreencodedFile: 29 case kFileFormatPcm16kHzFile: 30 case kFileFormatPcm8kHzFile: 31 case kFileFormatPcm32kHzFile: 32 // audio formats 33 return new FilePlayerImpl(instanceID, fileFormat); 34 case kFileFormatAviFile: 35 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 36 return new VideoFilePlayerImpl(instanceID, fileFormat); 37 #else 38 assert(false); 39 return NULL; 40 #endif 41 } 42 assert(false); 43 return NULL; 44 } 45 46 void FilePlayer::DestroyFilePlayer(FilePlayer* player) 47 { 48 delete player; 49 } 50 51 FilePlayerImpl::FilePlayerImpl(const uint32_t instanceID, 52 const FileFormats fileFormat) 53 : _instanceID(instanceID), 54 _fileFormat(fileFormat), 55 _fileModule(*MediaFile::CreateMediaFile(instanceID)), 56 _decodedLengthInMS(0), 57 _audioDecoder(instanceID), 58 _codec(), 59 _numberOf10MsPerFrame(0), 60 _numberOf10MsInDecoder(0), 61 _resampler(), 62 _scaling(1.0) 63 { 64 _codec.plfreq = 0; 65 } 66 67 FilePlayerImpl::~FilePlayerImpl() 68 { 69 MediaFile::DestroyMediaFile(&_fileModule); 70 } 71 72 int32_t FilePlayerImpl::Frequency() const 73 { 74 if(_codec.plfreq == 0) 75 { 76 return -1; 77 } 78 // Make sure that sample rate is 8,16 or 32 kHz. E.g. WAVE files may have 79 // other sampling rates. 80 if(_codec.plfreq == 11000) 81 { 82 return 16000; 83 } 84 else if(_codec.plfreq == 22000) 85 { 86 return 32000; 87 } 88 else if(_codec.plfreq == 44000) 89 { 90 return 32000; 91 } 92 else if(_codec.plfreq == 48000) 93 { 94 return 32000; 95 } 96 else 97 { 98 return _codec.plfreq; 99 } 100 } 101 102 int32_t FilePlayerImpl::AudioCodec(CodecInst& audioCodec) const 103 { 104 audioCodec = _codec; 105 return 0; 106 } 107 108 int32_t FilePlayerImpl::Get10msAudioFromFile( 109 int16_t* outBuffer, 110 int& lengthInSamples, 111 int frequencyInHz) 112 { 113 if(_codec.plfreq == 0) 114 { 115 LOG(LS_WARNING) << "Get10msAudioFromFile() playing not started!" 116 << " codec freq = " << _codec.plfreq 117 << ", wanted freq = " << frequencyInHz; 118 return -1; 119 } 120 121 AudioFrame unresampledAudioFrame; 122 if(STR_CASE_CMP(_codec.plname, "L16") == 0) 123 { 124 unresampledAudioFrame.sample_rate_hz_ = _codec.plfreq; 125 126 // L16 is un-encoded data. Just pull 10 ms. 127 uint32_t lengthInBytes = 128 sizeof(unresampledAudioFrame.data_); 129 if (_fileModule.PlayoutAudioData( 130 (int8_t*)unresampledAudioFrame.data_, 131 lengthInBytes) == -1) 132 { 133 // End of file reached. 134 return -1; 135 } 136 if(lengthInBytes == 0) 137 { 138 lengthInSamples = 0; 139 return 0; 140 } 141 // One sample is two bytes. 142 unresampledAudioFrame.samples_per_channel_ = 143 (uint16_t)lengthInBytes >> 1; 144 145 }else { 146 // Decode will generate 10 ms of audio data. PlayoutAudioData(..) 147 // expects a full frame. If the frame size is larger than 10 ms, 148 // PlayoutAudioData(..) data should be called proportionally less often. 149 int16_t encodedBuffer[MAX_AUDIO_BUFFER_IN_SAMPLES]; 150 uint32_t encodedLengthInBytes = 0; 151 if(++_numberOf10MsInDecoder >= _numberOf10MsPerFrame) 152 { 153 _numberOf10MsInDecoder = 0; 154 uint32_t bytesFromFile = sizeof(encodedBuffer); 155 if (_fileModule.PlayoutAudioData((int8_t*)encodedBuffer, 156 bytesFromFile) == -1) 157 { 158 // End of file reached. 159 return -1; 160 } 161 encodedLengthInBytes = bytesFromFile; 162 } 163 if(_audioDecoder.Decode(unresampledAudioFrame,frequencyInHz, 164 (int8_t*)encodedBuffer, 165 encodedLengthInBytes) == -1) 166 { 167 return -1; 168 } 169 } 170 171 int outLen = 0; 172 if(_resampler.ResetIfNeeded(unresampledAudioFrame.sample_rate_hz_, 173 frequencyInHz, kResamplerSynchronous)) 174 { 175 LOG(LS_WARNING) << "Get10msAudioFromFile() unexpected codec."; 176 177 // New sampling frequency. Update state. 178 outLen = frequencyInHz / 100; 179 memset(outBuffer, 0, outLen * sizeof(int16_t)); 180 return 0; 181 } 182 _resampler.Push(unresampledAudioFrame.data_, 183 unresampledAudioFrame.samples_per_channel_, 184 outBuffer, 185 MAX_AUDIO_BUFFER_IN_SAMPLES, 186 outLen); 187 188 lengthInSamples = outLen; 189 190 if(_scaling != 1.0) 191 { 192 for (int i = 0;i < outLen; i++) 193 { 194 outBuffer[i] = (int16_t)(outBuffer[i] * _scaling); 195 } 196 } 197 _decodedLengthInMS += 10; 198 return 0; 199 } 200 201 int32_t FilePlayerImpl::RegisterModuleFileCallback(FileCallback* callback) 202 { 203 return _fileModule.SetModuleFileCallback(callback); 204 } 205 206 int32_t FilePlayerImpl::SetAudioScaling(float scaleFactor) 207 { 208 if((scaleFactor >= 0)&&(scaleFactor <= 2.0)) 209 { 210 _scaling = scaleFactor; 211 return 0; 212 } 213 LOG(LS_WARNING) << "SetAudioScaling() non-allowed scale factor."; 214 return -1; 215 } 216 217 int32_t FilePlayerImpl::StartPlayingFile(const char* fileName, 218 bool loop, 219 uint32_t startPosition, 220 float volumeScaling, 221 uint32_t notification, 222 uint32_t stopPosition, 223 const CodecInst* codecInst) 224 { 225 if (_fileFormat == kFileFormatPcm16kHzFile || 226 _fileFormat == kFileFormatPcm8kHzFile|| 227 _fileFormat == kFileFormatPcm32kHzFile ) 228 { 229 CodecInst codecInstL16; 230 strncpy(codecInstL16.plname,"L16",32); 231 codecInstL16.pltype = 93; 232 codecInstL16.channels = 1; 233 234 if (_fileFormat == kFileFormatPcm8kHzFile) 235 { 236 codecInstL16.rate = 128000; 237 codecInstL16.plfreq = 8000; 238 codecInstL16.pacsize = 80; 239 240 } else if(_fileFormat == kFileFormatPcm16kHzFile) 241 { 242 codecInstL16.rate = 256000; 243 codecInstL16.plfreq = 16000; 244 codecInstL16.pacsize = 160; 245 246 }else if(_fileFormat == kFileFormatPcm32kHzFile) 247 { 248 codecInstL16.rate = 512000; 249 codecInstL16.plfreq = 32000; 250 codecInstL16.pacsize = 160; 251 } else 252 { 253 LOG(LS_ERROR) << "StartPlayingFile() sample frequency not " 254 << "supported for PCM format."; 255 return -1; 256 } 257 258 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop, 259 _fileFormat, &codecInstL16, 260 startPosition, 261 stopPosition) == -1) 262 { 263 LOG(LS_WARNING) << "StartPlayingFile() failed to initialize " 264 << "pcm file " << fileName; 265 return -1; 266 } 267 SetAudioScaling(volumeScaling); 268 }else if(_fileFormat == kFileFormatPreencodedFile) 269 { 270 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop, 271 _fileFormat, codecInst) == -1) 272 { 273 LOG(LS_WARNING) << "StartPlayingFile() failed to initialize " 274 << "pre-encoded file " << fileName; 275 return -1; 276 } 277 } else 278 { 279 CodecInst* no_inst = NULL; 280 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop, 281 _fileFormat, no_inst, 282 startPosition, 283 stopPosition) == -1) 284 { 285 LOG(LS_WARNING) << "StartPlayingFile() failed to initialize file " 286 << fileName; 287 return -1; 288 } 289 SetAudioScaling(volumeScaling); 290 } 291 if (SetUpAudioDecoder() == -1) 292 { 293 StopPlayingFile(); 294 return -1; 295 } 296 return 0; 297 } 298 299 int32_t FilePlayerImpl::StartPlayingFile(InStream& sourceStream, 300 uint32_t startPosition, 301 float volumeScaling, 302 uint32_t notification, 303 uint32_t stopPosition, 304 const CodecInst* codecInst) 305 { 306 if (_fileFormat == kFileFormatPcm16kHzFile || 307 _fileFormat == kFileFormatPcm32kHzFile || 308 _fileFormat == kFileFormatPcm8kHzFile) 309 { 310 CodecInst codecInstL16; 311 strncpy(codecInstL16.plname,"L16",32); 312 codecInstL16.pltype = 93; 313 codecInstL16.channels = 1; 314 315 if (_fileFormat == kFileFormatPcm8kHzFile) 316 { 317 codecInstL16.rate = 128000; 318 codecInstL16.plfreq = 8000; 319 codecInstL16.pacsize = 80; 320 321 }else if (_fileFormat == kFileFormatPcm16kHzFile) 322 { 323 codecInstL16.rate = 256000; 324 codecInstL16.plfreq = 16000; 325 codecInstL16.pacsize = 160; 326 327 }else if (_fileFormat == kFileFormatPcm32kHzFile) 328 { 329 codecInstL16.rate = 512000; 330 codecInstL16.plfreq = 32000; 331 codecInstL16.pacsize = 160; 332 }else 333 { 334 LOG(LS_ERROR) << "StartPlayingFile() sample frequency not " 335 << "supported for PCM format."; 336 return -1; 337 } 338 if (_fileModule.StartPlayingAudioStream(sourceStream, notification, 339 _fileFormat, &codecInstL16, 340 startPosition, 341 stopPosition) == -1) 342 { 343 LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream " 344 << "playout."; 345 return -1; 346 } 347 348 }else if(_fileFormat == kFileFormatPreencodedFile) 349 { 350 if (_fileModule.StartPlayingAudioStream(sourceStream, notification, 351 _fileFormat, codecInst) == -1) 352 { 353 LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream " 354 << "playout."; 355 return -1; 356 } 357 } else { 358 CodecInst* no_inst = NULL; 359 if (_fileModule.StartPlayingAudioStream(sourceStream, notification, 360 _fileFormat, no_inst, 361 startPosition, 362 stopPosition) == -1) 363 { 364 LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream " 365 << "playout."; 366 return -1; 367 } 368 } 369 SetAudioScaling(volumeScaling); 370 371 if (SetUpAudioDecoder() == -1) 372 { 373 StopPlayingFile(); 374 return -1; 375 } 376 return 0; 377 } 378 379 int32_t FilePlayerImpl::StopPlayingFile() 380 { 381 memset(&_codec, 0, sizeof(CodecInst)); 382 _numberOf10MsPerFrame = 0; 383 _numberOf10MsInDecoder = 0; 384 return _fileModule.StopPlaying(); 385 } 386 387 bool FilePlayerImpl::IsPlayingFile() const 388 { 389 return _fileModule.IsPlaying(); 390 } 391 392 int32_t FilePlayerImpl::GetPlayoutPosition(uint32_t& durationMs) 393 { 394 return _fileModule.PlayoutPositionMs(durationMs); 395 } 396 397 int32_t FilePlayerImpl::SetUpAudioDecoder() 398 { 399 if ((_fileModule.codec_info(_codec) == -1)) 400 { 401 LOG(LS_WARNING) << "Failed to retrieve codec info of file data."; 402 return -1; 403 } 404 if( STR_CASE_CMP(_codec.plname, "L16") != 0 && 405 _audioDecoder.SetDecodeCodec(_codec,AMRFileStorage) == -1) 406 { 407 LOG(LS_WARNING) << "SetUpAudioDecoder() codec " << _codec.plname 408 << " not supported."; 409 return -1; 410 } 411 _numberOf10MsPerFrame = _codec.pacsize / (_codec.plfreq / 100); 412 _numberOf10MsInDecoder = 0; 413 return 0; 414 } 415 416 #ifdef WEBRTC_MODULE_UTILITY_VIDEO 417 VideoFilePlayerImpl::VideoFilePlayerImpl(uint32_t instanceID, 418 FileFormats fileFormat) 419 : FilePlayerImpl(instanceID, fileFormat), 420 video_decoder_(new VideoCoder()), 421 video_codec_info_(), 422 _decodedVideoFrames(0), 423 _encodedData(*new EncodedVideoData()), 424 _frameScaler(*new FrameScaler()), 425 _critSec(CriticalSectionWrapper::CreateCriticalSection()), 426 _startTime(), 427 _accumulatedRenderTimeMs(0), 428 _frameLengthMS(0), 429 _numberOfFramesRead(0), 430 _videoOnly(false) { 431 memset(&video_codec_info_, 0, sizeof(video_codec_info_)); 432 } 433 434 VideoFilePlayerImpl::~VideoFilePlayerImpl() 435 { 436 delete _critSec; 437 delete &_frameScaler; 438 video_decoder_.reset(); 439 delete &_encodedData; 440 } 441 442 int32_t VideoFilePlayerImpl::StartPlayingVideoFile( 443 const char* fileName, 444 bool loop, 445 bool videoOnly) 446 { 447 CriticalSectionScoped lock( _critSec); 448 449 if(_fileModule.StartPlayingVideoFile(fileName, loop, videoOnly, 450 _fileFormat) != 0) 451 { 452 return -1; 453 } 454 455 _decodedVideoFrames = 0; 456 _accumulatedRenderTimeMs = 0; 457 _frameLengthMS = 0; 458 _numberOfFramesRead = 0; 459 _videoOnly = videoOnly; 460 461 // Set up video_codec_info_ according to file, 462 if(SetUpVideoDecoder() != 0) 463 { 464 StopPlayingFile(); 465 return -1; 466 } 467 if(!videoOnly) 468 { 469 // Set up _codec according to file, 470 if(SetUpAudioDecoder() != 0) 471 { 472 StopPlayingFile(); 473 return -1; 474 } 475 } 476 return 0; 477 } 478 479 int32_t VideoFilePlayerImpl::StopPlayingFile() 480 { 481 CriticalSectionScoped lock( _critSec); 482 483 _decodedVideoFrames = 0; 484 video_decoder_.reset(new VideoCoder()); 485 486 return FilePlayerImpl::StopPlayingFile(); 487 } 488 489 int32_t VideoFilePlayerImpl::GetVideoFromFile(I420VideoFrame& videoFrame, 490 uint32_t outWidth, 491 uint32_t outHeight) 492 { 493 CriticalSectionScoped lock( _critSec); 494 495 int32_t retVal = GetVideoFromFile(videoFrame); 496 if(retVal != 0) 497 { 498 return retVal; 499 } 500 if (!videoFrame.IsZeroSize()) 501 { 502 retVal = _frameScaler.ResizeFrameIfNeeded(&videoFrame, outWidth, 503 outHeight); 504 } 505 return retVal; 506 } 507 508 int32_t VideoFilePlayerImpl::GetVideoFromFile(I420VideoFrame& videoFrame) 509 { 510 CriticalSectionScoped lock( _critSec); 511 // No new video data read from file. 512 if(_encodedData.payloadSize == 0) 513 { 514 videoFrame.ResetSize(); 515 return -1; 516 } 517 int32_t retVal = 0; 518 if(strncmp(video_codec_info_.plName, "I420", 5) == 0) 519 { 520 int size_y = video_codec_info_.width * video_codec_info_.height; 521 int half_width = (video_codec_info_.width + 1) / 2; 522 int half_height = (video_codec_info_.height + 1) / 2; 523 int size_uv = half_width * half_height; 524 525 // TODO(mikhal): Do we need to align the stride here? 526 const uint8_t* buffer_y = _encodedData.payloadData; 527 const uint8_t* buffer_u = buffer_y + size_y; 528 const uint8_t* buffer_v = buffer_u + size_uv; 529 videoFrame.CreateFrame(size_y, buffer_y, 530 size_uv, buffer_u, 531 size_uv, buffer_v, 532 video_codec_info_.width, video_codec_info_.height, 533 video_codec_info_.height, half_width, half_width); 534 }else 535 { 536 // Set the timestamp manually since there is no timestamp in the file. 537 // Update timestam according to 90 kHz stream. 538 _encodedData.timeStamp += (90000 / video_codec_info_.maxFramerate); 539 retVal = video_decoder_->Decode(videoFrame, _encodedData); 540 } 541 542 int64_t renderTimeMs = TickTime::MillisecondTimestamp(); 543 videoFrame.set_render_time_ms(renderTimeMs); 544 545 // Indicate that the current frame in the encoded buffer is old/has 546 // already been read. 547 _encodedData.payloadSize = 0; 548 if( retVal == 0) 549 { 550 _decodedVideoFrames++; 551 } 552 return retVal; 553 } 554 555 int32_t VideoFilePlayerImpl::video_codec_info( 556 VideoCodec& videoCodec) const 557 { 558 if(video_codec_info_.plName[0] == 0) 559 { 560 return -1; 561 } 562 memcpy(&videoCodec, &video_codec_info_, sizeof(VideoCodec)); 563 return 0; 564 } 565 566 int32_t VideoFilePlayerImpl::TimeUntilNextVideoFrame() 567 { 568 if(_fileFormat != kFileFormatAviFile) 569 { 570 return -1; 571 } 572 if(!_fileModule.IsPlaying()) 573 { 574 return -1; 575 } 576 if(_encodedData.payloadSize <= 0) 577 { 578 // Read next frame from file. 579 CriticalSectionScoped lock( _critSec); 580 581 if(_fileFormat == kFileFormatAviFile) 582 { 583 // Get next video frame 584 uint32_t encodedBufferLengthInBytes = _encodedData.bufferSize; 585 if(_fileModule.PlayoutAVIVideoData( 586 reinterpret_cast< int8_t*>(_encodedData.payloadData), 587 encodedBufferLengthInBytes) != 0) 588 { 589 LOG(LS_WARNING) << "Error reading video data."; 590 return -1; 591 } 592 _encodedData.payloadSize = encodedBufferLengthInBytes; 593 _encodedData.codec = video_codec_info_.codecType; 594 _numberOfFramesRead++; 595 596 if(_accumulatedRenderTimeMs == 0) 597 { 598 _startTime = TickTime::Now(); 599 // This if-statement should only trigger once. 600 _accumulatedRenderTimeMs = 1; 601 } else { 602 // A full seconds worth of frames have been read. 603 if(_numberOfFramesRead % video_codec_info_.maxFramerate == 0) 604 { 605 // Frame rate is in frames per seconds. Frame length is 606 // calculated as an integer division which means it may 607 // be rounded down. Compensate for this every second. 608 uint32_t rest = 1000%_frameLengthMS; 609 _accumulatedRenderTimeMs += rest; 610 } 611 _accumulatedRenderTimeMs += _frameLengthMS; 612 } 613 } 614 } 615 616 int64_t timeToNextFrame; 617 if(_videoOnly) 618 { 619 timeToNextFrame = _accumulatedRenderTimeMs - 620 (TickTime::Now() - _startTime).Milliseconds(); 621 622 } else { 623 // Synchronize with the audio stream instead of system clock. 624 timeToNextFrame = _accumulatedRenderTimeMs - _decodedLengthInMS; 625 } 626 if(timeToNextFrame < 0) 627 { 628 return 0; 629 630 } else if(timeToNextFrame > 0x0fffffff) 631 { 632 // Wraparound or audio stream has gone to far ahead of the video stream. 633 return -1; 634 } 635 return static_cast<int32_t>(timeToNextFrame); 636 } 637 638 int32_t VideoFilePlayerImpl::SetUpVideoDecoder() 639 { 640 if (_fileModule.VideoCodecInst(video_codec_info_) != 0) 641 { 642 LOG(LS_WARNING) << "SetVideoDecoder() failed to retrieve codec info of " 643 << "file data."; 644 return -1; 645 } 646 647 int32_t useNumberOfCores = 1; 648 if (video_decoder_->SetDecodeCodec(video_codec_info_, useNumberOfCores) != 649 0) { 650 LOG(LS_WARNING) << "SetUpVideoDecoder() codec " 651 << video_codec_info_.plName << " not supported."; 652 return -1; 653 } 654 655 _frameLengthMS = 1000/video_codec_info_.maxFramerate; 656 657 // Size of unencoded data (I420) should be the largest possible frame size 658 // in a file. 659 const uint32_t KReadBufferSize = 3 * video_codec_info_.width * 660 video_codec_info_.height / 2; 661 _encodedData.VerifyAndAllocate(KReadBufferSize); 662 _encodedData.encodedHeight = video_codec_info_.height; 663 _encodedData.encodedWidth = video_codec_info_.width; 664 _encodedData.payloadType = video_codec_info_.plType; 665 _encodedData.timeStamp = 0; 666 return 0; 667 } 668 #endif // WEBRTC_MODULE_UTILITY_VIDEO 669 } // namespace webrtc 670