Home | History | Annotate | Download | only in source
      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 {
     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 
     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
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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