OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/receiver/audio_decoder.h" | 5 #include "media/cast/receiver/audio_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 class AudioDecoder::ImplBase | 22 class AudioDecoder::ImplBase |
23 : public base::RefCountedThreadSafe<AudioDecoder::ImplBase> { | 23 : public base::RefCountedThreadSafe<AudioDecoder::ImplBase> { |
24 public: | 24 public: |
25 ImplBase(const scoped_refptr<CastEnvironment>& cast_environment, | 25 ImplBase(const scoped_refptr<CastEnvironment>& cast_environment, |
26 Codec codec, | 26 Codec codec, |
27 int num_channels, | 27 int num_channels, |
28 int sampling_rate) | 28 int sampling_rate) |
29 : cast_environment_(cast_environment), | 29 : cast_environment_(cast_environment), |
30 codec_(codec), | 30 codec_(codec), |
31 num_channels_(num_channels), | 31 num_channels_(num_channels), |
32 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), | 32 operational_status_(STATUS_UNINITIALIZED), |
33 seen_first_frame_(false) { | 33 seen_first_frame_(false) { |
34 if (num_channels_ <= 0 || sampling_rate <= 0 || sampling_rate % 100 != 0) | 34 if (num_channels_ <= 0 || sampling_rate <= 0 || sampling_rate % 100 != 0) |
35 cast_initialization_status_ = STATUS_INVALID_AUDIO_CONFIGURATION; | 35 operational_status_ = STATUS_INVALID_CONFIGURATION; |
36 } | 36 } |
37 | 37 |
38 CastInitializationStatus InitializationResult() const { | 38 OperationalStatus InitializationResult() const { |
39 return cast_initialization_status_; | 39 return operational_status_; |
40 } | 40 } |
41 | 41 |
42 void DecodeFrame(scoped_ptr<EncodedFrame> encoded_frame, | 42 void DecodeFrame(scoped_ptr<EncodedFrame> encoded_frame, |
43 const DecodeFrameCallback& callback) { | 43 const DecodeFrameCallback& callback) { |
44 DCHECK_EQ(cast_initialization_status_, STATUS_AUDIO_INITIALIZED); | 44 DCHECK_EQ(operational_status_, STATUS_INITIALIZED); |
45 | 45 |
46 static_assert(sizeof(encoded_frame->frame_id) == sizeof(last_frame_id_), | 46 static_assert(sizeof(encoded_frame->frame_id) == sizeof(last_frame_id_), |
47 "size of frame_id types do not match"); | 47 "size of frame_id types do not match"); |
48 bool is_continuous = true; | 48 bool is_continuous = true; |
49 if (seen_first_frame_) { | 49 if (seen_first_frame_) { |
50 const uint32 frames_ahead = encoded_frame->frame_id - last_frame_id_; | 50 const uint32 frames_ahead = encoded_frame->frame_id - last_frame_id_; |
51 if (frames_ahead > 1) { | 51 if (frames_ahead > 1) { |
52 RecoverBecauseFramesWereDropped(); | 52 RecoverBecauseFramesWereDropped(); |
53 is_continuous = false; | 53 is_continuous = false; |
54 } | 54 } |
(...skipping 18 matching lines...) Expand all Loading... |
73 | 73 |
74 virtual void RecoverBecauseFramesWereDropped() {} | 74 virtual void RecoverBecauseFramesWereDropped() {} |
75 | 75 |
76 // Note: Implementation of Decode() is allowed to mutate |data|. | 76 // Note: Implementation of Decode() is allowed to mutate |data|. |
77 virtual scoped_ptr<AudioBus> Decode(uint8* data, int len) = 0; | 77 virtual scoped_ptr<AudioBus> Decode(uint8* data, int len) = 0; |
78 | 78 |
79 const scoped_refptr<CastEnvironment> cast_environment_; | 79 const scoped_refptr<CastEnvironment> cast_environment_; |
80 const Codec codec_; | 80 const Codec codec_; |
81 const int num_channels_; | 81 const int num_channels_; |
82 | 82 |
83 // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED. | 83 // Subclass' ctor is expected to set this to STATUS_INITIALIZED. |
84 CastInitializationStatus cast_initialization_status_; | 84 OperationalStatus operational_status_; |
85 | 85 |
86 private: | 86 private: |
87 bool seen_first_frame_; | 87 bool seen_first_frame_; |
88 uint32 last_frame_id_; | 88 uint32 last_frame_id_; |
89 | 89 |
90 DISALLOW_COPY_AND_ASSIGN(ImplBase); | 90 DISALLOW_COPY_AND_ASSIGN(ImplBase); |
91 }; | 91 }; |
92 | 92 |
93 class AudioDecoder::OpusImpl : public AudioDecoder::ImplBase { | 93 class AudioDecoder::OpusImpl : public AudioDecoder::ImplBase { |
94 public: | 94 public: |
95 OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment, | 95 OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment, |
96 int num_channels, | 96 int num_channels, |
97 int sampling_rate) | 97 int sampling_rate) |
98 : ImplBase(cast_environment, | 98 : ImplBase(cast_environment, |
99 CODEC_AUDIO_OPUS, | 99 CODEC_AUDIO_OPUS, |
100 num_channels, | 100 num_channels, |
101 sampling_rate), | 101 sampling_rate), |
102 decoder_memory_(new uint8[opus_decoder_get_size(num_channels)]), | 102 decoder_memory_(new uint8[opus_decoder_get_size(num_channels)]), |
103 opus_decoder_(reinterpret_cast<OpusDecoder*>(decoder_memory_.get())), | 103 opus_decoder_(reinterpret_cast<OpusDecoder*>(decoder_memory_.get())), |
104 max_samples_per_frame_( | 104 max_samples_per_frame_( |
105 kOpusMaxFrameDurationMillis * sampling_rate / 1000), | 105 kOpusMaxFrameDurationMillis * sampling_rate / 1000), |
106 buffer_(new float[max_samples_per_frame_ * num_channels]) { | 106 buffer_(new float[max_samples_per_frame_ * num_channels]) { |
107 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) | 107 if (ImplBase::operational_status_ != STATUS_UNINITIALIZED) |
108 return; | 108 return; |
109 if (opus_decoder_init(opus_decoder_, sampling_rate, num_channels) != | 109 if (opus_decoder_init(opus_decoder_, sampling_rate, num_channels) != |
110 OPUS_OK) { | 110 OPUS_OK) { |
111 ImplBase::cast_initialization_status_ = | 111 ImplBase::operational_status_ = STATUS_INVALID_CONFIGURATION; |
112 STATUS_INVALID_AUDIO_CONFIGURATION; | |
113 return; | 112 return; |
114 } | 113 } |
115 ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; | 114 ImplBase::operational_status_ = STATUS_INITIALIZED; |
116 } | 115 } |
117 | 116 |
118 private: | 117 private: |
119 ~OpusImpl() override {} | 118 ~OpusImpl() override {} |
120 | 119 |
121 void RecoverBecauseFramesWereDropped() override { | 120 void RecoverBecauseFramesWereDropped() override { |
122 // Passing NULL for the input data notifies the decoder of frame loss. | 121 // Passing NULL for the input data notifies the decoder of frame loss. |
123 const opus_int32 result = | 122 const opus_int32 result = |
124 opus_decode_float( | 123 opus_decode_float( |
125 opus_decoder_, NULL, 0, buffer_.get(), max_samples_per_frame_, 0); | 124 opus_decoder_, NULL, 0, buffer_.get(), max_samples_per_frame_, 0); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 161 |
163 class AudioDecoder::Pcm16Impl : public AudioDecoder::ImplBase { | 162 class AudioDecoder::Pcm16Impl : public AudioDecoder::ImplBase { |
164 public: | 163 public: |
165 Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment, | 164 Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment, |
166 int num_channels, | 165 int num_channels, |
167 int sampling_rate) | 166 int sampling_rate) |
168 : ImplBase(cast_environment, | 167 : ImplBase(cast_environment, |
169 CODEC_AUDIO_PCM16, | 168 CODEC_AUDIO_PCM16, |
170 num_channels, | 169 num_channels, |
171 sampling_rate) { | 170 sampling_rate) { |
172 if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED) | 171 if (ImplBase::operational_status_ != STATUS_UNINITIALIZED) |
173 return; | 172 return; |
174 ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED; | 173 ImplBase::operational_status_ = STATUS_INITIALIZED; |
175 } | 174 } |
176 | 175 |
177 private: | 176 private: |
178 ~Pcm16Impl() override {} | 177 ~Pcm16Impl() override {} |
179 | 178 |
180 scoped_ptr<AudioBus> Decode(uint8* data, int len) override { | 179 scoped_ptr<AudioBus> Decode(uint8* data, int len) override { |
181 scoped_ptr<AudioBus> audio_bus; | 180 scoped_ptr<AudioBus> audio_bus; |
182 const int num_samples = len / sizeof(int16) / num_channels_; | 181 const int num_samples = len / sizeof(int16) / num_channels_; |
183 if (num_samples <= 0) | 182 if (num_samples <= 0) |
184 return audio_bus.Pass(); | 183 return audio_bus.Pass(); |
(...skipping 27 matching lines...) Expand all Loading... |
212 impl_ = new Pcm16Impl(cast_environment, channels, sampling_rate); | 211 impl_ = new Pcm16Impl(cast_environment, channels, sampling_rate); |
213 break; | 212 break; |
214 default: | 213 default: |
215 NOTREACHED() << "Unknown or unspecified codec."; | 214 NOTREACHED() << "Unknown or unspecified codec."; |
216 break; | 215 break; |
217 } | 216 } |
218 } | 217 } |
219 | 218 |
220 AudioDecoder::~AudioDecoder() {} | 219 AudioDecoder::~AudioDecoder() {} |
221 | 220 |
222 CastInitializationStatus AudioDecoder::InitializationResult() const { | 221 OperationalStatus AudioDecoder::InitializationResult() const { |
223 if (impl_.get()) | 222 if (impl_.get()) |
224 return impl_->InitializationResult(); | 223 return impl_->InitializationResult(); |
225 return STATUS_UNSUPPORTED_AUDIO_CODEC; | 224 return STATUS_UNSUPPORTED_CODEC; |
226 } | 225 } |
227 | 226 |
228 void AudioDecoder::DecodeFrame( | 227 void AudioDecoder::DecodeFrame( |
229 scoped_ptr<EncodedFrame> encoded_frame, | 228 scoped_ptr<EncodedFrame> encoded_frame, |
230 const DecodeFrameCallback& callback) { | 229 const DecodeFrameCallback& callback) { |
231 DCHECK(encoded_frame.get()); | 230 DCHECK(encoded_frame.get()); |
232 DCHECK(!callback.is_null()); | 231 DCHECK(!callback.is_null()); |
233 if (!impl_.get() || | 232 if (!impl_.get() || impl_->InitializationResult() != STATUS_INITIALIZED) { |
234 impl_->InitializationResult() != STATUS_AUDIO_INITIALIZED) { | |
235 callback.Run(make_scoped_ptr<AudioBus>(NULL), false); | 233 callback.Run(make_scoped_ptr<AudioBus>(NULL), false); |
236 return; | 234 return; |
237 } | 235 } |
238 cast_environment_->PostTask(CastEnvironment::AUDIO, | 236 cast_environment_->PostTask(CastEnvironment::AUDIO, |
239 FROM_HERE, | 237 FROM_HERE, |
240 base::Bind(&AudioDecoder::ImplBase::DecodeFrame, | 238 base::Bind(&AudioDecoder::ImplBase::DecodeFrame, |
241 impl_, | 239 impl_, |
242 base::Passed(&encoded_frame), | 240 base::Passed(&encoded_frame), |
243 callback)); | 241 callback)); |
244 } | 242 } |
245 | 243 |
246 } // namespace cast | 244 } // namespace cast |
247 } // namespace media | 245 } // namespace media |
OLD | NEW |