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