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