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.
5 #include "media/cast/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
,
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
<EncodedFrame
> encoded_frame
,
43 const DecodeFrameCallback
& callback
) {
44 DCHECK_EQ(cast_initialization_status_
, STATUS_AUDIO_INITIALIZED
);
46 static_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_
;
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 ~OpusImpl() override
{}
121 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 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 ~Pcm16Impl() override
{}
180 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
,
206 : cast_environment_(cast_environment
) {
208 case CODEC_AUDIO_OPUS
:
209 impl_
= new OpusImpl(cast_environment
, channels
, sampling_rate
);
211 case CODEC_AUDIO_PCM16
:
212 impl_
= new Pcm16Impl(cast_environment
, channels
, sampling_rate
);
215 NOTREACHED() << "Unknown or unspecified codec.";
220 AudioDecoder::~AudioDecoder() {}
222 CastInitializationStatus
AudioDecoder::InitializationResult() const {
224 return impl_
->InitializationResult();
225 return STATUS_UNSUPPORTED_AUDIO_CODEC
;
228 void AudioDecoder::DecodeFrame(
229 scoped_ptr
<EncodedFrame
> encoded_frame
,
230 const DecodeFrameCallback
& callback
) {
231 DCHECK(encoded_frame
.get());
232 DCHECK(!callback
.is_null());
234 impl_
->InitializationResult() != STATUS_AUDIO_INITIALIZED
) {
235 callback
.Run(make_scoped_ptr
<AudioBus
>(NULL
), false);
238 cast_environment_
->PostTask(CastEnvironment::AUDIO
,
240 base::Bind(&AudioDecoder::ImplBase::DecodeFrame
,
242 base::Passed(&encoded_frame
),