1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/codec/audio_decoder_opus.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "base/time/time.h"
10 #include "remoting/proto/audio.pb.h"
11 #include "third_party/opus/src/include/opus.h"
17 // Maximum size of an Opus frame in milliseconds.
18 const int kMaxFrameSizeMs
= 120;
20 // Hosts will never generate more than 100 frames in a single packet.
21 const int kMaxFramesPerPacket
= 100;
23 const AudioPacket::SamplingRate kSamplingRate
=
24 AudioPacket::SAMPLING_RATE_48000
;
28 AudioDecoderOpus::AudioDecoderOpus()
34 AudioDecoderOpus::~AudioDecoderOpus() {
38 void AudioDecoderOpus::InitDecoder() {
41 decoder_
= opus_decoder_create(kSamplingRate
, channels_
, &error
);
43 LOG(ERROR
) << "Failed to create OPUS decoder; Error code: " << error
;
47 void AudioDecoderOpus::DestroyDecoder() {
49 opus_decoder_destroy(decoder_
);
54 bool AudioDecoderOpus::ResetForPacket(AudioPacket
* packet
) {
55 if (packet
->channels() != channels_
||
56 packet
->sampling_rate() != sampling_rate_
) {
59 channels_
= packet
->channels();
60 sampling_rate_
= packet
->sampling_rate();
62 if (channels_
<= 0 || channels_
> 2 ||
63 sampling_rate_
!= kSamplingRate
) {
64 LOG(WARNING
) << "Unsupported OPUS parameters: "
65 << channels_
<< " channels with "
66 << sampling_rate_
<< " samples per second.";
75 return decoder_
!= NULL
;
79 scoped_ptr
<AudioPacket
> AudioDecoderOpus::Decode(
80 scoped_ptr
<AudioPacket
> packet
) {
81 if (packet
->encoding() != AudioPacket::ENCODING_OPUS
) {
82 LOG(WARNING
) << "Received an audio packet with encoding "
83 << packet
->encoding() << " when an OPUS packet was expected.";
86 if (packet
->data_size() > kMaxFramesPerPacket
) {
87 LOG(WARNING
) << "Received an packet with too many frames.";
91 if (!ResetForPacket(packet
.get())) {
95 // Create a new packet of decoded data.
96 scoped_ptr
<AudioPacket
> decoded_packet(new AudioPacket());
97 decoded_packet
->set_encoding(AudioPacket::ENCODING_RAW
);
98 decoded_packet
->set_sampling_rate(kSamplingRate
);
99 decoded_packet
->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2
);
100 decoded_packet
->set_channels(packet
->channels());
102 int max_frame_samples
= kMaxFrameSizeMs
* kSamplingRate
/
103 base::Time::kMillisecondsPerSecond
;
104 int max_frame_bytes
= max_frame_samples
* channels_
*
105 decoded_packet
->bytes_per_sample();
107 std::string
* decoded_data
= decoded_packet
->add_data();
108 decoded_data
->resize(packet
->data_size() * max_frame_bytes
);
111 for (int i
= 0; i
< packet
->data_size(); ++i
) {
113 reinterpret_cast<int16
*>(string_as_array(decoded_data
) + buffer_pos
);
114 CHECK_LE(buffer_pos
+ max_frame_bytes
,
115 static_cast<int>(decoded_data
->size()));
116 std::string
* frame
= packet
->mutable_data(i
);
117 unsigned char* frame_data
=
118 reinterpret_cast<unsigned char*>(string_as_array(frame
));
119 int result
= opus_decode(decoder_
, frame_data
, frame
->size(),
120 pcm_buffer
, max_frame_samples
, 0);
122 LOG(ERROR
) << "Failed decoding Opus frame. Error code: " << result
;
127 buffer_pos
+= result
* packet
->channels() *
128 decoded_packet
->bytes_per_sample();
135 decoded_data
->resize(buffer_pos
);
137 return decoded_packet
.Pass();
140 } // namespace remoting