Home | History | Annotate | Download | only in source
      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 {
     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 
     34 void FilePlayer::DestroyFilePlayer(FilePlayer* player)
     35 {
     36     delete player;
     37 }
     38 
     39 FilePlayerImpl::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 
     55 FilePlayerImpl::~FilePlayerImpl()
     56 {
     57     MediaFile::DestroyMediaFile(&_fileModule);
     58 }
     59 
     60 int32_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 
     90 int32_t FilePlayerImpl::AudioCodec(CodecInst& audioCodec) const
     91 {
     92     audioCodec = _codec;
     93     return 0;
     94 }
     95 
     96 int32_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 
    188 int32_t FilePlayerImpl::RegisterModuleFileCallback(FileCallback* callback)
    189 {
    190     return _fileModule.SetModuleFileCallback(callback);
    191 }
    192 
    193 int32_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 
    204 int32_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 
    286 int32_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 
    366 int32_t FilePlayerImpl::StopPlayingFile()
    367 {
    368     memset(&_codec, 0, sizeof(CodecInst));
    369     _numberOf10MsPerFrame  = 0;
    370     _numberOf10MsInDecoder = 0;
    371     return _fileModule.StopPlaying();
    372 }
    373 
    374 bool FilePlayerImpl::IsPlayingFile() const
    375 {
    376     return _fileModule.IsPlaying();
    377 }
    378 
    379 int32_t FilePlayerImpl::GetPlayoutPosition(uint32_t& durationMs)
    380 {
    381     return _fileModule.PlayoutPositionMs(durationMs);
    382 }
    383 
    384 int32_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