Make an AudioEncoder subclass for Opus

BUG=3926
R=henrik.lundin@webrtc.org, kjellander@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/23239004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7552 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
kwiberg@webrtc.org
2014-10-29 07:28:36 +00:00
parent 2623695dfb
commit 663fdd02fd
6 changed files with 185 additions and 53 deletions

View File

@ -33,13 +33,13 @@ class AudioEncoder {
// output.
bool Encode(uint32_t timestamp,
const int16_t* audio,
size_t num_samples,
size_t num_samples_per_channel,
size_t max_encoded_bytes,
uint8_t* encoded,
size_t* encoded_bytes,
uint32_t* encoded_timestamp) {
CHECK_EQ(num_samples,
static_cast<size_t>(sample_rate_hz() / 100 * num_channels()));
CHECK_EQ(num_samples_per_channel,
static_cast<size_t>(sample_rate_hz() / 100));
bool ret = Encode(timestamp,
audio,
max_encoded_bytes,

View File

@ -0,0 +1,104 @@
/*
* 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.
*/
#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
namespace webrtc {
namespace {
// We always encode at 48 kHz.
const int kSampleRateHz = 48000;
int DivExact(int a, int b) {
CHECK_EQ(a % b, 0);
return a / b;
}
int16_t ClampInt16(size_t x) {
return static_cast<int16_t>(
std::min(x, static_cast<size_t>(std::numeric_limits<int16_t>::max())));
}
int16_t CastInt16(size_t x) {
DCHECK_LE(x, static_cast<size_t>(std::numeric_limits<int16_t>::max()));
return static_cast<int16_t>(x);
}
} // namespace
AudioEncoderOpus::Config::Config() : frame_size_ms(20), num_channels(1) {}
bool AudioEncoderOpus::Config::IsOk() const {
if (frame_size_ms <= 0 || frame_size_ms % 10 != 0)
return false;
if (num_channels <= 0)
return false;
return true;
}
AudioEncoderOpus::AudioEncoderOpus(const Config& config)
: num_10ms_frames_per_packet_(DivExact(config.frame_size_ms, 10)),
num_channels_(config.num_channels),
samples_per_10ms_frame_(DivExact(kSampleRateHz, 100) * num_channels_) {
CHECK(config.IsOk());
input_buffer_.reserve(num_10ms_frames_per_packet_ * samples_per_10ms_frame_);
CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, num_channels_));
}
AudioEncoderOpus::~AudioEncoderOpus() {
CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
}
int AudioEncoderOpus::sample_rate_hz() const {
return kSampleRateHz;
}
int AudioEncoderOpus::num_channels() const {
return num_channels_;
}
int AudioEncoderOpus::num_10ms_frames_per_packet() const {
return num_10ms_frames_per_packet_;
}
bool AudioEncoderOpus::Encode(uint32_t timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded,
size_t* encoded_bytes,
uint32_t* encoded_timestamp) {
if (input_buffer_.empty())
first_timestamp_in_buffer_ = timestamp;
input_buffer_.insert(input_buffer_.end(), audio,
audio + samples_per_10ms_frame_);
if (input_buffer_.size() < (static_cast<size_t>(num_10ms_frames_per_packet_) *
samples_per_10ms_frame_)) {
*encoded_bytes = 0;
return true;
}
CHECK_EQ(input_buffer_.size(),
static_cast<size_t>(num_10ms_frames_per_packet_) *
samples_per_10ms_frame_);
int16_t r = WebRtcOpus_Encode(
inst_, &input_buffer_[0],
DivExact(CastInt16(input_buffer_.size()), num_channels_),
ClampInt16(max_encoded_bytes), encoded);
input_buffer_.clear();
if (r < 0)
return false;
*encoded_bytes = r;
*encoded_timestamp = first_timestamp_in_buffer_;
return true;
}
} // namespace webrtc

View File

@ -0,0 +1,55 @@
/*
* 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.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_AUDIO_ENCODER_OPUS_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_AUDIO_ENCODER_OPUS_H_
#include <vector>
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
namespace webrtc {
class AudioEncoderOpus : public AudioEncoder {
public:
struct Config {
Config();
bool IsOk() const;
int frame_size_ms;
int num_channels;
};
explicit AudioEncoderOpus(const Config& config);
virtual ~AudioEncoderOpus() OVERRIDE;
virtual int sample_rate_hz() const OVERRIDE;
virtual int num_channels() const OVERRIDE;
virtual int num_10ms_frames_per_packet() const OVERRIDE;
protected:
virtual bool Encode(uint32_t timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded,
size_t* encoded_bytes,
uint32_t* encoded_timestamp) OVERRIDE;
private:
const int num_10ms_frames_per_packet_;
const int num_channels_;
const int samples_per_10ms_frame_;
std::vector<int16_t> input_buffer_;
OpusEncInst* inst_;
uint32_t first_timestamp_in_buffer_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_AUDIO_ENCODER_OPUS_H_

View File

@ -27,6 +27,8 @@
'<(webrtc_root)',
],
'sources': [
'audio_encoder_opus.cc',
'interface/audio_encoder_opus.h',
'interface/opus_interface.h',
'opus_inst.h',
'opus_interface.c',