Line data Source code
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/voice_engine/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/system_wrappers/include/critical_section_wrapper.h"
18 : #include "webrtc/system_wrappers/include/logging.h"
19 : #include "webrtc/typedefs.h"
20 : #include "webrtc/voice_engine/coder.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 0 : FilePlayerImpl::FilePlayerImpl(const uint32_t instanceID,
74 0 : const FileFormats fileFormat)
75 : : _fileFormat(fileFormat),
76 0 : _fileModule(*MediaFile::CreateMediaFile(instanceID)),
77 : _decodedLengthInMS(0),
78 : _audioDecoder(instanceID),
79 : _codec(),
80 : _numberOf10MsPerFrame(0),
81 : _numberOf10MsInDecoder(0),
82 : _resampler(),
83 0 : _scaling(1.0) {
84 0 : _codec.plfreq = 0;
85 0 : }
86 :
87 0 : FilePlayerImpl::~FilePlayerImpl() {
88 0 : MediaFile::DestroyMediaFile(&_fileModule);
89 0 : }
90 :
91 0 : int32_t FilePlayerImpl::Frequency() const {
92 0 : if (_codec.plfreq == 0) {
93 0 : 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 0 : if (_codec.plfreq == 11000) {
98 0 : return 16000;
99 0 : } else if (_codec.plfreq == 22000) {
100 0 : return 32000;
101 0 : } else if (_codec.plfreq == 44100) {
102 0 : return 32000;
103 0 : } else if (_codec.plfreq == 48000) {
104 0 : return 32000;
105 : } else {
106 0 : return _codec.plfreq;
107 : }
108 : }
109 :
110 0 : int32_t FilePlayerImpl::AudioCodec(CodecInst* audioCodec) const {
111 0 : *audioCodec = _codec;
112 0 : return 0;
113 : }
114 :
115 0 : int32_t FilePlayerImpl::Get10msAudioFromFile(int16_t* outBuffer,
116 : size_t* lengthInSamples,
117 : int frequencyInHz) {
118 0 : if (_codec.plfreq == 0) {
119 0 : LOG(LS_WARNING) << "Get10msAudioFromFile() playing not started!"
120 0 : << " codec freq = " << _codec.plfreq
121 0 : << ", wanted freq = " << frequencyInHz;
122 0 : return -1;
123 : }
124 :
125 0 : AudioFrame unresampledAudioFrame;
126 0 : if (STR_CASE_CMP(_codec.plname, "L16") == 0) {
127 0 : unresampledAudioFrame.sample_rate_hz_ = _codec.plfreq;
128 :
129 : // L16 is un-encoded data. Just pull 10 ms.
130 0 : size_t lengthInBytes = sizeof(unresampledAudioFrame.data_);
131 0 : if (_fileModule.PlayoutAudioData(
132 : reinterpret_cast<int8_t*>(unresampledAudioFrame.data_),
133 0 : lengthInBytes) == -1) {
134 : // End of file reached.
135 0 : return -1;
136 : }
137 0 : if (lengthInBytes == 0) {
138 0 : *lengthInSamples = 0;
139 0 : return 0;
140 : }
141 : // One sample is two bytes.
142 0 : 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 0 : size_t encodedLengthInBytes = 0;
150 0 : if (++_numberOf10MsInDecoder >= _numberOf10MsPerFrame) {
151 0 : _numberOf10MsInDecoder = 0;
152 0 : size_t bytesFromFile = sizeof(encodedBuffer);
153 0 : if (_fileModule.PlayoutAudioData(reinterpret_cast<int8_t*>(encodedBuffer),
154 0 : bytesFromFile) == -1) {
155 : // End of file reached.
156 0 : return -1;
157 : }
158 0 : encodedLengthInBytes = bytesFromFile;
159 : }
160 0 : if (_audioDecoder.Decode(&unresampledAudioFrame, frequencyInHz,
161 : reinterpret_cast<int8_t*>(encodedBuffer),
162 : encodedLengthInBytes) == -1) {
163 0 : return -1;
164 : }
165 : }
166 :
167 0 : size_t outLen = 0;
168 0 : if (_resampler.ResetIfNeeded(unresampledAudioFrame.sample_rate_hz_,
169 : frequencyInHz, 1)) {
170 0 : LOG(LS_WARNING) << "Get10msAudioFromFile() unexpected codec.";
171 :
172 : // New sampling frequency. Update state.
173 0 : outLen = static_cast<size_t>(frequencyInHz / 100);
174 0 : memset(outBuffer, 0, outLen * sizeof(int16_t));
175 0 : return 0;
176 : }
177 0 : _resampler.Push(unresampledAudioFrame.data_,
178 : unresampledAudioFrame.samples_per_channel_, outBuffer,
179 0 : MAX_AUDIO_BUFFER_IN_SAMPLES, outLen);
180 :
181 0 : *lengthInSamples = outLen;
182 :
183 0 : if (_scaling != 1.0) {
184 0 : for (size_t i = 0; i < outLen; i++) {
185 0 : outBuffer[i] = (int16_t)(outBuffer[i] * _scaling);
186 : }
187 : }
188 0 : _decodedLengthInMS += 10;
189 0 : return 0;
190 : }
191 :
192 0 : int32_t FilePlayerImpl::RegisterModuleFileCallback(FileCallback* callback) {
193 0 : return _fileModule.SetModuleFileCallback(callback);
194 : }
195 :
196 0 : int32_t FilePlayerImpl::SetAudioScaling(float scaleFactor) {
197 0 : if ((scaleFactor >= 0) && (scaleFactor <= 2.0)) {
198 0 : _scaling = scaleFactor;
199 0 : return 0;
200 : }
201 0 : LOG(LS_WARNING) << "SetAudioScaling() non-allowed scale factor.";
202 0 : return -1;
203 : }
204 :
205 0 : 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 0 : if (_fileFormat == kFileFormatPcm16kHzFile ||
213 0 : _fileFormat == kFileFormatPcm8kHzFile ||
214 0 : _fileFormat == kFileFormatPcm32kHzFile) {
215 : CodecInst codecInstL16;
216 0 : strncpy(codecInstL16.plname, "L16", 32);
217 0 : codecInstL16.pltype = 93;
218 0 : codecInstL16.channels = 1;
219 :
220 0 : if (_fileFormat == kFileFormatPcm8kHzFile) {
221 0 : codecInstL16.rate = 128000;
222 0 : codecInstL16.plfreq = 8000;
223 0 : codecInstL16.pacsize = 80;
224 :
225 0 : } else if (_fileFormat == kFileFormatPcm16kHzFile) {
226 0 : codecInstL16.rate = 256000;
227 0 : codecInstL16.plfreq = 16000;
228 0 : codecInstL16.pacsize = 160;
229 :
230 0 : } else if (_fileFormat == kFileFormatPcm32kHzFile) {
231 0 : codecInstL16.rate = 512000;
232 0 : codecInstL16.plfreq = 32000;
233 0 : codecInstL16.pacsize = 160;
234 : } else {
235 0 : LOG(LS_ERROR) << "StartPlayingFile() sample frequency not "
236 0 : << "supported for PCM format.";
237 0 : return -1;
238 : }
239 :
240 0 : if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
241 0 : _fileFormat, &codecInstL16,
242 0 : startPosition, stopPosition) == -1) {
243 0 : LOG(LS_WARNING) << "StartPlayingFile() failed to initialize "
244 0 : << "pcm file " << fileName;
245 0 : return -1;
246 : }
247 0 : SetAudioScaling(volumeScaling);
248 0 : } else if (_fileFormat == kFileFormatPreencodedFile) {
249 0 : if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
250 0 : _fileFormat, codecInst) == -1) {
251 0 : LOG(LS_WARNING) << "StartPlayingFile() failed to initialize "
252 0 : << "pre-encoded file " << fileName;
253 0 : return -1;
254 : }
255 : } else {
256 0 : CodecInst* no_inst = NULL;
257 0 : if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
258 0 : _fileFormat, no_inst, startPosition,
259 0 : stopPosition) == -1) {
260 0 : LOG(LS_WARNING) << "StartPlayingFile() failed to initialize file "
261 0 : << fileName;
262 0 : return -1;
263 : }
264 0 : SetAudioScaling(volumeScaling);
265 : }
266 0 : if (SetUpAudioDecoder() == -1) {
267 0 : StopPlayingFile();
268 0 : return -1;
269 : }
270 0 : return 0;
271 : }
272 :
273 0 : 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 0 : if (_fileFormat == kFileFormatPcm16kHzFile ||
280 0 : _fileFormat == kFileFormatPcm32kHzFile ||
281 0 : _fileFormat == kFileFormatPcm8kHzFile) {
282 : CodecInst codecInstL16;
283 0 : strncpy(codecInstL16.plname, "L16", 32);
284 0 : codecInstL16.pltype = 93;
285 0 : codecInstL16.channels = 1;
286 :
287 0 : if (_fileFormat == kFileFormatPcm8kHzFile) {
288 0 : codecInstL16.rate = 128000;
289 0 : codecInstL16.plfreq = 8000;
290 0 : codecInstL16.pacsize = 80;
291 :
292 0 : } else if (_fileFormat == kFileFormatPcm16kHzFile) {
293 0 : codecInstL16.rate = 256000;
294 0 : codecInstL16.plfreq = 16000;
295 0 : codecInstL16.pacsize = 160;
296 :
297 0 : } else if (_fileFormat == kFileFormatPcm32kHzFile) {
298 0 : codecInstL16.rate = 512000;
299 0 : codecInstL16.plfreq = 32000;
300 0 : codecInstL16.pacsize = 160;
301 : } else {
302 0 : LOG(LS_ERROR) << "StartPlayingFile() sample frequency not "
303 0 : << "supported for PCM format.";
304 0 : return -1;
305 : }
306 0 : if (_fileModule.StartPlayingAudioStream(
307 0 : *sourceStream, notification, _fileFormat, &codecInstL16,
308 0 : startPosition, stopPosition) == -1) {
309 0 : LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream "
310 0 : << "playout.";
311 0 : return -1;
312 0 : }
313 :
314 0 : } else if (_fileFormat == kFileFormatPreencodedFile) {
315 0 : if (_fileModule.StartPlayingAudioStream(*sourceStream, notification,
316 0 : _fileFormat, codecInst) == -1) {
317 0 : LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream "
318 0 : << "playout.";
319 0 : return -1;
320 : }
321 : } else {
322 0 : CodecInst* no_inst = NULL;
323 0 : if (_fileModule.StartPlayingAudioStream(*sourceStream, notification,
324 0 : _fileFormat, no_inst, startPosition,
325 0 : stopPosition) == -1) {
326 0 : LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream "
327 0 : << "playout.";
328 0 : return -1;
329 : }
330 : }
331 0 : SetAudioScaling(volumeScaling);
332 :
333 0 : if (SetUpAudioDecoder() == -1) {
334 0 : StopPlayingFile();
335 0 : return -1;
336 : }
337 0 : return 0;
338 : }
339 :
340 0 : int32_t FilePlayerImpl::StopPlayingFile() {
341 0 : memset(&_codec, 0, sizeof(CodecInst));
342 0 : _numberOf10MsPerFrame = 0;
343 0 : _numberOf10MsInDecoder = 0;
344 0 : return _fileModule.StopPlaying();
345 : }
346 :
347 0 : bool FilePlayerImpl::IsPlayingFile() const {
348 0 : return _fileModule.IsPlaying();
349 : }
350 :
351 0 : int32_t FilePlayerImpl::GetPlayoutPosition(uint32_t* durationMs) {
352 0 : return _fileModule.PlayoutPositionMs(*durationMs);
353 : }
354 :
355 0 : int32_t FilePlayerImpl::SetUpAudioDecoder() {
356 0 : if ((_fileModule.codec_info(_codec) == -1)) {
357 0 : LOG(LS_WARNING) << "Failed to retrieve codec info of file data.";
358 0 : return -1;
359 : }
360 0 : if (STR_CASE_CMP(_codec.plname, "L16") != 0 &&
361 0 : _audioDecoder.SetDecodeCodec(_codec) == -1) {
362 0 : LOG(LS_WARNING) << "SetUpAudioDecoder() codec " << _codec.plname
363 0 : << " not supported.";
364 0 : return -1;
365 : }
366 0 : _numberOf10MsPerFrame = _codec.pacsize / (_codec.plfreq / 100);
367 0 : _numberOf10MsInDecoder = 0;
368 0 : return 0;
369 : }
370 :
371 : } // namespace
372 :
373 0 : std::unique_ptr<FilePlayer> FilePlayer::CreateFilePlayer(
374 : uint32_t instanceID,
375 : FileFormats fileFormat) {
376 0 : 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 0 : new FilePlayerImpl(instanceID, fileFormat));
386 : default:
387 0 : assert(false);
388 : return nullptr;
389 : }
390 : }
391 :
392 : } // namespace webrtc
|