| Index: webrtc/modules/media_file/source/media_file_utility.cc
|
| diff --git a/webrtc/modules/media_file/source/media_file_utility.cc b/webrtc/modules/media_file/source/media_file_utility.cc
|
| deleted file mode 100644
|
| index fad7fe40794f79ea95914a7cf6b73c5575fcbefd..0000000000000000000000000000000000000000
|
| --- a/webrtc/modules/media_file/source/media_file_utility.cc
|
| +++ /dev/null
|
| @@ -1,1656 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#include "webrtc/modules/media_file/source/media_file_utility.h"
|
| -
|
| -#include <assert.h>
|
| -#include <sys/stat.h>
|
| -#include <sys/types.h>
|
| -#include <limits>
|
| -
|
| -#include "webrtc/base/format_macros.h"
|
| -#include "webrtc/common_audio/wav_header.h"
|
| -#include "webrtc/common_types.h"
|
| -#include "webrtc/engine_configurations.h"
|
| -#include "webrtc/modules/include/module_common_types.h"
|
| -#include "webrtc/system_wrappers/include/file_wrapper.h"
|
| -#include "webrtc/system_wrappers/include/trace.h"
|
| -
|
| -namespace {
|
| -
|
| -// First 16 bytes the WAVE header. ckID should be "RIFF", wave_ckID should be
|
| -// "WAVE" and ckSize is the chunk size (4 + n)
|
| -struct WAVE_RIFF_header
|
| -{
|
| - int8_t ckID[4];
|
| - int32_t ckSize;
|
| - int8_t wave_ckID[4];
|
| -};
|
| -
|
| -// First 8 byte of the format chunk. fmt_ckID should be "fmt ". fmt_ckSize is
|
| -// the chunk size (16, 18 or 40 byte)
|
| -struct WAVE_CHUNK_header
|
| -{
|
| - int8_t fmt_ckID[4];
|
| - int32_t fmt_ckSize;
|
| -};
|
| -} // unnamed namespace
|
| -
|
| -namespace webrtc {
|
| -ModuleFileUtility::ModuleFileUtility(const int32_t id)
|
| - : _wavFormatObj(),
|
| - _dataSize(0),
|
| - _readSizeBytes(0),
|
| - _id(id),
|
| - _stopPointInMs(0),
|
| - _startPointInMs(0),
|
| - _playoutPositionMs(0),
|
| - _bytesWritten(0),
|
| - codec_info_(),
|
| - _codecId(kCodecNoCodec),
|
| - _bytesPerSample(0),
|
| - _readPos(0),
|
| - _reading(false),
|
| - _writing(false),
|
| - _tempData() {
|
| - WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
|
| - "ModuleFileUtility::ModuleFileUtility()");
|
| - memset(&codec_info_,0,sizeof(CodecInst));
|
| - codec_info_.pltype = -1;
|
| -}
|
| -
|
| -ModuleFileUtility::~ModuleFileUtility()
|
| -{
|
| - WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
|
| - "ModuleFileUtility::~ModuleFileUtility()");
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::ReadWavHeader(InStream& wav)
|
| -{
|
| - WAVE_RIFF_header RIFFheaderObj;
|
| - WAVE_CHUNK_header CHUNKheaderObj;
|
| - // TODO (hellner): tmpStr and tmpStr2 seems unnecessary here.
|
| - char tmpStr[6] = "FOUR";
|
| - unsigned char tmpStr2[4];
|
| - int32_t i, len;
|
| - bool dataFound = false;
|
| - bool fmtFound = false;
|
| - int8_t dummyRead;
|
| -
|
| -
|
| - _dataSize = 0;
|
| - len = wav.Read(&RIFFheaderObj, sizeof(WAVE_RIFF_header));
|
| - if(len != sizeof(WAVE_RIFF_header))
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "Not a wave file (too short)");
|
| - return -1;
|
| - }
|
| -
|
| - for (i = 0; i < 4; i++)
|
| - {
|
| - tmpStr[i] = RIFFheaderObj.ckID[i];
|
| - }
|
| - if(strcmp(tmpStr, "RIFF") != 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "Not a wave file (does not have RIFF)");
|
| - return -1;
|
| - }
|
| - for (i = 0; i < 4; i++)
|
| - {
|
| - tmpStr[i] = RIFFheaderObj.wave_ckID[i];
|
| - }
|
| - if(strcmp(tmpStr, "WAVE") != 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "Not a wave file (does not have WAVE)");
|
| - return -1;
|
| - }
|
| -
|
| - len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header));
|
| -
|
| - // WAVE files are stored in little endian byte order. Make sure that the
|
| - // data can be read on big endian as well.
|
| - // TODO (hellner): little endian to system byte order should be done in
|
| - // in a subroutine.
|
| - memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4);
|
| - CHUNKheaderObj.fmt_ckSize =
|
| - (int32_t) ((uint32_t) tmpStr2[0] +
|
| - (((uint32_t)tmpStr2[1])<<8) +
|
| - (((uint32_t)tmpStr2[2])<<16) +
|
| - (((uint32_t)tmpStr2[3])<<24));
|
| -
|
| - memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4);
|
| -
|
| - while ((len == sizeof(WAVE_CHUNK_header)) && (!fmtFound || !dataFound))
|
| - {
|
| - if(strcmp(tmpStr, "fmt ") == 0)
|
| - {
|
| - len = wav.Read(&_wavFormatObj, sizeof(WAVE_FMTINFO_header));
|
| -
|
| - memcpy(tmpStr2, &_wavFormatObj.formatTag, 2);
|
| - _wavFormatObj.formatTag =
|
| - (uint32_t)tmpStr2[0] + (((uint32_t)tmpStr2[1])<<8);
|
| - memcpy(tmpStr2, &_wavFormatObj.nChannels, 2);
|
| - _wavFormatObj.nChannels =
|
| - (int16_t) ((uint32_t)tmpStr2[0] +
|
| - (((uint32_t)tmpStr2[1])<<8));
|
| - memcpy(tmpStr2, &_wavFormatObj.nSamplesPerSec, 4);
|
| - _wavFormatObj.nSamplesPerSec =
|
| - (int32_t) ((uint32_t)tmpStr2[0] +
|
| - (((uint32_t)tmpStr2[1])<<8) +
|
| - (((uint32_t)tmpStr2[2])<<16) +
|
| - (((uint32_t)tmpStr2[3])<<24));
|
| - memcpy(tmpStr2, &_wavFormatObj.nAvgBytesPerSec, 4);
|
| - _wavFormatObj.nAvgBytesPerSec =
|
| - (int32_t) ((uint32_t)tmpStr2[0] +
|
| - (((uint32_t)tmpStr2[1])<<8) +
|
| - (((uint32_t)tmpStr2[2])<<16) +
|
| - (((uint32_t)tmpStr2[3])<<24));
|
| - memcpy(tmpStr2, &_wavFormatObj.nBlockAlign, 2);
|
| - _wavFormatObj.nBlockAlign =
|
| - (int16_t) ((uint32_t)tmpStr2[0] +
|
| - (((uint32_t)tmpStr2[1])<<8));
|
| - memcpy(tmpStr2, &_wavFormatObj.nBitsPerSample, 2);
|
| - _wavFormatObj.nBitsPerSample =
|
| - (int16_t) ((uint32_t)tmpStr2[0] +
|
| - (((uint32_t)tmpStr2[1])<<8));
|
| -
|
| - for (i = 0;
|
| - i < (CHUNKheaderObj.fmt_ckSize -
|
| - (int32_t)sizeof(WAVE_FMTINFO_header));
|
| - i++)
|
| - {
|
| - len = wav.Read(&dummyRead, 1);
|
| - if(len != 1)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "File corrupted, reached EOF (reading fmt)");
|
| - return -1;
|
| - }
|
| - }
|
| - fmtFound = true;
|
| - }
|
| - else if(strcmp(tmpStr, "data") == 0)
|
| - {
|
| - _dataSize = CHUNKheaderObj.fmt_ckSize;
|
| - dataFound = true;
|
| - break;
|
| - }
|
| - else
|
| - {
|
| - for (i = 0; i < (CHUNKheaderObj.fmt_ckSize); i++)
|
| - {
|
| - len = wav.Read(&dummyRead, 1);
|
| - if(len != 1)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "File corrupted, reached EOF (reading other)");
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| -
|
| - len = wav.Read(&CHUNKheaderObj, sizeof(WAVE_CHUNK_header));
|
| -
|
| - memcpy(tmpStr2, &CHUNKheaderObj.fmt_ckSize, 4);
|
| - CHUNKheaderObj.fmt_ckSize =
|
| - (int32_t) ((uint32_t)tmpStr2[0] +
|
| - (((uint32_t)tmpStr2[1])<<8) +
|
| - (((uint32_t)tmpStr2[2])<<16) +
|
| - (((uint32_t)tmpStr2[3])<<24));
|
| -
|
| - memcpy(tmpStr, CHUNKheaderObj.fmt_ckID, 4);
|
| - }
|
| -
|
| - // Either a proper format chunk has been read or a data chunk was come
|
| - // across.
|
| - if( (_wavFormatObj.formatTag != kWavFormatPcm) &&
|
| - (_wavFormatObj.formatTag != kWavFormatALaw) &&
|
| - (_wavFormatObj.formatTag != kWavFormatMuLaw))
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "Coding formatTag value=%d not supported!",
|
| - _wavFormatObj.formatTag);
|
| - return -1;
|
| - }
|
| - if((_wavFormatObj.nChannels < 1) ||
|
| - (_wavFormatObj.nChannels > 2))
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "nChannels value=%d not supported!",
|
| - _wavFormatObj.nChannels);
|
| - return -1;
|
| - }
|
| -
|
| - if((_wavFormatObj.nBitsPerSample != 8) &&
|
| - (_wavFormatObj.nBitsPerSample != 16))
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "nBitsPerSample value=%d not supported!",
|
| - _wavFormatObj.nBitsPerSample);
|
| - return -1;
|
| - }
|
| -
|
| - // Calculate the number of bytes that 10 ms of audio data correspond to.
|
| - if(_wavFormatObj.formatTag == kWavFormatPcm)
|
| - {
|
| - // TODO (hellner): integer division for 22050 and 11025 would yield
|
| - // the same result as the else statement. Remove those
|
| - // special cases?
|
| - if(_wavFormatObj.nSamplesPerSec == 44100)
|
| - {
|
| - _readSizeBytes = 440 * _wavFormatObj.nChannels *
|
| - (_wavFormatObj.nBitsPerSample / 8);
|
| - } else if(_wavFormatObj.nSamplesPerSec == 22050) {
|
| - _readSizeBytes = 220 * _wavFormatObj.nChannels *
|
| - (_wavFormatObj.nBitsPerSample / 8);
|
| - } else if(_wavFormatObj.nSamplesPerSec == 11025) {
|
| - _readSizeBytes = 110 * _wavFormatObj.nChannels *
|
| - (_wavFormatObj.nBitsPerSample / 8);
|
| - } else {
|
| - _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) *
|
| - _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8);
|
| - }
|
| -
|
| - } else {
|
| - _readSizeBytes = (_wavFormatObj.nSamplesPerSec/100) *
|
| - _wavFormatObj.nChannels * (_wavFormatObj.nBitsPerSample / 8);
|
| - }
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitWavCodec(uint32_t samplesPerSec,
|
| - uint32_t channels,
|
| - uint32_t bitsPerSample,
|
| - uint32_t formatTag)
|
| -{
|
| - codec_info_.pltype = -1;
|
| - codec_info_.plfreq = samplesPerSec;
|
| - codec_info_.channels = channels;
|
| - codec_info_.rate = bitsPerSample * samplesPerSec;
|
| -
|
| - // Calculate the packet size for 10ms frames
|
| - switch(formatTag)
|
| - {
|
| - case kWavFormatALaw:
|
| - strcpy(codec_info_.plname, "PCMA");
|
| - _codecId = kCodecPcma;
|
| - codec_info_.pltype = 8;
|
| - codec_info_.pacsize = codec_info_.plfreq / 100;
|
| - break;
|
| - case kWavFormatMuLaw:
|
| - strcpy(codec_info_.plname, "PCMU");
|
| - _codecId = kCodecPcmu;
|
| - codec_info_.pltype = 0;
|
| - codec_info_.pacsize = codec_info_.plfreq / 100;
|
| - break;
|
| - case kWavFormatPcm:
|
| - codec_info_.pacsize = (bitsPerSample * (codec_info_.plfreq / 100)) / 8;
|
| - if(samplesPerSec == 8000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - _codecId = kCodecL16_8Khz;
|
| - }
|
| - else if(samplesPerSec == 16000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - _codecId = kCodecL16_16kHz;
|
| - }
|
| - else if(samplesPerSec == 32000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - _codecId = kCodecL16_32Khz;
|
| - }
|
| - // Set the packet size for "odd" sampling frequencies so that it
|
| - // properly corresponds to _readSizeBytes.
|
| - else if(samplesPerSec == 11025)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - _codecId = kCodecL16_16kHz;
|
| - codec_info_.pacsize = 110;
|
| - codec_info_.plfreq = 11000;
|
| - }
|
| - else if(samplesPerSec == 22050)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - _codecId = kCodecL16_16kHz;
|
| - codec_info_.pacsize = 220;
|
| - codec_info_.plfreq = 22000;
|
| - }
|
| - else if(samplesPerSec == 44100)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - _codecId = kCodecL16_16kHz;
|
| - codec_info_.pacsize = 440;
|
| - codec_info_.plfreq = 44000;
|
| - }
|
| - else if(samplesPerSec == 48000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - _codecId = kCodecL16_16kHz;
|
| - codec_info_.pacsize = 480;
|
| - codec_info_.plfreq = 48000;
|
| - }
|
| - else
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "Unsupported PCM frequency!");
|
| - return -1;
|
| - }
|
| - break;
|
| - default:
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "unknown WAV format TAG!");
|
| - return -1;
|
| - break;
|
| - }
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitWavReading(InStream& wav,
|
| - const uint32_t start,
|
| - const uint32_t stop)
|
| -{
|
| -
|
| - _reading = false;
|
| -
|
| - if(ReadWavHeader(wav) == -1)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "failed to read WAV header!");
|
| - return -1;
|
| - }
|
| -
|
| - _playoutPositionMs = 0;
|
| - _readPos = 0;
|
| -
|
| - if(start > 0)
|
| - {
|
| - uint8_t dummy[WAV_MAX_BUFFER_SIZE];
|
| - int32_t readLength;
|
| - if(_readSizeBytes <= WAV_MAX_BUFFER_SIZE)
|
| - {
|
| - while (_playoutPositionMs < start)
|
| - {
|
| - readLength = wav.Read(dummy, _readSizeBytes);
|
| - if(readLength == _readSizeBytes)
|
| - {
|
| - _readPos += readLength;
|
| - _playoutPositionMs += 10;
|
| - }
|
| - else // Must have reached EOF before start position!
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "InitWavReading(), EOF before start position");
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| - else
|
| - {
|
| - return -1;
|
| - }
|
| - }
|
| - if( InitWavCodec(_wavFormatObj.nSamplesPerSec, _wavFormatObj.nChannels,
|
| - _wavFormatObj.nBitsPerSample,
|
| - _wavFormatObj.formatTag) != 0)
|
| - {
|
| - return -1;
|
| - }
|
| - _bytesPerSample = _wavFormatObj.nBitsPerSample / 8;
|
| -
|
| -
|
| - _startPointInMs = start;
|
| - _stopPointInMs = stop;
|
| - _reading = true;
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::ReadWavDataAsMono(
|
| - InStream& wav,
|
| - int8_t* outData,
|
| - const size_t bufferSize)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::ReadWavDataAsMono(wav= 0x%x, outData= 0x%d, "
|
| - "bufSize= %" PRIuS ")",
|
| - &wav,
|
| - outData,
|
| - bufferSize);
|
| -
|
| - // The number of bytes that should be read from file.
|
| - const uint32_t totalBytesNeeded = _readSizeBytes;
|
| - // The number of bytes that will be written to outData.
|
| - const uint32_t bytesRequested = (codec_info_.channels == 2) ?
|
| - totalBytesNeeded >> 1 : totalBytesNeeded;
|
| - if(bufferSize < bytesRequested)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsMono: output buffer is too short!");
|
| - return -1;
|
| - }
|
| - if(outData == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsMono: output buffer NULL!");
|
| - return -1;
|
| - }
|
| -
|
| - if(!_reading)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsMono: no longer reading file.");
|
| - return -1;
|
| - }
|
| -
|
| - int32_t bytesRead = ReadWavData(
|
| - wav,
|
| - (codec_info_.channels == 2) ? _tempData : (uint8_t*)outData,
|
| - totalBytesNeeded);
|
| - if(bytesRead == 0)
|
| - {
|
| - return 0;
|
| - }
|
| - if(bytesRead < 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsMono: failed to read data from WAV file.");
|
| - return -1;
|
| - }
|
| - // Output data is should be mono.
|
| - if(codec_info_.channels == 2)
|
| - {
|
| - for (uint32_t i = 0; i < bytesRequested / _bytesPerSample; i++)
|
| - {
|
| - // Sample value is the average of left and right buffer rounded to
|
| - // closest integer value. Note samples can be either 1 or 2 byte.
|
| - if(_bytesPerSample == 1)
|
| - {
|
| - _tempData[i] = ((_tempData[2 * i] + _tempData[(2 * i) + 1] +
|
| - 1) >> 1);
|
| - }
|
| - else
|
| - {
|
| - int16_t* sampleData = (int16_t*) _tempData;
|
| - sampleData[i] = ((sampleData[2 * i] + sampleData[(2 * i) + 1] +
|
| - 1) >> 1);
|
| - }
|
| - }
|
| - memcpy(outData, _tempData, bytesRequested);
|
| - }
|
| - return bytesRequested;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::ReadWavDataAsStereo(
|
| - InStream& wav,
|
| - int8_t* outDataLeft,
|
| - int8_t* outDataRight,
|
| - const size_t bufferSize)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::ReadWavDataAsStereo(wav= 0x%x, outLeft= 0x%x, "
|
| - "outRight= 0x%x, bufSize= %" PRIuS ")",
|
| - &wav,
|
| - outDataLeft,
|
| - outDataRight,
|
| - bufferSize);
|
| -
|
| - if((outDataLeft == NULL) ||
|
| - (outDataRight == NULL))
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsMono: an input buffer is NULL!");
|
| - return -1;
|
| - }
|
| - if(codec_info_.channels != 2)
|
| - {
|
| - WEBRTC_TRACE(
|
| - kTraceError,
|
| - kTraceFile,
|
| - _id,
|
| - "ReadWavDataAsStereo: WAV file does not contain stereo data!");
|
| - return -1;
|
| - }
|
| - if(! _reading)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsStereo: no longer reading file.");
|
| - return -1;
|
| - }
|
| -
|
| - // The number of bytes that should be read from file.
|
| - const uint32_t totalBytesNeeded = _readSizeBytes;
|
| - // The number of bytes that will be written to the left and the right
|
| - // buffers.
|
| - const uint32_t bytesRequested = totalBytesNeeded >> 1;
|
| - if(bufferSize < bytesRequested)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavData: Output buffers are too short!");
|
| - assert(false);
|
| - return -1;
|
| - }
|
| -
|
| - int32_t bytesRead = ReadWavData(wav, _tempData, totalBytesNeeded);
|
| - if(bytesRead <= 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsStereo: failed to read data from WAV file.");
|
| - return -1;
|
| - }
|
| -
|
| - // Turn interleaved audio to left and right buffer. Note samples can be
|
| - // either 1 or 2 bytes
|
| - if(_bytesPerSample == 1)
|
| - {
|
| - for (uint32_t i = 0; i < bytesRequested; i++)
|
| - {
|
| - outDataLeft[i] = _tempData[2 * i];
|
| - outDataRight[i] = _tempData[(2 * i) + 1];
|
| - }
|
| - }
|
| - else if(_bytesPerSample == 2)
|
| - {
|
| - int16_t* sampleData = reinterpret_cast<int16_t*>(_tempData);
|
| - int16_t* outLeft = reinterpret_cast<int16_t*>(outDataLeft);
|
| - int16_t* outRight = reinterpret_cast<int16_t*>(
|
| - outDataRight);
|
| -
|
| - // Bytes requested to samples requested.
|
| - uint32_t sampleCount = bytesRequested >> 1;
|
| - for (uint32_t i = 0; i < sampleCount; i++)
|
| - {
|
| - outLeft[i] = sampleData[2 * i];
|
| - outRight[i] = sampleData[(2 * i) + 1];
|
| - }
|
| - } else {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavStereoData: unsupported sample size %d!",
|
| - _bytesPerSample);
|
| - assert(false);
|
| - return -1;
|
| - }
|
| - return bytesRequested;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::ReadWavData(
|
| - InStream& wav,
|
| - uint8_t* buffer,
|
| - const uint32_t dataLengthInBytes)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::ReadWavData(wav= 0x%x, buffer= 0x%x, dataLen= %ld)",
|
| - &wav,
|
| - buffer,
|
| - dataLengthInBytes);
|
| -
|
| -
|
| - if(buffer == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadWavDataAsMono: output buffer NULL!");
|
| - return -1;
|
| - }
|
| -
|
| - // Make sure that a read won't return too few samples.
|
| - // TODO (hellner): why not read the remaining bytes needed from the start
|
| - // of the file?
|
| - if((_dataSize - _readPos) < (int32_t)dataLengthInBytes)
|
| - {
|
| - // Rewind() being -1 may be due to the file not supposed to be looped.
|
| - if(wav.Rewind() == -1)
|
| - {
|
| - _reading = false;
|
| - return 0;
|
| - }
|
| - if(InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1)
|
| - {
|
| - _reading = false;
|
| - return -1;
|
| - }
|
| - }
|
| -
|
| - int32_t bytesRead = wav.Read(buffer, dataLengthInBytes);
|
| - if(bytesRead < 0)
|
| - {
|
| - _reading = false;
|
| - return -1;
|
| - }
|
| -
|
| - // This should never happen due to earlier sanity checks.
|
| - // TODO (hellner): change to an assert and fail here since this should
|
| - // never happen...
|
| - if(bytesRead < (int32_t)dataLengthInBytes)
|
| - {
|
| - if((wav.Rewind() == -1) ||
|
| - (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1))
|
| - {
|
| - _reading = false;
|
| - return -1;
|
| - }
|
| - else
|
| - {
|
| - bytesRead = wav.Read(buffer, dataLengthInBytes);
|
| - if(bytesRead < (int32_t)dataLengthInBytes)
|
| - {
|
| - _reading = false;
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| -
|
| - _readPos += bytesRead;
|
| -
|
| - // TODO (hellner): Why is dataLengthInBytes let dictate the number of bytes
|
| - // to read when exactly 10ms should be read?!
|
| - _playoutPositionMs += 10;
|
| - if((_stopPointInMs > 0) &&
|
| - (_playoutPositionMs >= _stopPointInMs))
|
| - {
|
| - if((wav.Rewind() == -1) ||
|
| - (InitWavReading(wav, _startPointInMs, _stopPointInMs) == -1))
|
| - {
|
| - _reading = false;
|
| - }
|
| - }
|
| - return bytesRead;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitWavWriting(OutStream& wav,
|
| - const CodecInst& codecInst)
|
| -{
|
| -
|
| - if(set_codec_info(codecInst) != 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "codecInst identifies unsupported codec!");
|
| - return -1;
|
| - }
|
| - _writing = false;
|
| - uint32_t channels = (codecInst.channels == 0) ?
|
| - 1 : codecInst.channels;
|
| -
|
| - if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0)
|
| - {
|
| - _bytesPerSample = 1;
|
| - if(WriteWavHeader(wav, 8000, _bytesPerSample, channels,
|
| - kWavFormatMuLaw, 0) == -1)
|
| - {
|
| - return -1;
|
| - }
|
| - }else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0)
|
| - {
|
| - _bytesPerSample = 1;
|
| - if(WriteWavHeader(wav, 8000, _bytesPerSample, channels, kWavFormatALaw,
|
| - 0) == -1)
|
| - {
|
| - return -1;
|
| - }
|
| - }
|
| - else if(STR_CASE_CMP(codecInst.plname, "L16") == 0)
|
| - {
|
| - _bytesPerSample = 2;
|
| - if(WriteWavHeader(wav, codecInst.plfreq, _bytesPerSample, channels,
|
| - kWavFormatPcm, 0) == -1)
|
| - {
|
| - return -1;
|
| - }
|
| - }
|
| - else
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "codecInst identifies unsupported codec for WAV file!");
|
| - return -1;
|
| - }
|
| - _writing = true;
|
| - _bytesWritten = 0;
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::WriteWavData(OutStream& out,
|
| - const int8_t* buffer,
|
| - const size_t dataLength)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::WriteWavData(out= 0x%x, buf= 0x%x, dataLen= %" PRIuS
|
| - ")",
|
| - &out,
|
| - buffer,
|
| - dataLength);
|
| -
|
| - if(buffer == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "WriteWavData: input buffer NULL!");
|
| - return -1;
|
| - }
|
| -
|
| - if(!out.Write(buffer, dataLength))
|
| - {
|
| - return -1;
|
| - }
|
| - _bytesWritten += dataLength;
|
| - return static_cast<int32_t>(dataLength);
|
| -}
|
| -
|
| -
|
| -int32_t ModuleFileUtility::WriteWavHeader(
|
| - OutStream& wav,
|
| - const uint32_t freq,
|
| - const uint32_t bytesPerSample,
|
| - const uint32_t channels,
|
| - const uint32_t format,
|
| - const uint32_t lengthInBytes)
|
| -{
|
| - // Frame size in bytes for 10 ms of audio.
|
| - // TODO (hellner): 44.1 kHz has 440 samples frame size. Doesn't seem to
|
| - // be taken into consideration here!
|
| - const int32_t frameSize = (freq / 100) * channels;
|
| -
|
| - // Calculate the number of full frames that the wave file contain.
|
| - const int32_t dataLengthInBytes = frameSize * (lengthInBytes / frameSize);
|
| -
|
| - uint8_t buf[kWavHeaderSize];
|
| - webrtc::WriteWavHeader(buf, channels, freq, static_cast<WavFormat>(format),
|
| - bytesPerSample, dataLengthInBytes / bytesPerSample);
|
| - wav.Write(buf, kWavHeaderSize);
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::UpdateWavHeader(OutStream& wav)
|
| -{
|
| - int32_t res = -1;
|
| - if(wav.Rewind() == -1)
|
| - {
|
| - return -1;
|
| - }
|
| - uint32_t channels = (codec_info_.channels == 0) ?
|
| - 1 : codec_info_.channels;
|
| -
|
| - if(STR_CASE_CMP(codec_info_.plname, "L16") == 0)
|
| - {
|
| - res = WriteWavHeader(wav, codec_info_.plfreq, 2, channels,
|
| - kWavFormatPcm, _bytesWritten);
|
| - } else if(STR_CASE_CMP(codec_info_.plname, "PCMU") == 0) {
|
| - res = WriteWavHeader(wav, 8000, 1, channels, kWavFormatMuLaw,
|
| - _bytesWritten);
|
| - } else if(STR_CASE_CMP(codec_info_.plname, "PCMA") == 0) {
|
| - res = WriteWavHeader(wav, 8000, 1, channels, kWavFormatALaw,
|
| - _bytesWritten);
|
| - } else {
|
| - // Allow calling this API even if not writing to a WAVE file.
|
| - // TODO (hellner): why?!
|
| - return 0;
|
| - }
|
| - return res;
|
| -}
|
| -
|
| -
|
| -int32_t ModuleFileUtility::InitPreEncodedReading(InStream& in,
|
| - const CodecInst& cinst)
|
| -{
|
| -
|
| - uint8_t preEncodedID;
|
| - in.Read(&preEncodedID, 1);
|
| -
|
| - MediaFileUtility_CodecType codecType =
|
| - (MediaFileUtility_CodecType)preEncodedID;
|
| -
|
| - if(set_codec_info(cinst) != 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "Pre-encoded file send codec mismatch!");
|
| - return -1;
|
| - }
|
| - if(codecType != _codecId)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "Pre-encoded file format codec mismatch!");
|
| - return -1;
|
| - }
|
| - memcpy(&codec_info_,&cinst,sizeof(CodecInst));
|
| - _reading = true;
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::ReadPreEncodedData(
|
| - InStream& in,
|
| - int8_t* outData,
|
| - const size_t bufferSize)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::ReadPreEncodedData(in= 0x%x, outData= 0x%x, "
|
| - "bufferSize= %" PRIuS ")",
|
| - &in,
|
| - outData,
|
| - bufferSize);
|
| -
|
| - if(outData == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id, "output buffer NULL");
|
| - }
|
| -
|
| - uint32_t frameLen;
|
| - uint8_t buf[64];
|
| - // Each frame has a two byte header containing the frame length.
|
| - int32_t res = in.Read(buf, 2);
|
| - if(res != 2)
|
| - {
|
| - if(!in.Rewind())
|
| - {
|
| - // The first byte is the codec identifier.
|
| - in.Read(buf, 1);
|
| - res = in.Read(buf, 2);
|
| - }
|
| - else
|
| - {
|
| - return -1;
|
| - }
|
| - }
|
| - frameLen = buf[0] + buf[1] * 256;
|
| - if(bufferSize < frameLen)
|
| - {
|
| - WEBRTC_TRACE(
|
| - kTraceError,
|
| - kTraceFile,
|
| - _id,
|
| - "buffer not large enough to read %d bytes of pre-encoded data!",
|
| - frameLen);
|
| - return -1;
|
| - }
|
| - return in.Read(outData, frameLen);
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitPreEncodedWriting(
|
| - OutStream& out,
|
| - const CodecInst& codecInst)
|
| -{
|
| -
|
| - if(set_codec_info(codecInst) != 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id, "CodecInst not recognized!");
|
| - return -1;
|
| - }
|
| - _writing = true;
|
| - _bytesWritten = 1;
|
| - out.Write(&_codecId, 1);
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::WritePreEncodedData(
|
| - OutStream& out,
|
| - const int8_t* buffer,
|
| - const size_t dataLength)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::WritePreEncodedData(out= 0x%x, inData= 0x%x, "
|
| - "dataLen= %" PRIuS ")",
|
| - &out,
|
| - buffer,
|
| - dataLength);
|
| -
|
| - if(buffer == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
|
| - }
|
| -
|
| - size_t bytesWritten = 0;
|
| - // The first two bytes is the size of the frame.
|
| - int16_t lengthBuf;
|
| - lengthBuf = (int16_t)dataLength;
|
| - if(dataLength > static_cast<size_t>(std::numeric_limits<int16_t>::max()) ||
|
| - !out.Write(&lengthBuf, 2))
|
| - {
|
| - return -1;
|
| - }
|
| - bytesWritten = 2;
|
| -
|
| - if(!out.Write(buffer, dataLength))
|
| - {
|
| - return -1;
|
| - }
|
| - bytesWritten += dataLength;
|
| - return static_cast<int32_t>(bytesWritten);
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitCompressedReading(
|
| - InStream& in,
|
| - const uint32_t start,
|
| - const uint32_t stop)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceDebug,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::InitCompressedReading(in= 0x%x, start= %d,\
|
| - stop= %d)",
|
| - &in,
|
| - start,
|
| - stop);
|
| -
|
| -#if defined(WEBRTC_CODEC_ILBC)
|
| - int16_t read_len = 0;
|
| -#endif
|
| - _codecId = kCodecNoCodec;
|
| - _playoutPositionMs = 0;
|
| - _reading = false;
|
| -
|
| - _startPointInMs = start;
|
| - _stopPointInMs = stop;
|
| -
|
| - // Read the codec name
|
| - int32_t cnt = 0;
|
| - char buf[64];
|
| - do
|
| - {
|
| - in.Read(&buf[cnt++], 1);
|
| - } while ((buf[cnt-1] != '\n') && (64 > cnt));
|
| -
|
| - if(cnt==64)
|
| - {
|
| - return -1;
|
| - } else {
|
| - buf[cnt]=0;
|
| - }
|
| -
|
| -#ifdef WEBRTC_CODEC_ILBC
|
| - if(!strcmp("#!iLBC20\n", buf))
|
| - {
|
| - codec_info_.pltype = 102;
|
| - strcpy(codec_info_.plname, "ilbc");
|
| - codec_info_.plfreq = 8000;
|
| - codec_info_.pacsize = 160;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 13300;
|
| - _codecId = kCodecIlbc20Ms;
|
| -
|
| - if(_startPointInMs > 0)
|
| - {
|
| - while (_playoutPositionMs <= _startPointInMs)
|
| - {
|
| - read_len = in.Read(buf, 38);
|
| - if(read_len == 38)
|
| - {
|
| - _playoutPositionMs += 20;
|
| - }
|
| - else
|
| - {
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - if(!strcmp("#!iLBC30\n", buf))
|
| - {
|
| - codec_info_.pltype = 102;
|
| - strcpy(codec_info_.plname, "ilbc");
|
| - codec_info_.plfreq = 8000;
|
| - codec_info_.pacsize = 240;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 13300;
|
| - _codecId = kCodecIlbc30Ms;
|
| -
|
| - if(_startPointInMs > 0)
|
| - {
|
| - while (_playoutPositionMs <= _startPointInMs)
|
| - {
|
| - read_len = in.Read(buf, 50);
|
| - if(read_len == 50)
|
| - {
|
| - _playoutPositionMs += 20;
|
| - }
|
| - else
|
| - {
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -#endif
|
| - if(_codecId == kCodecNoCodec)
|
| - {
|
| - return -1;
|
| - }
|
| - _reading = true;
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::ReadCompressedData(InStream& in,
|
| - int8_t* outData,
|
| - size_t bufferSize)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::ReadCompressedData(in=0x%x, outData=0x%x, bytes=%"
|
| - PRIuS ")",
|
| - &in,
|
| - outData,
|
| - bufferSize);
|
| -
|
| - uint32_t bytesRead = 0;
|
| -
|
| - if(! _reading)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id, "not currently reading!");
|
| - return -1;
|
| - }
|
| -
|
| -#ifdef WEBRTC_CODEC_ILBC
|
| - if((_codecId == kCodecIlbc20Ms) ||
|
| - (_codecId == kCodecIlbc30Ms))
|
| - {
|
| - uint32_t byteSize = 0;
|
| - if(_codecId == kCodecIlbc30Ms)
|
| - {
|
| - byteSize = 50;
|
| - }
|
| - if(_codecId == kCodecIlbc20Ms)
|
| - {
|
| - byteSize = 38;
|
| - }
|
| - if(bufferSize < byteSize)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "output buffer is too short to read ILBC compressed\
|
| - data.");
|
| - assert(false);
|
| - return -1;
|
| - }
|
| -
|
| - bytesRead = in.Read(outData, byteSize);
|
| - if(bytesRead != byteSize)
|
| - {
|
| - if(!in.Rewind())
|
| - {
|
| - InitCompressedReading(in, _startPointInMs, _stopPointInMs);
|
| - bytesRead = in.Read(outData, byteSize);
|
| - if(bytesRead != byteSize)
|
| - {
|
| - _reading = false;
|
| - return -1;
|
| - }
|
| - }
|
| - else
|
| - {
|
| - _reading = false;
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| -#endif
|
| - if(bytesRead == 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadCompressedData() no bytes read, codec not supported");
|
| - return -1;
|
| - }
|
| -
|
| - _playoutPositionMs += 20;
|
| - if((_stopPointInMs > 0) &&
|
| - (_playoutPositionMs >= _stopPointInMs))
|
| - {
|
| - if(!in.Rewind())
|
| - {
|
| - InitCompressedReading(in, _startPointInMs, _stopPointInMs);
|
| - }
|
| - else
|
| - {
|
| - _reading = false;
|
| - }
|
| - }
|
| - return bytesRead;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitCompressedWriting(
|
| - OutStream& out,
|
| - const CodecInst& codecInst)
|
| -{
|
| - WEBRTC_TRACE(kTraceDebug, kTraceFile, _id,
|
| - "ModuleFileUtility::InitCompressedWriting(out= 0x%x,\
|
| - codecName= %s)",
|
| - &out, codecInst.plname);
|
| -
|
| - _writing = false;
|
| -
|
| -#ifdef WEBRTC_CODEC_ILBC
|
| - if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0)
|
| - {
|
| - if(codecInst.pacsize == 160)
|
| - {
|
| - _codecId = kCodecIlbc20Ms;
|
| - out.Write("#!iLBC20\n",9);
|
| - }
|
| - else if(codecInst.pacsize == 240)
|
| - {
|
| - _codecId = kCodecIlbc30Ms;
|
| - out.Write("#!iLBC30\n",9);
|
| - }
|
| - else
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "codecInst defines unsupported compression codec!");
|
| - return -1;
|
| - }
|
| - memcpy(&codec_info_,&codecInst,sizeof(CodecInst));
|
| - _writing = true;
|
| - return 0;
|
| - }
|
| -#endif
|
| -
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "codecInst defines unsupported compression codec!");
|
| - return -1;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::WriteCompressedData(
|
| - OutStream& out,
|
| - const int8_t* buffer,
|
| - const size_t dataLength)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::WriteCompressedData(out= 0x%x, buf= 0x%x, "
|
| - "dataLen= %" PRIuS ")",
|
| - &out,
|
| - buffer,
|
| - dataLength);
|
| -
|
| - if(buffer == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
|
| - }
|
| -
|
| - if(!out.Write(buffer, dataLength))
|
| - {
|
| - return -1;
|
| - }
|
| - return static_cast<int32_t>(dataLength);
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitPCMReading(InStream& pcm,
|
| - const uint32_t start,
|
| - const uint32_t stop,
|
| - uint32_t freq)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceInfo,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::InitPCMReading(pcm= 0x%x, start=%d, stop=%d,\
|
| - freq=%d)",
|
| - &pcm,
|
| - start,
|
| - stop,
|
| - freq);
|
| -
|
| - int8_t dummy[320];
|
| - int32_t read_len;
|
| -
|
| - _playoutPositionMs = 0;
|
| - _startPointInMs = start;
|
| - _stopPointInMs = stop;
|
| - _reading = false;
|
| -
|
| - if(freq == 8000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - codec_info_.pltype = -1;
|
| - codec_info_.plfreq = 8000;
|
| - codec_info_.pacsize = 160;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 128000;
|
| - _codecId = kCodecL16_8Khz;
|
| - }
|
| - else if(freq == 16000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - codec_info_.pltype = -1;
|
| - codec_info_.plfreq = 16000;
|
| - codec_info_.pacsize = 320;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 256000;
|
| - _codecId = kCodecL16_16kHz;
|
| - }
|
| - else if(freq == 32000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - codec_info_.pltype = -1;
|
| - codec_info_.plfreq = 32000;
|
| - codec_info_.pacsize = 320;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 512000;
|
| - _codecId = kCodecL16_32Khz;
|
| - }
|
| -
|
| - // Readsize for 10ms of audio data (2 bytes per sample).
|
| - _readSizeBytes = 2 * codec_info_. plfreq / 100;
|
| - if(_startPointInMs > 0)
|
| - {
|
| - while (_playoutPositionMs < _startPointInMs)
|
| - {
|
| - read_len = pcm.Read(dummy, _readSizeBytes);
|
| - if(read_len == _readSizeBytes)
|
| - {
|
| - _playoutPositionMs += 10;
|
| - }
|
| - else // Must have reached EOF before start position!
|
| - {
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| - _reading = true;
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::ReadPCMData(InStream& pcm,
|
| - int8_t* outData,
|
| - size_t bufferSize)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::ReadPCMData(pcm= 0x%x, outData= 0x%x, bufSize= %"
|
| - PRIuS ")",
|
| - &pcm,
|
| - outData,
|
| - bufferSize);
|
| -
|
| - if(outData == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,"buffer NULL");
|
| - }
|
| -
|
| - // Readsize for 10ms of audio data (2 bytes per sample).
|
| - uint32_t bytesRequested = 2 * codec_info_.plfreq / 100;
|
| - if(bufferSize < bytesRequested)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadPCMData: buffer not long enough for a 10ms frame.");
|
| - assert(false);
|
| - return -1;
|
| - }
|
| -
|
| - uint32_t bytesRead = pcm.Read(outData, bytesRequested);
|
| - if(bytesRead < bytesRequested)
|
| - {
|
| - if(pcm.Rewind() == -1)
|
| - {
|
| - _reading = false;
|
| - }
|
| - else
|
| - {
|
| - if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs,
|
| - codec_info_.plfreq) == -1)
|
| - {
|
| - _reading = false;
|
| - }
|
| - else
|
| - {
|
| - int32_t rest = bytesRequested - bytesRead;
|
| - int32_t len = pcm.Read(&(outData[bytesRead]), rest);
|
| - if(len == rest)
|
| - {
|
| - bytesRead += len;
|
| - }
|
| - else
|
| - {
|
| - _reading = false;
|
| - }
|
| - }
|
| - if(bytesRead <= 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "ReadPCMData: Failed to rewind audio file.");
|
| - return -1;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if(bytesRead <= 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
|
| - "ReadPCMData: end of file");
|
| - return -1;
|
| - }
|
| - _playoutPositionMs += 10;
|
| - if(_stopPointInMs && _playoutPositionMs >= _stopPointInMs)
|
| - {
|
| - if(!pcm.Rewind())
|
| - {
|
| - if(InitPCMReading(pcm, _startPointInMs, _stopPointInMs,
|
| - codec_info_.plfreq) == -1)
|
| - {
|
| - _reading = false;
|
| - }
|
| - }
|
| - }
|
| - return bytesRead;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::InitPCMWriting(OutStream& out, uint32_t freq)
|
| -{
|
| -
|
| - if(freq == 8000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - codec_info_.pltype = -1;
|
| - codec_info_.plfreq = 8000;
|
| - codec_info_.pacsize = 160;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 128000;
|
| -
|
| - _codecId = kCodecL16_8Khz;
|
| - }
|
| - else if(freq == 16000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - codec_info_.pltype = -1;
|
| - codec_info_.plfreq = 16000;
|
| - codec_info_.pacsize = 320;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 256000;
|
| -
|
| - _codecId = kCodecL16_16kHz;
|
| - }
|
| - else if(freq == 32000)
|
| - {
|
| - strcpy(codec_info_.plname, "L16");
|
| - codec_info_.pltype = -1;
|
| - codec_info_.plfreq = 32000;
|
| - codec_info_.pacsize = 320;
|
| - codec_info_.channels = 1;
|
| - codec_info_.rate = 512000;
|
| -
|
| - _codecId = kCodecL16_32Khz;
|
| - }
|
| - if((_codecId != kCodecL16_8Khz) &&
|
| - (_codecId != kCodecL16_16kHz) &&
|
| - (_codecId != kCodecL16_32Khz))
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "CodecInst is not 8KHz PCM or 16KHz PCM!");
|
| - return -1;
|
| - }
|
| - _writing = true;
|
| - _bytesWritten = 0;
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::WritePCMData(OutStream& out,
|
| - const int8_t* buffer,
|
| - const size_t dataLength)
|
| -{
|
| - WEBRTC_TRACE(
|
| - kTraceStream,
|
| - kTraceFile,
|
| - _id,
|
| - "ModuleFileUtility::WritePCMData(out= 0x%x, buf= 0x%x, dataLen= %" PRIuS
|
| - ")",
|
| - &out,
|
| - buffer,
|
| - dataLength);
|
| -
|
| - if(buffer == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id, "buffer NULL");
|
| - }
|
| -
|
| - if(!out.Write(buffer, dataLength))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - _bytesWritten += dataLength;
|
| - return static_cast<int32_t>(dataLength);
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::codec_info(CodecInst& codecInst)
|
| -{
|
| - WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
|
| - "ModuleFileUtility::codec_info(codecInst= 0x%x)", &codecInst);
|
| -
|
| - if(!_reading && !_writing)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "CodecInst: not currently reading audio file!");
|
| - return -1;
|
| - }
|
| - memcpy(&codecInst,&codec_info_,sizeof(CodecInst));
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::set_codec_info(const CodecInst& codecInst)
|
| -{
|
| -
|
| - _codecId = kCodecNoCodec;
|
| - if(STR_CASE_CMP(codecInst.plname, "PCMU") == 0)
|
| - {
|
| - _codecId = kCodecPcmu;
|
| - }
|
| - else if(STR_CASE_CMP(codecInst.plname, "PCMA") == 0)
|
| - {
|
| - _codecId = kCodecPcma;
|
| - }
|
| - else if(STR_CASE_CMP(codecInst.plname, "L16") == 0)
|
| - {
|
| - if(codecInst.plfreq == 8000)
|
| - {
|
| - _codecId = kCodecL16_8Khz;
|
| - }
|
| - else if(codecInst.plfreq == 16000)
|
| - {
|
| - _codecId = kCodecL16_16kHz;
|
| - }
|
| - else if(codecInst.plfreq == 32000)
|
| - {
|
| - _codecId = kCodecL16_32Khz;
|
| - }
|
| - }
|
| -#ifdef WEBRTC_CODEC_ILBC
|
| - else if(STR_CASE_CMP(codecInst.plname, "ilbc") == 0)
|
| - {
|
| - if(codecInst.pacsize == 160)
|
| - {
|
| - _codecId = kCodecIlbc20Ms;
|
| - }
|
| - else if(codecInst.pacsize == 240)
|
| - {
|
| - _codecId = kCodecIlbc30Ms;
|
| - }
|
| - }
|
| -#endif
|
| -#if(defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
|
| - else if(STR_CASE_CMP(codecInst.plname, "isac") == 0)
|
| - {
|
| - if(codecInst.plfreq == 16000)
|
| - {
|
| - _codecId = kCodecIsac;
|
| - }
|
| - else if(codecInst.plfreq == 32000)
|
| - {
|
| - _codecId = kCodecIsacSwb;
|
| - }
|
| - }
|
| -#endif
|
| -#ifdef WEBRTC_CODEC_G722
|
| - else if(STR_CASE_CMP(codecInst.plname, "G722") == 0)
|
| - {
|
| - _codecId = kCodecG722;
|
| - }
|
| -#endif
|
| - if(_codecId == kCodecNoCodec)
|
| - {
|
| - return -1;
|
| - }
|
| - memcpy(&codec_info_, &codecInst, sizeof(CodecInst));
|
| - return 0;
|
| -}
|
| -
|
| -int32_t ModuleFileUtility::FileDurationMs(const char* fileName,
|
| - const FileFormats fileFormat,
|
| - const uint32_t freqInHz)
|
| -{
|
| -
|
| - if(fileName == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id, "filename NULL");
|
| - return -1;
|
| - }
|
| -
|
| - int32_t time_in_ms = -1;
|
| - struct stat file_size;
|
| - if(stat(fileName,&file_size) == -1)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "failed to retrieve file size with stat!");
|
| - return -1;
|
| - }
|
| - FileWrapper* inStreamObj = FileWrapper::Create();
|
| - if(inStreamObj == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceMemory, kTraceFile, _id,
|
| - "failed to create InStream object!");
|
| - return -1;
|
| - }
|
| - if(inStreamObj->OpenFile(fileName, true) == -1)
|
| - {
|
| - delete inStreamObj;
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "failed to open file %s!", fileName);
|
| - return -1;
|
| - }
|
| -
|
| - switch (fileFormat)
|
| - {
|
| - case kFileFormatWavFile:
|
| - {
|
| - if(ReadWavHeader(*inStreamObj) == -1)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "failed to read WAV file header!");
|
| - return -1;
|
| - }
|
| - time_in_ms = ((file_size.st_size - 44) /
|
| - (_wavFormatObj.nAvgBytesPerSec/1000));
|
| - break;
|
| - }
|
| - case kFileFormatPcm16kHzFile:
|
| - {
|
| - // 16 samples per ms. 2 bytes per sample.
|
| - int32_t denominator = 16*2;
|
| - time_in_ms = (file_size.st_size)/denominator;
|
| - break;
|
| - }
|
| - case kFileFormatPcm8kHzFile:
|
| - {
|
| - // 8 samples per ms. 2 bytes per sample.
|
| - int32_t denominator = 8*2;
|
| - time_in_ms = (file_size.st_size)/denominator;
|
| - break;
|
| - }
|
| - case kFileFormatCompressedFile:
|
| - {
|
| - int32_t cnt = 0;
|
| - int32_t read_len = 0;
|
| - char buf[64];
|
| - do
|
| - {
|
| - read_len = inStreamObj->Read(&buf[cnt++], 1);
|
| - if(read_len != 1)
|
| - {
|
| - return -1;
|
| - }
|
| - } while ((buf[cnt-1] != '\n') && (64 > cnt));
|
| -
|
| - if(cnt == 64)
|
| - {
|
| - return -1;
|
| - }
|
| - else
|
| - {
|
| - buf[cnt] = 0;
|
| - }
|
| -#ifdef WEBRTC_CODEC_ILBC
|
| - if(!strcmp("#!iLBC20\n", buf))
|
| - {
|
| - // 20 ms is 304 bits
|
| - time_in_ms = ((file_size.st_size)*160)/304;
|
| - break;
|
| - }
|
| - if(!strcmp("#!iLBC30\n", buf))
|
| - {
|
| - // 30 ms takes 400 bits.
|
| - // file size in bytes * 8 / 400 is the number of
|
| - // 30 ms frames in the file ->
|
| - // time_in_ms = file size * 8 / 400 * 30
|
| - time_in_ms = ((file_size.st_size)*240)/400;
|
| - break;
|
| - }
|
| -#endif
|
| - break;
|
| - }
|
| - case kFileFormatPreencodedFile:
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "cannot determine duration of Pre-Encoded file!");
|
| - break;
|
| - }
|
| - default:
|
| - WEBRTC_TRACE(kTraceError, kTraceFile, _id,
|
| - "unsupported file format %d!", fileFormat);
|
| - break;
|
| - }
|
| - inStreamObj->CloseFile();
|
| - delete inStreamObj;
|
| - return time_in_ms;
|
| -}
|
| -
|
| -uint32_t ModuleFileUtility::PlayoutPositionMs()
|
| -{
|
| - WEBRTC_TRACE(kTraceStream, kTraceFile, _id,
|
| - "ModuleFileUtility::PlayoutPosition()");
|
| -
|
| - if(_reading)
|
| - {
|
| - return _playoutPositionMs;
|
| - }
|
| - else
|
| - {
|
| - return 0;
|
| - }
|
| -}
|
| -} // namespace webrtc
|
|
|