| 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 |