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