• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include "webrtc/common_types.h"
18 #include "webrtc/engine_configurations.h"
19 #include "webrtc/modules/interface/module_common_types.h"
20 #include "webrtc/system_wrappers/interface/file_wrapper.h"
21 #include "webrtc/system_wrappers/interface/trace.h"
22 
23 #ifdef WEBRTC_MODULE_UTILITY_VIDEO
24     #include "avi_file.h"
25 #endif
26 
27 namespace {
28 enum WaveFormats
29 {
30     kWaveFormatPcm   = 0x0001,
31     kWaveFormatALaw  = 0x0006,
32     kWaveFormatMuLaw = 0x0007
33 };
34 
35 // First 16 bytes the WAVE header. ckID should be "RIFF", wave_ckID should be
36 // "WAVE" and ckSize is the chunk size (4 + n)
37 struct WAVE_RIFF_header
38 {
39     int8_t  ckID[4];
40     int32_t ckSize;
41     int8_t  wave_ckID[4];
42 };
43 
44 // First 8 byte of the format chunk. fmt_ckID should be "fmt ". fmt_ckSize is
45 // the chunk size (16, 18 or 40 byte)
46 struct WAVE_CHUNK_header
47 {
48    int8_t  fmt_ckID[4];
49    int32_t fmt_ckSize;
50 };
51 }  // unnamed namespace
52 
53 namespace webrtc {
ModuleFileUtility(const int32_t id)54 ModuleFileUtility::ModuleFileUtility(const int32_t id)
55     : _wavFormatObj(),
56       _dataSize(0),
57       _readSizeBytes(0),
58       _id(id),
59       _stopPointInMs(0),
60       _startPointInMs(0),
61       _playoutPositionMs(0),
62       _bytesWritten(0),
63       codec_info_(),
64       _codecId(kCodecNoCodec),
65       _bytesPerSample(0),
66       _readPos(0),
67       _reading(false),
68       _writing(false),
69       _tempData()
70 #ifdef WEBRTC_MODULE_UTILITY_VIDEO
71       ,
72       _aviAudioInFile(0),
73       _aviVideoInFile(0),
74       _aviOutFile(0)
75 #endif
76 {
77     WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
78                  "ModuleFileUtility::ModuleFileUtility()");
79     memset(&codec_info_,0,sizeof(CodecInst));
80     codec_info_.pltype = -1;
81 #ifdef WEBRTC_MODULE_UTILITY_VIDEO
82     memset(&_videoCodec,0,sizeof(_videoCodec));
83 #endif
84 }
85 
~ModuleFileUtility()86 ModuleFileUtility::~ModuleFileUtility()
87 {
88     WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
89                  "ModuleFileUtility::~ModuleFileUtility()");
90 #ifdef WEBRTC_MODULE_UTILITY_VIDEO
91     delete _aviAudioInFile;
92     delete _aviVideoInFile;
93 #endif
94 }
95 
96 #ifdef WEBRTC_MODULE_UTILITY_VIDEO
InitAviWriting(const char * filename,const CodecInst & audioCodecInst,const VideoCodec & videoCodecInst,const bool videoOnly)97 int32_t ModuleFileUtility::InitAviWriting(
98     const char* filename,
99     const CodecInst& audioCodecInst,
100     const VideoCodec& videoCodecInst,
101     const bool videoOnly /*= false*/)
102 {
103     _writing = false;
104 
105     delete _aviOutFile;
106     _aviOutFile = new AviFile( );
107 
108     AVISTREAMHEADER videoStreamHeader;
109     videoStreamHeader.fccType = AviFile::MakeFourCc('v', 'i', 'd', 's');
110 
111 #ifdef VIDEOCODEC_I420
112     if (strncmp(videoCodecInst.plName, "I420", 7) == 0)
113     {
114         videoStreamHeader.fccHandler = AviFile::MakeFourCc('I','4','2','0');
115     }
116 #endif
117 #ifdef VIDEOCODEC_VP8
118     if (strncmp(videoCodecInst.plName, "VP8", 7) == 0)
119     {
120         videoStreamHeader.fccHandler = AviFile::MakeFourCc('V','P','8','0');
121     }
122 #endif
123     if (videoStreamHeader.fccHandler == 0)
124     {
125         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
126                      "InitAviWriting() Codec not supported");
127 
128         return -1;
129     }
130     videoStreamHeader.dwScale                = 1;
131     videoStreamHeader.dwRate                 = videoCodecInst.maxFramerate;
132     videoStreamHeader.dwSuggestedBufferSize  = videoCodecInst.height *
133         (videoCodecInst.width >> 1) * 3;
134     videoStreamHeader.dwQuality              = (uint32_t)-1;
135     videoStreamHeader.dwSampleSize           = 0;
136     videoStreamHeader.rcFrame.top            = 0;
137     videoStreamHeader.rcFrame.bottom         = videoCodecInst.height;
138     videoStreamHeader.rcFrame.left           = 0;
139     videoStreamHeader.rcFrame.right          = videoCodecInst.width;
140 
141     BITMAPINFOHEADER bitMapInfoHeader;
142     bitMapInfoHeader.biSize         = sizeof(BITMAPINFOHEADER);
143     bitMapInfoHeader.biHeight       = videoCodecInst.height;
144     bitMapInfoHeader.biWidth        = videoCodecInst.width;
145     bitMapInfoHeader.biPlanes       = 1;
146     bitMapInfoHeader.biBitCount     = 12;
147     bitMapInfoHeader.biClrImportant = 0;
148     bitMapInfoHeader.biClrUsed      = 0;
149     bitMapInfoHeader.biCompression  = videoStreamHeader.fccHandler;
150     bitMapInfoHeader.biSizeImage    = bitMapInfoHeader.biWidth *
151         bitMapInfoHeader.biHeight * bitMapInfoHeader.biBitCount / 8;
152 
153     if (_aviOutFile->CreateVideoStream(
154         videoStreamHeader,
155         bitMapInfoHeader,
156         NULL,
157         0) != 0)
158     {
159         return -1;
160     }
161 
162     if(!videoOnly)
163     {
164         AVISTREAMHEADER audioStreamHeader;
165         audioStreamHeader.fccType = AviFile::MakeFourCc('a', 'u', 'd', 's');
166         // fccHandler is the FOURCC of the codec for decoding the stream.
167         // It's an optional parameter that is not used by audio streams.
168         audioStreamHeader.fccHandler   = 0;
169         audioStreamHeader.dwScale      = 1;
170 
171         WAVEFORMATEX waveFormatHeader;
172         waveFormatHeader.cbSize          = 0;
173         waveFormatHeader.nChannels       = 1;
174 
175         if (strncmp(audioCodecInst.plname, "PCMU", 4) == 0)
176         {
177             audioStreamHeader.dwSampleSize = 1;
178             audioStreamHeader.dwRate       = 8000;
179             audioStreamHeader.dwQuality    = (uint32_t)-1;
180             audioStreamHeader.dwSuggestedBufferSize = 80;
181 
182             waveFormatHeader.nAvgBytesPerSec = 8000;
183             waveFormatHeader.nSamplesPerSec  = 8000;
184             waveFormatHeader.wBitsPerSample  = 8;
185             waveFormatHeader.nBlockAlign     = 1;
186             waveFormatHeader.wFormatTag      = kWaveFormatMuLaw;
187 
188         } else if (strncmp(audioCodecInst.plname, "PCMA", 4) == 0)
189         {
190             audioStreamHeader.dwSampleSize = 1;
191             audioStreamHeader.dwRate       = 8000;
192             audioStreamHeader.dwQuality    = (uint32_t)-1;
193             audioStreamHeader.dwSuggestedBufferSize = 80;
194 
195             waveFormatHeader.nAvgBytesPerSec = 8000;
196             waveFormatHeader.nSamplesPerSec  = 8000;
197             waveFormatHeader.wBitsPerSample  = 8;
198             waveFormatHeader.nBlockAlign     = 1;
199             waveFormatHeader.wFormatTag      = kWaveFormatALaw;
200 
201         } else if (strncmp(audioCodecInst.plname, "L16", 3) == 0)
202         {
203             audioStreamHeader.dwSampleSize = 2;
204             audioStreamHeader.dwRate       = audioCodecInst.plfreq;
205             audioStreamHeader.dwQuality    = (uint32_t)-1;
206             audioStreamHeader.dwSuggestedBufferSize =
207                 (audioCodecInst.plfreq/100) * 2;
208 
209             waveFormatHeader.nAvgBytesPerSec = audioCodecInst.plfreq * 2;
210             waveFormatHeader.nSamplesPerSec  = audioCodecInst.plfreq;
211             waveFormatHeader.wBitsPerSample  = 16;
212             waveFormatHeader.nBlockAlign     = 2;
213             waveFormatHeader.wFormatTag      = kWaveFormatPcm;
214         } else
215         {
216             return -1;
217         }
218 
219         if(_aviOutFile->CreateAudioStream(
220             audioStreamHeader,
221             waveFormatHeader) != 0)
222         {
223             return -1;
224         }
225 
226 
227         if( InitWavCodec(waveFormatHeader.nSamplesPerSec,
228             waveFormatHeader.nChannels,
229             waveFormatHeader.wBitsPerSample,
230             waveFormatHeader.wFormatTag) != 0)
231         {
232             return -1;
233         }
234     }
235     _aviOutFile->Create(filename);
236     _writing = true;
237     return 0;
238 }
239 
WriteAviAudioData(const int8_t * buffer,uint32_t bufferLengthInBytes)240 int32_t ModuleFileUtility::WriteAviAudioData(
241     const int8_t* buffer,
242     uint32_t bufferLengthInBytes)
243 {
244     if( _aviOutFile != 0)
245     {
246         return _aviOutFile->WriteAudio(
247             reinterpret_cast<const uint8_t*>(buffer),
248             bufferLengthInBytes);
249     }
250     else
251     {
252         WEBRTC_TRACE(kTraceError, kTraceFile, _id, "AVI file not initialized");
253         return -1;
254     }
255 }
256 
WriteAviVideoData(const int8_t * buffer,uint32_t bufferLengthInBytes)257 int32_t ModuleFileUtility::WriteAviVideoData(
258         const int8_t* buffer,
259         uint32_t bufferLengthInBytes)
260 {
261     if( _aviOutFile != 0)
262     {
263         return _aviOutFile->WriteVideo(
264             reinterpret_cast<const uint8_t*>(buffer),
265             bufferLengthInBytes);
266     }
267     else
268     {
269         WEBRTC_TRACE(kTraceError, kTraceFile, _id, "AVI file not initialized");
270         return -1;
271     }
272 }
273 
274 
CloseAviFile()275 int32_t ModuleFileUtility::CloseAviFile( )
276 {
277     if( _reading && _aviAudioInFile)
278     {
279         delete _aviAudioInFile;
280         _aviAudioInFile = 0;
281     }
282 
283     if( _reading && _aviVideoInFile)
284     {
285         delete _aviVideoInFile;
286         _aviVideoInFile = 0;
287     }
288 
289     if( _writing && _aviOutFile)
290     {
291         delete _aviOutFile;
292         _aviOutFile = 0;
293     }
294     return 0;
295 }
296 
297 
InitAviReading(const char * filename,bool videoOnly,bool loop)298 int32_t ModuleFileUtility::InitAviReading(const char* filename, bool videoOnly,
299                                           bool loop)
300 {
301     _reading = false;
302     delete _aviVideoInFile;
303     _aviVideoInFile = new AviFile( );
304 
305     if ((_aviVideoInFile != 0) && _aviVideoInFile->Open(AviFile::AVI_VIDEO,
306                                                         filename, loop) == -1)
307     {
308         WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
309                      "Unable to open AVI file (video)");
310         return -1;
311     }
312 
313 
314     AVISTREAMHEADER videoInStreamHeader;
315     BITMAPINFOHEADER bitmapInfo;
316     char codecConfigParameters[AviFile::CODEC_CONFIG_LENGTH] = {};
317     int32_t configLength = 0;
318     if( _aviVideoInFile->GetVideoStreamInfo(videoInStreamHeader, bitmapInfo,
319                                             codecConfigParameters,
320                                             configLength) != 0)
321     {
322         return -1;
323     }
324     _videoCodec.width = static_cast<uint16_t>(
325         videoInStreamHeader.rcFrame.right);
326     _videoCodec.height = static_cast<uint16_t>(
327         videoInStreamHeader.rcFrame.bottom);
328     _videoCodec.maxFramerate = static_cast<uint8_t>(
329         videoInStreamHeader.dwRate);
330 
331     const size_t plnameLen = sizeof(_videoCodec.plName) / sizeof(char);
332     if (bitmapInfo.biCompression == AviFile::MakeFourCc('I','4','2','0'))
333     {
334         strncpy(_videoCodec.plName, "I420", plnameLen);
335        _videoCodec.codecType = kVideoCodecI420;
336     }
337     else if (bitmapInfo.biCompression ==
338              AviFile::MakeFourCc('V', 'P', '8', '0'))
339     {
340         strncpy(_videoCodec.plName, "VP8", plnameLen);
341         _videoCodec.codecType = kVideoCodecVP8;
342     }
343     else
344     {
345         return -1;
346     }
347 
348     if(!videoOnly)
349     {
350         delete _aviAudioInFile;
351         _aviAudioInFile = new AviFile();
352 
353         if ( (_aviAudioInFile != 0) &&
354             _aviAudioInFile->Open(AviFile::AVI_AUDIO, filename, loop) == -1)
355         {
356             WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
357                          "Unable to open AVI file (audio)");
358             return -1;
359         }
360 
361         WAVEFORMATEX waveHeader;
362         if(_aviAudioInFile->GetAudioStreamInfo(waveHeader) != 0)
363         {
364             return -1;
365         }
366         if(InitWavCodec(waveHeader.nSamplesPerSec, waveHeader.nChannels,
367                         waveHeader.wBitsPerSample, waveHeader.wFormatTag) != 0)
368         {
369             return -1;
370         }
371     }
372     _reading = true;
373     return 0;
374 }
375 
ReadAviAudioData(int8_t * outBuffer,const uint32_t bufferLengthInBytes)376 int32_t ModuleFileUtility::ReadAviAudioData(
377     int8_t*  outBuffer,
378     const uint32_t bufferLengthInBytes)
379 {
380     if(_aviAudioInFile == 0)
381     {
382         WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "AVI file not opened.");
383         return -1;
384     }
385 
386     int32_t length = bufferLengthInBytes;
387     if(_aviAudioInFile->ReadAudio(
388         reinterpret_cast<uint8_t*>(outBuffer),
389         length) != 0)
390     {
391         return -1;
392     }
393     else
394     {
395         return length;
396     }
397 }
398 
ReadAviVideoData(int8_t * outBuffer,const uint32_t bufferLengthInBytes)399 int32_t ModuleFileUtility::ReadAviVideoData(
400     int8_t* outBuffer,
401     const uint32_t bufferLengthInBytes)
402 {
403     if(_aviVideoInFile == 0)
404     {
405         WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "AVI file not opened.");
406         return -1;
407     }
408 
409     int32_t length = bufferLengthInBytes;
410     if( _aviVideoInFile->ReadVideo(
411         reinterpret_cast<uint8_t*>(outBuffer),
412         length) != 0)
413     {
414         return -1;
415     } else {
416         return length;
417     }
418 }
419 
VideoCodecInst(VideoCodec & codecInst)420 int32_t ModuleFileUtility::VideoCodecInst(VideoCodec& codecInst)
421 {
422     WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
423                "ModuleFileUtility::CodecInst(codecInst= 0x%x)", &codecInst);
424 
425    if(!_reading)
426     {
427         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
428                      "CodecInst: not currently reading audio file!");
429         return -1;
430     }
431     memcpy(&codecInst,&_videoCodec,sizeof(VideoCodec));
432     return 0;
433 }
434 #endif
435 
ReadWavHeader(InStream & wav)436 int32_t ModuleFileUtility::ReadWavHeader(InStream& wav)
437 {
438     WAVE_RIFF_header RIFFheaderObj;
439     WAVE_CHUNK_header CHUNKheaderObj;
440     // TODO (hellner): tmpStr and tmpStr2 seems unnecessary here.
441     char tmpStr[6] = "FOUR";
442     unsigned char tmpStr2[4];
443     int32_t i, len;
444     bool dataFound = false;
445     bool fmtFound = false;
446     int8_t dummyRead;
447 
448 
449     _dataSize = 0;
450     len = wav.Read(&RIFFheaderObj, sizeof(WAVE_RIFF_header));
451     if(len != sizeof(WAVE_RIFF_header))
452     {
453         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
454                      "Not a wave file (too short)");
455         return -1;
456     }
457 
458     for (i = 0; i < 4; i++)
459     {
460         tmpStr[i] = RIFFheaderObj.ckID[i];
461     }
462     if(strcmp(tmpStr, "RIFF") != 0)
463     {
464         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
465                      "Not a wave file (does not have RIFF)");
466         return -1;
467     }
468     for (i = 0; i < 4; i++)
469     {
470         tmpStr[i] = RIFFheaderObj.wave_ckID[i];
471     }
472     if(strcmp(tmpStr, "WAVE") != 0)
473     {
474         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
475                      "Not a wave file (does not have WAVE)");
476         return -1;
477     }
478 
479     len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header));
480 
481     // WAVE files are stored in little endian byte order. Make sure that the
482     // data can be read on big endian as well.
483     // TODO (hellner): little endian to system byte order should be done in
484     //                 in a subroutine.
485     memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4);
486     CHUNKheaderObj.fmt_ckSize =
487         (int32_t) ((uint32_t) tmpStr2[0] +
488                          (((uint32_t)tmpStr2[1])<<8) +
489                          (((uint32_t)tmpStr2[2])<<16) +
490                          (((uint32_t)tmpStr2[3])<<24));
491 
492     memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4);
493 
494     while ((len == sizeof(WAVE_CHUNK_header)) && (!fmtFound || !dataFound))
495     {
496         if(strcmp(tmpStr, "fmt ") == 0)
497         {
498             len = wav.Read(&_wavFormatObj, sizeof(WAVE_FMTINFO_header));
499 
500             memcpy(tmpStr2, &_wavFormatObj.formatTag, 2);
501             _wavFormatObj.formatTag =
502                 (WaveFormats) ((uint32_t)tmpStr2[0] +
503                                (((uint32_t)tmpStr2[1])<<8));
504             memcpy(tmpStr2, &_wavFormatObj.nChannels, 2);
505             _wavFormatObj.nChannels =
506                 (int16_t) ((uint32_t)tmpStr2[0] +
507                                  (((uint32_t)tmpStr2[1])<<8));
508             memcpy(tmpStr2, &_wavFormatObj.nSamplesPerSec, 4);
509             _wavFormatObj.nSamplesPerSec =
510                 (int32_t) ((uint32_t)tmpStr2[0] +
511                                  (((uint32_t)tmpStr2[1])<<8) +
512                                  (((uint32_t)tmpStr2[2])<<16) +
513                                  (((uint32_t)tmpStr2[3])<<24));
514             memcpy(tmpStr2, &_wavFormatObj.nAvgBytesPerSec, 4);
515             _wavFormatObj.nAvgBytesPerSec =
516                 (int32_t) ((uint32_t)tmpStr2[0] +
517                                  (((uint32_t)tmpStr2[1])<<8) +
518                                  (((uint32_t)tmpStr2[2])<<16) +
519                                  (((uint32_t)tmpStr2[3])<<24));
520             memcpy(tmpStr2, &_wavFormatObj.nBlockAlign, 2);
521             _wavFormatObj.nBlockAlign =
522                 (int16_t) ((uint32_t)tmpStr2[0] +
523                                  (((uint32_t)tmpStr2[1])<<8));
524             memcpy(tmpStr2, &_wavFormatObj.nBitsPerSample, 2);
525             _wavFormatObj.nBitsPerSample =
526                 (int16_t) ((uint32_t)tmpStr2[0] +
527                                  (((uint32_t)tmpStr2[1])<<8));
528 
529             for (i = 0;
530                  i < (CHUNKheaderObj.fmt_ckSize -
531                       (int32_t)sizeof(WAVE_FMTINFO_header));
532                  i++)
533             {
534                 len = wav.Read(&dummyRead, 1);
535                 if(len != 1)
536                 {
537                     WEBRTC_TRACE(kTraceError, kTraceFile, _id,
538                                  "File corrupted, reached EOF (reading fmt)");
539                     return -1;
540                 }
541             }
542             fmtFound = true;
543         }
544         else if(strcmp(tmpStr, "data") == 0)
545         {
546             _dataSize = CHUNKheaderObj.fmt_ckSize;
547             dataFound = true;
548             break;
549         }
550         else
551         {
552             for (i = 0; i < (CHUNKheaderObj.fmt_ckSize); i++)
553             {
554                 len = wav.Read(&dummyRead, 1);
555                 if(len != 1)
556                 {
557                     WEBRTC_TRACE(kTraceError, kTraceFile, _id,
558                                  "File corrupted, reached EOF (reading other)");
559                     return -1;
560                 }
561             }
562         }
563 
564         len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header));
565 
566         memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4);
567         CHUNKheaderObj.fmt_ckSize =
568             (int32_t) ((uint32_t)tmpStr2[0] +
569                              (((uint32_t)tmpStr2[1])<<8) +
570                              (((uint32_t)tmpStr2[2])<<16) +
571                              (((uint32_t)tmpStr2[3])<<24));
572 
573         memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4);
574     }
575 
576     // Either a proper format chunk has been read or a data chunk was come
577     // across.
578     if( (_wavFormatObj.formatTag != kWaveFormatPcm) &&
579         (_wavFormatObj.formatTag != kWaveFormatALaw) &&
580         (_wavFormatObj.formatTag != kWaveFormatMuLaw))
581     {
582         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
583                      "Coding formatTag value=%d not supported!",
584                      _wavFormatObj.formatTag);
585         return -1;
586     }
587     if((_wavFormatObj.nChannels < 1) ||
588         (_wavFormatObj.nChannels > 2))
589     {
590         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
591                      "nChannels value=%d not supported!",
592                      _wavFormatObj.nChannels);
593         return -1;
594     }
595 
596     if((_wavFormatObj.nBitsPerSample != 8) &&
597         (_wavFormatObj.nBitsPerSample != 16))
598     {
599         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
600                      "nBitsPerSample value=%d not supported!",
601                      _wavFormatObj.nBitsPerSample);
602         return -1;
603     }
604 
605     // Calculate the number of bytes that 10 ms of audio data correspond to.
606     if(_wavFormatObj.formatTag == kWaveFormatPcm)
607     {
608         // TODO (hellner): integer division for 22050 and 11025 would yield
609         //                 the same result as the else statement. Remove those
610         //                 special cases?
611         if(_wavFormatObj.nSamplesPerSec == 44100)
612         {
613             _readSizeBytes = 440 * _wavFormatObj.nChannels *
614                 (_wavFormatObj.nBitsPerSample / 8);
615         } else if(_wavFormatObj.nSamplesPerSec == 22050) {
616             _readSizeBytes = 220 * _wavFormatObj.nChannels *
617                 (_wavFormatObj.nBitsPerSample / 8);
618         } else if(_wavFormatObj.nSamplesPerSec == 11025) {
619             _readSizeBytes = 110 * _wavFormatObj.nChannels *
620                 (_wavFormatObj.nBitsPerSample / 8);
621         } else {
622             _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) *
623               _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8);
624         }
625 
626     } else {
627         _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) *
628             _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8);
629     }
630     return 0;
631 }
632 
InitWavCodec(uint32_t samplesPerSec,uint32_t channels,uint32_t bitsPerSample,uint32_t formatTag)633 int32_t ModuleFileUtility::InitWavCodec(uint32_t samplesPerSec,
634                                         uint32_t channels,
635                                         uint32_t bitsPerSample,
636                                         uint32_t formatTag)
637 {
638     codec_info_.pltype   = -1;
639     codec_info_.plfreq   = samplesPerSec;
640     codec_info_.channels = channels;
641     codec_info_.rate     = bitsPerSample * samplesPerSec;
642 
643     // Calculate the packet size for 10ms frames
644     switch(formatTag)
645     {
646     case kWaveFormatALaw:
647         strcpy(codec_info_.plname, "PCMA");
648         _codecId = kCodecPcma;
649         codec_info_.pltype = 8;
650         codec_info_.pacsize  = codec_info_.plfreq / 100;
651         break;
652     case kWaveFormatMuLaw:
653         strcpy(codec_info_.plname, "PCMU");
654         _codecId = kCodecPcmu;
655         codec_info_.pltype = 0;
656         codec_info_.pacsize  = codec_info_.plfreq / 100;
657          break;
658     case kWaveFormatPcm:
659         codec_info_.pacsize  = (bitsPerSample * (codec_info_.plfreq / 100)) / 8;
660         if(samplesPerSec == 8000)
661         {
662             strcpy(codec_info_.plname, "L16");
663             _codecId = kCodecL16_8Khz;
664         }
665         else if(samplesPerSec == 16000)
666         {
667             strcpy(codec_info_.plname, "L16");
668             _codecId = kCodecL16_16kHz;
669         }
670         else if(samplesPerSec == 32000)
671         {
672             strcpy(codec_info_.plname, "L16");
673             _codecId = kCodecL16_32Khz;
674         }
675         // Set the packet size for "odd" sampling frequencies so that it
676         // properly corresponds to _readSizeBytes.
677         else if(samplesPerSec == 11025)
678         {
679             strcpy(codec_info_.plname, "L16");
680             _codecId = kCodecL16_16kHz;
681             codec_info_.pacsize = 110;
682             codec_info_.plfreq = 11000;
683         }
684         else if(samplesPerSec == 22050)
685         {
686             strcpy(codec_info_.plname, "L16");
687             _codecId = kCodecL16_16kHz;
688             codec_info_.pacsize = 220;
689             codec_info_.plfreq = 22000;
690         }
691         else if(samplesPerSec == 44100)
692         {
693             strcpy(codec_info_.plname, "L16");
694             _codecId = kCodecL16_16kHz;
695             codec_info_.pacsize = 440;
696             codec_info_.plfreq = 44000;
697         }
698         else if(samplesPerSec == 48000)
699         {
700             strcpy(codec_info_.plname, "L16");
701             _codecId = kCodecL16_16kHz;
702             codec_info_.pacsize = 480;
703             codec_info_.plfreq = 48000;
704         }
705         else
706         {
707             WEBRTC_TRACE(kTraceError, kTraceFile, _id,
708                          "Unsupported PCM frequency!");
709             return -1;
710         }
711         break;
712         default:
713             WEBRTC_TRACE(kTraceError, kTraceFile, _id,
714                          "unknown WAV format TAG!");
715             return -1;
716             break;
717     }
718     return 0;
719 }
720 
InitWavReading(InStream & wav,const uint32_t start,const uint32_t stop)721 int32_t ModuleFileUtility::InitWavReading(InStream& wav,
722                                           const uint32_t start,
723                                           const uint32_t stop)
724 {
725 
726     _reading = false;
727 
728     if(ReadWavHeader(wav) == -1)
729     {
730         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
731                      "failed to read WAV header!");
732         return -1;
733     }
734 
735     _playoutPositionMs = 0;
736     _readPos = 0;
737 
738     if(start > 0)
739     {
740         uint8_t dummy[WAV_MAX_BUFFER_SIZE];
741         int32_t readLength;
742         if(_readSizeBytes <= WAV_MAX_BUFFER_SIZE)
743         {
744             while (_playoutPositionMs < start)
745             {
746                 readLength = wav.Read(dummy, _readSizeBytes);
747                 if(readLength == _readSizeBytes)
748                 {
749                     _readPos += readLength;
750                     _playoutPositionMs += 10;
751                 }
752                 else // Must have reached EOF before start position!
753                 {
754                     WEBRTC_TRACE(kTraceError, kTraceFile, _id,
755                        "InitWavReading(), EOF before start position");
756                     return -1;
757                 }
758             }
759         }
760         else
761         {
762             return -1;
763         }
764     }
765     if( InitWavCodec(_wavFormatObj.nSamplesPerSec, _wavFormatObj.nChannels,
766                      _wavFormatObj.nBitsPerSample,
767                      _wavFormatObj.formatTag) != 0)
768     {
769         return -1;
770     }
771     _bytesPerSample = _wavFormatObj.nBitsPerSample / 8;
772 
773 
774     _startPointInMs = start;
775     _stopPointInMs = stop;
776     _reading = true;
777     return 0;
778 }
779 
ReadWavDataAsMono(InStream & wav,int8_t * outData,const uint32_t bufferSize)780 int32_t ModuleFileUtility::ReadWavDataAsMono(
781     InStream& wav,
782     int8_t* outData,
783     const uint32_t bufferSize)
784 {
785     WEBRTC_TRACE(
786         kTraceStream,
787         kTraceFile,
788         _id,
789         "ModuleFileUtility::ReadWavDataAsMono(wav= 0x%x, outData= 0x%d,\
790  bufSize= %ld)",
791         &wav,
792         outData,
793         bufferSize);
794 
795     // The number of bytes that should be read from file.
796     const uint32_t totalBytesNeeded = _readSizeBytes;
797     // The number of bytes that will be written to outData.
798     const uint32_t bytesRequested = (codec_info_.channels == 2) ?
799         totalBytesNeeded >> 1 : totalBytesNeeded;
800     if(bufferSize < bytesRequested)
801     {
802         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
803                      "ReadWavDataAsMono: output buffer is too short!");
804         return -1;
805     }
806     if(outData == NULL)
807     {
808         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
809                      "ReadWavDataAsMono: output buffer NULL!");
810         return -1;
811     }
812 
813     if(!_reading)
814     {
815         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
816                      "ReadWavDataAsMono: no longer reading file.");
817         return -1;
818     }
819 
820     int32_t bytesRead = ReadWavData(
821         wav,
822         (codec_info_.channels == 2) ? _tempData : (uint8_t*)outData,
823         totalBytesNeeded);
824     if(bytesRead == 0)
825     {
826         return 0;
827     }
828     if(bytesRead < 0)
829     {
830         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
831                      "ReadWavDataAsMono: failed to read data from WAV file.");
832         return -1;
833     }
834     // Output data is should be mono.
835     if(codec_info_.channels == 2)
836     {
837         for (uint32_t i = 0; i < bytesRequested / _bytesPerSample; i++)
838         {
839             // Sample value is the average of left and right buffer rounded to
840             // closest integer value. Note samples can be either 1 or 2 byte.
841             if(_bytesPerSample == 1)
842             {
843                 _tempData[i] = ((_tempData[2 * i] + _tempData[(2 * i) + 1] +
844                                  1) >> 1);
845             }
846             else
847             {
848                 int16_t* sampleData = (int16_t*) _tempData;
849                 sampleData[i] = ((sampleData[2 * i] + sampleData[(2 * i) + 1] +
850                                   1) >> 1);
851             }
852         }
853         memcpy(outData, _tempData, bytesRequested);
854     }
855     return bytesRequested;
856 }
857 
ReadWavDataAsStereo(InStream & wav,int8_t * outDataLeft,int8_t * outDataRight,const uint32_t bufferSize)858 int32_t ModuleFileUtility::ReadWavDataAsStereo(
859     InStream& wav,
860     int8_t* outDataLeft,
861     int8_t* outDataRight,
862     const uint32_t bufferSize)
863 {
864     WEBRTC_TRACE(
865         kTraceStream,
866         kTraceFile,
867         _id,
868         "ModuleFileUtility::ReadWavDataAsStereo(wav= 0x%x, outLeft= 0x%x,\
869  outRight= 0x%x, bufSize= %ld)",
870         &wav,
871         outDataLeft,
872         outDataRight,
873         bufferSize);
874 
875     if((outDataLeft == NULL) ||
876        (outDataRight == NULL))
877     {
878         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
879                      "ReadWavDataAsMono: an input buffer is NULL!");
880         return -1;
881     }
882     if(codec_info_.channels != 2)
883     {
884         WEBRTC_TRACE(
885             kTraceError,
886             kTraceFile,
887             _id,
888             "ReadWavDataAsStereo: WAV file does not contain stereo data!");
889         return -1;
890     }
891     if(! _reading)
892     {
893         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
894                      "ReadWavDataAsStereo: no longer reading file.");
895         return -1;
896     }
897 
898     // The number of bytes that should be read from file.
899     const uint32_t totalBytesNeeded = _readSizeBytes;
900     // The number of bytes that will be written to the left and the right
901     // buffers.
902     const uint32_t bytesRequested = totalBytesNeeded >> 1;
903     if(bufferSize < bytesRequested)
904     {
905         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
906                      "ReadWavData: Output buffers are too short!");
907         assert(false);
908         return -1;
909     }
910 
911     int32_t bytesRead = ReadWavData(wav, _tempData, totalBytesNeeded);
912     if(bytesRead <= 0)
913     {
914         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
915                      "ReadWavDataAsStereo: failed to read data from WAV file.");
916         return -1;
917     }
918 
919     // Turn interleaved audio to left and right buffer. Note samples can be
920     // either 1 or 2 bytes
921     if(_bytesPerSample == 1)
922     {
923         for (uint32_t i = 0; i < bytesRequested; i++)
924         {
925             outDataLeft[i]  = _tempData[2 * i];
926             outDataRight[i] = _tempData[(2 * i) + 1];
927         }
928     }
929     else if(_bytesPerSample == 2)
930     {
931         int16_t* sampleData = reinterpret_cast<int16_t*>(_tempData);
932         int16_t* outLeft = reinterpret_cast<int16_t*>(outDataLeft);
933         int16_t* outRight = reinterpret_cast<int16_t*>(
934             outDataRight);
935 
936         // Bytes requested to samples requested.
937         uint32_t sampleCount = bytesRequested >> 1;
938         for (uint32_t i = 0; i < sampleCount; i++)
939         {
940             outLeft[i] = sampleData[2 * i];
941             outRight[i] = sampleData[(2 * i) + 1];
942         }
943     } else {
944         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
945                    "ReadWavStereoData: unsupported sample size %d!",
946                    _bytesPerSample);
947         assert(false);
948         return -1;
949     }
950     return bytesRequested;
951 }
952 
ReadWavData(InStream & wav,uint8_t * buffer,const uint32_t dataLengthInBytes)953 int32_t ModuleFileUtility::ReadWavData(
954     InStream& wav,
955     uint8_t* buffer,
956     const uint32_t dataLengthInBytes)
957 {
958     WEBRTC_TRACE(
959         kTraceStream,
960         kTraceFile,
961         _id,
962         "ModuleFileUtility::ReadWavData(wav= 0x%x, buffer= 0x%x, dataLen= %ld)",
963         &wav,
964         buffer,
965         dataLengthInBytes);
966 
967 
968     if(buffer == NULL)
969     {
970         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
971                      "ReadWavDataAsMono: output buffer NULL!");
972         return -1;
973     }
974 
975     // Make sure that a read won't return too few samples.
976     // TODO (hellner): why not read the remaining bytes needed from the start
977     //                 of the file?
978     if((_dataSize - _readPos) < (int32_t)dataLengthInBytes)
979     {
980         // Rewind() being -1 may be due to the file not supposed to be looped.
981         if(wav.Rewind() == -1)
982         {
983             _reading = false;
984             return 0;
985         }
986         if(InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1)
987         {
988             _reading = false;
989             return -1;
990         }
991     }
992 
993     int32_t bytesRead = wav.Read(buffer, dataLengthInBytes);
994     if(bytesRead < 0)
995     {
996         _reading = false;
997         return -1;
998     }
999 
1000     // This should never happen due to earlier sanity checks.
1001     // TODO (hellner): change to an assert and fail here since this should
1002     //                 never happen...
1003     if(bytesRead < (int32_t)dataLengthInBytes)
1004     {
1005         if((wav.Rewind() == -1) ||
1006             (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1))
1007         {
1008             _reading = false;
1009             return -1;
1010         }
1011         else
1012         {
1013             bytesRead = wav.Read(buffer, dataLengthInBytes);
1014             if(bytesRead < (int32_t)dataLengthInBytes)
1015             {
1016                 _reading = false;
1017                 return -1;
1018             }
1019         }
1020     }
1021 
1022     _readPos += bytesRead;
1023 
1024     // TODO (hellner): Why is dataLengthInBytes let dictate the number of bytes
1025     //                 to read when exactly 10ms should be read?!
1026     _playoutPositionMs += 10;
1027     if((_stopPointInMs > 0) &&
1028         (_playoutPositionMs >= _stopPointInMs))
1029     {
1030         if((wav.Rewind() == -1) ||
1031             (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1))
1032         {
1033             _reading = false;
1034         }
1035     }
1036     return bytesRead;
1037 }
1038 
InitWavWriting(OutStream & wav,const CodecInst & codecInst)1039 int32_t ModuleFileUtility::InitWavWriting(OutStream& wav,
1040                                           const CodecInst& codecInst)
1041 {
1042 
1043     if(set_codec_info(codecInst) != 0)
1044     {
1045         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1046                      "codecInst identifies unsupported codec!");
1047         return -1;
1048     }
1049     _writing = false;
1050     uint32_t channels = (codecInst.channels == 0) ?
1051         1 : codecInst.channels;
1052 
1053     if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0)
1054     {
1055         _bytesPerSample = 1;
1056         if(WriteWavHeader(wav, 8000, _bytesPerSample, channels,
1057                           kWaveFormatMuLaw, 0) == -1)
1058         {
1059             return -1;
1060         }
1061     }else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0)
1062     {
1063         _bytesPerSample = 1;
1064         if(WriteWavHeader(wav, 8000, _bytesPerSample, channels, kWaveFormatALaw,
1065                           0) == -1)
1066         {
1067             return -1;
1068         }
1069     }
1070     else if(STR_CASE_CMP(codecInst.plname, "L16") == 0)
1071     {
1072         _bytesPerSample = 2;
1073         if(WriteWavHeader(wav, codecInst.plfreq, _bytesPerSample, channels,
1074                           kWaveFormatPcm, 0) == -1)
1075         {
1076             return -1;
1077         }
1078     }
1079     else
1080     {
1081         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1082                    "codecInst identifies unsupported codec for WAV file!");
1083         return -1;
1084     }
1085     _writing = true;
1086     _bytesWritten = 0;
1087     return 0;
1088 }
1089 
WriteWavData(OutStream & out,const int8_t * buffer,const uint32_t dataLength)1090 int32_t ModuleFileUtility::WriteWavData(OutStream& out,
1091                                         const int8_t*  buffer,
1092                                         const uint32_t dataLength)
1093 {
1094     WEBRTC_TRACE(
1095         kTraceStream,
1096         kTraceFile,
1097         _id,
1098         "ModuleFileUtility::WriteWavData(out= 0x%x, buf= 0x%x, dataLen= %d)",
1099         &out,
1100         buffer,
1101         dataLength);
1102 
1103     if(buffer == NULL)
1104     {
1105         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1106                      "WriteWavData: input buffer NULL!");
1107         return -1;
1108     }
1109 
1110     if(!out.Write(buffer, dataLength))
1111     {
1112         return -1;
1113     }
1114     _bytesWritten += dataLength;
1115     return dataLength;
1116 }
1117 
1118 
WriteWavHeader(OutStream & wav,const uint32_t freq,const uint32_t bytesPerSample,const uint32_t channels,const uint32_t format,const uint32_t lengthInBytes)1119 int32_t ModuleFileUtility::WriteWavHeader(
1120     OutStream& wav,
1121     const uint32_t freq,
1122     const uint32_t bytesPerSample,
1123     const uint32_t channels,
1124     const uint32_t format,
1125     const uint32_t lengthInBytes)
1126 {
1127 
1128     // Frame size in bytes for 10 ms of audio.
1129     // TODO (hellner): 44.1 kHz has 440 samples frame size. Doesn't seem to
1130     //                 be taken into consideration here!
1131     int32_t frameSize = (freq / 100) * bytesPerSample * channels;
1132 
1133     // Calculate the number of full frames that the wave file contain.
1134     const int32_t dataLengthInBytes = frameSize *
1135         (lengthInBytes / frameSize);
1136 
1137     int8_t tmpStr[4];
1138     int8_t tmpChar;
1139     uint32_t tmpLong;
1140 
1141     memcpy(tmpStr, "RIFF", 4);
1142     wav.Write(tmpStr, 4);
1143 
1144     tmpLong = dataLengthInBytes + 36;
1145     tmpChar = (int8_t)(tmpLong);
1146     wav.Write(&tmpChar, 1);
1147     tmpChar = (int8_t)(tmpLong >> 8);
1148     wav.Write(&tmpChar, 1);
1149     tmpChar = (int8_t)(tmpLong >> 16);
1150     wav.Write(&tmpChar, 1);
1151     tmpChar = (int8_t)(tmpLong >> 24);
1152     wav.Write(&tmpChar, 1);
1153 
1154     memcpy(tmpStr, "WAVE", 4);
1155     wav.Write(tmpStr, 4);
1156 
1157     memcpy(tmpStr, "fmt ", 4);
1158     wav.Write(tmpStr, 4);
1159 
1160     tmpChar = 16;
1161     wav.Write(&tmpChar, 1);
1162     tmpChar = 0;
1163     wav.Write(&tmpChar, 1);
1164     tmpChar = 0;
1165     wav.Write(&tmpChar, 1);
1166     tmpChar = 0;
1167     wav.Write(&tmpChar, 1);
1168 
1169     tmpChar = (int8_t)(format);
1170     wav.Write(&tmpChar, 1);
1171     tmpChar = 0;
1172     wav.Write(&tmpChar, 1);
1173 
1174     tmpChar = (int8_t)(channels);
1175     wav.Write(&tmpChar, 1);
1176     tmpChar = 0;
1177     wav.Write(&tmpChar, 1);
1178 
1179     tmpLong = freq;
1180     tmpChar = (int8_t)(tmpLong);
1181     wav.Write(&tmpChar, 1);
1182     tmpChar = (int8_t)(tmpLong >> 8);
1183     wav.Write(&tmpChar, 1);
1184     tmpChar = (int8_t)(tmpLong >> 16);
1185     wav.Write(&tmpChar, 1);
1186     tmpChar = (int8_t)(tmpLong >> 24);
1187     wav.Write(&tmpChar, 1);
1188 
1189     // nAverageBytesPerSec = Sample rate * Bytes per sample * Channels
1190     tmpLong = bytesPerSample * freq * channels;
1191     tmpChar = (int8_t)(tmpLong);
1192     wav.Write(&tmpChar, 1);
1193     tmpChar = (int8_t)(tmpLong >> 8);
1194     wav.Write(&tmpChar, 1);
1195     tmpChar = (int8_t)(tmpLong >> 16);
1196     wav.Write(&tmpChar, 1);
1197     tmpChar = (int8_t)(tmpLong >> 24);
1198     wav.Write(&tmpChar, 1);
1199 
1200     // nBlockAlign = Bytes per sample * Channels
1201     tmpChar = (int8_t)(bytesPerSample * channels);
1202     wav.Write(&tmpChar, 1);
1203     tmpChar = 0;
1204     wav.Write(&tmpChar, 1);
1205 
1206     tmpChar = (int8_t)(bytesPerSample*8);
1207     wav.Write(&tmpChar, 1);
1208     tmpChar = 0;
1209     wav.Write(&tmpChar, 1);
1210 
1211     memcpy(tmpStr, "data", 4);
1212     wav.Write(tmpStr, 4);
1213 
1214     tmpLong = dataLengthInBytes;
1215     tmpChar = (int8_t)(tmpLong);
1216     wav.Write(&tmpChar, 1);
1217     tmpChar = (int8_t)(tmpLong >> 8);
1218     wav.Write(&tmpChar, 1);
1219     tmpChar = (int8_t)(tmpLong >> 16);
1220     wav.Write(&tmpChar, 1);
1221     tmpChar = (int8_t)(tmpLong >> 24);
1222     wav.Write(&tmpChar, 1);
1223 
1224     return 0;
1225 }
1226 
UpdateWavHeader(OutStream & wav)1227 int32_t ModuleFileUtility::UpdateWavHeader(OutStream& wav)
1228 {
1229     int32_t res = -1;
1230     if(wav.Rewind() == -1)
1231     {
1232         return -1;
1233     }
1234     uint32_t channels = (codec_info_.channels == 0) ?
1235         1 : codec_info_.channels;
1236 
1237     if(STR_CASE_CMP(codec_info_.plname, "L16") == 0)
1238     {
1239         res = WriteWavHeader(wav, codec_info_.plfreq, 2, channels,
1240                              kWaveFormatPcm, _bytesWritten);
1241     } else if(STR_CASE_CMP(codec_info_.plname, "PCMU") == 0) {
1242             res = WriteWavHeader(wav, 8000, 1, channels, kWaveFormatMuLaw,
1243                                  _bytesWritten);
1244     } else if(STR_CASE_CMP(codec_info_.plname, "PCMA") == 0) {
1245             res = WriteWavHeader(wav, 8000, 1, channels, kWaveFormatALaw,
1246                                  _bytesWritten);
1247     } else {
1248         // Allow calling this API even if not writing to a WAVE file.
1249         // TODO (hellner): why?!
1250         return 0;
1251     }
1252     return res;
1253 }
1254 
1255 
InitPreEncodedReading(InStream & in,const CodecInst & cinst)1256 int32_t ModuleFileUtility::InitPreEncodedReading(InStream& in,
1257                                                  const CodecInst& cinst)
1258 {
1259 
1260     uint8_t preEncodedID;
1261     in.Read(&preEncodedID, 1);
1262 
1263     MediaFileUtility_CodecType codecType =
1264         (MediaFileUtility_CodecType)preEncodedID;
1265 
1266     if(set_codec_info(cinst) != 0)
1267     {
1268         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1269                      "Pre-encoded file send codec mismatch!");
1270         return -1;
1271     }
1272     if(codecType != _codecId)
1273     {
1274         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1275                      "Pre-encoded file format codec mismatch!");
1276         return -1;
1277     }
1278     memcpy(&codec_info_,&cinst,sizeof(CodecInst));
1279     _reading = true;
1280     return 0;
1281 }
1282 
ReadPreEncodedData(InStream & in,int8_t * outData,const uint32_t bufferSize)1283 int32_t ModuleFileUtility::ReadPreEncodedData(
1284     InStream& in,
1285     int8_t* outData,
1286     const uint32_t bufferSize)
1287 {
1288     WEBRTC_TRACE(
1289         kTraceStream,
1290         kTraceFile,
1291         _id,
1292         "ModuleFileUtility::ReadPreEncodedData(in= 0x%x, outData= 0x%x,\
1293  bufferSize= %d)",
1294         &in,
1295         outData,
1296         bufferSize);
1297 
1298     if(outData == NULL)
1299     {
1300         WEBRTC_TRACE(kTraceError, kTraceFile, _id, "output buffer NULL");
1301     }
1302 
1303     uint32_t frameLen;
1304     uint8_t buf[64];
1305     // Each frame has a two byte header containing the frame length.
1306     int32_t res = in.Read(buf, 2);
1307     if(res != 2)
1308     {
1309         if(!in.Rewind())
1310         {
1311             // The first byte is the codec identifier.
1312             in.Read(buf, 1);
1313             res = in.Read(buf, 2);
1314         }
1315         else
1316         {
1317             return -1;
1318         }
1319     }
1320     frameLen = buf[0] + buf[1] * 256;
1321     if(bufferSize < frameLen)
1322     {
1323         WEBRTC_TRACE(
1324             kTraceError,
1325             kTraceFile,
1326             _id,
1327             "buffer not large enough to read %d bytes of pre-encoded data!",
1328             frameLen);
1329         return -1;
1330     }
1331     return in.Read(outData, frameLen);
1332 }
1333 
InitPreEncodedWriting(OutStream & out,const CodecInst & codecInst)1334 int32_t ModuleFileUtility::InitPreEncodedWriting(
1335     OutStream& out,
1336     const CodecInst& codecInst)
1337 {
1338 
1339     if(set_codec_info(codecInst) != 0)
1340     {
1341         WEBRTC_TRACE(kTraceError, kTraceFile, _id, "CodecInst not recognized!");
1342         return -1;
1343     }
1344     _writing = true;
1345     _bytesWritten = 1;
1346      out.Write(&_codecId, 1);
1347      return 0;
1348 }
1349 
WritePreEncodedData(OutStream & out,const int8_t * buffer,const uint32_t dataLength)1350 int32_t ModuleFileUtility::WritePreEncodedData(
1351     OutStream& out,
1352     const int8_t*  buffer,
1353     const uint32_t dataLength)
1354 {
1355     WEBRTC_TRACE(
1356         kTraceStream,
1357         kTraceFile,
1358         _id,
1359         "ModuleFileUtility::WritePreEncodedData(out= 0x%x, inData= 0x%x,\
1360  dataLen= %d)",
1361         &out,
1362         buffer,
1363         dataLength);
1364 
1365     if(buffer == NULL)
1366     {
1367         WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
1368     }
1369 
1370     int32_t bytesWritten = 0;
1371     // The first two bytes is the size of the frame.
1372     int16_t lengthBuf;
1373     lengthBuf = (int16_t)dataLength;
1374     if(!out.Write(&lengthBuf, 2))
1375     {
1376        return -1;
1377     }
1378     bytesWritten = 2;
1379 
1380     if(!out.Write(buffer, dataLength))
1381     {
1382         return -1;
1383     }
1384     bytesWritten += dataLength;
1385     return bytesWritten;
1386 }
1387 
InitCompressedReading(InStream & in,const uint32_t start,const uint32_t stop)1388 int32_t ModuleFileUtility::InitCompressedReading(
1389     InStream& in,
1390     const uint32_t start,
1391     const uint32_t stop)
1392 {
1393     WEBRTC_TRACE(
1394         kTraceDebug,
1395         kTraceFile,
1396         _id,
1397         "ModuleFileUtility::InitCompressedReading(in= 0x%x, start= %d,\
1398  stop= %d)",
1399         &in,
1400         start,
1401         stop);
1402 
1403 #if defined(WEBRTC_CODEC_AMR) || defined(WEBRTC_CODEC_AMRWB) || \
1404     defined(WEBRTC_CODEC_ILBC)
1405     int16_t read_len = 0;
1406 #endif
1407     _codecId = kCodecNoCodec;
1408     _playoutPositionMs = 0;
1409     _reading = false;
1410 
1411     _startPointInMs = start;
1412     _stopPointInMs = stop;
1413 
1414 #ifdef WEBRTC_CODEC_AMR
1415     int32_t AMRmode2bytes[9]={12,13,15,17,19,20,26,31,5};
1416 #endif
1417 #ifdef WEBRTC_CODEC_AMRWB
1418     int32_t AMRWBmode2bytes[10]={17,23,32,36,40,46,50,58,60,6};
1419 #endif
1420 
1421     // Read the codec name
1422     int32_t cnt = 0;
1423     char buf[64];
1424     do
1425     {
1426         in.Read(&buf[cnt++], 1);
1427     } while ((buf[cnt-1] != '\n') && (64 > cnt));
1428 
1429     if(cnt==64)
1430     {
1431         return -1;
1432     } else {
1433         buf[cnt]=0;
1434     }
1435 
1436 #ifdef WEBRTC_CODEC_AMR
1437     if(!strcmp("#!AMR\n", buf))
1438     {
1439         strcpy(codec_info_.plname, "amr");
1440         codec_info_.pacsize = 160;
1441         _codecId = kCodecAmr;
1442         codec_info_.pltype = 112;
1443         codec_info_.rate = 12200;
1444         codec_info_.plfreq = 8000;
1445         codec_info_.channels = 1;
1446 
1447         int16_t mode = 0;
1448         if(_startPointInMs > 0)
1449         {
1450             while (_playoutPositionMs <= _startPointInMs)
1451             {
1452                 // First read byte contain the AMR mode.
1453                 read_len = in.Read(buf, 1);
1454                 if(read_len != 1)
1455                 {
1456                     return -1;
1457                 }
1458 
1459                 mode = (buf[0]>>3)&0xF;
1460                 if((mode < 0) || (mode > 8))
1461                 {
1462                     if(mode != 15)
1463                     {
1464                         return -1;
1465                     }
1466                 }
1467                 if(mode != 15)
1468                 {
1469                     read_len = in.Read(&buf[1], AMRmode2bytes[mode]);
1470                     if(read_len != AMRmode2bytes[mode])
1471                     {
1472                         return -1;
1473                     }
1474                 }
1475                 _playoutPositionMs += 20;
1476             }
1477         }
1478     }
1479 #endif
1480 #ifdef WEBRTC_CODEC_AMRWB
1481     if(!strcmp("#!AMRWB\n", buf))
1482     {
1483         strcpy(codec_info_.plname, "amr-wb");
1484         codec_info_.pacsize = 320;
1485         _codecId = kCodecAmrWb;
1486         codec_info_.pltype = 120;
1487         codec_info_.rate = 20000;
1488         codec_info_.plfreq = 16000;
1489         codec_info_.channels = 1;
1490 
1491         int16_t mode = 0;
1492         if(_startPointInMs > 0)
1493         {
1494             while (_playoutPositionMs <= _startPointInMs)
1495             {
1496                 // First read byte contain the AMR mode.
1497                 read_len = in.Read(buf, 1);
1498                 if(read_len != 1)
1499                 {
1500                     return -1;
1501                 }
1502 
1503                 mode = (buf[0]>>3)&0xF;
1504                 if((mode < 0) || (mode > 9))
1505                 {
1506                     if(mode != 15)
1507                     {
1508                         return -1;
1509                     }
1510                 }
1511                 if(mode != 15)
1512                 {
1513                     read_len = in.Read(&buf[1], AMRWBmode2bytes[mode]);
1514                     if(read_len != AMRWBmode2bytes[mode])
1515                     {
1516                         return -1;
1517                     }
1518                 }
1519                 _playoutPositionMs += 20;
1520             }
1521         }
1522     }
1523 #endif
1524 #ifdef WEBRTC_CODEC_ILBC
1525     if(!strcmp("#!iLBC20\n", buf))
1526     {
1527         codec_info_.pltype = 102;
1528         strcpy(codec_info_.plname, "ilbc");
1529         codec_info_.plfreq   = 8000;
1530         codec_info_.pacsize  = 160;
1531         codec_info_.channels = 1;
1532         codec_info_.rate     = 13300;
1533         _codecId = kCodecIlbc20Ms;
1534 
1535         if(_startPointInMs > 0)
1536         {
1537             while (_playoutPositionMs <= _startPointInMs)
1538             {
1539                 read_len = in.Read(buf, 38);
1540                 if(read_len == 38)
1541                 {
1542                     _playoutPositionMs += 20;
1543                 }
1544                 else
1545                 {
1546                     return -1;
1547                 }
1548             }
1549         }
1550     }
1551 
1552     if(!strcmp("#!iLBC30\n", buf))
1553     {
1554         codec_info_.pltype = 102;
1555         strcpy(codec_info_.plname, "ilbc");
1556         codec_info_.plfreq   = 8000;
1557         codec_info_.pacsize  = 240;
1558         codec_info_.channels = 1;
1559         codec_info_.rate     = 13300;
1560         _codecId = kCodecIlbc30Ms;
1561 
1562         if(_startPointInMs > 0)
1563         {
1564             while (_playoutPositionMs <= _startPointInMs)
1565             {
1566                 read_len = in.Read(buf, 50);
1567                 if(read_len == 50)
1568                 {
1569                     _playoutPositionMs += 20;
1570                 }
1571                 else
1572                 {
1573                     return -1;
1574                 }
1575             }
1576         }
1577     }
1578 #endif
1579     if(_codecId == kCodecNoCodec)
1580     {
1581         return -1;
1582     }
1583     _reading = true;
1584     return 0;
1585 }
1586 
ReadCompressedData(InStream & in,int8_t * outData,uint32_t bufferSize)1587 int32_t ModuleFileUtility::ReadCompressedData(InStream& in,
1588                                               int8_t* outData,
1589                                               uint32_t bufferSize)
1590 {
1591     WEBRTC_TRACE(
1592         kTraceStream,
1593         kTraceFile,
1594         _id,
1595         "ModuleFileUtility::ReadCompressedData(in=0x%x, outData=0x%x,\
1596  bytes=%ld)",
1597         &in,
1598         outData,
1599         bufferSize);
1600 
1601 #ifdef WEBRTC_CODEC_AMR
1602     uint32_t AMRmode2bytes[9]={12,13,15,17,19,20,26,31,5};
1603 #endif
1604 #ifdef WEBRTC_CODEC_AMRWB
1605     uint32_t AMRWBmode2bytes[10]={17,23,32,36,40,46,50,58,60,6};
1606 #endif
1607     uint32_t bytesRead = 0;
1608 
1609     if(! _reading)
1610     {
1611         WEBRTC_TRACE(kTraceError, kTraceFile, _id, "not currently reading!");
1612         return -1;
1613     }
1614 
1615 #ifdef WEBRTC_CODEC_AMR
1616     if(_codecId == kCodecAmr)
1617     {
1618         int32_t res = in.Read(outData, 1);
1619         if(res != 1)
1620         {
1621             if(!in.Rewind())
1622             {
1623                 InitCompressedReading(in, _startPointInMs, _stopPointInMs);
1624                 res = in.Read(outData, 1);
1625                 if(res != 1)
1626                 {
1627                     _reading = false;
1628                     return -1;
1629                 }
1630             }
1631             else
1632             {
1633                 _reading = false;
1634                 return -1;
1635             }
1636         }
1637          const int16_t mode = (outData[0]>>3)&0xF;
1638         if((mode < 0) ||
1639            (mode > 8))
1640         {
1641             if(mode != 15)
1642             {
1643                 return -1;
1644             }
1645         }
1646         if(mode != 15)
1647         {
1648             if(bufferSize < AMRmode2bytes[mode] + 1)
1649             {
1650                 WEBRTC_TRACE(
1651                     kTraceError,
1652                     kTraceFile,
1653                     _id,
1654                     "output buffer is too short to read AMR compressed data.");
1655                 assert(false);
1656                 return -1;
1657             }
1658             bytesRead = in.Read(&outData[1], AMRmode2bytes[mode]);
1659             if(bytesRead != AMRmode2bytes[mode])
1660             {
1661                 _reading = false;
1662                 return -1;
1663             }
1664             // Count the mode byte to bytes read.
1665             bytesRead++;
1666         }
1667         else
1668         {
1669             bytesRead = 1;
1670         }
1671     }
1672 #endif
1673 #ifdef WEBRTC_CODEC_AMRWB
1674     if(_codecId == kCodecAmrWb)
1675     {
1676         int32_t res = in.Read(outData, 1);
1677         if(res != 1)
1678         {
1679             if(!in.Rewind())
1680             {
1681                 InitCompressedReading(in, _startPointInMs, _stopPointInMs);
1682                 res = in.Read(outData, 1);
1683                 if(res != 1)
1684                 {
1685                     _reading = false;
1686                     return -1;
1687                 }
1688             }
1689             else
1690             {
1691                 _reading = false;
1692                 return -1;
1693             }
1694         }
1695          int16_t mode = (outData[0]>>3)&0xF;
1696         if((mode < 0) ||
1697            (mode > 8))
1698         {
1699             if(mode != 15)
1700             {
1701                 return -1;
1702             }
1703         }
1704         if(mode != 15)
1705         {
1706             if(bufferSize < AMRWBmode2bytes[mode] + 1)
1707             {
1708                 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1709                            "output buffer is too short to read AMRWB\
1710  compressed.");
1711                 assert(false);
1712                 return -1;
1713             }
1714              bytesRead = in.Read(&outData[1], AMRWBmode2bytes[mode]);
1715             if(bytesRead != AMRWBmode2bytes[mode])
1716             {
1717                 _reading = false;
1718                 return -1;
1719             }
1720             bytesRead++;
1721         }
1722         else
1723         {
1724             bytesRead = 1;
1725         }
1726     }
1727 #endif
1728 #ifdef WEBRTC_CODEC_ILBC
1729     if((_codecId == kCodecIlbc20Ms) ||
1730         (_codecId == kCodecIlbc30Ms))
1731     {
1732         uint32_t byteSize = 0;
1733          if(_codecId == kCodecIlbc30Ms)
1734         {
1735             byteSize = 50;
1736         }
1737         if(_codecId == kCodecIlbc20Ms)
1738         {
1739             byteSize = 38;
1740         }
1741         if(bufferSize < byteSize)
1742         {
1743             WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1744                            "output buffer is too short to read ILBC compressed\
1745  data.");
1746             assert(false);
1747             return -1;
1748         }
1749 
1750         bytesRead = in.Read(outData, byteSize);
1751         if(bytesRead != byteSize)
1752         {
1753             if(!in.Rewind())
1754             {
1755                 InitCompressedReading(in, _startPointInMs, _stopPointInMs);
1756                 bytesRead = in.Read(outData, byteSize);
1757                 if(bytesRead != byteSize)
1758                 {
1759                     _reading = false;
1760                     return -1;
1761                 }
1762             }
1763             else
1764             {
1765                 _reading = false;
1766                 return -1;
1767             }
1768         }
1769     }
1770 #endif
1771     if(bytesRead == 0)
1772     {
1773         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1774                      "ReadCompressedData() no bytes read, codec not supported");
1775         return -1;
1776     }
1777 
1778     _playoutPositionMs += 20;
1779     if((_stopPointInMs > 0) &&
1780         (_playoutPositionMs >= _stopPointInMs))
1781     {
1782         if(!in.Rewind())
1783         {
1784             InitCompressedReading(in, _startPointInMs, _stopPointInMs);
1785         }
1786         else
1787         {
1788             _reading = false;
1789         }
1790     }
1791     return bytesRead;
1792 }
1793 
InitCompressedWriting(OutStream & out,const CodecInst & codecInst)1794 int32_t ModuleFileUtility::InitCompressedWriting(
1795     OutStream& out,
1796     const CodecInst& codecInst)
1797 {
1798     WEBRTC_TRACE(kTraceDebug, kTraceFile, _id,
1799                "ModuleFileUtility::InitCompressedWriting(out= 0x%x,\
1800  codecName= %s)",
1801                &out, codecInst.plname);
1802 
1803     _writing = false;
1804 
1805 #ifdef WEBRTC_CODEC_AMR
1806     if(STR_CASE_CMP(codecInst.plname, "amr") == 0)
1807     {
1808         if(codecInst.pacsize == 160)
1809         {
1810             memcpy(&codec_info_,&codecInst,sizeof(CodecInst));
1811             _codecId = kCodecAmr;
1812             out.Write("#!AMR\n",6);
1813             _writing = true;
1814             return 0;
1815         }
1816     }
1817 #endif
1818 #ifdef WEBRTC_CODEC_AMRWB
1819     if(STR_CASE_CMP(codecInst.plname, "amr-wb") == 0)
1820     {
1821         if(codecInst.pacsize == 320)
1822         {
1823             memcpy(&codec_info_,&codecInst,sizeof(CodecInst));
1824             _codecId = kCodecAmrWb;
1825             out.Write("#!AMRWB\n",8);
1826             _writing = true;
1827             return 0;
1828         }
1829     }
1830 #endif
1831 #ifdef WEBRTC_CODEC_ILBC
1832     if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0)
1833     {
1834         if(codecInst.pacsize == 160)
1835         {
1836             _codecId = kCodecIlbc20Ms;
1837             out.Write("#!iLBC20\n",9);
1838         }
1839         else if(codecInst.pacsize == 240)
1840         {
1841             _codecId = kCodecIlbc30Ms;
1842             out.Write("#!iLBC30\n",9);
1843         }
1844         else
1845         {
1846           WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1847                        "codecInst defines unsupported compression codec!");
1848             return -1;
1849         }
1850         memcpy(&codec_info_,&codecInst,sizeof(CodecInst));
1851         _writing = true;
1852         return 0;
1853     }
1854 #endif
1855 
1856     WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1857                  "codecInst defines unsupported compression codec!");
1858     return -1;
1859 }
1860 
WriteCompressedData(OutStream & out,const int8_t * buffer,const uint32_t dataLength)1861 int32_t ModuleFileUtility::WriteCompressedData(
1862     OutStream& out,
1863     const int8_t* buffer,
1864     const uint32_t dataLength)
1865 {
1866     WEBRTC_TRACE(
1867         kTraceStream,
1868         kTraceFile,
1869         _id,
1870         "ModuleFileUtility::WriteCompressedData(out= 0x%x, buf= 0x%x,\
1871  dataLen= %d)",
1872         &out,
1873         buffer,
1874         dataLength);
1875 
1876     if(buffer == NULL)
1877     {
1878         WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
1879     }
1880 
1881     if(!out.Write(buffer, dataLength))
1882     {
1883         return -1;
1884     }
1885     return dataLength;
1886 }
1887 
InitPCMReading(InStream & pcm,const uint32_t start,const uint32_t stop,uint32_t freq)1888 int32_t ModuleFileUtility::InitPCMReading(InStream& pcm,
1889                                           const uint32_t start,
1890                                           const uint32_t stop,
1891                                           uint32_t freq)
1892 {
1893     WEBRTC_TRACE(
1894         kTraceInfo,
1895         kTraceFile,
1896         _id,
1897         "ModuleFileUtility::InitPCMReading(pcm= 0x%x, start=%d, stop=%d,\
1898  freq=%d)",
1899         &pcm,
1900         start,
1901         stop,
1902         freq);
1903 
1904     int8_t dummy[320];
1905     int32_t read_len;
1906 
1907     _playoutPositionMs = 0;
1908     _startPointInMs = start;
1909     _stopPointInMs = stop;
1910     _reading = false;
1911 
1912     if(freq == 8000)
1913     {
1914         strcpy(codec_info_.plname, "L16");
1915         codec_info_.pltype   = -1;
1916         codec_info_.plfreq   = 8000;
1917         codec_info_.pacsize  = 160;
1918         codec_info_.channels = 1;
1919         codec_info_.rate     = 128000;
1920         _codecId = kCodecL16_8Khz;
1921     }
1922     else if(freq == 16000)
1923     {
1924         strcpy(codec_info_.plname, "L16");
1925         codec_info_.pltype   = -1;
1926         codec_info_.plfreq   = 16000;
1927         codec_info_.pacsize  = 320;
1928         codec_info_.channels = 1;
1929         codec_info_.rate     = 256000;
1930         _codecId = kCodecL16_16kHz;
1931     }
1932     else if(freq == 32000)
1933     {
1934         strcpy(codec_info_.plname, "L16");
1935         codec_info_.pltype   = -1;
1936         codec_info_.plfreq   = 32000;
1937         codec_info_.pacsize  = 320;
1938         codec_info_.channels = 1;
1939         codec_info_.rate     = 512000;
1940         _codecId = kCodecL16_32Khz;
1941     }
1942 
1943     // Readsize for 10ms of audio data (2 bytes per sample).
1944     _readSizeBytes = 2 * codec_info_. plfreq / 100;
1945     if(_startPointInMs > 0)
1946     {
1947         while (_playoutPositionMs < _startPointInMs)
1948         {
1949             read_len = pcm.Read(dummy, _readSizeBytes);
1950             if(read_len == _readSizeBytes)
1951             {
1952                 _playoutPositionMs += 10;
1953             }
1954             else // Must have reached EOF before start position!
1955             {
1956                 return -1;
1957             }
1958         }
1959     }
1960     _reading = true;
1961     return 0;
1962 }
1963 
ReadPCMData(InStream & pcm,int8_t * outData,uint32_t bufferSize)1964 int32_t ModuleFileUtility::ReadPCMData(InStream& pcm,
1965                                        int8_t* outData,
1966                                        uint32_t bufferSize)
1967 {
1968     WEBRTC_TRACE(
1969         kTraceStream,
1970         kTraceFile,
1971         _id,
1972         "ModuleFileUtility::ReadPCMData(pcm= 0x%x, outData= 0x%x, bufSize= %d)",
1973         &pcm,
1974         outData,
1975         bufferSize);
1976 
1977     if(outData == NULL)
1978     {
1979         WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
1980     }
1981 
1982     // Readsize for 10ms of audio data (2 bytes per sample).
1983     uint32_t bytesRequested = 2 * codec_info_.plfreq / 100;
1984     if(bufferSize <  bytesRequested)
1985     {
1986         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
1987                    "ReadPCMData: buffer not long enough for a 10ms frame.");
1988         assert(false);
1989         return -1;
1990     }
1991 
1992     uint32_t bytesRead = pcm.Read(outData, bytesRequested);
1993     if(bytesRead < bytesRequested)
1994     {
1995         if(pcm.Rewind() == -1)
1996         {
1997             _reading = false;
1998         }
1999         else
2000         {
2001             if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs,
2002                               codec_info_.plfreq) == -1)
2003             {
2004                 _reading = false;
2005             }
2006             else
2007             {
2008                 int32_t rest = bytesRequested - bytesRead;
2009                 int32_t len = pcm.Read(&(outData[bytesRead]), rest);
2010                 if(len == rest)
2011                 {
2012                     bytesRead += len;
2013                 }
2014                 else
2015                 {
2016                     _reading = false;
2017                 }
2018             }
2019             if(bytesRead <= 0)
2020             {
2021                 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2022                         "ReadPCMData: Failed to rewind audio file.");
2023                 return -1;
2024             }
2025         }
2026     }
2027 
2028     if(bytesRead <= 0)
2029     {
2030         WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
2031                    "ReadPCMData: end of file");
2032         return -1;
2033     }
2034     _playoutPositionMs += 10;
2035     if(_stopPointInMs && _playoutPositionMs >= _stopPointInMs)
2036     {
2037         if(!pcm.Rewind())
2038         {
2039             if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs,
2040                               codec_info_.plfreq) == -1)
2041             {
2042                 _reading = false;
2043             }
2044         }
2045     }
2046     return bytesRead;
2047 }
2048 
InitPCMWriting(OutStream & out,uint32_t freq)2049 int32_t ModuleFileUtility::InitPCMWriting(OutStream& out, uint32_t freq)
2050 {
2051 
2052     if(freq == 8000)
2053     {
2054         strcpy(codec_info_.plname, "L16");
2055         codec_info_.pltype   = -1;
2056         codec_info_.plfreq   = 8000;
2057         codec_info_.pacsize  = 160;
2058         codec_info_.channels = 1;
2059         codec_info_.rate     = 128000;
2060 
2061         _codecId = kCodecL16_8Khz;
2062     }
2063     else if(freq == 16000)
2064     {
2065         strcpy(codec_info_.plname, "L16");
2066         codec_info_.pltype   = -1;
2067         codec_info_.plfreq   = 16000;
2068         codec_info_.pacsize  = 320;
2069         codec_info_.channels = 1;
2070         codec_info_.rate     = 256000;
2071 
2072         _codecId = kCodecL16_16kHz;
2073     }
2074     else if(freq == 32000)
2075     {
2076         strcpy(codec_info_.plname, "L16");
2077         codec_info_.pltype   = -1;
2078         codec_info_.plfreq   = 32000;
2079         codec_info_.pacsize  = 320;
2080         codec_info_.channels = 1;
2081         codec_info_.rate     = 512000;
2082 
2083         _codecId = kCodecL16_32Khz;
2084     }
2085     if((_codecId != kCodecL16_8Khz) &&
2086        (_codecId != kCodecL16_16kHz) &&
2087        (_codecId != kCodecL16_32Khz))
2088     {
2089         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2090                      "CodecInst is not 8KHz PCM or 16KHz PCM!");
2091         return -1;
2092     }
2093     _writing = true;
2094     _bytesWritten = 0;
2095     return 0;
2096 }
2097 
WritePCMData(OutStream & out,const int8_t * buffer,const uint32_t dataLength)2098 int32_t ModuleFileUtility::WritePCMData(OutStream& out,
2099                                         const int8_t*  buffer,
2100                                         const uint32_t dataLength)
2101 {
2102     WEBRTC_TRACE(
2103         kTraceStream,
2104         kTraceFile,
2105         _id,
2106         "ModuleFileUtility::WritePCMData(out= 0x%x, buf= 0x%x, dataLen= %d)",
2107         &out,
2108         buffer,
2109         dataLength);
2110 
2111     if(buffer == NULL)
2112     {
2113         WEBRTC_TRACE(kTraceError, kTraceFile, _id, "buffer NULL");
2114     }
2115 
2116     if(!out.Write(buffer, dataLength))
2117     {
2118         return -1;
2119     }
2120 
2121     _bytesWritten += dataLength;
2122     return dataLength;
2123 }
2124 
codec_info(CodecInst & codecInst)2125 int32_t ModuleFileUtility::codec_info(CodecInst& codecInst)
2126 {
2127     WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
2128                  "ModuleFileUtility::codec_info(codecInst= 0x%x)", &codecInst);
2129 
2130     if(!_reading && !_writing)
2131     {
2132         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2133                      "CodecInst: not currently reading audio file!");
2134         return -1;
2135     }
2136     memcpy(&codecInst,&codec_info_,sizeof(CodecInst));
2137     return 0;
2138 }
2139 
set_codec_info(const CodecInst & codecInst)2140 int32_t ModuleFileUtility::set_codec_info(const CodecInst& codecInst)
2141 {
2142 
2143     _codecId = kCodecNoCodec;
2144     if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0)
2145     {
2146         _codecId = kCodecPcmu;
2147     }
2148     else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0)
2149     {
2150         _codecId = kCodecPcma;
2151     }
2152     else if(STR_CASE_CMP(codecInst.plname, "L16") == 0)
2153     {
2154         if(codecInst.plfreq == 8000)
2155         {
2156             _codecId = kCodecL16_8Khz;
2157         }
2158         else if(codecInst.plfreq == 16000)
2159         {
2160             _codecId = kCodecL16_16kHz;
2161         }
2162         else if(codecInst.plfreq == 32000)
2163         {
2164             _codecId = kCodecL16_32Khz;
2165         }
2166     }
2167 #ifdef WEBRTC_CODEC_AMR
2168     else if(STR_CASE_CMP(codecInst.plname, "amr") == 0)
2169     {
2170         _codecId = kCodecAmr;
2171     }
2172 #endif
2173 #ifdef WEBRTC_CODEC_AMRWB
2174     else if(STR_CASE_CMP(codecInst.plname, "amr-wb") == 0)
2175     {
2176         _codecId = kCodecAmrWb;
2177     }
2178 #endif
2179 #ifdef WEBRTC_CODEC_ILBC
2180     else if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0)
2181     {
2182         if(codecInst.pacsize == 160)
2183         {
2184             _codecId = kCodecIlbc20Ms;
2185         }
2186         else if(codecInst.pacsize == 240)
2187         {
2188             _codecId = kCodecIlbc30Ms;
2189         }
2190     }
2191 #endif
2192 #if(defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
2193     else if(STR_CASE_CMP(codecInst.plname, "isac") == 0)
2194     {
2195         if(codecInst.plfreq == 16000)
2196         {
2197             _codecId = kCodecIsac;
2198         }
2199         else if(codecInst.plfreq == 32000)
2200         {
2201             _codecId = kCodecIsacSwb;
2202         }
2203     }
2204 #endif
2205 #ifdef WEBRTC_CODEC_ISACLC
2206     else if(STR_CASE_CMP(codecInst.plname, "isaclc") == 0)
2207     {
2208         _codecId = kCodecIsacLc;
2209     }
2210 #endif
2211 #ifdef WEBRTC_CODEC_G722
2212     else if(STR_CASE_CMP(codecInst.plname, "G722") == 0)
2213     {
2214         _codecId = kCodecG722;
2215     }
2216 #endif
2217     else if(STR_CASE_CMP(codecInst.plname, "G7221") == 0)
2218     {
2219 #ifdef WEBRTC_CODEC_G722_1
2220         if(codecInst.plfreq == 16000)
2221         {
2222             if(codecInst.rate == 16000)
2223             {
2224                 _codecId = kCodecG722_1_16Kbps;
2225             }
2226             else if(codecInst.rate == 24000)
2227             {
2228                 _codecId = kCodecG722_1_24Kbps;
2229             }
2230             else if(codecInst.rate == 32000)
2231             {
2232                 _codecId = kCodecG722_1_32Kbps;
2233             }
2234         }
2235 #endif
2236 #ifdef WEBRTC_CODEC_G722_1C
2237         if(codecInst.plfreq == 32000)
2238         {
2239             if(codecInst.rate == 48000)
2240             {
2241                 _codecId = kCodecG722_1c_48;
2242             }
2243             else if(codecInst.rate == 32000)
2244             {
2245                 _codecId = kCodecG722_1c_32;
2246             }
2247             else if(codecInst.rate == 24000)
2248             {
2249                 _codecId = kCodecG722_1c_24;
2250             }
2251         }
2252 #endif
2253     }
2254 #ifdef WEBRTC_CODEC_G726
2255     else if(STR_CASE_CMP(codecInst.plname, "G726-40") == 0)
2256     {
2257         _codecId = kCodecG726_40;
2258     }
2259     else if(STR_CASE_CMP(codecInst.plname, "G726-32") == 0)
2260     {
2261         _codecId = kCodecG726_24;
2262     }
2263     else if(STR_CASE_CMP(codecInst.plname, "G726-24") == 0)
2264     {
2265         _codecId = kCodecG726_32;
2266     }
2267     else if(STR_CASE_CMP(codecInst.plname, "G726-16") == 0)
2268     {
2269         _codecId = kCodecG726_16;
2270     }
2271 #endif
2272 #ifdef WEBRTC_CODEC_G729
2273     else if(STR_CASE_CMP(codecInst.plname, "G729") == 0)
2274     {
2275         _codecId = kCodecG729;
2276     }
2277 #endif
2278 #ifdef WEBRTC_CODEC_G729_1
2279     else if(STR_CASE_CMP(codecInst.plname, "G7291") == 0)
2280     {
2281         _codecId = kCodecG729_1;
2282     }
2283 #endif
2284 #ifdef WEBRTC_CODEC_SPEEX
2285     else if(STR_CASE_CMP(codecInst.plname, "speex") == 0)
2286     {
2287         if(codecInst.plfreq == 8000)
2288         {
2289             _codecId = kCodecSpeex8Khz;
2290         }
2291         else if(codecInst.plfreq == 16000)
2292         {
2293             _codecId = kCodecSpeex16Khz;
2294         }
2295     }
2296 #endif
2297     if(_codecId == kCodecNoCodec)
2298     {
2299         return -1;
2300     }
2301     memcpy(&codec_info_, &codecInst, sizeof(CodecInst));
2302     return 0;
2303 }
2304 
FileDurationMs(const char * fileName,const FileFormats fileFormat,const uint32_t freqInHz)2305 int32_t ModuleFileUtility::FileDurationMs(const char* fileName,
2306                                           const FileFormats fileFormat,
2307                                           const uint32_t freqInHz)
2308 {
2309 
2310     if(fileName == NULL)
2311     {
2312         WEBRTC_TRACE(kTraceError, kTraceFile, _id, "filename NULL");
2313         return -1;
2314     }
2315 
2316     int32_t time_in_ms = -1;
2317     struct stat file_size;
2318     if(stat(fileName,&file_size) == -1)
2319     {
2320         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2321                      "failed to retrieve file size with stat!");
2322         return -1;
2323     }
2324     FileWrapper* inStreamObj = FileWrapper::Create();
2325     if(inStreamObj == NULL)
2326     {
2327         WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
2328                      "failed to create InStream object!");
2329         return -1;
2330     }
2331     if(inStreamObj->OpenFile(fileName, true) == -1)
2332     {
2333         delete inStreamObj;
2334         WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2335                      "failed to open file %s!", fileName);
2336         return -1;
2337     }
2338 
2339     switch (fileFormat)
2340     {
2341         case kFileFormatWavFile:
2342         {
2343             if(ReadWavHeader(*inStreamObj) == -1)
2344             {
2345                 WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2346                              "failed to read WAV file header!");
2347                 return -1;
2348             }
2349             time_in_ms = ((file_size.st_size - 44) /
2350                           (_wavFormatObj.nAvgBytesPerSec/1000));
2351             break;
2352         }
2353         case kFileFormatPcm16kHzFile:
2354         {
2355             // 16 samples per ms. 2 bytes per sample.
2356             int32_t denominator = 16*2;
2357             time_in_ms = (file_size.st_size)/denominator;
2358             break;
2359         }
2360         case kFileFormatPcm8kHzFile:
2361         {
2362             // 8 samples per ms. 2 bytes per sample.
2363             int32_t denominator = 8*2;
2364             time_in_ms = (file_size.st_size)/denominator;
2365             break;
2366         }
2367         case kFileFormatCompressedFile:
2368         {
2369             int32_t cnt = 0;
2370             int32_t read_len = 0;
2371             char buf[64];
2372             do
2373             {
2374                 read_len = inStreamObj->Read(&buf[cnt++], 1);
2375                 if(read_len != 1)
2376                 {
2377                     return -1;
2378                 }
2379             } while ((buf[cnt-1] != '\n') && (64 > cnt));
2380 
2381             if(cnt == 64)
2382             {
2383                 return -1;
2384             }
2385             else
2386             {
2387                 buf[cnt] = 0;
2388             }
2389 #ifdef WEBRTC_CODEC_AMR
2390             if(!strcmp("#!AMR\n", buf))
2391             {
2392                 uint8_t dummy;
2393                 read_len = inStreamObj->Read(&dummy, 1);
2394                 if(read_len != 1)
2395                 {
2396                     return -1;
2397                 }
2398 
2399                 int16_t AMRMode = (dummy>>3)&0xF;
2400 
2401                 // TODO (hellner): use tables instead of hardcoding like this!
2402                 //                 Additionally, this calculation does not
2403                 //                 take octet alignment into consideration.
2404                 switch (AMRMode)
2405                 {
2406                         // Mode 0: 4.75 kbit/sec -> 95 bits per 20 ms frame.
2407                         // 20 ms = 95 bits ->
2408                         // file size in bytes * 8 / 95 is the number of
2409                         // 20 ms frames in the file ->
2410                         // time_in_ms = file size * 8 / 95 * 20
2411                     case 0:
2412                         time_in_ms = ((file_size.st_size)*160)/95;
2413                         break;
2414                         // Mode 1: 5.15 kbit/sec -> 103 bits per 20 ms frame.
2415                     case 1:
2416                         time_in_ms = ((file_size.st_size)*160)/103;
2417                         break;
2418                         // Mode 2: 5.90 kbit/sec -> 118 bits per 20 ms frame.
2419                     case 2:
2420                         time_in_ms = ((file_size.st_size)*160)/118;
2421                         break;
2422                         // Mode 3: 6.70 kbit/sec -> 134 bits per 20 ms frame.
2423                     case 3:
2424                         time_in_ms = ((file_size.st_size)*160)/134;
2425                         break;
2426                         // Mode 4: 7.40 kbit/sec -> 148 bits per 20 ms frame.
2427                     case 4:
2428                         time_in_ms = ((file_size.st_size)*160)/148;
2429                         break;
2430                         // Mode 5: 7.95 bit/sec -> 159 bits per 20 ms frame.
2431                     case 5:
2432                         time_in_ms = ((file_size.st_size)*160)/159;
2433                         break;
2434                         // Mode 6: 10.2 bit/sec -> 204 bits per 20 ms frame.
2435                     case 6:
2436                         time_in_ms = ((file_size.st_size)*160)/204;
2437                         break;
2438                         // Mode 7: 12.2 bit/sec -> 244 bits per 20 ms frame.
2439                     case 7:
2440                         time_in_ms = ((file_size.st_size)*160)/244;
2441                         break;
2442                         // Mode 8: SID Mode -> 39 bits per 20 ms frame.
2443                     case 8:
2444                         time_in_ms = ((file_size.st_size)*160)/39;
2445                         break;
2446                     default:
2447                         break;
2448                 }
2449             }
2450 #endif
2451 #ifdef WEBRTC_CODEC_AMRWB
2452             if(!strcmp("#!AMRWB\n", buf))
2453             {
2454                 uint8_t dummy;
2455                 read_len = inStreamObj->Read(&dummy, 1);
2456                 if(read_len != 1)
2457                 {
2458                     return -1;
2459                 }
2460 
2461                 // TODO (hellner): use tables instead of hardcoding like this!
2462                 int16_t AMRWBMode = (dummy>>3)&0xF;
2463                 switch(AMRWBMode)
2464                 {
2465                         // Mode 0: 6.6 kbit/sec -> 132 bits per 20 ms frame.
2466                     case 0:
2467                         time_in_ms = ((file_size.st_size)*160)/132;
2468                         break;
2469                         // Mode 1: 8.85 kbit/sec -> 177 bits per 20 ms frame.
2470                     case 1:
2471                         time_in_ms = ((file_size.st_size)*160)/177;
2472                         break;
2473                         // Mode 2: 12.65 kbit/sec -> 253 bits per 20 ms frame.
2474                     case 2:
2475                         time_in_ms = ((file_size.st_size)*160)/253;
2476                         break;
2477                         // Mode 3: 14.25 kbit/sec -> 285 bits per 20 ms frame.
2478                     case 3:
2479                         time_in_ms = ((file_size.st_size)*160)/285;
2480                         break;
2481                         // Mode 4: 15.85 kbit/sec -> 317 bits per 20 ms frame.
2482                     case 4:
2483                         time_in_ms = ((file_size.st_size)*160)/317;
2484                         break;
2485                         // Mode 5: 18.25 kbit/sec -> 365 bits per 20 ms frame.
2486                     case 5:
2487                         time_in_ms = ((file_size.st_size)*160)/365;
2488                         break;
2489                         // Mode 6: 19.85 kbit/sec -> 397 bits per 20 ms frame.
2490                     case 6:
2491                         time_in_ms = ((file_size.st_size)*160)/397;
2492                         break;
2493                         // Mode 7: 23.05 kbit/sec -> 461 bits per 20 ms frame.
2494                     case 7:
2495                         time_in_ms = ((file_size.st_size)*160)/461;
2496                         break;
2497                         // Mode 8: 23.85 kbit/sec -> 477 bits per 20 ms frame.
2498                     case 8:
2499                         time_in_ms = ((file_size.st_size)*160)/477;
2500                         break;
2501                     default:
2502                         delete inStreamObj;
2503                         return -1;
2504                 }
2505             }
2506 #endif
2507 #ifdef WEBRTC_CODEC_ILBC
2508             if(!strcmp("#!iLBC20\n", buf))
2509             {
2510                 // 20 ms is 304 bits
2511                 time_in_ms = ((file_size.st_size)*160)/304;
2512                 break;
2513             }
2514             if(!strcmp("#!iLBC30\n", buf))
2515             {
2516                 // 30 ms takes 400 bits.
2517                 // file size in bytes * 8 / 400 is the number of
2518                 // 30 ms frames in the file ->
2519                 // time_in_ms = file size * 8 / 400 * 30
2520                 time_in_ms = ((file_size.st_size)*240)/400;
2521                 break;
2522             }
2523 #endif
2524             break;
2525         }
2526         case kFileFormatPreencodedFile:
2527         {
2528             WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2529                          "cannot determine duration of Pre-Encoded file!");
2530             break;
2531         }
2532         default:
2533             WEBRTC_TRACE(kTraceError, kTraceFile, _id,
2534                          "unsupported file format %d!", fileFormat);
2535             break;
2536     }
2537     inStreamObj->CloseFile();
2538     delete inStreamObj;
2539     return time_in_ms;
2540 }
2541 
PlayoutPositionMs()2542 uint32_t ModuleFileUtility::PlayoutPositionMs()
2543 {
2544     WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
2545                "ModuleFileUtility::PlayoutPosition()");
2546 
2547     if(_reading)
2548     {
2549         return _playoutPositionMs;
2550     }
2551     else
2552     {
2553         return 0;
2554     }
2555 }
2556 }  // namespace webrtc
2557