1 // Copyright 2014 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.
4 
5 #include "media/cast/receiver/audio_decoder.h"
6 
7 #include <stdint.h>
8 
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/sys_byteorder.h"
18 #include "build/build_config.h"
19 #include "third_party/opus/src/include/opus.h"
20 
21 namespace media {
22 namespace cast {
23 
24 // Base class that handles the common problem of detecting dropped frames, and
25 // then invoking the Decode() method implemented by the subclasses to convert
26 // the encoded payload data into usable audio data.
27 class AudioDecoder::ImplBase
28     : public base::RefCountedThreadSafe<AudioDecoder::ImplBase> {
29  public:
ImplBase(const scoped_refptr<CastEnvironment> & cast_environment,Codec codec,int num_channels,int sampling_rate)30   ImplBase(const scoped_refptr<CastEnvironment>& cast_environment,
31            Codec codec,
32            int num_channels,
33            int sampling_rate)
34       : cast_environment_(cast_environment),
35         codec_(codec),
36         num_channels_(num_channels),
37         operational_status_(STATUS_UNINITIALIZED) {
38     if (num_channels_ <= 0 || sampling_rate <= 0 || sampling_rate % 100 != 0) {
39       operational_status_ = STATUS_INVALID_CONFIGURATION;
40     }
41   }
42 
InitializationResult() const43   OperationalStatus InitializationResult() const {
44     return operational_status_;
45   }
46 
DecodeFrame(std::unique_ptr<EncodedFrame> encoded_frame,DecodeFrameCallback callback)47   void DecodeFrame(std::unique_ptr<EncodedFrame> encoded_frame,
48                    DecodeFrameCallback callback) {
49     DCHECK_EQ(operational_status_, STATUS_INITIALIZED);
50 
51     bool is_continuous = true;
52     DCHECK(!encoded_frame->frame_id.is_null());
53     if (!last_frame_id_.is_null()) {
54       if (encoded_frame->frame_id > (last_frame_id_ + 1)) {
55         RecoverBecauseFramesWereDropped();
56         is_continuous = false;
57       }
58     }
59     last_frame_id_ = encoded_frame->frame_id;
60 
61     std::unique_ptr<AudioBus> decoded_audio =
62         Decode(encoded_frame->mutable_bytes(),
63                static_cast<int>(encoded_frame->data.size()));
64     if (!decoded_audio) {
65       VLOG(2) << "Decoding of frame " << encoded_frame->frame_id << " failed.";
66       cast_environment_->PostTask(
67           CastEnvironment::MAIN, FROM_HERE,
68           base::BindOnce(std::move(callback), std::move(decoded_audio), false));
69       return;
70     }
71 
72     std::unique_ptr<FrameEvent> event(new FrameEvent());
73     event->timestamp = cast_environment_->Clock()->NowTicks();
74     event->type = FRAME_DECODED;
75     event->media_type = AUDIO_EVENT;
76     event->rtp_timestamp = encoded_frame->rtp_timestamp;
77     event->frame_id = encoded_frame->frame_id;
78     cast_environment_->logger()->DispatchFrameEvent(std::move(event));
79 
80     cast_environment_->PostTask(
81         CastEnvironment::MAIN, FROM_HERE,
82         base::BindOnce(std::move(callback), std::move(decoded_audio),
83                        is_continuous));
84   }
85 
86  protected:
87   friend class base::RefCountedThreadSafe<ImplBase>;
88   virtual ~ImplBase() = default;
89 
RecoverBecauseFramesWereDropped()90   virtual void RecoverBecauseFramesWereDropped() {}
91 
92   // Note: Implementation of Decode() is allowed to mutate |data|.
93   virtual std::unique_ptr<AudioBus> Decode(uint8_t* data, int len) = 0;
94 
95   const scoped_refptr<CastEnvironment> cast_environment_;
96   const Codec codec_;
97   const int num_channels_;
98 
99   // Subclass' ctor is expected to set this to STATUS_INITIALIZED.
100   OperationalStatus operational_status_;
101 
102  private:
103   FrameId last_frame_id_;
104 
105   DISALLOW_COPY_AND_ASSIGN(ImplBase);
106 };
107 
108 class AudioDecoder::OpusImpl final : public AudioDecoder::ImplBase {
109  public:
OpusImpl(const scoped_refptr<CastEnvironment> & cast_environment,int num_channels,int sampling_rate)110   OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment,
111            int num_channels,
112            int sampling_rate)
113       : ImplBase(cast_environment,
114                  CODEC_AUDIO_OPUS,
115                  num_channels,
116                  sampling_rate),
117         decoder_memory_(new uint8_t[opus_decoder_get_size(num_channels)]),
118         opus_decoder_(reinterpret_cast<OpusDecoder*>(decoder_memory_.get())),
119         max_samples_per_frame_(kOpusMaxFrameDurationMillis * sampling_rate /
120                                1000),
121         buffer_(new float[max_samples_per_frame_ * num_channels]) {
122     if (ImplBase::operational_status_ != STATUS_UNINITIALIZED) {
123       return;
124     }
125     if (opus_decoder_init(opus_decoder_, sampling_rate, num_channels) !=
126             OPUS_OK) {
127       ImplBase::operational_status_ = STATUS_INVALID_CONFIGURATION;
128       return;
129     }
130     ImplBase::operational_status_ = STATUS_INITIALIZED;
131   }
132 
133  private:
134   ~OpusImpl() final = default;
135 
RecoverBecauseFramesWereDropped()136   void RecoverBecauseFramesWereDropped() final {
137     // Passing nullptr for the input data notifies the decoder of frame loss.
138     const opus_int32 result = opus_decode_float(
139         opus_decoder_, nullptr, 0, buffer_.get(), max_samples_per_frame_, 0);
140     DCHECK_GE(result, 0);
141   }
142 
Decode(uint8_t * data,int len)143   std::unique_ptr<AudioBus> Decode(uint8_t* data, int len) final {
144     std::unique_ptr<AudioBus> audio_bus;
145     const opus_int32 num_samples_decoded = opus_decode_float(
146         opus_decoder_, data, len, buffer_.get(), max_samples_per_frame_, 0);
147     if (num_samples_decoded <= 0)
148       return audio_bus;  // Decode error.
149 
150     // Copy interleaved samples from |buffer_| into a new AudioBus (where
151     // samples are stored in planar format, for each channel).
152     audio_bus = AudioBus::Create(num_channels_, num_samples_decoded);
153     // TODO(miu): This should be moved into AudioBus::FromInterleaved().
154     for (int ch = 0; ch < num_channels_; ++ch) {
155       const float* src = buffer_.get() + ch;
156       const float* const src_end = src + num_samples_decoded * num_channels_;
157       float* dest = audio_bus->channel(ch);
158       for (; src < src_end; src += num_channels_, ++dest)
159         *dest = *src;
160     }
161     return audio_bus;
162   }
163 
164   const std::unique_ptr<uint8_t[]> decoder_memory_;
165   OpusDecoder* const opus_decoder_;
166   const int max_samples_per_frame_;
167   const std::unique_ptr<float[]> buffer_;
168 
169   // According to documentation in third_party/opus/src/include/opus.h, we must
170   // provide enough space in |buffer_| to contain 120ms of samples.  At 48 kHz,
171   // then, that means 5760 samples times the number of channels.
172   static const int kOpusMaxFrameDurationMillis = 120;
173 
174   DISALLOW_COPY_AND_ASSIGN(OpusImpl);
175 };
176 
177 class AudioDecoder::Pcm16Impl final : public AudioDecoder::ImplBase {
178  public:
Pcm16Impl(const scoped_refptr<CastEnvironment> & cast_environment,int num_channels,int sampling_rate)179   Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment,
180             int num_channels,
181             int sampling_rate)
182       : ImplBase(cast_environment,
183                  CODEC_AUDIO_PCM16,
184                  num_channels,
185                  sampling_rate) {
186     if (ImplBase::operational_status_ != STATUS_UNINITIALIZED)
187       return;
188     ImplBase::operational_status_ = STATUS_INITIALIZED;
189   }
190 
191  private:
192   ~Pcm16Impl() final = default;
193 
Decode(uint8_t * data,int len)194   std::unique_ptr<AudioBus> Decode(uint8_t* data, int len) final {
195     std::unique_ptr<AudioBus> audio_bus;
196     const int num_samples = len / sizeof(int16_t) / num_channels_;
197     if (num_samples <= 0)
198       return audio_bus;
199 
200     int16_t* const pcm_data = reinterpret_cast<int16_t*>(data);
201 #if defined(ARCH_CPU_LITTLE_ENDIAN)
202     // Convert endianness.
203     const int num_elements = num_samples * num_channels_;
204     for (int i = 0; i < num_elements; ++i)
205       pcm_data[i] = static_cast<int16_t>(base::NetToHost16(pcm_data[i]));
206 #endif
207     audio_bus = AudioBus::Create(num_channels_, num_samples);
208     audio_bus->FromInterleaved<SignedInt16SampleTypeTraits>(pcm_data,
209                                                             num_samples);
210     return audio_bus;
211   }
212 
213   DISALLOW_COPY_AND_ASSIGN(Pcm16Impl);
214 };
215 
AudioDecoder(const scoped_refptr<CastEnvironment> & cast_environment,int channels,int sampling_rate,Codec codec)216 AudioDecoder::AudioDecoder(
217     const scoped_refptr<CastEnvironment>& cast_environment,
218     int channels,
219     int sampling_rate,
220     Codec codec)
221     : cast_environment_(cast_environment) {
222   switch (codec) {
223     case CODEC_AUDIO_OPUS:
224       impl_ = new OpusImpl(cast_environment, channels, sampling_rate);
225       break;
226     case CODEC_AUDIO_PCM16:
227       impl_ = new Pcm16Impl(cast_environment, channels, sampling_rate);
228       break;
229     default:
230       NOTREACHED() << "Unknown or unspecified codec.";
231       break;
232   }
233 }
234 
235 AudioDecoder::~AudioDecoder() = default;
236 
InitializationResult() const237 OperationalStatus AudioDecoder::InitializationResult() const {
238   if (impl_.get())
239     return impl_->InitializationResult();
240   return STATUS_UNSUPPORTED_CODEC;
241 }
242 
DecodeFrame(std::unique_ptr<EncodedFrame> encoded_frame,DecodeFrameCallback callback)243 void AudioDecoder::DecodeFrame(std::unique_ptr<EncodedFrame> encoded_frame,
244                                DecodeFrameCallback callback) {
245   DCHECK(encoded_frame.get());
246   DCHECK(!callback.is_null());
247   if (!impl_.get() || impl_->InitializationResult() != STATUS_INITIALIZED) {
248     std::move(callback).Run(base::WrapUnique<AudioBus>(nullptr), false);
249     return;
250   }
251   cast_environment_->PostTask(
252       CastEnvironment::AUDIO, FROM_HERE,
253       base::BindOnce(&AudioDecoder::ImplBase::DecodeFrame, impl_,
254                      std::move(encoded_frame), std::move(callback)));
255 }
256 
257 }  // namespace cast
258 }  // namespace media
259