LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/media_file - media_file_utility.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 551 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13