1 // Copyright 2013 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 "media/cast/audio_receiver/audio_decoder.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"
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
> {
25 ImplBase(const scoped_refptr
<CastEnvironment
>& cast_environment
,
26 transport::AudioCodec codec
,
29 : cast_environment_(cast_environment
),
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
;
38 CastInitializationStatus
InitializationResult() const {
39 return cast_initialization_status_
;
42 void DecodeFrame(scoped_ptr
<transport::EncodedFrame
> encoded_frame
,
43 const DecodeFrameCallback
& callback
) {
44 DCHECK_EQ(cast_initialization_status_
, STATUS_AUDIO_INITIALIZED
);
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;
56 seen_first_frame_
= true;
58 last_frame_id_
= encoded_frame
->frame_id
;
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
,
66 base::Passed(&decoded_audio
),
71 friend class base::RefCountedThreadSafe
<ImplBase
>;
72 virtual ~ImplBase() {}
74 virtual void RecoverBecauseFramesWereDropped() {}
76 // Note: Implementation of Decode() is allowed to mutate |data|.
77 virtual scoped_ptr
<AudioBus
> Decode(uint8
* data
, int len
) = 0;
79 const scoped_refptr
<CastEnvironment
> cast_environment_
;
80 const transport::AudioCodec codec_
;
81 const int num_channels_
;
83 // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED.
84 CastInitializationStatus cast_initialization_status_
;
87 bool seen_first_frame_
;
88 uint32 last_frame_id_
;
90 DISALLOW_COPY_AND_ASSIGN(ImplBase
);
93 class AudioDecoder::OpusImpl
: public AudioDecoder::ImplBase
{
95 OpusImpl(const scoped_refptr
<CastEnvironment
>& cast_environment
,
98 : ImplBase(cast_environment
,
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
)
109 if (opus_decoder_init(opus_decoder_
, sampling_rate
, num_channels
) !=
111 ImplBase::cast_initialization_status_
=
112 STATUS_INVALID_AUDIO_CONFIGURATION
;
115 ImplBase::cast_initialization_status_
= STATUS_AUDIO_INITIALIZED
;
119 virtual ~OpusImpl() {}
121 virtual void RecoverBecauseFramesWereDropped() OVERRIDE
{
122 // Passing NULL for the input data notifies the decoder of frame loss.
123 const opus_int32 result
=
125 opus_decoder_
, NULL
, 0, buffer_
.get(), max_samples_per_frame_
, 0);
126 DCHECK_GE(result
, 0);
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.
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
)
147 return audio_bus
.Pass();
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_
;
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;
160 DISALLOW_COPY_AND_ASSIGN(OpusImpl
);
163 class AudioDecoder::Pcm16Impl
: public AudioDecoder::ImplBase
{
165 Pcm16Impl(const scoped_refptr
<CastEnvironment
>& cast_environment
,
168 : ImplBase(cast_environment
,
172 if (ImplBase::cast_initialization_status_
!= STATUS_AUDIO_UNINITIALIZED
)
174 ImplBase::cast_initialization_status_
= STATUS_AUDIO_INITIALIZED
;
178 virtual ~Pcm16Impl() {}
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();
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
]));
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();
198 DISALLOW_COPY_AND_ASSIGN(Pcm16Impl
);
201 AudioDecoder::AudioDecoder(
202 const scoped_refptr
<CastEnvironment
>& cast_environment
,
203 const AudioReceiverConfig
& audio_config
)
204 : cast_environment_(cast_environment
) {
205 switch (audio_config
.codec
) {
206 case transport::kOpus
:
207 impl_
= new OpusImpl(cast_environment
,
208 audio_config
.channels
,
209 audio_config
.frequency
);
211 case transport::kPcm16
:
212 impl_
= new Pcm16Impl(cast_environment
,
213 audio_config
.channels
,
214 audio_config
.frequency
);
217 NOTREACHED() << "Unknown or unspecified codec.";
222 AudioDecoder::~AudioDecoder() {}
224 CastInitializationStatus
AudioDecoder::InitializationResult() const {
226 return impl_
->InitializationResult();
227 return STATUS_UNSUPPORTED_AUDIO_CODEC
;
230 void AudioDecoder::DecodeFrame(
231 scoped_ptr
<transport::EncodedFrame
> encoded_frame
,
232 const DecodeFrameCallback
& callback
) {
233 DCHECK(encoded_frame
.get());
234 DCHECK(!callback
.is_null());
235 if (!impl_
|| impl_
->InitializationResult() != STATUS_AUDIO_INITIALIZED
) {
236 callback
.Run(make_scoped_ptr
<AudioBus
>(NULL
), false);
239 cast_environment_
->PostTask(CastEnvironment::AUDIO
,
241 base::Bind(&AudioDecoder::ImplBase::DecodeFrame
,
243 base::Passed(&encoded_frame
),