mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00
Delete unused MediaFile module.
Delete the subdirectory modules/media_file, and all references to it. Bug: none Change-Id: I19d86420a7d1d51cb6174c914a90484918106c5a Reviewed-on: https://webrtc-review.googlesource.com/40540 Reviewed-by: Magnus Flodman <mflodman@webrtc.org> Commit-Queue: Niels Moller <nisse@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21790}
This commit is contained in:
parent
88a0c4add3
commit
e48c61fca7
16 changed files with 0 additions and 1491 deletions
|
@ -29,7 +29,6 @@ CPPLINT_BLACKLIST = [
|
|||
'modules/audio_processing',
|
||||
'modules/desktop_capture',
|
||||
'modules/include/module_common_types.h',
|
||||
'modules/media_file',
|
||||
'modules/utility',
|
||||
'modules/video_capture',
|
||||
'p2p/base/session.cc',
|
||||
|
|
|
@ -17,7 +17,6 @@ group("modules") {
|
|||
"audio_processing",
|
||||
"bitrate_controller",
|
||||
"congestion_controller",
|
||||
"media_file",
|
||||
"pacing",
|
||||
"remote_bitrate_estimator",
|
||||
"rtp_rtcp",
|
||||
|
@ -251,7 +250,6 @@ if (rtc_include_tests) {
|
|||
"audio_processing:audio_processing_unittests",
|
||||
"bitrate_controller:bitrate_controller_unittests",
|
||||
"congestion_controller:congestion_controller_unittests",
|
||||
"media_file:media_file_unittests",
|
||||
"pacing:pacing_unittests",
|
||||
"remote_bitrate_estimator:remote_bitrate_estimator_unittests",
|
||||
"rtp_rtcp:rtp_rtcp_unittests",
|
||||
|
|
|
@ -5,7 +5,6 @@ include_rules = [
|
|||
"+modules/audio_coding",
|
||||
"+modules/audio_device",
|
||||
"+modules/audio_processing",
|
||||
"+modules/media_file",
|
||||
"+modules/pacing",
|
||||
"+modules/rtp_rtcp",
|
||||
"+modules/utility",
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
# Copyright (c) 2014 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.
|
||||
|
||||
import("../../webrtc.gni")
|
||||
|
||||
config("media_file_config") {
|
||||
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
||||
}
|
||||
|
||||
rtc_static_library("media_file") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"media_file.h",
|
||||
"media_file_defines.h",
|
||||
"media_file_impl.cc",
|
||||
"media_file_impl.h",
|
||||
"media_file_utility.cc",
|
||||
"media_file_utility.h",
|
||||
]
|
||||
|
||||
public_configs = [ ":media_file_config" ]
|
||||
|
||||
# TODO(jschuh): Bug 1348: fix this warning.
|
||||
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
|
||||
|
||||
if (!build_with_chromium && is_clang) {
|
||||
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
||||
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
"..:module_api",
|
||||
"../..:webrtc_common",
|
||||
"../../:typedefs",
|
||||
"../../common_audio",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_source_set("media_file_unittests") {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"media_file_unittest.cc",
|
||||
]
|
||||
deps = [
|
||||
":media_file",
|
||||
"../../test:test_support",
|
||||
]
|
||||
if (is_win) {
|
||||
cflags = [
|
||||
# TODO(kjellander): bugs.webrtc.org/261: Fix this warning.
|
||||
"/wd4373", # virtual function override.
|
||||
]
|
||||
}
|
||||
if (!build_with_chromium && is_clang) {
|
||||
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
||||
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
include_rules = [
|
||||
"+common_audio",
|
||||
"+system_wrappers",
|
||||
]
|
|
@ -1,8 +0,0 @@
|
|||
mflodman@webrtc.org
|
||||
perkj@webrtc.org
|
||||
niklas.enbom@webrtc.org
|
||||
|
||||
# These are for the common case of adding or renaming files. If you're doing
|
||||
# structural changes, please get a review from a reviewer in this file.
|
||||
per-file *.gn=*
|
||||
per-file *.gni=*
|
|
@ -1,84 +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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_MEDIA_FILE_MEDIA_FILE_H_
|
||||
#define MODULES_MEDIA_FILE_MEDIA_FILE_H_
|
||||
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/include/module.h"
|
||||
#include "modules/include/module_common_types.h"
|
||||
#include "modules/media_file/media_file_defines.h"
|
||||
#include "typedefs.h" // NOLINT(build/include)
|
||||
|
||||
namespace webrtc {
|
||||
class MediaFile : public Module
|
||||
{
|
||||
public:
|
||||
// Factory method. Constructor disabled. id is the identifier for the
|
||||
// MediaFile instance.
|
||||
static MediaFile* CreateMediaFile(const int32_t id);
|
||||
static void DestroyMediaFile(MediaFile* module);
|
||||
|
||||
// Put 10-60ms of audio data from file into the audioBuffer depending on
|
||||
// codec frame size. dataLengthInBytes is both an input and output
|
||||
// parameter. As input parameter it indicates the size of audioBuffer.
|
||||
// As output parameter it indicates the number of bytes written to
|
||||
// audioBuffer.
|
||||
// Note: This API only play mono audio but can be used on file containing
|
||||
// audio with more channels (in which case the audio will be converted to
|
||||
// mono).
|
||||
virtual int32_t PlayoutAudioData(
|
||||
int8_t* audioBuffer,
|
||||
size_t& dataLengthInBytes) = 0;
|
||||
|
||||
// Prepare for playing audio from stream.
|
||||
// FileCallback::PlayNotification(..) will be called after
|
||||
// notificationTimeMs of the file has been played if notificationTimeMs is
|
||||
// greater than zero. format specifies the type of file fileName refers to.
|
||||
// codecInst specifies the encoding of the audio data. Note that
|
||||
// file formats that contain this information (like WAV files) don't need to
|
||||
// provide a non-NULL codecInst. startPointMs and stopPointMs, unless zero,
|
||||
// specify what part of the file should be read. From startPointMs ms to
|
||||
// stopPointMs ms.
|
||||
// Note: codecInst.channels should be set to 2 for stereo (and 1 for
|
||||
// mono). Stereo audio is only supported for WAV files.
|
||||
virtual int32_t StartPlayingAudioStream(
|
||||
InStream& stream,
|
||||
const uint32_t notificationTimeMs = 0,
|
||||
const FileFormats format = kFileFormatPcm16kHzFile,
|
||||
const CodecInst* codecInst = NULL,
|
||||
const uint32_t startPointMs = 0,
|
||||
const uint32_t stopPointMs = 0) = 0;
|
||||
|
||||
// Stop playing from file or stream.
|
||||
virtual int32_t StopPlaying() = 0;
|
||||
|
||||
// Return true if playing.
|
||||
virtual bool IsPlaying() = 0;
|
||||
|
||||
|
||||
// Set durationMs to the number of ms that has been played from file.
|
||||
virtual int32_t PlayoutPositionMs(
|
||||
uint32_t& durationMs) const = 0;
|
||||
|
||||
// Register callback to receive media file related notifications. Disables
|
||||
// callbacks if callback is NULL.
|
||||
virtual int32_t SetModuleFileCallback(FileCallback* callback) = 0;
|
||||
|
||||
// Update codecInst according to the current audio codec being used for
|
||||
// reading or writing.
|
||||
virtual int32_t codec_info(CodecInst& codecInst) const = 0;
|
||||
|
||||
protected:
|
||||
MediaFile() {}
|
||||
virtual ~MediaFile() {}
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_MEDIA_FILE_MEDIA_FILE_H_
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_MEDIA_FILE_MEDIA_FILE_DEFINES_H_
|
||||
#define MODULES_MEDIA_FILE_MEDIA_FILE_DEFINES_H_
|
||||
|
||||
#include "modules/include/module_common_types.h"
|
||||
#include "typedefs.h" // NOLINT(build/include)
|
||||
|
||||
namespace webrtc {
|
||||
// Callback class for the MediaFile class.
|
||||
class FileCallback
|
||||
{
|
||||
public:
|
||||
virtual ~FileCallback(){}
|
||||
|
||||
// This function is called by MediaFile when a file has been playing for
|
||||
// durationMs ms. id is the identifier for the MediaFile instance calling
|
||||
// the callback.
|
||||
virtual void PlayNotification(const int32_t id,
|
||||
const uint32_t durationMs) = 0;
|
||||
|
||||
// This function is called by MediaFile when a file has been recording for
|
||||
// durationMs ms. id is the identifier for the MediaFile instance calling
|
||||
// the callback.
|
||||
virtual void RecordNotification(const int32_t id,
|
||||
const uint32_t durationMs) = 0;
|
||||
|
||||
// This function is called by MediaFile when a file has been stopped
|
||||
// playing. id is the identifier for the MediaFile instance calling the
|
||||
// callback.
|
||||
virtual void PlayFileEnded(const int32_t id) = 0;
|
||||
|
||||
// This function is called by MediaFile when a file has been stopped
|
||||
// recording. id is the identifier for the MediaFile instance calling the
|
||||
// callback.
|
||||
virtual void RecordFileEnded(const int32_t id) = 0;
|
||||
|
||||
protected:
|
||||
FileCallback() {}
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_MEDIA_FILE_MEDIA_FILE_DEFINES_H_
|
|
@ -1,356 +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 <assert.h>
|
||||
|
||||
#include "modules/media_file/media_file_impl.h"
|
||||
#include "rtc_base/format_macros.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
MediaFile* MediaFile::CreateMediaFile(const int32_t id) {
|
||||
return new MediaFileImpl(id);
|
||||
}
|
||||
|
||||
void MediaFile::DestroyMediaFile(MediaFile* module) {
|
||||
delete static_cast<MediaFileImpl*>(module);
|
||||
}
|
||||
|
||||
MediaFileImpl::MediaFileImpl(const int32_t id)
|
||||
: _id(id),
|
||||
_ptrFileUtilityObj(NULL),
|
||||
codec_info_(),
|
||||
_ptrInStream(NULL),
|
||||
_fileFormat((FileFormats)-1),
|
||||
_playoutPositionMs(0),
|
||||
_notificationMs(0),
|
||||
_playingActive(false),
|
||||
_fileName(),
|
||||
_ptrCallback(NULL) {
|
||||
RTC_LOG(LS_INFO) << "MediaFileImpl()";
|
||||
|
||||
codec_info_.plname[0] = '\0';
|
||||
_fileName[0] = '\0';
|
||||
}
|
||||
|
||||
MediaFileImpl::~MediaFileImpl() {
|
||||
RTC_LOG(LS_INFO) << "~MediaFileImpl()";
|
||||
{
|
||||
rtc::CritScope lock(&_crit);
|
||||
|
||||
if (_playingActive) {
|
||||
StopPlaying();
|
||||
}
|
||||
|
||||
delete _ptrFileUtilityObj;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t MediaFileImpl::TimeUntilNextProcess() {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "TimeUntilNextProcess: This method is not used by MediaFile class.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MediaFileImpl::Process() {
|
||||
RTC_LOG(LS_WARNING) << "Process: This method is not used by MediaFile class.";
|
||||
}
|
||||
|
||||
int32_t MediaFileImpl::PlayoutAudioData(int8_t* buffer,
|
||||
size_t& dataLengthInBytes) {
|
||||
RTC_LOG(LS_INFO) << "MediaFileImpl::PlayoutData(buffer= "
|
||||
<< static_cast<void*>(buffer)
|
||||
<< ", bufLen= " << dataLengthInBytes << ")";
|
||||
|
||||
const size_t bufferLengthInBytes = dataLengthInBytes;
|
||||
dataLengthInBytes = 0;
|
||||
|
||||
if (buffer == NULL || bufferLengthInBytes == 0) {
|
||||
RTC_LOG(LS_ERROR) << "Buffer pointer or length is NULL!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t bytesRead = 0;
|
||||
{
|
||||
rtc::CritScope lock(&_crit);
|
||||
|
||||
if (!_playingActive) {
|
||||
RTC_LOG(LS_WARNING) << "Not currently playing!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_ptrFileUtilityObj) {
|
||||
RTC_LOG(LS_ERROR) << "Playing, but no FileUtility object!";
|
||||
StopPlaying();
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (_fileFormat) {
|
||||
case kFileFormatPcm32kHzFile:
|
||||
case kFileFormatPcm16kHzFile:
|
||||
case kFileFormatPcm8kHzFile:
|
||||
bytesRead = _ptrFileUtilityObj->ReadPCMData(*_ptrInStream, buffer,
|
||||
bufferLengthInBytes);
|
||||
break;
|
||||
case kFileFormatWavFile:
|
||||
bytesRead = _ptrFileUtilityObj->ReadWavDataAsMono(*_ptrInStream, buffer,
|
||||
bufferLengthInBytes);
|
||||
break;
|
||||
default: {
|
||||
RTC_LOG(LS_ERROR) << "Invalid file format: " << _fileFormat;
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesRead > 0) {
|
||||
dataLengthInBytes = static_cast<size_t>(bytesRead);
|
||||
}
|
||||
}
|
||||
HandlePlayCallbacks(bytesRead);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MediaFileImpl::HandlePlayCallbacks(int32_t bytesRead) {
|
||||
bool playEnded = false;
|
||||
uint32_t callbackNotifyMs = 0;
|
||||
|
||||
if (bytesRead > 0) {
|
||||
// Check if it's time for PlayNotification(..).
|
||||
_playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
|
||||
if (_notificationMs) {
|
||||
if (_playoutPositionMs >= _notificationMs) {
|
||||
_notificationMs = 0;
|
||||
callbackNotifyMs = _playoutPositionMs;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If no bytes were read assume end of file.
|
||||
StopPlaying();
|
||||
playEnded = true;
|
||||
}
|
||||
|
||||
// Only _callbackCrit may and should be taken when making callbacks.
|
||||
rtc::CritScope lock(&_callbackCrit);
|
||||
if (_ptrCallback) {
|
||||
if (callbackNotifyMs) {
|
||||
_ptrCallback->PlayNotification(_id, callbackNotifyMs);
|
||||
}
|
||||
if (playEnded) {
|
||||
_ptrCallback->PlayFileEnded(_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MediaFileImpl::StartPlayingAudioStream(
|
||||
InStream& stream,
|
||||
const uint32_t notificationTimeMs,
|
||||
const FileFormats format,
|
||||
const CodecInst* codecInst,
|
||||
const uint32_t startPointMs,
|
||||
const uint32_t stopPointMs) {
|
||||
return StartPlayingStream(stream, false, notificationTimeMs, format,
|
||||
codecInst, startPointMs, stopPointMs);
|
||||
}
|
||||
|
||||
int32_t MediaFileImpl::StartPlayingStream(InStream& stream,
|
||||
bool loop,
|
||||
const uint32_t notificationTimeMs,
|
||||
const FileFormats format,
|
||||
const CodecInst* codecInst,
|
||||
const uint32_t startPointMs,
|
||||
const uint32_t stopPointMs) {
|
||||
if (!ValidFileFormat(format, codecInst)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ValidFilePositions(startPointMs, stopPointMs)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtc::CritScope lock(&_crit);
|
||||
if (_playingActive) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "StartPlaying called, but already playing file "
|
||||
<< ((_fileName[0] == '\0') ? "(name not set)" : _fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_ptrFileUtilityObj != NULL) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "StartPlaying called, but FileUtilityObj already exists!";
|
||||
StopPlaying();
|
||||
return -1;
|
||||
}
|
||||
|
||||
_ptrFileUtilityObj = new ModuleFileUtility();
|
||||
if (_ptrFileUtilityObj == NULL) {
|
||||
RTC_LOG(LS_INFO) << "Failed to create FileUtilityObj!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case kFileFormatWavFile: {
|
||||
if (_ptrFileUtilityObj->InitWavReading(stream, startPointMs,
|
||||
stopPointMs) == -1) {
|
||||
RTC_LOG(LS_ERROR) << "Not a valid WAV file!";
|
||||
StopPlaying();
|
||||
return -1;
|
||||
}
|
||||
_fileFormat = kFileFormatWavFile;
|
||||
break;
|
||||
}
|
||||
case kFileFormatPcm8kHzFile:
|
||||
case kFileFormatPcm16kHzFile:
|
||||
case kFileFormatPcm32kHzFile: {
|
||||
// ValidFileFormat() called in the beginneing of this function
|
||||
// prevents codecInst from being NULL here.
|
||||
assert(codecInst != NULL);
|
||||
if (!ValidFrequency(codecInst->plfreq) ||
|
||||
_ptrFileUtilityObj->InitPCMReading(stream, startPointMs, stopPointMs,
|
||||
codecInst->plfreq) == -1) {
|
||||
RTC_LOG(LS_ERROR) << "Not a valid raw 8 or 16 KHz PCM file!";
|
||||
StopPlaying();
|
||||
return -1;
|
||||
}
|
||||
|
||||
_fileFormat = format;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
RTC_LOG(LS_ERROR) << "Invalid file format: " << format;
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_ptrFileUtilityObj->codec_info(codec_info_) == -1) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to retrieve codec info!";
|
||||
StopPlaying();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((codec_info_.channels == 2) && (_fileFormat != kFileFormatWavFile)) {
|
||||
RTC_LOG(LS_WARNING) << "Stereo is only allowed for WAV files";
|
||||
StopPlaying();
|
||||
return -1;
|
||||
}
|
||||
_playingActive = true;
|
||||
_playoutPositionMs = _ptrFileUtilityObj->PlayoutPositionMs();
|
||||
_ptrInStream = &stream;
|
||||
_notificationMs = notificationTimeMs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t MediaFileImpl::StopPlaying() {
|
||||
rtc::CritScope lock(&_crit);
|
||||
if (_ptrFileUtilityObj) {
|
||||
delete _ptrFileUtilityObj;
|
||||
_ptrFileUtilityObj = NULL;
|
||||
}
|
||||
if (_ptrInStream) {
|
||||
_ptrInStream = NULL;
|
||||
}
|
||||
|
||||
codec_info_.pltype = 0;
|
||||
codec_info_.plname[0] = '\0';
|
||||
|
||||
if (!_playingActive) {
|
||||
RTC_LOG(LS_WARNING) << "playing is not active!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
_playingActive = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MediaFileImpl::IsPlaying() {
|
||||
RTC_LOG(LS_VERBOSE) << "MediaFileImpl::IsPlaying()";
|
||||
rtc::CritScope lock(&_crit);
|
||||
return _playingActive;
|
||||
}
|
||||
|
||||
int32_t MediaFileImpl::SetModuleFileCallback(FileCallback* callback) {
|
||||
rtc::CritScope lock(&_callbackCrit);
|
||||
|
||||
_ptrCallback = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t MediaFileImpl::PlayoutPositionMs(uint32_t& positionMs) const {
|
||||
rtc::CritScope lock(&_crit);
|
||||
if (!_playingActive) {
|
||||
positionMs = 0;
|
||||
return -1;
|
||||
}
|
||||
positionMs = _playoutPositionMs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t MediaFileImpl::codec_info(CodecInst& codecInst) const {
|
||||
rtc::CritScope lock(&_crit);
|
||||
if (!_playingActive) {
|
||||
RTC_LOG(LS_ERROR) << "Playout has not been initialized!";
|
||||
return -1;
|
||||
}
|
||||
if (codec_info_.pltype == 0 && codec_info_.plname[0] == '\0') {
|
||||
RTC_LOG(LS_ERROR) << "The CodecInst for Playback is unknown!";
|
||||
return -1;
|
||||
}
|
||||
memcpy(&codecInst, &codec_info_, sizeof(CodecInst));
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MediaFileImpl::ValidFileFormat(const FileFormats format,
|
||||
const CodecInst* codecInst) {
|
||||
if (codecInst == NULL) {
|
||||
if (format == kFileFormatPcm8kHzFile || format == kFileFormatPcm16kHzFile ||
|
||||
format == kFileFormatPcm32kHzFile) {
|
||||
RTC_LOG(LS_ERROR) << "Codec info required for file format specified!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MediaFileImpl::ValidFileName(const char* fileName) {
|
||||
if ((fileName == NULL) || (fileName[0] == '\0')) {
|
||||
RTC_LOG(LS_ERROR) << "FileName not specified!";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MediaFileImpl::ValidFilePositions(const uint32_t startPointMs,
|
||||
const uint32_t stopPointMs) {
|
||||
if (startPointMs == 0 && stopPointMs == 0) // Default values
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (stopPointMs && (startPointMs >= stopPointMs)) {
|
||||
RTC_LOG(LS_ERROR) << "startPointMs must be less than stopPointMs!";
|
||||
return false;
|
||||
}
|
||||
if (stopPointMs && ((stopPointMs - startPointMs) < 20)) {
|
||||
RTC_LOG(LS_ERROR) << "minimum play duration for files is 20 ms!";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MediaFileImpl::ValidFrequency(const uint32_t frequency) {
|
||||
if ((frequency == 8000) || (frequency == 16000) || (frequency == 32000) ||
|
||||
(frequency == 48000)) {
|
||||
return true;
|
||||
}
|
||||
RTC_LOG(LS_ERROR) << "Frequency should be 8000, 16000, 32000, or 48000 (Hz)";
|
||||
return false;
|
||||
}
|
||||
} // namespace webrtc
|
|
@ -1,102 +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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_MEDIA_FILE_MEDIA_FILE_IMPL_H_
|
||||
#define MODULES_MEDIA_FILE_MEDIA_FILE_IMPL_H_
|
||||
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/include/module_common_types.h"
|
||||
#include "modules/media_file/media_file.h"
|
||||
#include "modules/media_file/media_file_defines.h"
|
||||
#include "modules/media_file/media_file_utility.h"
|
||||
#include "rtc_base/criticalsection.h"
|
||||
|
||||
namespace webrtc {
|
||||
class MediaFileImpl : public MediaFile
|
||||
{
|
||||
|
||||
public:
|
||||
MediaFileImpl(const int32_t id);
|
||||
~MediaFileImpl();
|
||||
|
||||
void Process() override;
|
||||
int64_t TimeUntilNextProcess() override;
|
||||
|
||||
// MediaFile functions
|
||||
int32_t PlayoutAudioData(int8_t* audioBuffer,
|
||||
size_t& dataLengthInBytes) override;
|
||||
|
||||
int32_t StartPlayingAudioStream(
|
||||
InStream& stream,
|
||||
const uint32_t notificationTimeMs = 0,
|
||||
const FileFormats format = kFileFormatPcm16kHzFile,
|
||||
const CodecInst* codecInst = NULL,
|
||||
const uint32_t startPointMs = 0,
|
||||
const uint32_t stopPointMs = 0) override;
|
||||
|
||||
int32_t StopPlaying() override;
|
||||
|
||||
bool IsPlaying() override;
|
||||
|
||||
int32_t PlayoutPositionMs(uint32_t& positionMs) const override;
|
||||
|
||||
int32_t SetModuleFileCallback(FileCallback* callback) override;
|
||||
|
||||
int32_t codec_info(CodecInst& codecInst) const override;
|
||||
|
||||
private:
|
||||
// Returns true if the combination of format and codecInst is valid.
|
||||
static bool ValidFileFormat(const FileFormats format,
|
||||
const CodecInst* codecInst);
|
||||
|
||||
|
||||
// Returns true if the filename is valid
|
||||
static bool ValidFileName(const char* fileName);
|
||||
|
||||
// Returns true if the combination of startPointMs and stopPointMs is valid.
|
||||
static bool ValidFilePositions(const uint32_t startPointMs,
|
||||
const uint32_t stopPointMs);
|
||||
|
||||
// Returns true if frequencyInHz is a supported frequency.
|
||||
static bool ValidFrequency(const uint32_t frequencyInHz);
|
||||
|
||||
void HandlePlayCallbacks(int32_t bytesRead);
|
||||
|
||||
int32_t StartPlayingStream(
|
||||
InStream& stream,
|
||||
bool loop,
|
||||
const uint32_t notificationTimeMs,
|
||||
const FileFormats format,
|
||||
const CodecInst* codecInst,
|
||||
const uint32_t startPointMs,
|
||||
const uint32_t stopPointMs);
|
||||
|
||||
int32_t _id;
|
||||
rtc::CriticalSection _crit;
|
||||
rtc::CriticalSection _callbackCrit;
|
||||
|
||||
ModuleFileUtility* _ptrFileUtilityObj;
|
||||
CodecInst codec_info_;
|
||||
|
||||
InStream* _ptrInStream;
|
||||
|
||||
FileFormats _fileFormat;
|
||||
uint32_t _playoutPositionMs;
|
||||
uint32_t _notificationMs;
|
||||
|
||||
bool _playingActive;
|
||||
|
||||
char _fileName[512];
|
||||
|
||||
FileCallback* _ptrCallback;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_MEDIA_FILE_MEDIA_FILE_IMPL_H_
|
|
@ -1,26 +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 "modules/media_file/media_file.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
class MediaFileTest : public testing::Test {
|
||||
protected:
|
||||
void SetUp() {
|
||||
// Use number 0 as the the identifier and pass to CreateMediaFile.
|
||||
media_file_ = webrtc::MediaFile::CreateMediaFile(0);
|
||||
ASSERT_TRUE(media_file_ != NULL);
|
||||
}
|
||||
void TearDown() {
|
||||
webrtc::MediaFile::DestroyMediaFile(media_file_);
|
||||
media_file_ = NULL;
|
||||
}
|
||||
webrtc::MediaFile* media_file_;
|
||||
};
|
|
@ -1,629 +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 "modules/media_file/media_file_utility.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits>
|
||||
|
||||
#include "common_audio/wav_header.h"
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/include/module_common_types.h"
|
||||
#include "rtc_base/format_macros.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "typedefs.h" // NOLINT(build/include)
|
||||
|
||||
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];
|
||||
uint32_t fmt_ckSize;
|
||||
};
|
||||
} // unnamed namespace
|
||||
|
||||
namespace webrtc {
|
||||
ModuleFileUtility::ModuleFileUtility()
|
||||
: _wavFormatObj(),
|
||||
_dataSize(0),
|
||||
_readSizeBytes(0),
|
||||
_stopPointInMs(0),
|
||||
_startPointInMs(0),
|
||||
_playoutPositionMs(0),
|
||||
codec_info_(),
|
||||
_codecId(kCodecNoCodec),
|
||||
_bytesPerSample(0),
|
||||
_readPos(0),
|
||||
_reading(false),
|
||||
_tempData() {
|
||||
RTC_LOG(LS_INFO) << "ModuleFileUtility::ModuleFileUtility()";
|
||||
memset(&codec_info_, 0, sizeof(CodecInst));
|
||||
codec_info_.pltype = -1;
|
||||
}
|
||||
|
||||
ModuleFileUtility::~ModuleFileUtility() {
|
||||
RTC_LOG(LS_INFO) << "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];
|
||||
size_t i;
|
||||
bool dataFound = false;
|
||||
bool fmtFound = false;
|
||||
int8_t dummyRead;
|
||||
|
||||
_dataSize = 0;
|
||||
int len = wav.Read(&RIFFheaderObj, sizeof(WAVE_RIFF_header));
|
||||
if (len != static_cast<int>(sizeof(WAVE_RIFF_header))) {
|
||||
RTC_LOG(LS_ERROR) << "Not a wave file (too short)";
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
tmpStr[i] = RIFFheaderObj.ckID[i];
|
||||
}
|
||||
if (strcmp(tmpStr, "RIFF") != 0) {
|
||||
RTC_LOG(LS_ERROR) << "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) {
|
||||
RTC_LOG(LS_ERROR) << "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 =
|
||||
(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 == static_cast<int>(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));
|
||||
|
||||
if (CHUNKheaderObj.fmt_ckSize < sizeof(WAVE_FMTINFO_header)) {
|
||||
RTC_LOG(LS_ERROR) << "Chunk size is too small";
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < CHUNKheaderObj.fmt_ckSize - sizeof(WAVE_FMTINFO_header);
|
||||
i++) {
|
||||
len = wav.Read(&dummyRead, 1);
|
||||
if (len != 1) {
|
||||
RTC_LOG(LS_ERROR) << "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) {
|
||||
RTC_LOG(LS_ERROR) << "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 =
|
||||
(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)) {
|
||||
RTC_LOG(LS_ERROR) << "Coding formatTag value=" << _wavFormatObj.formatTag
|
||||
<< " not supported!";
|
||||
return -1;
|
||||
}
|
||||
if ((_wavFormatObj.nChannels < 1) || (_wavFormatObj.nChannels > 2)) {
|
||||
RTC_LOG(LS_ERROR) << "nChannels value=" << _wavFormatObj.nChannels
|
||||
<< " not supported!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((_wavFormatObj.nBitsPerSample != 8) &&
|
||||
(_wavFormatObj.nBitsPerSample != 16)) {
|
||||
RTC_LOG(LS_ERROR) << "nBitsPerSample value=" << _wavFormatObj.nBitsPerSample
|
||||
<< " not supported!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Calculate the number of bytes that 10 ms of audio data correspond to.
|
||||
size_t samples_per_10ms =
|
||||
((_wavFormatObj.formatTag == kWavFormatPcm) &&
|
||||
(_wavFormatObj.nSamplesPerSec == 44100))
|
||||
? 440
|
||||
: static_cast<size_t>(_wavFormatObj.nSamplesPerSec / 100);
|
||||
_readSizeBytes = samples_per_10ms * _wavFormatObj.nChannels *
|
||||
(_wavFormatObj.nBitsPerSample / 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ModuleFileUtility::InitWavCodec(uint32_t samplesPerSec,
|
||||
size_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 {
|
||||
RTC_LOG(LS_ERROR) << "Unsupported PCM frequency!";
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
RTC_LOG(LS_ERROR) << "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) {
|
||||
RTC_LOG(LS_ERROR) << "failed to read WAV header!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
_playoutPositionMs = 0;
|
||||
_readPos = 0;
|
||||
|
||||
if (start > 0) {
|
||||
uint8_t dummy[WAV_MAX_BUFFER_SIZE];
|
||||
int readLength;
|
||||
if (_readSizeBytes <= WAV_MAX_BUFFER_SIZE) {
|
||||
while (_playoutPositionMs < start) {
|
||||
readLength = wav.Read(dummy, _readSizeBytes);
|
||||
if (readLength == static_cast<int>(_readSizeBytes)) {
|
||||
_readPos += _readSizeBytes;
|
||||
_playoutPositionMs += 10;
|
||||
} else // Must have reached EOF before start position!
|
||||
{
|
||||
RTC_LOG(LS_ERROR) << "InitWavReading(), EOF before start position";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (InitWavCodec(_wavFormatObj.nSamplesPerSec, _wavFormatObj.nChannels,
|
||||
_wavFormatObj.nBitsPerSample,
|
||||
_wavFormatObj.formatTag) != 0) {
|
||||
return -1;
|
||||
}
|
||||
_bytesPerSample = static_cast<size_t>(_wavFormatObj.nBitsPerSample / 8);
|
||||
|
||||
_startPointInMs = start;
|
||||
_stopPointInMs = stop;
|
||||
_reading = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ModuleFileUtility::ReadWavDataAsMono(InStream& wav,
|
||||
int8_t* outData,
|
||||
const size_t bufferSize) {
|
||||
RTC_LOG(LS_VERBOSE) << "ModuleFileUtility::ReadWavDataAsMono(wav= " << &wav
|
||||
<< ", outData= " << static_cast<void*>(outData)
|
||||
<< ", bufSize= " << bufferSize << ")";
|
||||
|
||||
// The number of bytes that should be read from file.
|
||||
const size_t totalBytesNeeded = _readSizeBytes;
|
||||
// The number of bytes that will be written to outData.
|
||||
const size_t bytesRequested =
|
||||
(codec_info_.channels == 2) ? totalBytesNeeded >> 1 : totalBytesNeeded;
|
||||
if (bufferSize < bytesRequested) {
|
||||
RTC_LOG(LS_ERROR) << "ReadWavDataAsMono: output buffer is too short!";
|
||||
return -1;
|
||||
}
|
||||
if (outData == NULL) {
|
||||
RTC_LOG(LS_ERROR) << "ReadWavDataAsMono: output buffer NULL!";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_reading) {
|
||||
RTC_LOG(LS_ERROR) << "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) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "ReadWavDataAsMono: failed to read data from WAV file.";
|
||||
return -1;
|
||||
}
|
||||
// Output data is should be mono.
|
||||
if (codec_info_.channels == 2) {
|
||||
for (size_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 static_cast<int32_t>(bytesRequested);
|
||||
}
|
||||
|
||||
int32_t ModuleFileUtility::ReadWavData(InStream& wav,
|
||||
uint8_t* buffer,
|
||||
size_t dataLengthInBytes) {
|
||||
RTC_LOG(LS_VERBOSE) << "ModuleFileUtility::ReadWavData(wav= " << &wav
|
||||
<< ", buffer= " << static_cast<void*>(buffer)
|
||||
<< ", dataLen= " << dataLengthInBytes << ")";
|
||||
|
||||
if (buffer == NULL) {
|
||||
RTC_LOG(LS_ERROR) << "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 + 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::InitPCMReading(InStream& pcm,
|
||||
const uint32_t start,
|
||||
const uint32_t stop,
|
||||
uint32_t freq) {
|
||||
RTC_LOG(LS_VERBOSE) << "ModuleFileUtility::InitPCMReading(pcm= " << &pcm
|
||||
<< ", start=" << start << ", stop=" << stop
|
||||
<< ", freq=" << freq << ")";
|
||||
|
||||
int8_t dummy[320];
|
||||
int 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;
|
||||
} else if (freq == 48000) {
|
||||
strcpy(codec_info_.plname, "L16");
|
||||
codec_info_.pltype = -1;
|
||||
codec_info_.plfreq = 48000;
|
||||
codec_info_.pacsize = 480;
|
||||
codec_info_.channels = 1;
|
||||
codec_info_.rate = 768000;
|
||||
_codecId = kCodecL16_48Khz;
|
||||
}
|
||||
|
||||
// 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 != static_cast<int>(_readSizeBytes)) {
|
||||
return -1; // Must have reached EOF before start position!
|
||||
}
|
||||
_playoutPositionMs += 10;
|
||||
}
|
||||
}
|
||||
_reading = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ModuleFileUtility::ReadPCMData(InStream& pcm,
|
||||
int8_t* outData,
|
||||
size_t bufferSize) {
|
||||
RTC_LOG(LS_VERBOSE) << "ModuleFileUtility::ReadPCMData(pcm= " << &pcm
|
||||
<< ", outData= " << static_cast<void*>(outData)
|
||||
<< ", bufSize= " << bufferSize << ")";
|
||||
|
||||
if (outData == NULL) {
|
||||
RTC_LOG(LS_ERROR) << "buffer NULL";
|
||||
}
|
||||
|
||||
// Readsize for 10ms of audio data (2 bytes per sample).
|
||||
size_t bytesRequested = static_cast<size_t>(2 * codec_info_.plfreq / 100);
|
||||
if (bufferSize < bytesRequested) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "ReadPCMData: buffer not long enough for a 10ms frame.";
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int bytesRead = pcm.Read(outData, bytesRequested);
|
||||
if (bytesRead < static_cast<int>(bytesRequested)) {
|
||||
if (pcm.Rewind() == -1) {
|
||||
_reading = false;
|
||||
} else {
|
||||
if (InitPCMReading(pcm, _startPointInMs, _stopPointInMs,
|
||||
codec_info_.plfreq) == -1) {
|
||||
_reading = false;
|
||||
} else {
|
||||
size_t rest = bytesRequested - bytesRead;
|
||||
int len = pcm.Read(&(outData[bytesRead]), rest);
|
||||
if (len == static_cast<int>(rest)) {
|
||||
bytesRead += len;
|
||||
} else {
|
||||
_reading = false;
|
||||
}
|
||||
}
|
||||
if (bytesRead <= 0) {
|
||||
RTC_LOG(LS_ERROR) << "ReadPCMData: Failed to rewind audio file.";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesRead <= 0) {
|
||||
RTC_LOG(LS_VERBOSE) << "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::codec_info(CodecInst& codecInst) {
|
||||
RTC_LOG(LS_VERBOSE) << "ModuleFileUtility::codec_info(codecInst= "
|
||||
<< &codecInst << ")";
|
||||
|
||||
if (!_reading) {
|
||||
RTC_LOG(LS_ERROR) << "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;
|
||||
} else if (codecInst.plfreq == 48000) {
|
||||
_codecId = kCodecL16_48Khz;
|
||||
}
|
||||
}
|
||||
#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
|
||||
else if (STR_CASE_CMP(codecInst.plname, "G722") == 0) {
|
||||
_codecId = kCodecG722;
|
||||
}
|
||||
if (_codecId == kCodecNoCodec) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(&codec_info_, &codecInst, sizeof(CodecInst));
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ModuleFileUtility::PlayoutPositionMs() {
|
||||
RTC_LOG(LS_VERBOSE) << "ModuleFileUtility::PlayoutPosition()";
|
||||
|
||||
return _reading ? _playoutPositionMs : 0;
|
||||
}
|
||||
} // namespace webrtc
|
|
@ -1,158 +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.
|
||||
*/
|
||||
|
||||
// Note: the class cannot be used for reading and writing at the same time.
|
||||
#ifndef MODULES_MEDIA_FILE_MEDIA_FILE_UTILITY_H_
|
||||
#define MODULES_MEDIA_FILE_MEDIA_FILE_UTILITY_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/media_file/media_file_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
class InStream;
|
||||
class OutStream;
|
||||
|
||||
class ModuleFileUtility
|
||||
{
|
||||
public:
|
||||
|
||||
ModuleFileUtility();
|
||||
~ModuleFileUtility();
|
||||
|
||||
// Prepare for playing audio from stream.
|
||||
// startPointMs and stopPointMs, unless zero, specify what part of the file
|
||||
// should be read. From startPointMs ms to stopPointMs ms.
|
||||
int32_t InitWavReading(InStream& stream,
|
||||
const uint32_t startPointMs = 0,
|
||||
const uint32_t stopPointMs = 0);
|
||||
|
||||
// Put 10-60ms of audio data from stream into the audioBuffer depending on
|
||||
// codec frame size. dataLengthInBytes indicates the size of audioBuffer.
|
||||
// The return value is the number of bytes written to audioBuffer.
|
||||
// Note: This API only play mono audio but can be used on file containing
|
||||
// audio with more channels (in which case the audio will be converted to
|
||||
// mono).
|
||||
int32_t ReadWavDataAsMono(InStream& stream, int8_t* audioBuffer,
|
||||
const size_t dataLengthInBytes);
|
||||
|
||||
// Prepare for playing audio from stream.
|
||||
// startPointMs and stopPointMs, unless zero, specify what part of the file
|
||||
// should be read. From startPointMs ms to stopPointMs ms.
|
||||
// freqInHz is the PCM sampling frequency.
|
||||
// NOTE, allowed frequencies are 8000, 16000 and 32000 (Hz)
|
||||
int32_t InitPCMReading(InStream& stream,
|
||||
const uint32_t startPointMs = 0,
|
||||
const uint32_t stopPointMs = 0,
|
||||
const uint32_t freqInHz = 16000);
|
||||
|
||||
// Put 10-60ms of audio data from stream into the audioBuffer depending on
|
||||
// codec frame size. dataLengthInBytes indicates the size of audioBuffer.
|
||||
// The return value is the number of bytes written to audioBuffer.
|
||||
int32_t ReadPCMData(InStream& stream, int8_t* audioBuffer,
|
||||
const size_t dataLengthInBytes);
|
||||
|
||||
// Return the number of ms that have been played so far.
|
||||
uint32_t PlayoutPositionMs();
|
||||
|
||||
// Update codecInst according to the current audio codec being used for
|
||||
// reading or writing.
|
||||
int32_t codec_info(CodecInst& codecInst);
|
||||
|
||||
private:
|
||||
// Biggest WAV frame supported is 10 ms at 48kHz of 2 channel, 16 bit audio.
|
||||
static const size_t WAV_MAX_BUFFER_SIZE = 480 * 2 * 2;
|
||||
|
||||
|
||||
int32_t InitWavCodec(uint32_t samplesPerSec,
|
||||
size_t channels,
|
||||
uint32_t bitsPerSample,
|
||||
uint32_t formatTag);
|
||||
|
||||
// Parse the WAV header in stream.
|
||||
int32_t ReadWavHeader(InStream& stream);
|
||||
|
||||
// Put dataLengthInBytes of audio data from stream into the audioBuffer.
|
||||
// The return value is the number of bytes written to audioBuffer.
|
||||
int32_t ReadWavData(InStream& stream, uint8_t* audioBuffer,
|
||||
size_t dataLengthInBytes);
|
||||
|
||||
// Update the current audio codec being used for reading or writing
|
||||
// according to codecInst.
|
||||
int32_t set_codec_info(const CodecInst& codecInst);
|
||||
|
||||
struct WAVE_FMTINFO_header
|
||||
{
|
||||
int16_t formatTag;
|
||||
int16_t nChannels;
|
||||
int32_t nSamplesPerSec;
|
||||
int32_t nAvgBytesPerSec;
|
||||
int16_t nBlockAlign;
|
||||
int16_t nBitsPerSample;
|
||||
};
|
||||
// Identifiers for preencoded files.
|
||||
enum MediaFileUtility_CodecType
|
||||
{
|
||||
kCodecNoCodec = 0,
|
||||
kCodecIsac,
|
||||
kCodecIsacSwb,
|
||||
kCodecIsacLc,
|
||||
kCodecL16_8Khz,
|
||||
kCodecL16_16kHz,
|
||||
kCodecL16_32Khz,
|
||||
kCodecL16_48Khz,
|
||||
kCodecPcmu,
|
||||
kCodecPcma,
|
||||
kCodecIlbc20Ms,
|
||||
kCodecIlbc30Ms,
|
||||
kCodecG722,
|
||||
kCodecG722_1_32Kbps,
|
||||
kCodecG722_1_24Kbps,
|
||||
kCodecG722_1_16Kbps,
|
||||
kCodecG722_1c_48,
|
||||
kCodecG722_1c_32,
|
||||
kCodecG722_1c_24,
|
||||
kCodecAmr,
|
||||
kCodecAmrWb,
|
||||
kCodecG729,
|
||||
kCodecG729_1,
|
||||
kCodecG726_40,
|
||||
kCodecG726_32,
|
||||
kCodecG726_24,
|
||||
kCodecG726_16
|
||||
};
|
||||
|
||||
// TODO (hellner): why store multiple formats. Just store either codec_info_
|
||||
// or _wavFormatObj and supply conversion functions.
|
||||
WAVE_FMTINFO_header _wavFormatObj;
|
||||
size_t _dataSize; // Chunk size if reading a WAV file
|
||||
// Number of bytes to read. I.e. frame size in bytes. May be multiple
|
||||
// chunks if reading WAV.
|
||||
size_t _readSizeBytes;
|
||||
|
||||
uint32_t _stopPointInMs;
|
||||
uint32_t _startPointInMs;
|
||||
uint32_t _playoutPositionMs;
|
||||
|
||||
CodecInst codec_info_;
|
||||
MediaFileUtility_CodecType _codecId;
|
||||
|
||||
// The amount of bytes, on average, used for one audio sample.
|
||||
size_t _bytesPerSample;
|
||||
size_t _readPos;
|
||||
|
||||
bool _reading;
|
||||
|
||||
// Scratch buffer used for turning stereo audio to mono.
|
||||
uint8_t _tempData[WAV_MAX_BUFFER_SIZE];
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // MODULES_MEDIA_FILE_MEDIA_FILE_UTILITY_H_
|
|
@ -38,7 +38,6 @@ rtc_static_library("utility") {
|
|||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base:rtc_task_queue",
|
||||
"../../system_wrappers",
|
||||
"../media_file",
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -708,7 +708,6 @@ rtc_source_set("test_renderer_generic") {
|
|||
"../api:libjingle_peerconnection_api",
|
||||
"../common_video",
|
||||
"../media:rtc_media_base",
|
||||
"../modules/media_file",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"//testing/gtest",
|
||||
|
|
|
@ -10,7 +10,6 @@ include_rules = [
|
|||
"+modules/audio_device",
|
||||
"+modules/audio_mixer",
|
||||
"+modules/audio_processing",
|
||||
"+modules/media_file",
|
||||
"+modules/rtp_rtcp",
|
||||
"+modules/video_capture",
|
||||
"+modules/video_coding",
|
||||
|
|
Loading…
Reference in a new issue