diff options
Diffstat (limited to 'webrtc/modules/media_file/source/media_file_utility.cc')
-rw-r--r-- | webrtc/modules/media_file/source/media_file_utility.cc | 1656 |
1 files changed, 0 insertions, 1656 deletions
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 61ae442d0e..0000000000 --- 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/interface/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 |