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 {
CreateFilePlayer(uint32_t instanceID,FileFormats fileFormat)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 
DestroyFilePlayer(FilePlayer * player)34 void FilePlayer::DestroyFilePlayer(FilePlayer* player)
35 {
36     delete player;
37 }
38 
FilePlayerImpl(const uint32_t instanceID,const FileFormats fileFormat)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 
~FilePlayerImpl()55 FilePlayerImpl::~FilePlayerImpl()
56 {
57     MediaFile::DestroyMediaFile(&_fileModule);
58 }
59 
Frequency() const60 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 
AudioCodec(CodecInst & audioCodec) const90 int32_t FilePlayerImpl::AudioCodec(CodecInst& audioCodec) const
91 {
92     audioCodec = _codec;
93     return 0;
94 }
95 
Get10msAudioFromFile(int16_t * outBuffer,size_t & lengthInSamples,int frequencyInHz)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 
RegisterModuleFileCallback(FileCallback * callback)188 int32_t FilePlayerImpl::RegisterModuleFileCallback(FileCallback* callback)
189 {
190     return _fileModule.SetModuleFileCallback(callback);
191 }
192 
SetAudioScaling(float scaleFactor)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 
StartPlayingFile(const char * fileName,bool loop,uint32_t startPosition,float volumeScaling,uint32_t notification,uint32_t stopPosition,const CodecInst * codecInst)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 
StartPlayingFile(InStream & sourceStream,uint32_t startPosition,float volumeScaling,uint32_t notification,uint32_t stopPosition,const CodecInst * codecInst)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 
StopPlayingFile()366 int32_t FilePlayerImpl::StopPlayingFile()
367 {
368     memset(&_codec, 0, sizeof(CodecInst));
369     _numberOf10MsPerFrame  = 0;
370     _numberOf10MsInDecoder = 0;
371     return _fileModule.StopPlaying();
372 }
373 
IsPlayingFile() const374 bool FilePlayerImpl::IsPlayingFile() const
375 {
376     return _fileModule.IsPlaying();
377 }
378 
GetPlayoutPosition(uint32_t & durationMs)379 int32_t FilePlayerImpl::GetPlayoutPosition(uint32_t& durationMs)
380 {
381     return _fileModule.PlayoutPositionMs(durationMs);
382 }
383 
SetUpAudioDecoder()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