blob: e35626c76068d13574d2f4a27402b20dabe1021e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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 <assert.h>
12
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000013#include "webrtc/base/format_macros.h"
Henrik Kjellander0b9e29c2015-11-16 11:12:24 +010014#include "webrtc/modules/media_file/media_file_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010015#include "webrtc/system_wrappers/include/file_wrapper.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010016#include "webrtc/system_wrappers/include/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000017
niklase@google.com470e71d2011-07-07 08:21:25 +000018namespace webrtc {
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +000019MediaFile* MediaFile::CreateMediaFile(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000020{
niklase@google.com470e71d2011-07-07 08:21:25 +000021 return new MediaFileImpl(id);
22}
23
24void MediaFile::DestroyMediaFile(MediaFile* module)
25{
niklase@google.com470e71d2011-07-07 08:21:25 +000026 delete static_cast<MediaFileImpl*>(module);
27}
28
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +000029MediaFileImpl::MediaFileImpl(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000030 : _id(id),
niklase@google.com470e71d2011-07-07 08:21:25 +000031 _ptrFileUtilityObj(NULL),
32 codec_info_(),
33 _ptrInStream(NULL),
34 _ptrOutStream(NULL),
35 _fileFormat((FileFormats)-1),
36 _recordDurationMs(0),
37 _playoutPositionMs(0),
38 _notificationMs(0),
39 _playingActive(false),
40 _recordingActive(false),
41 _isStereo(false),
42 _openFile(false),
43 _fileName(),
44 _ptrCallback(NULL)
45{
46 WEBRTC_TRACE(kTraceMemory, kTraceFile, id, "Created");
47
48 codec_info_.plname[0] = '\0';
49 _fileName[0] = '\0';
50}
51
52
53MediaFileImpl::~MediaFileImpl()
54{
55 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id, "~MediaFileImpl()");
56 {
kthelgason6bfe49c2017-03-30 01:14:41 -070057 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +000058
59 if(_playingActive)
60 {
61 StopPlaying();
62 }
63
64 if(_recordingActive)
65 {
66 StopRecording();
67 }
68
69 delete _ptrFileUtilityObj;
70
71 if(_openFile)
72 {
73 delete _ptrInStream;
74 _ptrInStream = NULL;
75 delete _ptrOutStream;
76 _ptrOutStream = NULL;
77 }
78 }
niklase@google.com470e71d2011-07-07 08:21:25 +000079}
80
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000081int64_t MediaFileImpl::TimeUntilNextProcess()
niklase@google.com470e71d2011-07-07 08:21:25 +000082{
83 WEBRTC_TRACE(
84 kTraceWarning,
85 kTraceFile,
86 _id,
87 "TimeUntilNextProcess: This method is not used by MediaFile class.");
88 return -1;
89}
90
pbosa26ac922016-02-25 04:50:01 -080091void MediaFileImpl::Process()
niklase@google.com470e71d2011-07-07 08:21:25 +000092{
93 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
94 "Process: This method is not used by MediaFile class.");
niklase@google.com470e71d2011-07-07 08:21:25 +000095}
96
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +000097int32_t MediaFileImpl::PlayoutAudioData(int8_t* buffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000098 size_t& dataLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +000099{
niklase@google.com470e71d2011-07-07 08:21:25 +0000100 WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000101 "MediaFileImpl::PlayoutData(buffer= 0x%x, bufLen= %" PRIuS ")",
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 buffer, dataLengthInBytes);
103
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000104 const size_t bufferLengthInBytes = dataLengthInBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 dataLengthInBytes = 0;
106
107 if(buffer == NULL || bufferLengthInBytes == 0)
108 {
109 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
110 "Buffer pointer or length is NULL!");
111 return -1;
112 }
113
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000114 int32_t bytesRead = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000115 {
kthelgason6bfe49c2017-03-30 01:14:41 -0700116 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000117
118 if(!_playingActive)
119 {
120 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
121 "Not currently playing!");
122 return -1;
123 }
124
125 if(!_ptrFileUtilityObj)
126 {
127 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
128 "Playing, but no FileUtility object!");
129 StopPlaying();
130 return -1;
131 }
132
133 switch(_fileFormat)
134 {
135 case kFileFormatPcm32kHzFile:
136 case kFileFormatPcm16kHzFile:
137 case kFileFormatPcm8kHzFile:
138 bytesRead = _ptrFileUtilityObj->ReadPCMData(
139 *_ptrInStream,
140 buffer,
141 bufferLengthInBytes);
142 break;
143 case kFileFormatCompressedFile:
144 bytesRead = _ptrFileUtilityObj->ReadCompressedData(
145 *_ptrInStream,
146 buffer,
147 bufferLengthInBytes);
148 break;
149 case kFileFormatWavFile:
150 bytesRead = _ptrFileUtilityObj->ReadWavDataAsMono(
151 *_ptrInStream,
152 buffer,
153 bufferLengthInBytes);
154 break;
155 case kFileFormatPreencodedFile:
156 bytesRead = _ptrFileUtilityObj->ReadPreEncodedData(
157 *_ptrInStream,
158 buffer,
159 bufferLengthInBytes);
160 if(bytesRead > 0)
161 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000162 dataLengthInBytes = static_cast<size_t>(bytesRead);
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 return 0;
164 }
165 break;
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000166 default:
niklase@google.com470e71d2011-07-07 08:21:25 +0000167 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000168 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000169 "Invalid file format: %d", _fileFormat);
niklase@google.com470e71d2011-07-07 08:21:25 +0000170 assert(false);
171 break;
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +0000172 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000173 }
174
175 if( bytesRead > 0)
176 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000177 dataLengthInBytes = static_cast<size_t>(bytesRead);
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 }
179 }
180 HandlePlayCallbacks(bytesRead);
181 return 0;
182}
183
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000184void MediaFileImpl::HandlePlayCallbacks(int32_t bytesRead)
niklase@google.com470e71d2011-07-07 08:21:25 +0000185{
186 bool playEnded = false;
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000187 uint32_t callbackNotifyMs = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188
189 if(bytesRead > 0)
190 {
191 // Check if it's time for PlayNotification(..).
192 _playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
193 if(_notificationMs)
194 {
195 if(_playoutPositionMs >= _notificationMs)
196 {
197 _notificationMs = 0;
198 callbackNotifyMs = _playoutPositionMs;
199 }
200 }
201 }
202 else
203 {
204 // If no bytes were read assume end of file.
205 StopPlaying();
206 playEnded = true;
207 }
208
209 // Only _callbackCrit may and should be taken when making callbacks.
kthelgason6bfe49c2017-03-30 01:14:41 -0700210 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 if(_ptrCallback)
212 {
213 if(callbackNotifyMs)
214 {
215 _ptrCallback->PlayNotification(_id, callbackNotifyMs);
216 }
217 if(playEnded)
218 {
219 _ptrCallback->PlayFileEnded(_id);
220 }
221 }
222}
223
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000224int32_t MediaFileImpl::PlayoutStereoData(
225 int8_t* bufferLeft,
226 int8_t* bufferRight,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000227 size_t& dataLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000228{
229 WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000230 "MediaFileImpl::PlayoutStereoData(Left = 0x%x, Right = 0x%x,"
231 " Len= %" PRIuS ")",
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 bufferLeft,
233 bufferRight,
234 dataLengthInBytes);
235
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000236 const size_t bufferLengthInBytes = dataLengthInBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237 dataLengthInBytes = 0;
238
239 if(bufferLeft == NULL || bufferRight == NULL || bufferLengthInBytes == 0)
240 {
241 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
242 "A buffer pointer or the length is NULL!");
243 return -1;
244 }
245
246 bool playEnded = false;
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000247 uint32_t callbackNotifyMs = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000248 {
kthelgason6bfe49c2017-03-30 01:14:41 -0700249 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000250
251 if(!_playingActive || !_isStereo)
252 {
253 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
254 "Not currently playing stereo!");
255 return -1;
256 }
257
258 if(!_ptrFileUtilityObj)
259 {
260 WEBRTC_TRACE(
261 kTraceError,
262 kTraceFile,
263 _id,
264 "Playing stereo, but the FileUtility objects is NULL!");
265 StopPlaying();
266 return -1;
267 }
268
269 // Stereo playout only supported for WAV files.
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000270 int32_t bytesRead = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000271 switch(_fileFormat)
272 {
273 case kFileFormatWavFile:
274 bytesRead = _ptrFileUtilityObj->ReadWavDataAsStereo(
275 *_ptrInStream,
276 bufferLeft,
277 bufferRight,
278 bufferLengthInBytes);
279 break;
280 default:
281 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
282 "Trying to read non-WAV as stereo audio\
283 (not supported)");
284 break;
285 }
286
287 if(bytesRead > 0)
288 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000289 dataLengthInBytes = static_cast<size_t>(bytesRead);
niklase@google.com470e71d2011-07-07 08:21:25 +0000290
291 // Check if it's time for PlayNotification(..).
292 _playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
293 if(_notificationMs)
294 {
295 if(_playoutPositionMs >= _notificationMs)
296 {
297 _notificationMs = 0;
298 callbackNotifyMs = _playoutPositionMs;
299 }
300 }
301 }
302 else
303 {
304 // If no bytes were read assume end of file.
305 StopPlaying();
306 playEnded = true;
307 }
308 }
309
kthelgason6bfe49c2017-03-30 01:14:41 -0700310 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 if(_ptrCallback)
312 {
313 if(callbackNotifyMs)
314 {
315 _ptrCallback->PlayNotification(_id, callbackNotifyMs);
316 }
317 if(playEnded)
318 {
319 _ptrCallback->PlayFileEnded(_id);
320 }
321 }
322 return 0;
323}
324
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000325int32_t MediaFileImpl::StartPlayingAudioFile(
leozwang@webrtc.org09e77192012-03-01 18:35:54 +0000326 const char* fileName,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000327 const uint32_t notificationTimeMs,
niklase@google.com470e71d2011-07-07 08:21:25 +0000328 const bool loop,
329 const FileFormats format,
330 const CodecInst* codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000331 const uint32_t startPointMs,
332 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000333{
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 if(!ValidFileName(fileName))
335 {
336 return -1;
337 }
338 if(!ValidFileFormat(format,codecInst))
339 {
340 return -1;
341 }
342 if(!ValidFilePositions(startPointMs,stopPointMs))
343 {
344 return -1;
345 }
346
347 // Check that the file will play longer than notificationTimeMs ms.
348 if((startPointMs && stopPointMs && !loop) &&
349 (notificationTimeMs > (stopPointMs - startPointMs)))
350 {
351 WEBRTC_TRACE(
352 kTraceError,
353 kTraceFile,
354 _id,
355 "specified notification time is longer than amount of ms that will\
356 be played");
357 return -1;
358 }
359
360 FileWrapper* inputStream = FileWrapper::Create();
361 if(inputStream == NULL)
362 {
363 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
364 "Failed to allocate input stream for file %s", fileName);
365 return -1;
366 }
367
tommia6219cc2016-06-15 10:30:14 -0700368 if (!inputStream->OpenFile(fileName, true)) {
369 delete inputStream;
370 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "Could not open input file %s",
371 fileName);
372 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000373 }
374
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000375 if(StartPlayingStream(*inputStream, loop, notificationTimeMs,
376 format, codecInst, startPointMs, stopPointMs) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000377 {
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000378 inputStream->CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000379 delete inputStream;
380 return -1;
381 }
382
kthelgason6bfe49c2017-03-30 01:14:41 -0700383 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000384 _openFile = true;
385 strncpy(_fileName, fileName, sizeof(_fileName));
386 _fileName[sizeof(_fileName) - 1] = '\0';
387 return 0;
388}
389
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000390int32_t MediaFileImpl::StartPlayingAudioStream(
niklase@google.com470e71d2011-07-07 08:21:25 +0000391 InStream& stream,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000392 const uint32_t notificationTimeMs,
niklase@google.com470e71d2011-07-07 08:21:25 +0000393 const FileFormats format,
394 const CodecInst* codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000395 const uint32_t startPointMs,
396 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000397{
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000398 return StartPlayingStream(stream, false, notificationTimeMs, format,
niklase@google.com470e71d2011-07-07 08:21:25 +0000399 codecInst, startPointMs, stopPointMs);
400}
401
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000402int32_t MediaFileImpl::StartPlayingStream(
niklase@google.com470e71d2011-07-07 08:21:25 +0000403 InStream& stream,
niklase@google.com470e71d2011-07-07 08:21:25 +0000404 bool loop,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000405 const uint32_t notificationTimeMs,
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 const FileFormats format,
407 const CodecInst* codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000408 const uint32_t startPointMs,
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000409 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000410{
niklase@google.com470e71d2011-07-07 08:21:25 +0000411 if(!ValidFileFormat(format,codecInst))
412 {
413 return -1;
414 }
415
416 if(!ValidFilePositions(startPointMs,stopPointMs))
417 {
418 return -1;
419 }
420
kthelgason6bfe49c2017-03-30 01:14:41 -0700421 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 if(_playingActive || _recordingActive)
423 {
424 WEBRTC_TRACE(
425 kTraceError,
426 kTraceFile,
427 _id,
428 "StartPlaying called, but already playing or recording file %s",
henrike@webrtc.org26085e12012-02-27 21:50:40 +0000429 (_fileName[0] == '\0') ? "(name not set)" : _fileName);
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 return -1;
431 }
432
433 if(_ptrFileUtilityObj != NULL)
434 {
435 WEBRTC_TRACE(kTraceError,
436 kTraceFile,
437 _id,
438 "StartPlaying called, but FileUtilityObj already exists!");
439 StopPlaying();
440 return -1;
441 }
442
443 _ptrFileUtilityObj = new ModuleFileUtility(_id);
444 if(_ptrFileUtilityObj == NULL)
445 {
446 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
447 "Failed to create FileUtilityObj!");
448 return -1;
449 }
450
451 switch(format)
452 {
453 case kFileFormatWavFile:
454 {
455 if(_ptrFileUtilityObj->InitWavReading(stream, startPointMs,
456 stopPointMs) == -1)
457 {
458 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
459 "Not a valid WAV file!");
460 StopPlaying();
461 return -1;
462 }
463 _fileFormat = kFileFormatWavFile;
464 break;
465 }
466 case kFileFormatCompressedFile:
467 {
468 if(_ptrFileUtilityObj->InitCompressedReading(stream, startPointMs,
469 stopPointMs) == -1)
470 {
471 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
472 "Not a valid Compressed file!");
473 StopPlaying();
474 return -1;
475 }
476 _fileFormat = kFileFormatCompressedFile;
477 break;
478 }
479 case kFileFormatPcm8kHzFile:
480 case kFileFormatPcm16kHzFile:
481 case kFileFormatPcm32kHzFile:
482 {
henrike@webrtc.org26085e12012-02-27 21:50:40 +0000483 // ValidFileFormat() called in the beginneing of this function
484 // prevents codecInst from being NULL here.
485 assert(codecInst != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000486 if(!ValidFrequency(codecInst->plfreq) ||
487 _ptrFileUtilityObj->InitPCMReading(stream, startPointMs,
488 stopPointMs,
489 codecInst->plfreq) == -1)
490 {
491 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
492 "Not a valid raw 8 or 16 KHz PCM file!");
493 StopPlaying();
494 return -1;
495 }
496
497 _fileFormat = format;
498 break;
499 }
500 case kFileFormatPreencodedFile:
501 {
henrike@webrtc.org26085e12012-02-27 21:50:40 +0000502 // ValidFileFormat() called in the beginneing of this function
503 // prevents codecInst from being NULL here.
504 assert(codecInst != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000505 if(_ptrFileUtilityObj->InitPreEncodedReading(stream, *codecInst) ==
506 -1)
507 {
508 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
509 "Not a valid PreEncoded file!");
510 StopPlaying();
511 return -1;
512 }
513
514 _fileFormat = kFileFormatPreencodedFile;
515 break;
516 }
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000517 default:
niklase@google.com470e71d2011-07-07 08:21:25 +0000518 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000519 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000520 "Invalid file format: %d", format);
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +0000521 assert(false);
522 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000523 }
524 }
525 if(_ptrFileUtilityObj->codec_info(codec_info_) == -1)
526 {
527 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
528 "Failed to retrieve codec info!");
529 StopPlaying();
530 return -1;
531 }
532
533 _isStereo = (codec_info_.channels == 2);
534 if(_isStereo && (_fileFormat != kFileFormatWavFile))
535 {
536 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
537 "Stereo is only allowed for WAV files");
538 StopPlaying();
539 return -1;
540 }
541 _playingActive = true;
542 _playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
543 _ptrInStream = &stream;
544 _notificationMs = notificationTimeMs;
545
546 return 0;
547}
548
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000549int32_t MediaFileImpl::StopPlaying()
niklase@google.com470e71d2011-07-07 08:21:25 +0000550{
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
kthelgason6bfe49c2017-03-30 01:14:41 -0700552 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553 _isStereo = false;
554 if(_ptrFileUtilityObj)
555 {
556 delete _ptrFileUtilityObj;
557 _ptrFileUtilityObj = NULL;
558 }
559 if(_ptrInStream)
560 {
561 // If MediaFileImpl opened the InStream it must be reclaimed here.
562 if(_openFile)
563 {
564 delete _ptrInStream;
565 _openFile = false;
566 }
567 _ptrInStream = NULL;
568 }
569
570 codec_info_.pltype = 0;
571 codec_info_.plname[0] = '\0';
572
573 if(!_playingActive)
574 {
575 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
576 "playing is not active!");
577 return -1;
578 }
579
580 _playingActive = false;
581 return 0;
582}
583
584bool MediaFileImpl::IsPlaying()
585{
586 WEBRTC_TRACE(kTraceStream, kTraceFile, _id, "MediaFileImpl::IsPlaying()");
kthelgason6bfe49c2017-03-30 01:14:41 -0700587 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000588 return _playingActive;
589}
590
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000591int32_t MediaFileImpl::IncomingAudioData(
592 const int8_t* buffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000593 const size_t bufferLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000594{
niklase@google.com470e71d2011-07-07 08:21:25 +0000595 WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000596 "MediaFile::IncomingData(buffer= 0x%x, bufLen= %" PRIuS,
niklase@google.com470e71d2011-07-07 08:21:25 +0000597 buffer, bufferLengthInBytes);
598
599 if(buffer == NULL || bufferLengthInBytes == 0)
600 {
601 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
602 "Buffer pointer or length is NULL!");
603 return -1;
604 }
605
606 bool recordingEnded = false;
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000607 uint32_t callbackNotifyMs = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000608 {
kthelgason6bfe49c2017-03-30 01:14:41 -0700609 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000610
611 if(!_recordingActive)
612 {
613 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
614 "Not currently recording!");
615 return -1;
616 }
617 if(_ptrOutStream == NULL)
618 {
619 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
620 "Recording is active, but output stream is NULL!");
621 assert(false);
622 return -1;
623 }
624
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000625 int32_t bytesWritten = 0;
626 uint32_t samplesWritten = codec_info_.pacsize;
niklase@google.com470e71d2011-07-07 08:21:25 +0000627 if(_ptrFileUtilityObj)
628 {
629 switch(_fileFormat)
630 {
631 case kFileFormatPcm8kHzFile:
632 case kFileFormatPcm16kHzFile:
633 case kFileFormatPcm32kHzFile:
634 bytesWritten = _ptrFileUtilityObj->WritePCMData(
635 *_ptrOutStream,
636 buffer,
637 bufferLengthInBytes);
638
639 // Sample size is 2 bytes.
640 if(bytesWritten > 0)
641 {
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000642 samplesWritten = bytesWritten/sizeof(int16_t);
niklase@google.com470e71d2011-07-07 08:21:25 +0000643 }
644 break;
645 case kFileFormatCompressedFile:
646 bytesWritten = _ptrFileUtilityObj->WriteCompressedData(
647 *_ptrOutStream, buffer, bufferLengthInBytes);
648 break;
649 case kFileFormatWavFile:
650 bytesWritten = _ptrFileUtilityObj->WriteWavData(
651 *_ptrOutStream,
652 buffer,
653 bufferLengthInBytes);
654 if(bytesWritten > 0 && STR_NCASE_CMP(codec_info_.plname,
655 "L16", 4) == 0)
656 {
657 // Sample size is 2 bytes.
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000658 samplesWritten = bytesWritten/sizeof(int16_t);
niklase@google.com470e71d2011-07-07 08:21:25 +0000659 }
660 break;
661 case kFileFormatPreencodedFile:
662 bytesWritten = _ptrFileUtilityObj->WritePreEncodedData(
663 *_ptrOutStream, buffer, bufferLengthInBytes);
664 break;
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000665 default:
niklase@google.com470e71d2011-07-07 08:21:25 +0000666 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000667 "Invalid file format: %d", _fileFormat);
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +0000668 assert(false);
niklase@google.com470e71d2011-07-07 08:21:25 +0000669 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000670 }
671 } else {
672 // TODO (hellner): quick look at the code makes me think that this
673 // code is never executed. Remove?
674 if(_ptrOutStream)
675 {
676 if(_ptrOutStream->Write(buffer, bufferLengthInBytes))
677 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000678 bytesWritten = static_cast<int32_t>(bufferLengthInBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000679 }
680 }
681 }
682
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000683 _recordDurationMs += samplesWritten / (codec_info_.plfreq / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000684
685 // Check if it's time for RecordNotification(..).
686 if(_notificationMs)
687 {
688 if(_recordDurationMs >= _notificationMs)
689 {
690 _notificationMs = 0;
691 callbackNotifyMs = _recordDurationMs;
692 }
693 }
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000694 if(bytesWritten < (int32_t)bufferLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000695 {
696 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
697 "Failed to write all requested bytes!");
698 StopRecording();
699 recordingEnded = true;
700 }
701 }
702
703 // Only _callbackCrit may and should be taken when making callbacks.
kthelgason6bfe49c2017-03-30 01:14:41 -0700704 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000705 if(_ptrCallback)
706 {
707 if(callbackNotifyMs)
708 {
709 _ptrCallback->RecordNotification(_id, callbackNotifyMs);
710 }
711 if(recordingEnded)
712 {
713 _ptrCallback->RecordFileEnded(_id);
714 return -1;
715 }
716 }
717 return 0;
718}
719
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000720int32_t MediaFileImpl::StartRecordingAudioFile(
leozwang@webrtc.org09e77192012-03-01 18:35:54 +0000721 const char* fileName,
niklase@google.com470e71d2011-07-07 08:21:25 +0000722 const FileFormats format,
723 const CodecInst& codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000724 const uint32_t notificationTimeMs,
725 const uint32_t maxSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000726{
niklase@google.com470e71d2011-07-07 08:21:25 +0000727 if(!ValidFileName(fileName))
728 {
729 return -1;
730 }
731 if(!ValidFileFormat(format,&codecInst))
732 {
733 return -1;
734 }
735
736 FileWrapper* outputStream = FileWrapper::Create();
737 if(outputStream == NULL)
738 {
739 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
740 "Failed to allocate memory for output stream");
741 return -1;
742 }
743
tommia6219cc2016-06-15 10:30:14 -0700744 if (!outputStream->OpenFile(fileName, false)) {
745 delete outputStream;
746 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
747 "Could not open output file '%s' for writing!", fileName);
748 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000749 }
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000750
niklase@google.com470e71d2011-07-07 08:21:25 +0000751 if(maxSizeBytes)
752 {
753 outputStream->SetMaxFileSize(maxSizeBytes);
754 }
755
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000756 if(StartRecordingAudioStream(*outputStream, format, codecInst,
757 notificationTimeMs) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000758 {
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000759 outputStream->CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000760 delete outputStream;
761 return -1;
762 }
763
kthelgason6bfe49c2017-03-30 01:14:41 -0700764 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000765 _openFile = true;
766 strncpy(_fileName, fileName, sizeof(_fileName));
767 _fileName[sizeof(_fileName) - 1] = '\0';
768 return 0;
769}
770
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000771int32_t MediaFileImpl::StartRecordingAudioStream(
niklase@google.com470e71d2011-07-07 08:21:25 +0000772 OutStream& stream,
773 const FileFormats format,
774 const CodecInst& codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000775 const uint32_t notificationTimeMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000776{
niklase@google.com470e71d2011-07-07 08:21:25 +0000777 // Check codec info
778 if(!ValidFileFormat(format,&codecInst))
779 {
780 return -1;
781 }
782
kthelgason6bfe49c2017-03-30 01:14:41 -0700783 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000784 if(_recordingActive || _playingActive)
785 {
786 WEBRTC_TRACE(
787 kTraceError,
788 kTraceFile,
789 _id,
790 "StartRecording called, but already recording or playing file %s!",
791 _fileName);
792 return -1;
793 }
794
795 if(_ptrFileUtilityObj != NULL)
796 {
797 WEBRTC_TRACE(
798 kTraceError,
799 kTraceFile,
800 _id,
801 "StartRecording called, but fileUtilityObj already exists!");
802 StopRecording();
803 return -1;
804 }
805
806 _ptrFileUtilityObj = new ModuleFileUtility(_id);
807 if(_ptrFileUtilityObj == NULL)
808 {
809 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
810 "Cannot allocate fileUtilityObj!");
811 return -1;
812 }
813
814 CodecInst tmpAudioCodec;
815 memcpy(&tmpAudioCodec, &codecInst, sizeof(CodecInst));
816 switch(format)
817 {
818 case kFileFormatWavFile:
819 {
820 if(_ptrFileUtilityObj->InitWavWriting(stream, codecInst) == -1)
821 {
822 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
823 "Failed to initialize WAV file!");
824 delete _ptrFileUtilityObj;
825 _ptrFileUtilityObj = NULL;
826 return -1;
827 }
828 _fileFormat = kFileFormatWavFile;
829 break;
830 }
831 case kFileFormatCompressedFile:
832 {
833 // Write compression codec name at beginning of file
834 if(_ptrFileUtilityObj->InitCompressedWriting(stream, codecInst) ==
835 -1)
836 {
837 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
838 "Failed to initialize Compressed file!");
839 delete _ptrFileUtilityObj;
840 _ptrFileUtilityObj = NULL;
841 return -1;
842 }
843 _fileFormat = kFileFormatCompressedFile;
844 break;
845 }
846 case kFileFormatPcm8kHzFile:
847 case kFileFormatPcm16kHzFile:
848 {
849 if(!ValidFrequency(codecInst.plfreq) ||
850 _ptrFileUtilityObj->InitPCMWriting(stream, codecInst.plfreq) ==
851 -1)
852 {
853 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
lliuubc436ed2017-03-31 16:32:28 -0700854 "Failed to initialize 8 or 16KHz PCM file!");
niklase@google.com470e71d2011-07-07 08:21:25 +0000855 delete _ptrFileUtilityObj;
856 _ptrFileUtilityObj = NULL;
857 return -1;
858 }
859 _fileFormat = format;
860 break;
861 }
862 case kFileFormatPreencodedFile:
863 {
864 if(_ptrFileUtilityObj->InitPreEncodedWriting(stream, codecInst) ==
865 -1)
866 {
867 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
868 "Failed to initialize Pre-Encoded file!");
869 delete _ptrFileUtilityObj;
870 _ptrFileUtilityObj = NULL;
871 return -1;
872 }
873
874 _fileFormat = kFileFormatPreencodedFile;
875 break;
876 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000877 default:
878 {
879 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
880 "Invalid file format %d specified!", format);
881 delete _ptrFileUtilityObj;
882 _ptrFileUtilityObj = NULL;
883 return -1;
884 }
885 }
886 _isStereo = (tmpAudioCodec.channels == 2);
887 if(_isStereo)
888 {
889 if(_fileFormat != kFileFormatWavFile)
890 {
891 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
892 "Stereo is only allowed for WAV files");
893 StopRecording();
894 return -1;
895 }
niklas.enbom@webrtc.org87885e82012-02-07 14:48:59 +0000896 if((STR_NCASE_CMP(tmpAudioCodec.plname, "L16", 4) != 0) &&
897 (STR_NCASE_CMP(tmpAudioCodec.plname, "PCMU", 5) != 0) &&
898 (STR_NCASE_CMP(tmpAudioCodec.plname, "PCMA", 5) != 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000899 {
900 WEBRTC_TRACE(
901 kTraceWarning,
902 kTraceFile,
903 _id,
904 "Stereo is only allowed for codec PCMU, PCMA and L16 ");
905 StopRecording();
906 return -1;
907 }
908 }
909 memcpy(&codec_info_, &tmpAudioCodec, sizeof(CodecInst));
910 _recordingActive = true;
911 _ptrOutStream = &stream;
912 _notificationMs = notificationTimeMs;
913 _recordDurationMs = 0;
914 return 0;
915}
916
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000917int32_t MediaFileImpl::StopRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000918{
niklase@google.com470e71d2011-07-07 08:21:25 +0000919
kthelgason6bfe49c2017-03-30 01:14:41 -0700920 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000921 if(!_recordingActive)
922 {
923 WEBRTC_TRACE(kTraceWarning, kTraceFile, _id,
924 "recording is not active!");
925 return -1;
926 }
927
928 _isStereo = false;
929
930 if(_ptrFileUtilityObj != NULL)
931 {
932 // Both AVI and WAV header has to be updated before closing the stream
933 // because they contain size information.
934 if((_fileFormat == kFileFormatWavFile) &&
935 (_ptrOutStream != NULL))
936 {
937 _ptrFileUtilityObj->UpdateWavHeader(*_ptrOutStream);
938 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000939 delete _ptrFileUtilityObj;
940 _ptrFileUtilityObj = NULL;
941 }
942
943 if(_ptrOutStream != NULL)
944 {
945 // If MediaFileImpl opened the OutStream it must be reclaimed here.
946 if(_openFile)
947 {
948 delete _ptrOutStream;
949 _openFile = false;
950 }
951 _ptrOutStream = NULL;
952 }
953
954 _recordingActive = false;
955 codec_info_.pltype = 0;
956 codec_info_.plname[0] = '\0';
957
958 return 0;
959}
960
961bool MediaFileImpl::IsRecording()
962{
963 WEBRTC_TRACE(kTraceStream, kTraceFile, _id, "MediaFileImpl::IsRecording()");
kthelgason6bfe49c2017-03-30 01:14:41 -0700964 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000965 return _recordingActive;
966}
967
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000968int32_t MediaFileImpl::RecordDurationMs(uint32_t& durationMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000969{
niklase@google.com470e71d2011-07-07 08:21:25 +0000970
kthelgason6bfe49c2017-03-30 01:14:41 -0700971 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000972 if(!_recordingActive)
973 {
974 durationMs = 0;
975 return -1;
976 }
977 durationMs = _recordDurationMs;
978 return 0;
979}
980
981bool MediaFileImpl::IsStereo()
982{
983 WEBRTC_TRACE(kTraceStream, kTraceFile, _id, "MediaFileImpl::IsStereo()");
kthelgason6bfe49c2017-03-30 01:14:41 -0700984 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000985 return _isStereo;
986}
987
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000988int32_t MediaFileImpl::SetModuleFileCallback(FileCallback* callback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000989{
niklase@google.com470e71d2011-07-07 08:21:25 +0000990
kthelgason6bfe49c2017-03-30 01:14:41 -0700991 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000992
993 _ptrCallback = callback;
994 return 0;
995}
996
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000997int32_t MediaFileImpl::FileDurationMs(const char* fileName,
998 uint32_t& durationMs,
999 const FileFormats format,
1000 const uint32_t freqInHz)
niklase@google.com470e71d2011-07-07 08:21:25 +00001001{
niklase@google.com470e71d2011-07-07 08:21:25 +00001002
1003 if(!ValidFileName(fileName))
1004 {
1005 return -1;
1006 }
1007 if(!ValidFrequency(freqInHz))
1008 {
1009 return -1;
1010 }
1011
1012 ModuleFileUtility* utilityObj = new ModuleFileUtility(_id);
1013 if(utilityObj == NULL)
1014 {
1015 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1016 "failed to allocate utility object!");
1017 return -1;
1018 }
1019
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +00001020 const int32_t duration = utilityObj->FileDurationMs(fileName, format,
1021 freqInHz);
niklase@google.com470e71d2011-07-07 08:21:25 +00001022 delete utilityObj;
1023 if(duration == -1)
1024 {
1025 durationMs = 0;
1026 return -1;
1027 }
1028
1029 durationMs = duration;
1030 return 0;
1031}
1032
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +00001033int32_t MediaFileImpl::PlayoutPositionMs(uint32_t& positionMs) const
niklase@google.com470e71d2011-07-07 08:21:25 +00001034{
kthelgason6bfe49c2017-03-30 01:14:41 -07001035 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +00001036 if(!_playingActive)
1037 {
1038 positionMs = 0;
1039 return -1;
1040 }
1041 positionMs = _playoutPositionMs;
1042 return 0;
1043}
1044
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +00001045int32_t MediaFileImpl::codec_info(CodecInst& codecInst) const
niklase@google.com470e71d2011-07-07 08:21:25 +00001046{
kthelgason6bfe49c2017-03-30 01:14:41 -07001047 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +00001048 if(!_playingActive && !_recordingActive)
1049 {
1050 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1051 "Neither playout nor recording has been initialized!");
1052 return -1;
1053 }
1054 if (codec_info_.pltype == 0 && codec_info_.plname[0] == '\0')
1055 {
1056 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1057 "The CodecInst for %s is unknown!",
1058 _playingActive ? "Playback" : "Recording");
1059 return -1;
1060 }
1061 memcpy(&codecInst,&codec_info_,sizeof(CodecInst));
1062 return 0;
1063}
1064
niklase@google.com470e71d2011-07-07 08:21:25 +00001065bool MediaFileImpl::ValidFileFormat(const FileFormats format,
1066 const CodecInst* codecInst)
1067{
1068 if(codecInst == NULL)
1069 {
1070 if(format == kFileFormatPreencodedFile ||
1071 format == kFileFormatPcm8kHzFile ||
1072 format == kFileFormatPcm16kHzFile ||
lliuubc436ed2017-03-31 16:32:28 -07001073 format == kFileFormatPcm32kHzFile)
niklase@google.com470e71d2011-07-07 08:21:25 +00001074 {
1075 WEBRTC_TRACE(kTraceError, kTraceFile, -1,
1076 "Codec info required for file format specified!");
1077 return false;
1078 }
1079 }
1080 return true;
1081}
1082
leozwang@webrtc.org09e77192012-03-01 18:35:54 +00001083bool MediaFileImpl::ValidFileName(const char* fileName)
niklase@google.com470e71d2011-07-07 08:21:25 +00001084{
1085 if((fileName == NULL) ||(fileName[0] == '\0'))
1086 {
1087 WEBRTC_TRACE(kTraceError, kTraceFile, -1, "FileName not specified!");
1088 return false;
1089 }
1090 return true;
1091}
1092
1093
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +00001094bool MediaFileImpl::ValidFilePositions(const uint32_t startPointMs,
1095 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +00001096{
1097 if(startPointMs == 0 && stopPointMs == 0) // Default values
1098 {
1099 return true;
1100 }
1101 if(stopPointMs &&(startPointMs >= stopPointMs))
1102 {
1103 WEBRTC_TRACE(kTraceError, kTraceFile, -1,
1104 "startPointMs must be less than stopPointMs!");
1105 return false;
1106 }
1107 if(stopPointMs &&((stopPointMs - startPointMs) < 20))
1108 {
1109 WEBRTC_TRACE(kTraceError, kTraceFile, -1,
1110 "minimum play duration for files is 20 ms!");
1111 return false;
1112 }
1113 return true;
1114}
1115
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +00001116bool MediaFileImpl::ValidFrequency(const uint32_t frequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00001117{
lliuubc436ed2017-03-31 16:32:28 -07001118 if((frequency == 8000) || (frequency == 16000)|| (frequency == 32000))
niklase@google.com470e71d2011-07-07 08:21:25 +00001119 {
1120 return true;
1121 }
1122 WEBRTC_TRACE(kTraceError, kTraceFile, -1,
lliuubc436ed2017-03-31 16:32:28 -07001123 "Frequency should be 8000, 16000 or 32000 (Hz)");
niklase@google.com470e71d2011-07-07 08:21:25 +00001124 return false;
1125}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001126} // namespace webrtc