Chromium Code Reviews

Side by Side Diff: webrtc/modules/media_file/source/media_file_utility.cc

Issue 1435093002: Remove include dirs from modules/{media_file,pacing} (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase fix Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « webrtc/modules/media_file/source/media_file_utility.h ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/media_file/source/media_file_utility.h"
12
13 #include <assert.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <limits>
17
18 #include "webrtc/base/format_macros.h"
19 #include "webrtc/common_audio/wav_header.h"
20 #include "webrtc/common_types.h"
21 #include "webrtc/engine_configurations.h"
22 #include "webrtc/modules/include/module_common_types.h"
23 #include "webrtc/system_wrappers/include/file_wrapper.h"
24 #include "webrtc/system_wrappers/include/trace.h"
25
26 namespace {
27
28 // First 16 bytes the WAVE header. ckID should be "RIFF", wave_ckID should be
29 // "WAVE" and ckSize is the chunk size (4 + n)
30 struct WAVE_RIFF_header
31 {
32 int8_t ckID[4];
33 int32_t ckSize;
34 int8_t wave_ckID[4];
35 };
36
37 // First 8 byte of the format chunk. fmt_ckID should be "fmt ". fmt_ckSize is
38 // the chunk size (16, 18 or 40 byte)
39 struct WAVE_CHUNK_header
40 {
41 int8_t fmt_ckID[4];
42 int32_t fmt_ckSize;
43 };
44 } // unnamed namespace
45
46 namespace webrtc {
47 ModuleFileUtility::ModuleFileUtility(const int32_t id)
48 : _wavFormatObj(),
49 _dataSize(0),
50 _readSizeBytes(0),
51 _id(id),
52 _stopPointInMs(0),
53 _startPointInMs(0),
54 _playoutPositionMs(0),
55 _bytesWritten(0),
56 codec_info_(),
57 _codecId(kCodecNoCodec),
58 _bytesPerSample(0),
59 _readPos(0),
60 _reading(false),
61 _writing(false),
62 _tempData() {
63 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
64 "ModuleFileUtility::ModuleFileUtility()");
65 memset(&codec_info_,0,sizeof(CodecInst));
66 codec_info_.pltype = -1;
67 }
68
69 ModuleFileUtility::~ModuleFileUtility()
70 {
71 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
72 "ModuleFileUtility::~ModuleFileUtility()");
73 }
74
75 int32_t ModuleFileUtility::ReadWavHeader(InStream& wav)
76 {
77 WAVE_RIFF_header RIFFheaderObj;
78 WAVE_CHUNK_header CHUNKheaderObj;
79 // TODO (hellner): tmpStr and tmpStr2 seems unnecessary here.
80 char tmpStr[6] = "FOUR";
81 unsigned char tmpStr2[4];
82 int32_t i, len;
83 bool dataFound = false;
84 bool fmtFound = false;
85 int8_t dummyRead;
86
87
88 _dataSize = 0;
89 len = wav.Read(&RIFFheaderObj, sizeof(WAVE_RIFF_header));
90 if(len != sizeof(WAVE_RIFF_header))
91 {
92 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
93 "Not a wave file (too short)");
94 return -1;
95 }
96
97 for (i = 0; i < 4; i++)
98 {
99 tmpStr[i] = RIFFheaderObj.ckID[i];
100 }
101 if(strcmp(tmpStr, "RIFF") != 0)
102 {
103 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
104 "Not a wave file (does not have RIFF)");
105 return -1;
106 }
107 for (i = 0; i < 4; i++)
108 {
109 tmpStr[i] = RIFFheaderObj.wave_ckID[i];
110 }
111 if(strcmp(tmpStr, "WAVE") != 0)
112 {
113 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
114 "Not a wave file (does not have WAVE)");
115 return -1;
116 }
117
118 len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header));
119
120 // WAVE files are stored in little endian byte order. Make sure that the
121 // data can be read on big endian as well.
122 // TODO (hellner): little endian to system byte order should be done in
123 // in a subroutine.
124 memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4);
125 CHUNKheaderObj.fmt_ckSize =
126 (int32_t) ((uint32_t) tmpStr2[0] +
127 (((uint32_t)tmpStr2[1])<<8) +
128 (((uint32_t)tmpStr2[2])<<16) +
129 (((uint32_t)tmpStr2[3])<<24));
130
131 memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4);
132
133 while ((len == sizeof(WAVE_CHUNK_header)) && (!fmtFound || !dataFound))
134 {
135 if(strcmp(tmpStr, "fmt ") == 0)
136 {
137 len = wav.Read(&_wavFormatObj, sizeof(WAVE_FMTINFO_header));
138
139 memcpy(tmpStr2, &_wavFormatObj.formatTag, 2);
140 _wavFormatObj.formatTag =
141 (uint32_t)tmpStr2[0] + (((uint32_t)tmpStr2[1])<<8);
142 memcpy(tmpStr2, &_wavFormatObj.nChannels, 2);
143 _wavFormatObj.nChannels =
144 (int16_t) ((uint32_t)tmpStr2[0] +
145 (((uint32_t)tmpStr2[1])<<8));
146 memcpy(tmpStr2, &_wavFormatObj.nSamplesPerSec, 4);
147 _wavFormatObj.nSamplesPerSec =
148 (int32_t) ((uint32_t)tmpStr2[0] +
149 (((uint32_t)tmpStr2[1])<<8) +
150 (((uint32_t)tmpStr2[2])<<16) +
151 (((uint32_t)tmpStr2[3])<<24));
152 memcpy(tmpStr2, &_wavFormatObj.nAvgBytesPerSec, 4);
153 _wavFormatObj.nAvgBytesPerSec =
154 (int32_t) ((uint32_t)tmpStr2[0] +
155 (((uint32_t)tmpStr2[1])<<8) +
156 (((uint32_t)tmpStr2[2])<<16) +
157 (((uint32_t)tmpStr2[3])<<24));
158 memcpy(tmpStr2, &_wavFormatObj.nBlockAlign, 2);
159 _wavFormatObj.nBlockAlign =
160 (int16_t) ((uint32_t)tmpStr2[0] +
161 (((uint32_t)tmpStr2[1])<<8));
162 memcpy(tmpStr2, &_wavFormatObj.nBitsPerSample, 2);
163 _wavFormatObj.nBitsPerSample =
164 (int16_t) ((uint32_t)tmpStr2[0] +
165 (((uint32_t)tmpStr2[1])<<8));
166
167 for (i = 0;
168 i < (CHUNKheaderObj.fmt_ckSize -
169 (int32_t)sizeof(WAVE_FMTINFO_header));
170 i++)
171 {
172 len = wav.Read(&dummyRead, 1);
173 if(len != 1)
174 {
175 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
176 "File corrupted, reached EOF (reading fmt)");
177 return -1;
178 }
179 }
180 fmtFound = true;
181 }
182 else if(strcmp(tmpStr, "data") == 0)
183 {
184 _dataSize = CHUNKheaderObj.fmt_ckSize;
185 dataFound = true;
186 break;
187 }
188 else
189 {
190 for (i = 0; i < (CHUNKheaderObj.fmt_ckSize); i++)
191 {
192 len = wav.Read(&dummyRead, 1);
193 if(len != 1)
194 {
195 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
196 "File corrupted, reached EOF (reading other)");
197 return -1;
198 }
199 }
200 }
201
202 len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header));
203
204 memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4);
205 CHUNKheaderObj.fmt_ckSize =
206 (int32_t) ((uint32_t)tmpStr2[0] +
207 (((uint32_t)tmpStr2[1])<<8) +
208 (((uint32_t)tmpStr2[2])<<16) +
209 (((uint32_t)tmpStr2[3])<<24));
210
211 memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4);
212 }
213
214 // Either a proper format chunk has been read or a data chunk was come
215 // across.
216 if( (_wavFormatObj.formatTag != kWavFormatPcm) &&
217 (_wavFormatObj.formatTag != kWavFormatALaw) &&
218 (_wavFormatObj.formatTag != kWavFormatMuLaw))
219 {
220 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
221 "Coding formatTag value=%d not supported!",
222 _wavFormatObj.formatTag);
223 return -1;
224 }
225 if((_wavFormatObj.nChannels < 1) ||
226 (_wavFormatObj.nChannels > 2))
227 {
228 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
229 "nChannels value=%d not supported!",
230 _wavFormatObj.nChannels);
231 return -1;
232 }
233
234 if((_wavFormatObj.nBitsPerSample != 8) &&
235 (_wavFormatObj.nBitsPerSample != 16))
236 {
237 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
238 "nBitsPerSample value=%d not supported!",
239 _wavFormatObj.nBitsPerSample);
240 return -1;
241 }
242
243 // Calculate the number of bytes that 10 ms of audio data correspond to.
244 if(_wavFormatObj.formatTag == kWavFormatPcm)
245 {
246 // TODO (hellner): integer division for 22050 and 11025 would yield
247 // the same result as the else statement. Remove those
248 // special cases?
249 if(_wavFormatObj.nSamplesPerSec == 44100)
250 {
251 _readSizeBytes = 440 * _wavFormatObj.nChannels *
252 (_wavFormatObj.nBitsPerSample / 8);
253 } else if(_wavFormatObj.nSamplesPerSec == 22050) {
254 _readSizeBytes = 220 * _wavFormatObj.nChannels *
255 (_wavFormatObj.nBitsPerSample / 8);
256 } else if(_wavFormatObj.nSamplesPerSec == 11025) {
257 _readSizeBytes = 110 * _wavFormatObj.nChannels *
258 (_wavFormatObj.nBitsPerSample / 8);
259 } else {
260 _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) *
261 _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8);
262 }
263
264 } else {
265 _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) *
266 _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8);
267 }
268 return 0;
269 }
270
271 int32_t ModuleFileUtility::InitWavCodec(uint32_t samplesPerSec,
272 uint32_t channels,
273 uint32_t bitsPerSample,
274 uint32_t formatTag)
275 {
276 codec_info_.pltype = -1;
277 codec_info_.plfreq = samplesPerSec;
278 codec_info_.channels = channels;
279 codec_info_.rate = bitsPerSample * samplesPerSec;
280
281 // Calculate the packet size for 10ms frames
282 switch(formatTag)
283 {
284 case kWavFormatALaw:
285 strcpy(codec_info_.plname, "PCMA");
286 _codecId = kCodecPcma;
287 codec_info_.pltype = 8;
288 codec_info_.pacsize = codec_info_.plfreq / 100;
289 break;
290 case kWavFormatMuLaw:
291 strcpy(codec_info_.plname, "PCMU");
292 _codecId = kCodecPcmu;
293 codec_info_.pltype = 0;
294 codec_info_.pacsize = codec_info_.plfreq / 100;
295 break;
296 case kWavFormatPcm:
297 codec_info_.pacsize = (bitsPerSample * (codec_info_.plfreq / 100)) / 8;
298 if(samplesPerSec == 8000)
299 {
300 strcpy(codec_info_.plname, "L16");
301 _codecId = kCodecL16_8Khz;
302 }
303 else if(samplesPerSec == 16000)
304 {
305 strcpy(codec_info_.plname, "L16");
306 _codecId = kCodecL16_16kHz;
307 }
308 else if(samplesPerSec == 32000)
309 {
310 strcpy(codec_info_.plname, "L16");
311 _codecId = kCodecL16_32Khz;
312 }
313 // Set the packet size for "odd" sampling frequencies so that it
314 // properly corresponds to _readSizeBytes.
315 else if(samplesPerSec == 11025)
316 {
317 strcpy(codec_info_.plname, "L16");
318 _codecId = kCodecL16_16kHz;
319 codec_info_.pacsize = 110;
320 codec_info_.plfreq = 11000;
321 }
322 else if(samplesPerSec == 22050)
323 {
324 strcpy(codec_info_.plname, "L16");
325 _codecId = kCodecL16_16kHz;
326 codec_info_.pacsize = 220;
327 codec_info_.plfreq = 22000;
328 }
329 else if(samplesPerSec == 44100)
330 {
331 strcpy(codec_info_.plname, "L16");
332 _codecId = kCodecL16_16kHz;
333 codec_info_.pacsize = 440;
334 codec_info_.plfreq = 44000;
335 }
336 else if(samplesPerSec == 48000)
337 {
338 strcpy(codec_info_.plname, "L16");
339 _codecId = kCodecL16_16kHz;
340 codec_info_.pacsize = 480;
341 codec_info_.plfreq = 48000;
342 }
343 else
344 {
345 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
346 "Unsupported PCM frequency!");
347 return -1;
348 }
349 break;
350 default:
351 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
352 "unknown WAV format TAG!");
353 return -1;
354 break;
355 }
356 return 0;
357 }
358
359 int32_t ModuleFileUtility::InitWavReading(InStream& wav,
360 const uint32_t start,
361 const uint32_t stop)
362 {
363
364 _reading = false;
365
366 if(ReadWavHeader(wav) == -1)
367 {
368 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
369 "failed to read WAV header!");
370 return -1;
371 }
372
373 _playoutPositionMs = 0;
374 _readPos = 0;
375
376 if(start > 0)
377 {
378 uint8_t dummy[WAV_MAX_BUFFER_SIZE];
379 int32_t readLength;
380 if(_readSizeBytes <= WAV_MAX_BUFFER_SIZE)
381 {
382 while (_playoutPositionMs < start)
383 {
384 readLength = wav.Read(dummy, _readSizeBytes);
385 if(readLength == _readSizeBytes)
386 {
387 _readPos += readLength;
388 _playoutPositionMs += 10;
389 }
390 else // Must have reached EOF before start position!
391 {
392 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
393 "InitWavReading(), EOF before start position");
394 return -1;
395 }
396 }
397 }
398 else
399 {
400 return -1;
401 }
402 }
403 if( InitWavCodec(_wavFormatObj.nSamplesPerSec, _wavFormatObj.nChannels,
404 _wavFormatObj.nBitsPerSample,
405 _wavFormatObj.formatTag) != 0)
406 {
407 return -1;
408 }
409 _bytesPerSample = _wavFormatObj.nBitsPerSample / 8;
410
411
412 _startPointInMs = start;
413 _stopPointInMs = stop;
414 _reading = true;
415 return 0;
416 }
417
418 int32_t ModuleFileUtility::ReadWavDataAsMono(
419 InStream& wav,
420 int8_t* outData,
421 const size_t bufferSize)
422 {
423 WEBRTC_TRACE(
424 kTraceStream,
425 kTraceFile,
426 _id,
427 "ModuleFileUtility::ReadWavDataAsMono(wav= 0x%x, outData= 0x%d, "
428 "bufSize= %" PRIuS ")",
429 &wav,
430 outData,
431 bufferSize);
432
433 // The number of bytes that should be read from file.
434 const uint32_t totalBytesNeeded = _readSizeBytes;
435 // The number of bytes that will be written to outData.
436 const uint32_t bytesRequested = (codec_info_.channels == 2) ?
437 totalBytesNeeded >> 1 : totalBytesNeeded;
438 if(bufferSize < bytesRequested)
439 {
440 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
441 "ReadWavDataAsMono: output buffer is too short!");
442 return -1;
443 }
444 if(outData == NULL)
445 {
446 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
447 "ReadWavDataAsMono: output buffer NULL!");
448 return -1;
449 }
450
451 if(!_reading)
452 {
453 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
454 "ReadWavDataAsMono: no longer reading file.");
455 return -1;
456 }
457
458 int32_t bytesRead = ReadWavData(
459 wav,
460 (codec_info_.channels == 2) ? _tempData : (uint8_t*)outData,
461 totalBytesNeeded);
462 if(bytesRead == 0)
463 {
464 return 0;
465 }
466 if(bytesRead < 0)
467 {
468 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
469 "ReadWavDataAsMono: failed to read data from WAV file.");
470 return -1;
471 }
472 // Output data is should be mono.
473 if(codec_info_.channels == 2)
474 {
475 for (uint32_t i = 0; i < bytesRequested / _bytesPerSample; i++)
476 {
477 // Sample value is the average of left and right buffer rounded to
478 // closest integer value. Note samples can be either 1 or 2 byte.
479 if(_bytesPerSample == 1)
480 {
481 _tempData[i] = ((_tempData[2 * i] + _tempData[(2 * i) + 1] +
482 1) >> 1);
483 }
484 else
485 {
486 int16_t* sampleData = (int16_t*) _tempData;
487 sampleData[i] = ((sampleData[2 * i] + sampleData[(2 * i) + 1] +
488 1) >> 1);
489 }
490 }
491 memcpy(outData, _tempData, bytesRequested);
492 }
493 return bytesRequested;
494 }
495
496 int32_t ModuleFileUtility::ReadWavDataAsStereo(
497 InStream& wav,
498 int8_t* outDataLeft,
499 int8_t* outDataRight,
500 const size_t bufferSize)
501 {
502 WEBRTC_TRACE(
503 kTraceStream,
504 kTraceFile,
505 _id,
506 "ModuleFileUtility::ReadWavDataAsStereo(wav= 0x%x, outLeft= 0x%x, "
507 "outRight= 0x%x, bufSize= %" PRIuS ")",
508 &wav,
509 outDataLeft,
510 outDataRight,
511 bufferSize);
512
513 if((outDataLeft == NULL) ||
514 (outDataRight == NULL))
515 {
516 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
517 "ReadWavDataAsMono: an input buffer is NULL!");
518 return -1;
519 }
520 if(codec_info_.channels != 2)
521 {
522 WEBRTC_TRACE(
523 kTraceError,
524 kTraceFile,
525 _id,
526 "ReadWavDataAsStereo: WAV file does not contain stereo data!");
527 return -1;
528 }
529 if(! _reading)
530 {
531 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
532 "ReadWavDataAsStereo: no longer reading file.");
533 return -1;
534 }
535
536 // The number of bytes that should be read from file.
537 const uint32_t totalBytesNeeded = _readSizeBytes;
538 // The number of bytes that will be written to the left and the right
539 // buffers.
540 const uint32_t bytesRequested = totalBytesNeeded >> 1;
541 if(bufferSize < bytesRequested)
542 {
543 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
544 "ReadWavData: Output buffers are too short!");
545 assert(false);
546 return -1;
547 }
548
549 int32_t bytesRead = ReadWavData(wav, _tempData, totalBytesNeeded);
550 if(bytesRead <= 0)
551 {
552 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
553 "ReadWavDataAsStereo: failed to read data from WAV file.");
554 return -1;
555 }
556
557 // Turn interleaved audio to left and right buffer. Note samples can be
558 // either 1 or 2 bytes
559 if(_bytesPerSample == 1)
560 {
561 for (uint32_t i = 0; i < bytesRequested; i++)
562 {
563 outDataLeft[i] = _tempData[2 * i];
564 outDataRight[i] = _tempData[(2 * i) + 1];
565 }
566 }
567 else if(_bytesPerSample == 2)
568 {
569 int16_t* sampleData = reinterpret_cast<int16_t*>(_tempData);
570 int16_t* outLeft = reinterpret_cast<int16_t*>(outDataLeft);
571 int16_t* outRight = reinterpret_cast<int16_t*>(
572 outDataRight);
573
574 // Bytes requested to samples requested.
575 uint32_t sampleCount = bytesRequested >> 1;
576 for (uint32_t i = 0; i < sampleCount; i++)
577 {
578 outLeft[i] = sampleData[2 * i];
579 outRight[i] = sampleData[(2 * i) + 1];
580 }
581 } else {
582 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
583 "ReadWavStereoData: unsupported sample size %d!",
584 _bytesPerSample);
585 assert(false);
586 return -1;
587 }
588 return bytesRequested;
589 }
590
591 int32_t ModuleFileUtility::ReadWavData(
592 InStream& wav,
593 uint8_t* buffer,
594 const uint32_t dataLengthInBytes)
595 {
596 WEBRTC_TRACE(
597 kTraceStream,
598 kTraceFile,
599 _id,
600 "ModuleFileUtility::ReadWavData(wav= 0x%x, buffer= 0x%x, dataLen= %ld)",
601 &wav,
602 buffer,
603 dataLengthInBytes);
604
605
606 if(buffer == NULL)
607 {
608 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
609 "ReadWavDataAsMono: output buffer NULL!");
610 return -1;
611 }
612
613 // Make sure that a read won't return too few samples.
614 // TODO (hellner): why not read the remaining bytes needed from the start
615 // of the file?
616 if((_dataSize - _readPos) < (int32_t)dataLengthInBytes)
617 {
618 // Rewind() being -1 may be due to the file not supposed to be looped.
619 if(wav.Rewind() == -1)
620 {
621 _reading = false;
622 return 0;
623 }
624 if(InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1)
625 {
626 _reading = false;
627 return -1;
628 }
629 }
630
631 int32_t bytesRead = wav.Read(buffer, dataLengthInBytes);
632 if(bytesRead < 0)
633 {
634 _reading = false;
635 return -1;
636 }
637
638 // This should never happen due to earlier sanity checks.
639 // TODO (hellner): change to an assert and fail here since this should
640 // never happen...
641 if(bytesRead < (int32_t)dataLengthInBytes)
642 {
643 if((wav.Rewind() == -1) ||
644 (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1))
645 {
646 _reading = false;
647 return -1;
648 }
649 else
650 {
651 bytesRead = wav.Read(buffer, dataLengthInBytes);
652 if(bytesRead < (int32_t)dataLengthInBytes)
653 {
654 _reading = false;
655 return -1;
656 }
657 }
658 }
659
660 _readPos += bytesRead;
661
662 // TODO (hellner): Why is dataLengthInBytes let dictate the number of bytes
663 // to read when exactly 10ms should be read?!
664 _playoutPositionMs += 10;
665 if((_stopPointInMs > 0) &&
666 (_playoutPositionMs >= _stopPointInMs))
667 {
668 if((wav.Rewind() == -1) ||
669 (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1))
670 {
671 _reading = false;
672 }
673 }
674 return bytesRead;
675 }
676
677 int32_t ModuleFileUtility::InitWavWriting(OutStream& wav,
678 const CodecInst& codecInst)
679 {
680
681 if(set_codec_info(codecInst) != 0)
682 {
683 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
684 "codecInst identifies unsupported codec!");
685 return -1;
686 }
687 _writing = false;
688 uint32_t channels = (codecInst.channels == 0) ?
689 1 : codecInst.channels;
690
691 if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0)
692 {
693 _bytesPerSample = 1;
694 if(WriteWavHeader(wav, 8000, _bytesPerSample, channels,
695 kWavFormatMuLaw, 0) == -1)
696 {
697 return -1;
698 }
699 }else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0)
700 {
701 _bytesPerSample = 1;
702 if(WriteWavHeader(wav, 8000, _bytesPerSample, channels, kWavFormatALaw,
703 0) == -1)
704 {
705 return -1;
706 }
707 }
708 else if(STR_CASE_CMP(codecInst.plname, "L16") == 0)
709 {
710 _bytesPerSample = 2;
711 if(WriteWavHeader(wav, codecInst.plfreq, _bytesPerSample, channels,
712 kWavFormatPcm, 0) == -1)
713 {
714 return -1;
715 }
716 }
717 else
718 {
719 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
720 "codecInst identifies unsupported codec for WAV file!");
721 return -1;
722 }
723 _writing = true;
724 _bytesWritten = 0;
725 return 0;
726 }
727
728 int32_t ModuleFileUtility::WriteWavData(OutStream& out,
729 const int8_t* buffer,
730 const size_t dataLength)
731 {
732 WEBRTC_TRACE(
733 kTraceStream,
734 kTraceFile,
735 _id,
736 "ModuleFileUtility::WriteWavData(out= 0x%x, buf= 0x%x, dataLen= %" PRIuS
737 ")",
738 &out,
739 buffer,
740 dataLength);
741
742 if(buffer == NULL)
743 {
744 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
745 "WriteWavData: input buffer NULL!");
746 return -1;
747 }
748
749 if(!out.Write(buffer, dataLength))
750 {
751 return -1;
752 }
753 _bytesWritten += dataLength;
754 return static_cast<int32_t>(dataLength);
755 }
756
757
758 int32_t ModuleFileUtility::WriteWavHeader(
759 OutStream& wav,
760 const uint32_t freq,
761 const uint32_t bytesPerSample,
762 const uint32_t channels,
763 const uint32_t format,
764 const uint32_t lengthInBytes)
765 {
766 // Frame size in bytes for 10 ms of audio.
767 // TODO (hellner): 44.1 kHz has 440 samples frame size. Doesn't seem to
768 // be taken into consideration here!
769 const int32_t frameSize = (freq / 100) * channels;
770
771 // Calculate the number of full frames that the wave file contain.
772 const int32_t dataLengthInBytes = frameSize * (lengthInBytes / frameSize);
773
774 uint8_t buf[kWavHeaderSize];
775 webrtc::WriteWavHeader(buf, channels, freq, static_cast<WavFormat>(format),
776 bytesPerSample, dataLengthInBytes / bytesPerSample);
777 wav.Write(buf, kWavHeaderSize);
778 return 0;
779 }
780
781 int32_t ModuleFileUtility::UpdateWavHeader(OutStream& wav)
782 {
783 int32_t res = -1;
784 if(wav.Rewind() == -1)
785 {
786 return -1;
787 }
788 uint32_t channels = (codec_info_.channels == 0) ?
789 1 : codec_info_.channels;
790
791 if(STR_CASE_CMP(codec_info_.plname, "L16") == 0)
792 {
793 res = WriteWavHeader(wav, codec_info_.plfreq, 2, channels,
794 kWavFormatPcm, _bytesWritten);
795 } else if(STR_CASE_CMP(codec_info_.plname, "PCMU") == 0) {
796 res = WriteWavHeader(wav, 8000, 1, channels, kWavFormatMuLaw,
797 _bytesWritten);
798 } else if(STR_CASE_CMP(codec_info_.plname, "PCMA") == 0) {
799 res = WriteWavHeader(wav, 8000, 1, channels, kWavFormatALaw,
800 _bytesWritten);
801 } else {
802 // Allow calling this API even if not writing to a WAVE file.
803 // TODO (hellner): why?!
804 return 0;
805 }
806 return res;
807 }
808
809
810 int32_t ModuleFileUtility::InitPreEncodedReading(InStream& in,
811 const CodecInst& cinst)
812 {
813
814 uint8_t preEncodedID;
815 in.Read(&preEncodedID, 1);
816
817 MediaFileUtility_CodecType codecType =
818 (MediaFileUtility_CodecType)preEncodedID;
819
820 if(set_codec_info(cinst) != 0)
821 {
822 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
823 "Pre-encoded file send codec mismatch!");
824 return -1;
825 }
826 if(codecType != _codecId)
827 {
828 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
829 "Pre-encoded file format codec mismatch!");
830 return -1;
831 }
832 memcpy(&codec_info_,&cinst,sizeof(CodecInst));
833 _reading = true;
834 return 0;
835 }
836
837 int32_t ModuleFileUtility::ReadPreEncodedData(
838 InStream& in,
839 int8_t* outData,
840 const size_t bufferSize)
841 {
842 WEBRTC_TRACE(
843 kTraceStream,
844 kTraceFile,
845 _id,
846 "ModuleFileUtility::ReadPreEncodedData(in= 0x%x, outData= 0x%x, "
847 "bufferSize= %" PRIuS ")",
848 &in,
849 outData,
850 bufferSize);
851
852 if(outData == NULL)
853 {
854 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "output buffer NULL");
855 }
856
857 uint32_t frameLen;
858 uint8_t buf[64];
859 // Each frame has a two byte header containing the frame length.
860 int32_t res = in.Read(buf, 2);
861 if(res != 2)
862 {
863 if(!in.Rewind())
864 {
865 // The first byte is the codec identifier.
866 in.Read(buf, 1);
867 res = in.Read(buf, 2);
868 }
869 else
870 {
871 return -1;
872 }
873 }
874 frameLen = buf[0] + buf[1] * 256;
875 if(bufferSize < frameLen)
876 {
877 WEBRTC_TRACE(
878 kTraceError,
879 kTraceFile,
880 _id,
881 "buffer not large enough to read %d bytes of pre-encoded data!",
882 frameLen);
883 return -1;
884 }
885 return in.Read(outData, frameLen);
886 }
887
888 int32_t ModuleFileUtility::InitPreEncodedWriting(
889 OutStream& out,
890 const CodecInst& codecInst)
891 {
892
893 if(set_codec_info(codecInst) != 0)
894 {
895 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "CodecInst not recognized!");
896 return -1;
897 }
898 _writing = true;
899 _bytesWritten = 1;
900 out.Write(&_codecId, 1);
901 return 0;
902 }
903
904 int32_t ModuleFileUtility::WritePreEncodedData(
905 OutStream& out,
906 const int8_t* buffer,
907 const size_t dataLength)
908 {
909 WEBRTC_TRACE(
910 kTraceStream,
911 kTraceFile,
912 _id,
913 "ModuleFileUtility::WritePreEncodedData(out= 0x%x, inData= 0x%x, "
914 "dataLen= %" PRIuS ")",
915 &out,
916 buffer,
917 dataLength);
918
919 if(buffer == NULL)
920 {
921 WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
922 }
923
924 size_t bytesWritten = 0;
925 // The first two bytes is the size of the frame.
926 int16_t lengthBuf;
927 lengthBuf = (int16_t)dataLength;
928 if(dataLength > static_cast<size_t>(std::numeric_limits<int16_t>::max()) ||
929 !out.Write(&lengthBuf, 2))
930 {
931 return -1;
932 }
933 bytesWritten = 2;
934
935 if(!out.Write(buffer, dataLength))
936 {
937 return -1;
938 }
939 bytesWritten += dataLength;
940 return static_cast<int32_t>(bytesWritten);
941 }
942
943 int32_t ModuleFileUtility::InitCompressedReading(
944 InStream& in,
945 const uint32_t start,
946 const uint32_t stop)
947 {
948 WEBRTC_TRACE(
949 kTraceDebug,
950 kTraceFile,
951 _id,
952 "ModuleFileUtility::InitCompressedReading(in= 0x%x, start= %d,\
953 stop= %d)",
954 &in,
955 start,
956 stop);
957
958 #if defined(WEBRTC_CODEC_ILBC)
959 int16_t read_len = 0;
960 #endif
961 _codecId = kCodecNoCodec;
962 _playoutPositionMs = 0;
963 _reading = false;
964
965 _startPointInMs = start;
966 _stopPointInMs = stop;
967
968 // Read the codec name
969 int32_t cnt = 0;
970 char buf[64];
971 do
972 {
973 in.Read(&buf[cnt++], 1);
974 } while ((buf[cnt-1] != '\n') && (64 > cnt));
975
976 if(cnt==64)
977 {
978 return -1;
979 } else {
980 buf[cnt]=0;
981 }
982
983 #ifdef WEBRTC_CODEC_ILBC
984 if(!strcmp("#!iLBC20\n", buf))
985 {
986 codec_info_.pltype = 102;
987 strcpy(codec_info_.plname, "ilbc");
988 codec_info_.plfreq = 8000;
989 codec_info_.pacsize = 160;
990 codec_info_.channels = 1;
991 codec_info_.rate = 13300;
992 _codecId = kCodecIlbc20Ms;
993
994 if(_startPointInMs > 0)
995 {
996 while (_playoutPositionMs <= _startPointInMs)
997 {
998 read_len = in.Read(buf, 38);
999 if(read_len == 38)
1000 {
1001 _playoutPositionMs += 20;
1002 }
1003 else
1004 {
1005 return -1;
1006 }
1007 }
1008 }
1009 }
1010
1011 if(!strcmp("#!iLBC30\n", buf))
1012 {
1013 codec_info_.pltype = 102;
1014 strcpy(codec_info_.plname, "ilbc");
1015 codec_info_.plfreq = 8000;
1016 codec_info_.pacsize = 240;
1017 codec_info_.channels = 1;
1018 codec_info_.rate = 13300;
1019 _codecId = kCodecIlbc30Ms;
1020
1021 if(_startPointInMs > 0)
1022 {
1023 while (_playoutPositionMs <= _startPointInMs)
1024 {
1025 read_len = in.Read(buf, 50);
1026 if(read_len == 50)
1027 {
1028 _playoutPositionMs += 20;
1029 }
1030 else
1031 {
1032 return -1;
1033 }
1034 }
1035 }
1036 }
1037 #endif
1038 if(_codecId == kCodecNoCodec)
1039 {
1040 return -1;
1041 }
1042 _reading = true;
1043 return 0;
1044 }
1045
1046 int32_t ModuleFileUtility::ReadCompressedData(InStream& in,
1047 int8_t* outData,
1048 size_t bufferSize)
1049 {
1050 WEBRTC_TRACE(
1051 kTraceStream,
1052 kTraceFile,
1053 _id,
1054 "ModuleFileUtility::ReadCompressedData(in=0x%x, outData=0x%x, bytes=%"
1055 PRIuS ")",
1056 &in,
1057 outData,
1058 bufferSize);
1059
1060 uint32_t bytesRead = 0;
1061
1062 if(! _reading)
1063 {
1064 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "not currently reading!");
1065 return -1;
1066 }
1067
1068 #ifdef WEBRTC_CODEC_ILBC
1069 if((_codecId == kCodecIlbc20Ms) ||
1070 (_codecId == kCodecIlbc30Ms))
1071 {
1072 uint32_t byteSize = 0;
1073 if(_codecId == kCodecIlbc30Ms)
1074 {
1075 byteSize = 50;
1076 }
1077 if(_codecId == kCodecIlbc20Ms)
1078 {
1079 byteSize = 38;
1080 }
1081 if(bufferSize < byteSize)
1082 {
1083 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1084 "output buffer is too short to read ILBC compressed\
1085 data.");
1086 assert(false);
1087 return -1;
1088 }
1089
1090 bytesRead = in.Read(outData, byteSize);
1091 if(bytesRead != byteSize)
1092 {
1093 if(!in.Rewind())
1094 {
1095 InitCompressedReading(in, _startPointInMs, _stopPointInMs);
1096 bytesRead = in.Read(outData, byteSize);
1097 if(bytesRead != byteSize)
1098 {
1099 _reading = false;
1100 return -1;
1101 }
1102 }
1103 else
1104 {
1105 _reading = false;
1106 return -1;
1107 }
1108 }
1109 }
1110 #endif
1111 if(bytesRead == 0)
1112 {
1113 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1114 "ReadCompressedData() no bytes read, codec not supported");
1115 return -1;
1116 }
1117
1118 _playoutPositionMs += 20;
1119 if((_stopPointInMs > 0) &&
1120 (_playoutPositionMs >= _stopPointInMs))
1121 {
1122 if(!in.Rewind())
1123 {
1124 InitCompressedReading(in, _startPointInMs, _stopPointInMs);
1125 }
1126 else
1127 {
1128 _reading = false;
1129 }
1130 }
1131 return bytesRead;
1132 }
1133
1134 int32_t ModuleFileUtility::InitCompressedWriting(
1135 OutStream& out,
1136 const CodecInst& codecInst)
1137 {
1138 WEBRTC_TRACE(kTraceDebug, kTraceFile, _id,
1139 "ModuleFileUtility::InitCompressedWriting(out= 0x%x,\
1140 codecName= %s)",
1141 &out, codecInst.plname);
1142
1143 _writing = false;
1144
1145 #ifdef WEBRTC_CODEC_ILBC
1146 if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0)
1147 {
1148 if(codecInst.pacsize == 160)
1149 {
1150 _codecId = kCodecIlbc20Ms;
1151 out.Write("#!iLBC20\n",9);
1152 }
1153 else if(codecInst.pacsize == 240)
1154 {
1155 _codecId = kCodecIlbc30Ms;
1156 out.Write("#!iLBC30\n",9);
1157 }
1158 else
1159 {
1160 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1161 "codecInst defines unsupported compression codec!");
1162 return -1;
1163 }
1164 memcpy(&codec_info_,&codecInst,sizeof(CodecInst));
1165 _writing = true;
1166 return 0;
1167 }
1168 #endif
1169
1170 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1171 "codecInst defines unsupported compression codec!");
1172 return -1;
1173 }
1174
1175 int32_t ModuleFileUtility::WriteCompressedData(
1176 OutStream& out,
1177 const int8_t* buffer,
1178 const size_t dataLength)
1179 {
1180 WEBRTC_TRACE(
1181 kTraceStream,
1182 kTraceFile,
1183 _id,
1184 "ModuleFileUtility::WriteCompressedData(out= 0x%x, buf= 0x%x, "
1185 "dataLen= %" PRIuS ")",
1186 &out,
1187 buffer,
1188 dataLength);
1189
1190 if(buffer == NULL)
1191 {
1192 WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
1193 }
1194
1195 if(!out.Write(buffer, dataLength))
1196 {
1197 return -1;
1198 }
1199 return static_cast<int32_t>(dataLength);
1200 }
1201
1202 int32_t ModuleFileUtility::InitPCMReading(InStream& pcm,
1203 const uint32_t start,
1204 const uint32_t stop,
1205 uint32_t freq)
1206 {
1207 WEBRTC_TRACE(
1208 kTraceInfo,
1209 kTraceFile,
1210 _id,
1211 "ModuleFileUtility::InitPCMReading(pcm= 0x%x, start=%d, stop=%d,\
1212 freq=%d)",
1213 &pcm,
1214 start,
1215 stop,
1216 freq);
1217
1218 int8_t dummy[320];
1219 int32_t read_len;
1220
1221 _playoutPositionMs = 0;
1222 _startPointInMs = start;
1223 _stopPointInMs = stop;
1224 _reading = false;
1225
1226 if(freq == 8000)
1227 {
1228 strcpy(codec_info_.plname, "L16");
1229 codec_info_.pltype = -1;
1230 codec_info_.plfreq = 8000;
1231 codec_info_.pacsize = 160;
1232 codec_info_.channels = 1;
1233 codec_info_.rate = 128000;
1234 _codecId = kCodecL16_8Khz;
1235 }
1236 else if(freq == 16000)
1237 {
1238 strcpy(codec_info_.plname, "L16");
1239 codec_info_.pltype = -1;
1240 codec_info_.plfreq = 16000;
1241 codec_info_.pacsize = 320;
1242 codec_info_.channels = 1;
1243 codec_info_.rate = 256000;
1244 _codecId = kCodecL16_16kHz;
1245 }
1246 else if(freq == 32000)
1247 {
1248 strcpy(codec_info_.plname, "L16");
1249 codec_info_.pltype = -1;
1250 codec_info_.plfreq = 32000;
1251 codec_info_.pacsize = 320;
1252 codec_info_.channels = 1;
1253 codec_info_.rate = 512000;
1254 _codecId = kCodecL16_32Khz;
1255 }
1256
1257 // Readsize for 10ms of audio data (2 bytes per sample).
1258 _readSizeBytes = 2 * codec_info_. plfreq / 100;
1259 if(_startPointInMs > 0)
1260 {
1261 while (_playoutPositionMs < _startPointInMs)
1262 {
1263 read_len = pcm.Read(dummy, _readSizeBytes);
1264 if(read_len == _readSizeBytes)
1265 {
1266 _playoutPositionMs += 10;
1267 }
1268 else // Must have reached EOF before start position!
1269 {
1270 return -1;
1271 }
1272 }
1273 }
1274 _reading = true;
1275 return 0;
1276 }
1277
1278 int32_t ModuleFileUtility::ReadPCMData(InStream& pcm,
1279 int8_t* outData,
1280 size_t bufferSize)
1281 {
1282 WEBRTC_TRACE(
1283 kTraceStream,
1284 kTraceFile,
1285 _id,
1286 "ModuleFileUtility::ReadPCMData(pcm= 0x%x, outData= 0x%x, bufSize= %"
1287 PRIuS ")",
1288 &pcm,
1289 outData,
1290 bufferSize);
1291
1292 if(outData == NULL)
1293 {
1294 WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
1295 }
1296
1297 // Readsize for 10ms of audio data (2 bytes per sample).
1298 uint32_t bytesRequested = 2 * codec_info_.plfreq / 100;
1299 if(bufferSize < bytesRequested)
1300 {
1301 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1302 "ReadPCMData: buffer not long enough for a 10ms frame.");
1303 assert(false);
1304 return -1;
1305 }
1306
1307 uint32_t bytesRead = pcm.Read(outData, bytesRequested);
1308 if(bytesRead < bytesRequested)
1309 {
1310 if(pcm.Rewind() == -1)
1311 {
1312 _reading = false;
1313 }
1314 else
1315 {
1316 if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs,
1317 codec_info_.plfreq) == -1)
1318 {
1319 _reading = false;
1320 }
1321 else
1322 {
1323 int32_t rest = bytesRequested - bytesRead;
1324 int32_t len = pcm.Read(&(outData[bytesRead]), rest);
1325 if(len == rest)
1326 {
1327 bytesRead += len;
1328 }
1329 else
1330 {
1331 _reading = false;
1332 }
1333 }
1334 if(bytesRead <= 0)
1335 {
1336 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1337 "ReadPCMData: Failed to rewind audio file.");
1338 return -1;
1339 }
1340 }
1341 }
1342
1343 if(bytesRead <= 0)
1344 {
1345 WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
1346 "ReadPCMData: end of file");
1347 return -1;
1348 }
1349 _playoutPositionMs += 10;
1350 if(_stopPointInMs && _playoutPositionMs >= _stopPointInMs)
1351 {
1352 if(!pcm.Rewind())
1353 {
1354 if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs,
1355 codec_info_.plfreq) == -1)
1356 {
1357 _reading = false;
1358 }
1359 }
1360 }
1361 return bytesRead;
1362 }
1363
1364 int32_t ModuleFileUtility::InitPCMWriting(OutStream& out, uint32_t freq)
1365 {
1366
1367 if(freq == 8000)
1368 {
1369 strcpy(codec_info_.plname, "L16");
1370 codec_info_.pltype = -1;
1371 codec_info_.plfreq = 8000;
1372 codec_info_.pacsize = 160;
1373 codec_info_.channels = 1;
1374 codec_info_.rate = 128000;
1375
1376 _codecId = kCodecL16_8Khz;
1377 }
1378 else if(freq == 16000)
1379 {
1380 strcpy(codec_info_.plname, "L16");
1381 codec_info_.pltype = -1;
1382 codec_info_.plfreq = 16000;
1383 codec_info_.pacsize = 320;
1384 codec_info_.channels = 1;
1385 codec_info_.rate = 256000;
1386
1387 _codecId = kCodecL16_16kHz;
1388 }
1389 else if(freq == 32000)
1390 {
1391 strcpy(codec_info_.plname, "L16");
1392 codec_info_.pltype = -1;
1393 codec_info_.plfreq = 32000;
1394 codec_info_.pacsize = 320;
1395 codec_info_.channels = 1;
1396 codec_info_.rate = 512000;
1397
1398 _codecId = kCodecL16_32Khz;
1399 }
1400 if((_codecId != kCodecL16_8Khz) &&
1401 (_codecId != kCodecL16_16kHz) &&
1402 (_codecId != kCodecL16_32Khz))
1403 {
1404 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1405 "CodecInst is not 8KHz PCM or 16KHz PCM!");
1406 return -1;
1407 }
1408 _writing = true;
1409 _bytesWritten = 0;
1410 return 0;
1411 }
1412
1413 int32_t ModuleFileUtility::WritePCMData(OutStream& out,
1414 const int8_t* buffer,
1415 const size_t dataLength)
1416 {
1417 WEBRTC_TRACE(
1418 kTraceStream,
1419 kTraceFile,
1420 _id,
1421 "ModuleFileUtility::WritePCMData(out= 0x%x, buf= 0x%x, dataLen= %" PRIuS
1422 ")",
1423 &out,
1424 buffer,
1425 dataLength);
1426
1427 if(buffer == NULL)
1428 {
1429 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "buffer NULL");
1430 }
1431
1432 if(!out.Write(buffer, dataLength))
1433 {
1434 return -1;
1435 }
1436
1437 _bytesWritten += dataLength;
1438 return static_cast<int32_t>(dataLength);
1439 }
1440
1441 int32_t ModuleFileUtility::codec_info(CodecInst& codecInst)
1442 {
1443 WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
1444 "ModuleFileUtility::codec_info(codecInst= 0x%x)", &codecInst);
1445
1446 if(!_reading && !_writing)
1447 {
1448 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1449 "CodecInst: not currently reading audio file!");
1450 return -1;
1451 }
1452 memcpy(&codecInst,&codec_info_,sizeof(CodecInst));
1453 return 0;
1454 }
1455
1456 int32_t ModuleFileUtility::set_codec_info(const CodecInst& codecInst)
1457 {
1458
1459 _codecId = kCodecNoCodec;
1460 if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0)
1461 {
1462 _codecId = kCodecPcmu;
1463 }
1464 else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0)
1465 {
1466 _codecId = kCodecPcma;
1467 }
1468 else if(STR_CASE_CMP(codecInst.plname, "L16") == 0)
1469 {
1470 if(codecInst.plfreq == 8000)
1471 {
1472 _codecId = kCodecL16_8Khz;
1473 }
1474 else if(codecInst.plfreq == 16000)
1475 {
1476 _codecId = kCodecL16_16kHz;
1477 }
1478 else if(codecInst.plfreq == 32000)
1479 {
1480 _codecId = kCodecL16_32Khz;
1481 }
1482 }
1483 #ifdef WEBRTC_CODEC_ILBC
1484 else if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0)
1485 {
1486 if(codecInst.pacsize == 160)
1487 {
1488 _codecId = kCodecIlbc20Ms;
1489 }
1490 else if(codecInst.pacsize == 240)
1491 {
1492 _codecId = kCodecIlbc30Ms;
1493 }
1494 }
1495 #endif
1496 #if(defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
1497 else if(STR_CASE_CMP(codecInst.plname, "isac") == 0)
1498 {
1499 if(codecInst.plfreq == 16000)
1500 {
1501 _codecId = kCodecIsac;
1502 }
1503 else if(codecInst.plfreq == 32000)
1504 {
1505 _codecId = kCodecIsacSwb;
1506 }
1507 }
1508 #endif
1509 #ifdef WEBRTC_CODEC_G722
1510 else if(STR_CASE_CMP(codecInst.plname, "G722") == 0)
1511 {
1512 _codecId = kCodecG722;
1513 }
1514 #endif
1515 if(_codecId == kCodecNoCodec)
1516 {
1517 return -1;
1518 }
1519 memcpy(&codec_info_, &codecInst, sizeof(CodecInst));
1520 return 0;
1521 }
1522
1523 int32_t ModuleFileUtility::FileDurationMs(const char* fileName,
1524 const FileFormats fileFormat,
1525 const uint32_t freqInHz)
1526 {
1527
1528 if(fileName == NULL)
1529 {
1530 WEBRTC_TRACE(kTraceError, kTraceFile, _id, "filename NULL");
1531 return -1;
1532 }
1533
1534 int32_t time_in_ms = -1;
1535 struct stat file_size;
1536 if(stat(fileName,&file_size) == -1)
1537 {
1538 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1539 "failed to retrieve file size with stat!");
1540 return -1;
1541 }
1542 FileWrapper* inStreamObj = FileWrapper::Create();
1543 if(inStreamObj == NULL)
1544 {
1545 WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
1546 "failed to create InStream object!");
1547 return -1;
1548 }
1549 if(inStreamObj->OpenFile(fileName, true) == -1)
1550 {
1551 delete inStreamObj;
1552 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1553 "failed to open file %s!", fileName);
1554 return -1;
1555 }
1556
1557 switch (fileFormat)
1558 {
1559 case kFileFormatWavFile:
1560 {
1561 if(ReadWavHeader(*inStreamObj) == -1)
1562 {
1563 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1564 "failed to read WAV file header!");
1565 return -1;
1566 }
1567 time_in_ms = ((file_size.st_size - 44) /
1568 (_wavFormatObj.nAvgBytesPerSec/1000));
1569 break;
1570 }
1571 case kFileFormatPcm16kHzFile:
1572 {
1573 // 16 samples per ms. 2 bytes per sample.
1574 int32_t denominator = 16*2;
1575 time_in_ms = (file_size.st_size)/denominator;
1576 break;
1577 }
1578 case kFileFormatPcm8kHzFile:
1579 {
1580 // 8 samples per ms. 2 bytes per sample.
1581 int32_t denominator = 8*2;
1582 time_in_ms = (file_size.st_size)/denominator;
1583 break;
1584 }
1585 case kFileFormatCompressedFile:
1586 {
1587 int32_t cnt = 0;
1588 int32_t read_len = 0;
1589 char buf[64];
1590 do
1591 {
1592 read_len = inStreamObj->Read(&buf[cnt++], 1);
1593 if(read_len != 1)
1594 {
1595 return -1;
1596 }
1597 } while ((buf[cnt-1] != '\n') && (64 > cnt));
1598
1599 if(cnt == 64)
1600 {
1601 return -1;
1602 }
1603 else
1604 {
1605 buf[cnt] = 0;
1606 }
1607 #ifdef WEBRTC_CODEC_ILBC
1608 if(!strcmp("#!iLBC20\n", buf))
1609 {
1610 // 20 ms is 304 bits
1611 time_in_ms = ((file_size.st_size)*160)/304;
1612 break;
1613 }
1614 if(!strcmp("#!iLBC30\n", buf))
1615 {
1616 // 30 ms takes 400 bits.
1617 // file size in bytes * 8 / 400 is the number of
1618 // 30 ms frames in the file ->
1619 // time_in_ms = file size * 8 / 400 * 30
1620 time_in_ms = ((file_size.st_size)*240)/400;
1621 break;
1622 }
1623 #endif
1624 break;
1625 }
1626 case kFileFormatPreencodedFile:
1627 {
1628 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1629 "cannot determine duration of Pre-Encoded file!");
1630 break;
1631 }
1632 default:
1633 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1634 "unsupported file format %d!", fileFormat);
1635 break;
1636 }
1637 inStreamObj->CloseFile();
1638 delete inStreamObj;
1639 return time_in_ms;
1640 }
1641
1642 uint32_t ModuleFileUtility::PlayoutPositionMs()
1643 {
1644 WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
1645 "ModuleFileUtility::PlayoutPosition()");
1646
1647 if(_reading)
1648 {
1649 return _playoutPositionMs;
1650 }
1651 else
1652 {
1653 return 0;
1654 }
1655 }
1656 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/media_file/source/media_file_utility.h ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »

Powered by Google App Engine