blob: a869625cf56eeb6fc6a850bae00fa41d256a51c5 [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
Henrik Kjellander0b9e29c2015-11-16 11:12:24 +010013#include "webrtc/modules/media_file/media_file_impl.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020014#include "webrtc/rtc_base/format_macros.h"
Sam Zackrisson45ca37c2017-08-22 13:44:09 +020015#include "webrtc/rtc_base/logging.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010016#include "webrtc/system_wrappers/include/file_wrapper.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{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +020046 LOG(LS_INFO) << "MediaFileImpl()";
niklase@google.com470e71d2011-07-07 08:21:25 +000047
48 codec_info_.plname[0] = '\0';
49 _fileName[0] = '\0';
50}
51
52
53MediaFileImpl::~MediaFileImpl()
54{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +020055 LOG(LS_INFO) << "~MediaFileImpl()";
niklase@google.com470e71d2011-07-07 08:21:25 +000056 {
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{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +020083 LOG(LS_WARNING)
84 << "TimeUntilNextProcess: This method is not used by MediaFile class.";
niklase@google.com470e71d2011-07-07 08:21:25 +000085 return -1;
86}
87
pbosa26ac922016-02-25 04:50:01 -080088void MediaFileImpl::Process()
niklase@google.com470e71d2011-07-07 08:21:25 +000089{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +020090 LOG(LS_WARNING) << "Process: This method is not used by MediaFile class.";
niklase@google.com470e71d2011-07-07 08:21:25 +000091}
92
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +000093int32_t MediaFileImpl::PlayoutAudioData(int8_t* buffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000094 size_t& dataLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +000095{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +020096 LOG(LS_INFO) << "MediaFileImpl::PlayoutData(buffer= "
97 << static_cast<void*>(buffer)
98 << ", bufLen= " << dataLengthInBytes << ")";
niklase@google.com470e71d2011-07-07 08:21:25 +000099
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000100 const size_t bufferLengthInBytes = dataLengthInBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101 dataLengthInBytes = 0;
102
103 if(buffer == NULL || bufferLengthInBytes == 0)
104 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200105 LOG(LS_ERROR) << "Buffer pointer or length is NULL!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000106 return -1;
107 }
108
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000109 int32_t bytesRead = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 {
kthelgason6bfe49c2017-03-30 01:14:41 -0700111 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000112
113 if(!_playingActive)
114 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200115 LOG(LS_WARNING) << "Not currently playing!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 return -1;
117 }
118
119 if(!_ptrFileUtilityObj)
120 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200121 LOG(LS_ERROR) << "Playing, but no FileUtility object!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000122 StopPlaying();
123 return -1;
124 }
125
126 switch(_fileFormat)
127 {
128 case kFileFormatPcm32kHzFile:
129 case kFileFormatPcm16kHzFile:
130 case kFileFormatPcm8kHzFile:
131 bytesRead = _ptrFileUtilityObj->ReadPCMData(
132 *_ptrInStream,
133 buffer,
134 bufferLengthInBytes);
135 break;
136 case kFileFormatCompressedFile:
137 bytesRead = _ptrFileUtilityObj->ReadCompressedData(
138 *_ptrInStream,
139 buffer,
140 bufferLengthInBytes);
141 break;
142 case kFileFormatWavFile:
143 bytesRead = _ptrFileUtilityObj->ReadWavDataAsMono(
144 *_ptrInStream,
145 buffer,
146 bufferLengthInBytes);
147 break;
148 case kFileFormatPreencodedFile:
149 bytesRead = _ptrFileUtilityObj->ReadPreEncodedData(
150 *_ptrInStream,
151 buffer,
152 bufferLengthInBytes);
153 if(bytesRead > 0)
154 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000155 dataLengthInBytes = static_cast<size_t>(bytesRead);
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 return 0;
157 }
158 break;
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000159 default:
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200161 LOG(LS_ERROR) << "Invalid file format: " << _fileFormat;
niklase@google.com470e71d2011-07-07 08:21:25 +0000162 assert(false);
163 break;
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +0000164 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000165 }
166
167 if( bytesRead > 0)
168 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000169 dataLengthInBytes = static_cast<size_t>(bytesRead);
niklase@google.com470e71d2011-07-07 08:21:25 +0000170 }
171 }
172 HandlePlayCallbacks(bytesRead);
173 return 0;
174}
175
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000176void MediaFileImpl::HandlePlayCallbacks(int32_t bytesRead)
niklase@google.com470e71d2011-07-07 08:21:25 +0000177{
178 bool playEnded = false;
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000179 uint32_t callbackNotifyMs = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180
181 if(bytesRead > 0)
182 {
183 // Check if it's time for PlayNotification(..).
184 _playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
185 if(_notificationMs)
186 {
187 if(_playoutPositionMs >= _notificationMs)
188 {
189 _notificationMs = 0;
190 callbackNotifyMs = _playoutPositionMs;
191 }
192 }
193 }
194 else
195 {
196 // If no bytes were read assume end of file.
197 StopPlaying();
198 playEnded = true;
199 }
200
201 // Only _callbackCrit may and should be taken when making callbacks.
kthelgason6bfe49c2017-03-30 01:14:41 -0700202 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000203 if(_ptrCallback)
204 {
205 if(callbackNotifyMs)
206 {
207 _ptrCallback->PlayNotification(_id, callbackNotifyMs);
208 }
209 if(playEnded)
210 {
211 _ptrCallback->PlayFileEnded(_id);
212 }
213 }
214}
215
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000216int32_t MediaFileImpl::PlayoutStereoData(
217 int8_t* bufferLeft,
218 int8_t* bufferRight,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000219 size_t& dataLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000220{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200221 LOG(LS_INFO)
222 << "MediaFileImpl::PlayoutStereoData(Left = "
223 << static_cast<void*>(bufferLeft) << ", Right = "
224 << static_cast<void*>(bufferRight) << ", Len= " << dataLengthInBytes
225 << ")";
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000227 const size_t bufferLengthInBytes = dataLengthInBytes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 dataLengthInBytes = 0;
229
230 if(bufferLeft == NULL || bufferRight == NULL || bufferLengthInBytes == 0)
231 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200232 LOG(LS_ERROR) << "A buffer pointer or the length is NULL!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000233 return -1;
234 }
235
236 bool playEnded = false;
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000237 uint32_t callbackNotifyMs = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238 {
kthelgason6bfe49c2017-03-30 01:14:41 -0700239 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000240
241 if(!_playingActive || !_isStereo)
242 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200243 LOG(LS_WARNING) << "Not currently playing stereo!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000244 return -1;
245 }
246
247 if(!_ptrFileUtilityObj)
248 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200249 LOG(LS_ERROR)
250 << "Playing stereo, but the FileUtility objects is NULL!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 StopPlaying();
252 return -1;
253 }
254
255 // Stereo playout only supported for WAV files.
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000256 int32_t bytesRead = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 switch(_fileFormat)
258 {
259 case kFileFormatWavFile:
260 bytesRead = _ptrFileUtilityObj->ReadWavDataAsStereo(
261 *_ptrInStream,
262 bufferLeft,
263 bufferRight,
264 bufferLengthInBytes);
265 break;
266 default:
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200267 LOG(LS_ERROR)
268 << "Trying to read non-WAV as stereo audio (not supported)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000269 break;
270 }
271
272 if(bytesRead > 0)
273 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000274 dataLengthInBytes = static_cast<size_t>(bytesRead);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275
276 // Check if it's time for PlayNotification(..).
277 _playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
278 if(_notificationMs)
279 {
280 if(_playoutPositionMs >= _notificationMs)
281 {
282 _notificationMs = 0;
283 callbackNotifyMs = _playoutPositionMs;
284 }
285 }
286 }
287 else
288 {
289 // If no bytes were read assume end of file.
290 StopPlaying();
291 playEnded = true;
292 }
293 }
294
kthelgason6bfe49c2017-03-30 01:14:41 -0700295 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000296 if(_ptrCallback)
297 {
298 if(callbackNotifyMs)
299 {
300 _ptrCallback->PlayNotification(_id, callbackNotifyMs);
301 }
302 if(playEnded)
303 {
304 _ptrCallback->PlayFileEnded(_id);
305 }
306 }
307 return 0;
308}
309
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000310int32_t MediaFileImpl::StartPlayingAudioFile(
leozwang@webrtc.org09e77192012-03-01 18:35:54 +0000311 const char* fileName,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000312 const uint32_t notificationTimeMs,
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 const bool loop,
314 const FileFormats format,
315 const CodecInst* codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000316 const uint32_t startPointMs,
317 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000318{
niklase@google.com470e71d2011-07-07 08:21:25 +0000319 if(!ValidFileName(fileName))
320 {
321 return -1;
322 }
323 if(!ValidFileFormat(format,codecInst))
324 {
325 return -1;
326 }
327 if(!ValidFilePositions(startPointMs,stopPointMs))
328 {
329 return -1;
330 }
331
332 // Check that the file will play longer than notificationTimeMs ms.
333 if((startPointMs && stopPointMs && !loop) &&
334 (notificationTimeMs > (stopPointMs - startPointMs)))
335 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200336 LOG(LS_ERROR) << "specified notification time is longer than amount of"
337 << " ms that will be played";
niklase@google.com470e71d2011-07-07 08:21:25 +0000338 return -1;
339 }
340
341 FileWrapper* inputStream = FileWrapper::Create();
342 if(inputStream == NULL)
343 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200344 LOG(LS_INFO) << "Failed to allocate input stream for file " << fileName;
niklase@google.com470e71d2011-07-07 08:21:25 +0000345 return -1;
346 }
347
tommia6219cc2016-06-15 10:30:14 -0700348 if (!inputStream->OpenFile(fileName, true)) {
349 delete inputStream;
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200350 LOG(LS_ERROR) << "Could not open input file " << fileName;
tommia6219cc2016-06-15 10:30:14 -0700351 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000352 }
353
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000354 if(StartPlayingStream(*inputStream, loop, notificationTimeMs,
355 format, codecInst, startPointMs, stopPointMs) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000356 {
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000357 inputStream->CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000358 delete inputStream;
359 return -1;
360 }
361
kthelgason6bfe49c2017-03-30 01:14:41 -0700362 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000363 _openFile = true;
364 strncpy(_fileName, fileName, sizeof(_fileName));
365 _fileName[sizeof(_fileName) - 1] = '\0';
366 return 0;
367}
368
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000369int32_t MediaFileImpl::StartPlayingAudioStream(
niklase@google.com470e71d2011-07-07 08:21:25 +0000370 InStream& stream,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000371 const uint32_t notificationTimeMs,
niklase@google.com470e71d2011-07-07 08:21:25 +0000372 const FileFormats format,
373 const CodecInst* codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000374 const uint32_t startPointMs,
375 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000376{
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000377 return StartPlayingStream(stream, false, notificationTimeMs, format,
niklase@google.com470e71d2011-07-07 08:21:25 +0000378 codecInst, startPointMs, stopPointMs);
379}
380
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000381int32_t MediaFileImpl::StartPlayingStream(
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 InStream& stream,
niklase@google.com470e71d2011-07-07 08:21:25 +0000383 bool loop,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000384 const uint32_t notificationTimeMs,
niklase@google.com470e71d2011-07-07 08:21:25 +0000385 const FileFormats format,
386 const CodecInst* codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000387 const uint32_t startPointMs,
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000388 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000389{
niklase@google.com470e71d2011-07-07 08:21:25 +0000390 if(!ValidFileFormat(format,codecInst))
391 {
392 return -1;
393 }
394
395 if(!ValidFilePositions(startPointMs,stopPointMs))
396 {
397 return -1;
398 }
399
kthelgason6bfe49c2017-03-30 01:14:41 -0700400 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000401 if(_playingActive || _recordingActive)
402 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200403 LOG(LS_ERROR)
404 << "StartPlaying called, but already playing or recording file "
405 << ((_fileName[0] == '\0') ? "(name not set)" : _fileName);
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 return -1;
407 }
408
409 if(_ptrFileUtilityObj != NULL)
410 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200411 LOG(LS_ERROR)
412 << "StartPlaying called, but FileUtilityObj already exists!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 StopPlaying();
414 return -1;
415 }
416
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200417 _ptrFileUtilityObj = new ModuleFileUtility();
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 if(_ptrFileUtilityObj == NULL)
419 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200420 LOG(LS_INFO) << "Failed to create FileUtilityObj!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000421 return -1;
422 }
423
424 switch(format)
425 {
426 case kFileFormatWavFile:
427 {
428 if(_ptrFileUtilityObj->InitWavReading(stream, startPointMs,
429 stopPointMs) == -1)
430 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200431 LOG(LS_ERROR) << "Not a valid WAV file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000432 StopPlaying();
433 return -1;
434 }
435 _fileFormat = kFileFormatWavFile;
436 break;
437 }
438 case kFileFormatCompressedFile:
439 {
440 if(_ptrFileUtilityObj->InitCompressedReading(stream, startPointMs,
441 stopPointMs) == -1)
442 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200443 LOG(LS_ERROR) << "Not a valid Compressed file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000444 StopPlaying();
445 return -1;
446 }
447 _fileFormat = kFileFormatCompressedFile;
448 break;
449 }
450 case kFileFormatPcm8kHzFile:
451 case kFileFormatPcm16kHzFile:
452 case kFileFormatPcm32kHzFile:
453 {
henrike@webrtc.org26085e12012-02-27 21:50:40 +0000454 // ValidFileFormat() called in the beginneing of this function
455 // prevents codecInst from being NULL here.
456 assert(codecInst != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000457 if(!ValidFrequency(codecInst->plfreq) ||
458 _ptrFileUtilityObj->InitPCMReading(stream, startPointMs,
459 stopPointMs,
460 codecInst->plfreq) == -1)
461 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200462 LOG(LS_ERROR) << "Not a valid raw 8 or 16 KHz PCM file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000463 StopPlaying();
464 return -1;
465 }
466
467 _fileFormat = format;
468 break;
469 }
470 case kFileFormatPreencodedFile:
471 {
henrike@webrtc.org26085e12012-02-27 21:50:40 +0000472 // ValidFileFormat() called in the beginneing of this function
473 // prevents codecInst from being NULL here.
474 assert(codecInst != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000475 if(_ptrFileUtilityObj->InitPreEncodedReading(stream, *codecInst) ==
476 -1)
477 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200478 LOG(LS_ERROR) << "Not a valid PreEncoded file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000479 StopPlaying();
480 return -1;
481 }
482
483 _fileFormat = kFileFormatPreencodedFile;
484 break;
485 }
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000486 default:
niklase@google.com470e71d2011-07-07 08:21:25 +0000487 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200488 LOG(LS_ERROR) << "Invalid file format: " << format;
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +0000489 assert(false);
490 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000491 }
492 }
493 if(_ptrFileUtilityObj->codec_info(codec_info_) == -1)
494 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200495 LOG(LS_ERROR) << "Failed to retrieve codec info!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000496 StopPlaying();
497 return -1;
498 }
499
500 _isStereo = (codec_info_.channels == 2);
501 if(_isStereo && (_fileFormat != kFileFormatWavFile))
502 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200503 LOG(LS_WARNING) << "Stereo is only allowed for WAV files";
niklase@google.com470e71d2011-07-07 08:21:25 +0000504 StopPlaying();
505 return -1;
506 }
507 _playingActive = true;
508 _playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
509 _ptrInStream = &stream;
510 _notificationMs = notificationTimeMs;
511
512 return 0;
513}
514
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000515int32_t MediaFileImpl::StopPlaying()
niklase@google.com470e71d2011-07-07 08:21:25 +0000516{
niklase@google.com470e71d2011-07-07 08:21:25 +0000517
kthelgason6bfe49c2017-03-30 01:14:41 -0700518 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519 _isStereo = false;
520 if(_ptrFileUtilityObj)
521 {
522 delete _ptrFileUtilityObj;
523 _ptrFileUtilityObj = NULL;
524 }
525 if(_ptrInStream)
526 {
527 // If MediaFileImpl opened the InStream it must be reclaimed here.
528 if(_openFile)
529 {
530 delete _ptrInStream;
531 _openFile = false;
532 }
533 _ptrInStream = NULL;
534 }
535
536 codec_info_.pltype = 0;
537 codec_info_.plname[0] = '\0';
538
539 if(!_playingActive)
540 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200541 LOG(LS_WARNING) << "playing is not active!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000542 return -1;
543 }
544
545 _playingActive = false;
546 return 0;
547}
548
549bool MediaFileImpl::IsPlaying()
550{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200551 LOG(LS_VERBOSE) << "MediaFileImpl::IsPlaying()";
kthelgason6bfe49c2017-03-30 01:14:41 -0700552 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553 return _playingActive;
554}
555
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000556int32_t MediaFileImpl::IncomingAudioData(
557 const int8_t* buffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000558 const size_t bufferLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000559{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200560 LOG(LS_INFO) << "MediaFile::IncomingData(buffer= "
561 << static_cast<const void*>(buffer) << ", bufLen= "
562 << bufferLengthInBytes << ")";
niklase@google.com470e71d2011-07-07 08:21:25 +0000563
564 if(buffer == NULL || bufferLengthInBytes == 0)
565 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200566 LOG(LS_ERROR) << "Buffer pointer or length is NULL!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000567 return -1;
568 }
569
570 bool recordingEnded = false;
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000571 uint32_t callbackNotifyMs = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000572 {
kthelgason6bfe49c2017-03-30 01:14:41 -0700573 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
575 if(!_recordingActive)
576 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200577 LOG(LS_WARNING) << "Not currently recording!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000578 return -1;
579 }
580 if(_ptrOutStream == NULL)
581 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200582 LOG(LS_ERROR) << "Recording is active, but output stream is NULL!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000583 assert(false);
584 return -1;
585 }
586
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000587 int32_t bytesWritten = 0;
588 uint32_t samplesWritten = codec_info_.pacsize;
niklase@google.com470e71d2011-07-07 08:21:25 +0000589 if(_ptrFileUtilityObj)
590 {
591 switch(_fileFormat)
592 {
593 case kFileFormatPcm8kHzFile:
594 case kFileFormatPcm16kHzFile:
595 case kFileFormatPcm32kHzFile:
596 bytesWritten = _ptrFileUtilityObj->WritePCMData(
597 *_ptrOutStream,
598 buffer,
599 bufferLengthInBytes);
600
601 // Sample size is 2 bytes.
602 if(bytesWritten > 0)
603 {
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000604 samplesWritten = bytesWritten/sizeof(int16_t);
niklase@google.com470e71d2011-07-07 08:21:25 +0000605 }
606 break;
607 case kFileFormatCompressedFile:
608 bytesWritten = _ptrFileUtilityObj->WriteCompressedData(
609 *_ptrOutStream, buffer, bufferLengthInBytes);
610 break;
611 case kFileFormatWavFile:
612 bytesWritten = _ptrFileUtilityObj->WriteWavData(
613 *_ptrOutStream,
614 buffer,
615 bufferLengthInBytes);
616 if(bytesWritten > 0 && STR_NCASE_CMP(codec_info_.plname,
617 "L16", 4) == 0)
618 {
619 // Sample size is 2 bytes.
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000620 samplesWritten = bytesWritten/sizeof(int16_t);
niklase@google.com470e71d2011-07-07 08:21:25 +0000621 }
622 break;
623 case kFileFormatPreencodedFile:
624 bytesWritten = _ptrFileUtilityObj->WritePreEncodedData(
625 *_ptrOutStream, buffer, bufferLengthInBytes);
626 break;
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000627 default:
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200628 LOG(LS_ERROR) << "Invalid file format: " << _fileFormat;
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +0000629 assert(false);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000631 }
632 } else {
633 // TODO (hellner): quick look at the code makes me think that this
634 // code is never executed. Remove?
635 if(_ptrOutStream)
636 {
637 if(_ptrOutStream->Write(buffer, bufferLengthInBytes))
638 {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000639 bytesWritten = static_cast<int32_t>(bufferLengthInBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000640 }
641 }
642 }
643
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000644 _recordDurationMs += samplesWritten / (codec_info_.plfreq / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000645
646 // Check if it's time for RecordNotification(..).
647 if(_notificationMs)
648 {
649 if(_recordDurationMs >= _notificationMs)
650 {
651 _notificationMs = 0;
652 callbackNotifyMs = _recordDurationMs;
653 }
654 }
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000655 if(bytesWritten < (int32_t)bufferLengthInBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200657 LOG(LS_WARNING) << "Failed to write all requested bytes!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000658 StopRecording();
659 recordingEnded = true;
660 }
661 }
662
663 // Only _callbackCrit may and should be taken when making callbacks.
kthelgason6bfe49c2017-03-30 01:14:41 -0700664 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000665 if(_ptrCallback)
666 {
667 if(callbackNotifyMs)
668 {
669 _ptrCallback->RecordNotification(_id, callbackNotifyMs);
670 }
671 if(recordingEnded)
672 {
673 _ptrCallback->RecordFileEnded(_id);
674 return -1;
675 }
676 }
677 return 0;
678}
679
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000680int32_t MediaFileImpl::StartRecordingAudioFile(
leozwang@webrtc.org09e77192012-03-01 18:35:54 +0000681 const char* fileName,
niklase@google.com470e71d2011-07-07 08:21:25 +0000682 const FileFormats format,
683 const CodecInst& codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000684 const uint32_t notificationTimeMs,
685 const uint32_t maxSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000686{
niklase@google.com470e71d2011-07-07 08:21:25 +0000687 if(!ValidFileName(fileName))
688 {
689 return -1;
690 }
691 if(!ValidFileFormat(format,&codecInst))
692 {
693 return -1;
694 }
695
696 FileWrapper* outputStream = FileWrapper::Create();
697 if(outputStream == NULL)
698 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200699 LOG(LS_INFO) << "Failed to allocate memory for output stream";
niklase@google.com470e71d2011-07-07 08:21:25 +0000700 return -1;
701 }
702
tommia6219cc2016-06-15 10:30:14 -0700703 if (!outputStream->OpenFile(fileName, false)) {
704 delete outputStream;
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200705 LOG(LS_ERROR) << "Could not open output file '" << fileName
706 << "' for writing!";
tommia6219cc2016-06-15 10:30:14 -0700707 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000708 }
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000709
niklase@google.com470e71d2011-07-07 08:21:25 +0000710 if(maxSizeBytes)
711 {
712 outputStream->SetMaxFileSize(maxSizeBytes);
713 }
714
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000715 if(StartRecordingAudioStream(*outputStream, format, codecInst,
716 notificationTimeMs) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000717 {
andresp@webrtc.orge8f50df2015-03-02 13:07:02 +0000718 outputStream->CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000719 delete outputStream;
720 return -1;
721 }
722
kthelgason6bfe49c2017-03-30 01:14:41 -0700723 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000724 _openFile = true;
725 strncpy(_fileName, fileName, sizeof(_fileName));
726 _fileName[sizeof(_fileName) - 1] = '\0';
727 return 0;
728}
729
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000730int32_t MediaFileImpl::StartRecordingAudioStream(
niklase@google.com470e71d2011-07-07 08:21:25 +0000731 OutStream& stream,
732 const FileFormats format,
733 const CodecInst& codecInst,
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000734 const uint32_t notificationTimeMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000735{
niklase@google.com470e71d2011-07-07 08:21:25 +0000736 // Check codec info
737 if(!ValidFileFormat(format,&codecInst))
738 {
739 return -1;
740 }
741
kthelgason6bfe49c2017-03-30 01:14:41 -0700742 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000743 if(_recordingActive || _playingActive)
744 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200745 LOG(LS_ERROR)
746 << "StartRecording called, but already recording or playing file "
747 << _fileName << "!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000748 return -1;
749 }
750
751 if(_ptrFileUtilityObj != NULL)
752 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200753 LOG(LS_ERROR)
754 << "StartRecording called, but fileUtilityObj already exists!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000755 StopRecording();
756 return -1;
757 }
758
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200759 _ptrFileUtilityObj = new ModuleFileUtility();
niklase@google.com470e71d2011-07-07 08:21:25 +0000760 if(_ptrFileUtilityObj == NULL)
761 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200762 LOG(LS_INFO) << "Cannot allocate fileUtilityObj!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000763 return -1;
764 }
765
766 CodecInst tmpAudioCodec;
767 memcpy(&tmpAudioCodec, &codecInst, sizeof(CodecInst));
768 switch(format)
769 {
770 case kFileFormatWavFile:
771 {
772 if(_ptrFileUtilityObj->InitWavWriting(stream, codecInst) == -1)
773 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200774 LOG(LS_ERROR) << "Failed to initialize WAV file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000775 delete _ptrFileUtilityObj;
776 _ptrFileUtilityObj = NULL;
777 return -1;
778 }
779 _fileFormat = kFileFormatWavFile;
780 break;
781 }
782 case kFileFormatCompressedFile:
783 {
784 // Write compression codec name at beginning of file
785 if(_ptrFileUtilityObj->InitCompressedWriting(stream, codecInst) ==
786 -1)
787 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200788 LOG(LS_ERROR) << "Failed to initialize Compressed file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000789 delete _ptrFileUtilityObj;
790 _ptrFileUtilityObj = NULL;
791 return -1;
792 }
793 _fileFormat = kFileFormatCompressedFile;
794 break;
795 }
796 case kFileFormatPcm8kHzFile:
797 case kFileFormatPcm16kHzFile:
798 {
799 if(!ValidFrequency(codecInst.plfreq) ||
800 _ptrFileUtilityObj->InitPCMWriting(stream, codecInst.plfreq) ==
801 -1)
802 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200803 LOG(LS_ERROR) << "Failed to initialize 8 or 16KHz PCM file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000804 delete _ptrFileUtilityObj;
805 _ptrFileUtilityObj = NULL;
806 return -1;
807 }
808 _fileFormat = format;
809 break;
810 }
811 case kFileFormatPreencodedFile:
812 {
813 if(_ptrFileUtilityObj->InitPreEncodedWriting(stream, codecInst) ==
814 -1)
815 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200816 LOG(LS_ERROR) << "Failed to initialize Pre-Encoded file!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000817 delete _ptrFileUtilityObj;
818 _ptrFileUtilityObj = NULL;
819 return -1;
820 }
821
822 _fileFormat = kFileFormatPreencodedFile;
823 break;
824 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000825 default:
826 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200827 LOG(LS_ERROR) << "Invalid file format " << format << " specified!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000828 delete _ptrFileUtilityObj;
829 _ptrFileUtilityObj = NULL;
830 return -1;
831 }
832 }
833 _isStereo = (tmpAudioCodec.channels == 2);
834 if(_isStereo)
835 {
836 if(_fileFormat != kFileFormatWavFile)
837 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200838 LOG(LS_WARNING) << "Stereo is only allowed for WAV files";
niklase@google.com470e71d2011-07-07 08:21:25 +0000839 StopRecording();
840 return -1;
841 }
niklas.enbom@webrtc.org87885e82012-02-07 14:48:59 +0000842 if((STR_NCASE_CMP(tmpAudioCodec.plname, "L16", 4) != 0) &&
843 (STR_NCASE_CMP(tmpAudioCodec.plname, "PCMU", 5) != 0) &&
844 (STR_NCASE_CMP(tmpAudioCodec.plname, "PCMA", 5) != 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000845 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200846 LOG(LS_WARNING)
847 << "Stereo is only allowed for codec PCMU, PCMA and L16 ";
niklase@google.com470e71d2011-07-07 08:21:25 +0000848 StopRecording();
849 return -1;
850 }
851 }
852 memcpy(&codec_info_, &tmpAudioCodec, sizeof(CodecInst));
853 _recordingActive = true;
854 _ptrOutStream = &stream;
855 _notificationMs = notificationTimeMs;
856 _recordDurationMs = 0;
857 return 0;
858}
859
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000860int32_t MediaFileImpl::StopRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000861{
niklase@google.com470e71d2011-07-07 08:21:25 +0000862
kthelgason6bfe49c2017-03-30 01:14:41 -0700863 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000864 if(!_recordingActive)
865 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200866 LOG(LS_WARNING) << "recording is not active!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000867 return -1;
868 }
869
870 _isStereo = false;
871
872 if(_ptrFileUtilityObj != NULL)
873 {
874 // Both AVI and WAV header has to be updated before closing the stream
875 // because they contain size information.
876 if((_fileFormat == kFileFormatWavFile) &&
877 (_ptrOutStream != NULL))
878 {
879 _ptrFileUtilityObj->UpdateWavHeader(*_ptrOutStream);
880 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000881 delete _ptrFileUtilityObj;
882 _ptrFileUtilityObj = NULL;
883 }
884
885 if(_ptrOutStream != NULL)
886 {
887 // If MediaFileImpl opened the OutStream it must be reclaimed here.
888 if(_openFile)
889 {
890 delete _ptrOutStream;
891 _openFile = false;
892 }
893 _ptrOutStream = NULL;
894 }
895
896 _recordingActive = false;
897 codec_info_.pltype = 0;
898 codec_info_.plname[0] = '\0';
899
900 return 0;
901}
902
903bool MediaFileImpl::IsRecording()
904{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200905 LOG(LS_VERBOSE) << "MediaFileImpl::IsRecording()";
kthelgason6bfe49c2017-03-30 01:14:41 -0700906 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000907 return _recordingActive;
908}
909
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000910int32_t MediaFileImpl::RecordDurationMs(uint32_t& durationMs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000911{
niklase@google.com470e71d2011-07-07 08:21:25 +0000912
kthelgason6bfe49c2017-03-30 01:14:41 -0700913 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000914 if(!_recordingActive)
915 {
916 durationMs = 0;
917 return -1;
918 }
919 durationMs = _recordDurationMs;
920 return 0;
921}
922
923bool MediaFileImpl::IsStereo()
924{
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200925 LOG(LS_VERBOSE) << "MediaFileImpl::IsStereo()";
kthelgason6bfe49c2017-03-30 01:14:41 -0700926 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000927 return _isStereo;
928}
929
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000930int32_t MediaFileImpl::SetModuleFileCallback(FileCallback* callback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000931{
niklase@google.com470e71d2011-07-07 08:21:25 +0000932
kthelgason6bfe49c2017-03-30 01:14:41 -0700933 rtc::CritScope lock(&_callbackCrit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000934
935 _ptrCallback = callback;
936 return 0;
937}
938
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000939int32_t MediaFileImpl::FileDurationMs(const char* fileName,
940 uint32_t& durationMs,
941 const FileFormats format,
942 const uint32_t freqInHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000943{
niklase@google.com470e71d2011-07-07 08:21:25 +0000944
945 if(!ValidFileName(fileName))
946 {
947 return -1;
948 }
949 if(!ValidFrequency(freqInHz))
950 {
951 return -1;
952 }
953
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200954 ModuleFileUtility* utilityObj = new ModuleFileUtility();
niklase@google.com470e71d2011-07-07 08:21:25 +0000955 if(utilityObj == NULL)
956 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200957 LOG(LS_ERROR) << "failed to allocate utility object!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000958 return -1;
959 }
960
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000961 const int32_t duration = utilityObj->FileDurationMs(fileName, format,
962 freqInHz);
niklase@google.com470e71d2011-07-07 08:21:25 +0000963 delete utilityObj;
964 if(duration == -1)
965 {
966 durationMs = 0;
967 return -1;
968 }
969
970 durationMs = duration;
971 return 0;
972}
973
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000974int32_t MediaFileImpl::PlayoutPositionMs(uint32_t& positionMs) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000975{
kthelgason6bfe49c2017-03-30 01:14:41 -0700976 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000977 if(!_playingActive)
978 {
979 positionMs = 0;
980 return -1;
981 }
982 positionMs = _playoutPositionMs;
983 return 0;
984}
985
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +0000986int32_t MediaFileImpl::codec_info(CodecInst& codecInst) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000987{
kthelgason6bfe49c2017-03-30 01:14:41 -0700988 rtc::CritScope lock(&_crit);
niklase@google.com470e71d2011-07-07 08:21:25 +0000989 if(!_playingActive && !_recordingActive)
990 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200991 LOG(LS_ERROR) << "Neither playout nor recording has been initialized!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000992 return -1;
993 }
994 if (codec_info_.pltype == 0 && codec_info_.plname[0] == '\0')
995 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +0200996 LOG(LS_ERROR) << "The CodecInst for "
997 << (_playingActive ? "Playback" : "Recording")
998 << " is unknown!";
niklase@google.com470e71d2011-07-07 08:21:25 +0000999 return -1;
1000 }
1001 memcpy(&codecInst,&codec_info_,sizeof(CodecInst));
1002 return 0;
1003}
1004
niklase@google.com470e71d2011-07-07 08:21:25 +00001005bool MediaFileImpl::ValidFileFormat(const FileFormats format,
1006 const CodecInst* codecInst)
1007{
1008 if(codecInst == NULL)
1009 {
1010 if(format == kFileFormatPreencodedFile ||
1011 format == kFileFormatPcm8kHzFile ||
1012 format == kFileFormatPcm16kHzFile ||
lliuubc436ed2017-03-31 16:32:28 -07001013 format == kFileFormatPcm32kHzFile)
niklase@google.com470e71d2011-07-07 08:21:25 +00001014 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +02001015 LOG(LS_ERROR) << "Codec info required for file format specified!";
niklase@google.com470e71d2011-07-07 08:21:25 +00001016 return false;
1017 }
1018 }
1019 return true;
1020}
1021
leozwang@webrtc.org09e77192012-03-01 18:35:54 +00001022bool MediaFileImpl::ValidFileName(const char* fileName)
niklase@google.com470e71d2011-07-07 08:21:25 +00001023{
1024 if((fileName == NULL) ||(fileName[0] == '\0'))
1025 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +02001026 LOG(LS_ERROR) << "FileName not specified!";
niklase@google.com470e71d2011-07-07 08:21:25 +00001027 return false;
1028 }
1029 return true;
1030}
1031
1032
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +00001033bool MediaFileImpl::ValidFilePositions(const uint32_t startPointMs,
1034 const uint32_t stopPointMs)
niklase@google.com470e71d2011-07-07 08:21:25 +00001035{
1036 if(startPointMs == 0 && stopPointMs == 0) // Default values
1037 {
1038 return true;
1039 }
1040 if(stopPointMs &&(startPointMs >= stopPointMs))
1041 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +02001042 LOG(LS_ERROR) << "startPointMs must be less than stopPointMs!";
niklase@google.com470e71d2011-07-07 08:21:25 +00001043 return false;
1044 }
1045 if(stopPointMs &&((stopPointMs - startPointMs) < 20))
1046 {
Sam Zackrisson45ca37c2017-08-22 13:44:09 +02001047 LOG(LS_ERROR) << "minimum play duration for files is 20 ms!";
niklase@google.com470e71d2011-07-07 08:21:25 +00001048 return false;
1049 }
1050 return true;
1051}
1052
pbos@webrtc.org0ea11c12013-04-09 13:31:37 +00001053bool MediaFileImpl::ValidFrequency(const uint32_t frequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00001054{
lliuubc436ed2017-03-31 16:32:28 -07001055 if((frequency == 8000) || (frequency == 16000)|| (frequency == 32000))
niklase@google.com470e71d2011-07-07 08:21:25 +00001056 {
1057 return true;
1058 }
Sam Zackrisson45ca37c2017-08-22 13:44:09 +02001059 LOG(LS_ERROR) << "Frequency should be 8000, 16000 or 32000 (Hz)";
niklase@google.com470e71d2011-07-07 08:21:25 +00001060 return false;
1061}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001062} // namespace webrtc