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