Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / media / cast / receiver / audio_decoder.cc
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
16 namespace media {
17 namespace 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.
22 class AudioDecoder::ImplBase
23     : public base::RefCountedThreadSafe<AudioDecoder::ImplBase> {
24  public:
25   ImplBase(const scoped_refptr<CastEnvironment>& cast_environment,
26            Codec 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<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 Codec 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
93 class 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                  CODEC_AUDIO_OPUS,
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
163 class 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                  CODEC_AUDIO_PCM16,
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
201 AudioDecoder::AudioDecoder(
202     const scoped_refptr<CastEnvironment>& cast_environment,
203     int channels,
204     int sampling_rate,
205     Codec codec)
206     : cast_environment_(cast_environment) {
207   switch (codec) {
208     case CODEC_AUDIO_OPUS:
209       impl_ = new OpusImpl(cast_environment, channels, sampling_rate);
210       break;
211     case CODEC_AUDIO_PCM16:
212       impl_ = new Pcm16Impl(cast_environment, channels, sampling_rate);
213       break;
214     default:
215       NOTREACHED() << "Unknown or unspecified codec.";
216       break;
217   }
218 }
219
220 AudioDecoder::~AudioDecoder() {}
221
222 CastInitializationStatus AudioDecoder::InitializationResult() const {
223   if (impl_)
224     return impl_->InitializationResult();
225   return STATUS_UNSUPPORTED_AUDIO_CODEC;
226 }
227
228 void AudioDecoder::DecodeFrame(
229     scoped_ptr<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