• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // https://github.com/google/opuscpp
16 
17 #include <iterator>
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include <android-base/logging.h>
23 #include "host/frontend/stream_audio/opuscpp/opus_wrapper.h"
24 
ErrorToString(int error)25 std::string opus::ErrorToString(int error) {
26   switch (error) {
27     case OPUS_OK:
28       return "OK";
29     case OPUS_BAD_ARG:
30       return "One or more invalid/out of range arguments.";
31     case OPUS_BUFFER_TOO_SMALL:
32       return "The mode struct passed is invalid.";
33     case OPUS_INTERNAL_ERROR:
34       return "An internal error was detected.";
35     case OPUS_INVALID_PACKET:
36       return "The compressed data passed is corrupted.";
37     case OPUS_UNIMPLEMENTED:
38       return "Invalid/unsupported request number.";
39     case OPUS_INVALID_STATE:
40       return "An encoder or decoder structure is invalid or already freed.";
41     default:
42       return "Unknown error code: " + std::to_string(error);
43   }
44 }
45 
operator ()(OpusEncoder * encoder) const46 void opus::internal::OpusDestroyer::operator()(OpusEncoder* encoder) const
47     noexcept {
48   opus_encoder_destroy(encoder);
49 }
50 
operator ()(OpusDecoder * decoder) const51 void opus::internal::OpusDestroyer::operator()(OpusDecoder* decoder) const
52     noexcept {
53   opus_decoder_destroy(decoder);
54 }
55 
Encoder(opus_int32 sample_rate,int num_channels,int application,int expected_loss_percent)56 opus::Encoder::Encoder(opus_int32 sample_rate, int num_channels,
57                        int application, int expected_loss_percent)
58     : num_channels_{num_channels} {
59   int error{};
60   encoder_.reset(
61       opus_encoder_create(sample_rate, num_channels, application, &error));
62   valid_ = error == OPUS_OK;
63   if (!valid()) {
64     LOG(INFO) << "Could not construct encoder. Error: " << ErrorToString(error);
65     return;
66   }
67   if (expected_loss_percent > 0) {
68     LOG(INFO) << "Enabling FEC in the encoder.";
69     Ctl(OPUS_SET_INBAND_FEC(1));
70     Ctl(OPUS_SET_PACKET_LOSS_PERC(expected_loss_percent));
71   }
72 }
73 
ResetState()74 bool opus::Encoder::ResetState() {
75   valid_ = Ctl(OPUS_RESET_STATE) == OPUS_OK;
76   return valid_;
77 }
78 
SetBitrate(int bitrate)79 bool opus::Encoder::SetBitrate(int bitrate) {
80   valid_ = Ctl(OPUS_SET_BITRATE(bitrate)) == OPUS_OK;
81   return valid_;
82 }
83 
SetVariableBitrate(int vbr)84 bool opus::Encoder::SetVariableBitrate(int vbr) {
85   valid_ = Ctl(OPUS_SET_VBR(vbr)) == OPUS_OK;
86   return valid_;
87 }
88 
SetComplexity(int complexity)89 bool opus::Encoder::SetComplexity(int complexity) {
90   valid_ = Ctl(OPUS_SET_COMPLEXITY(complexity)) == OPUS_OK;
91   return valid_;
92 }
93 
GetLookahead()94 int opus::Encoder::GetLookahead() {
95   opus_int32 skip{};
96   valid_ = Ctl(OPUS_GET_LOOKAHEAD(&skip)) == OPUS_OK;
97   return skip;
98 }
99 
Encode(const std::vector<opus_int16> & pcm,int frame_size)100 std::vector<std::vector<unsigned char>> opus::Encoder::Encode(
101     const std::vector<opus_int16>& pcm, int frame_size) {
102   constexpr auto sample_size = sizeof(pcm[0]);
103   const auto frame_length = frame_size * num_channels_ * sample_size;
104   auto data_length = pcm.size() * sample_size;
105   if (data_length % frame_length != 0u) {
106     LOG(WARNING) << "PCM samples contain an incomplete frame. Ignoring the "
107                     "incomplete frame.";
108     data_length -= (data_length % frame_length);
109   }
110 
111   std::vector<std::vector<unsigned char>> encoded;
112   for (std::size_t i{}; i < data_length; i += frame_length) {
113     encoded.push_back(EncodeFrame(pcm.begin() + (i / sample_size), frame_size));
114   }
115   return encoded;
116 }
117 
EncodeFrame(const std::vector<opus_int16>::const_iterator & frame_start,int frame_size)118 std::vector<unsigned char> opus::Encoder::EncodeFrame(
119     const std::vector<opus_int16>::const_iterator& frame_start,
120     int frame_size) {
121   const auto frame_length = (frame_size * num_channels_ * sizeof(*frame_start));
122   std::vector<unsigned char> encoded(frame_length);
123   auto num_bytes = opus_encode(encoder_.get(), &*frame_start, frame_size,
124                                encoded.data(), encoded.size());
125   if (num_bytes < 0) {
126     LOG(ERROR) << "Encode error: " << opus::ErrorToString(num_bytes);
127     return {};
128   }
129   encoded.resize(num_bytes);
130   return encoded;
131 }
132 
Decoder(opus_uint32 sample_rate,int num_channels)133 opus::Decoder::Decoder(opus_uint32 sample_rate, int num_channels)
134     : num_channels_(num_channels) {
135   int error{};
136   decoder_.reset(opus_decoder_create(sample_rate, num_channels, &error));
137   valid_ = error == OPUS_OK;
138 }
139 
Decode(const std::vector<std::vector<unsigned char>> & packets,int frame_size,bool decode_fec)140 std::vector<opus_int16> opus::Decoder::Decode(
141     const std::vector<std::vector<unsigned char>>& packets, int frame_size,
142     bool decode_fec) {
143   std::vector<opus_int16> decoded;
144   for (const auto& enc : packets) {
145     auto just_decoded = Decode(enc, frame_size, decode_fec);
146     decoded.insert(std::end(decoded), std::begin(just_decoded),
147                    std::end(just_decoded));
148   }
149   return decoded;
150 }
151 
Decode(const std::vector<unsigned char> & packet,int frame_size,bool decode_fec)152 std::vector<opus_int16> opus::Decoder::Decode(
153     const std::vector<unsigned char>& packet, int frame_size, bool decode_fec) {
154   const auto frame_length = (frame_size * num_channels_ * sizeof(opus_int16));
155   std::vector<opus_int16> decoded(frame_length);
156   auto num_samples = opus_decode(decoder_.get(), packet.data(), packet.size(),
157                                  decoded.data(), frame_size, decode_fec);
158   if (num_samples < 0) {
159     LOG(ERROR) << "Decode error: " << opus::ErrorToString(num_samples);
160     return {};
161   }
162   decoded.resize(num_samples * num_channels_);
163   return decoded;
164 }
165 
DecodeDummy(int frame_size)166 std::vector<opus_int16> opus::Decoder::DecodeDummy(int frame_size) {
167   const auto frame_length = (frame_size * num_channels_ * sizeof(opus_int16));
168   std::vector<opus_int16> decoded(frame_length);
169   auto num_samples =
170       opus_decode(decoder_.get(), nullptr, 0, decoded.data(), frame_size, true);
171   if (num_samples < 0) {
172     LOG(ERROR) << "Decode error: " << opus::ErrorToString(num_samples);
173     return {};
174   }
175   decoded.resize(num_samples * num_channels_);
176   return decoded;
177 }
178