| Index: media/cast/audio_receiver/audio_decoder.cc
|
| diff --git a/media/cast/audio_receiver/audio_decoder.cc b/media/cast/audio_receiver/audio_decoder.cc
|
| deleted file mode 100644
|
| index e4e9a1453eb68d71b96cb90a560de9698e97e874..0000000000000000000000000000000000000000
|
| --- a/media/cast/audio_receiver/audio_decoder.cc
|
| +++ /dev/null
|
| @@ -1,248 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "media/cast/audio_receiver/audio_decoder.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/location.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/ref_counted.h"
|
| -#include "base/sys_byteorder.h"
|
| -#include "media/cast/cast_defines.h"
|
| -#include "third_party/opus/src/include/opus.h"
|
| -
|
| -namespace media {
|
| -namespace cast {
|
| -
|
| -// Base class that handles the common problem of detecting dropped frames, and
|
| -// then invoking the Decode() method implemented by the subclasses to convert
|
| -// the encoded payload data into usable audio data.
|
| -class AudioDecoder::ImplBase
|
| - : public base::RefCountedThreadSafe<AudioDecoder::ImplBase> {
|
| - public:
|
| - ImplBase(const scoped_refptr<CastEnvironment>& cast_environment,
|
| - transport::AudioCodec codec,
|
| - int num_channels,
|
| - int sampling_rate)
|
| - : cast_environment_(cast_environment),
|
| - codec_(codec),
|
| - num_channels_(num_channels),
|
| - cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED),
|
| - seen_first_frame_(false) {
|
| - if (num_channels_ <= 0 || sampling_rate <= 0 || sampling_rate % 100 != 0)
|
| - cast_initialization_status_ = STATUS_INVALID_AUDIO_CONFIGURATION;
|
| - }
|
| -
|
| - CastInitializationStatus InitializationResult() const {
|
| - return cast_initialization_status_;
|
| - }
|
| -
|
| - void DecodeFrame(scoped_ptr<transport::EncodedFrame> encoded_frame,
|
| - const DecodeFrameCallback& callback) {
|
| - DCHECK_EQ(cast_initialization_status_, STATUS_AUDIO_INITIALIZED);
|
| -
|
| - COMPILE_ASSERT(sizeof(encoded_frame->frame_id) == sizeof(last_frame_id_),
|
| - size_of_frame_id_types_do_not_match);
|
| - bool is_continuous = true;
|
| - if (seen_first_frame_) {
|
| - const uint32 frames_ahead = encoded_frame->frame_id - last_frame_id_;
|
| - if (frames_ahead > 1) {
|
| - RecoverBecauseFramesWereDropped();
|
| - is_continuous = false;
|
| - }
|
| - } else {
|
| - seen_first_frame_ = true;
|
| - }
|
| - last_frame_id_ = encoded_frame->frame_id;
|
| -
|
| - scoped_ptr<AudioBus> decoded_audio = Decode(
|
| - encoded_frame->mutable_bytes(),
|
| - static_cast<int>(encoded_frame->data.size()));
|
| - cast_environment_->PostTask(CastEnvironment::MAIN,
|
| - FROM_HERE,
|
| - base::Bind(callback,
|
| - base::Passed(&decoded_audio),
|
| - is_continuous));
|
| - }
|
| -
|
| - protected:
|
| - friend class base::RefCountedThreadSafe<ImplBase>;
|
| - virtual ~ImplBase() {}
|
| -
|
| - virtual void RecoverBecauseFramesWereDropped() {}
|
| -
|
| - // Note: Implementation of Decode() is allowed to mutate |data|.
|
| - virtual scoped_ptr<AudioBus> Decode(uint8* data, int len) = 0;
|
| -
|
| - const scoped_refptr<CastEnvironment> cast_environment_;
|
| - const transport::AudioCodec codec_;
|
| - const int num_channels_;
|
| -
|
| - // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED.
|
| - CastInitializationStatus cast_initialization_status_;
|
| -
|
| - private:
|
| - bool seen_first_frame_;
|
| - uint32 last_frame_id_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ImplBase);
|
| -};
|
| -
|
| -class AudioDecoder::OpusImpl : public AudioDecoder::ImplBase {
|
| - public:
|
| - OpusImpl(const scoped_refptr<CastEnvironment>& cast_environment,
|
| - int num_channels,
|
| - int sampling_rate)
|
| - : ImplBase(cast_environment,
|
| - transport::kOpus,
|
| - num_channels,
|
| - sampling_rate),
|
| - decoder_memory_(new uint8[opus_decoder_get_size(num_channels)]),
|
| - opus_decoder_(reinterpret_cast<OpusDecoder*>(decoder_memory_.get())),
|
| - max_samples_per_frame_(
|
| - kOpusMaxFrameDurationMillis * sampling_rate / 1000),
|
| - buffer_(new float[max_samples_per_frame_ * num_channels]) {
|
| - if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED)
|
| - return;
|
| - if (opus_decoder_init(opus_decoder_, sampling_rate, num_channels) !=
|
| - OPUS_OK) {
|
| - ImplBase::cast_initialization_status_ =
|
| - STATUS_INVALID_AUDIO_CONFIGURATION;
|
| - return;
|
| - }
|
| - ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED;
|
| - }
|
| -
|
| - private:
|
| - virtual ~OpusImpl() {}
|
| -
|
| - virtual void RecoverBecauseFramesWereDropped() OVERRIDE {
|
| - // Passing NULL for the input data notifies the decoder of frame loss.
|
| - const opus_int32 result =
|
| - opus_decode_float(
|
| - opus_decoder_, NULL, 0, buffer_.get(), max_samples_per_frame_, 0);
|
| - DCHECK_GE(result, 0);
|
| - }
|
| -
|
| - virtual scoped_ptr<AudioBus> Decode(uint8* data, int len) OVERRIDE {
|
| - scoped_ptr<AudioBus> audio_bus;
|
| - const opus_int32 num_samples_decoded = opus_decode_float(
|
| - opus_decoder_, data, len, buffer_.get(), max_samples_per_frame_, 0);
|
| - if (num_samples_decoded <= 0)
|
| - return audio_bus.Pass(); // Decode error.
|
| -
|
| - // Copy interleaved samples from |buffer_| into a new AudioBus (where
|
| - // samples are stored in planar format, for each channel).
|
| - audio_bus = AudioBus::Create(num_channels_, num_samples_decoded).Pass();
|
| - // TODO(miu): This should be moved into AudioBus::FromInterleaved().
|
| - for (int ch = 0; ch < num_channels_; ++ch) {
|
| - const float* src = buffer_.get() + ch;
|
| - const float* const src_end = src + num_samples_decoded * num_channels_;
|
| - float* dest = audio_bus->channel(ch);
|
| - for (; src < src_end; src += num_channels_, ++dest)
|
| - *dest = *src;
|
| - }
|
| - return audio_bus.Pass();
|
| - }
|
| -
|
| - const scoped_ptr<uint8[]> decoder_memory_;
|
| - OpusDecoder* const opus_decoder_;
|
| - const int max_samples_per_frame_;
|
| - const scoped_ptr<float[]> buffer_;
|
| -
|
| - // According to documentation in third_party/opus/src/include/opus.h, we must
|
| - // provide enough space in |buffer_| to contain 120ms of samples. At 48 kHz,
|
| - // then, that means 5760 samples times the number of channels.
|
| - static const int kOpusMaxFrameDurationMillis = 120;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(OpusImpl);
|
| -};
|
| -
|
| -class AudioDecoder::Pcm16Impl : public AudioDecoder::ImplBase {
|
| - public:
|
| - Pcm16Impl(const scoped_refptr<CastEnvironment>& cast_environment,
|
| - int num_channels,
|
| - int sampling_rate)
|
| - : ImplBase(cast_environment,
|
| - transport::kPcm16,
|
| - num_channels,
|
| - sampling_rate) {
|
| - if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED)
|
| - return;
|
| - ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED;
|
| - }
|
| -
|
| - private:
|
| - virtual ~Pcm16Impl() {}
|
| -
|
| - virtual scoped_ptr<AudioBus> Decode(uint8* data, int len) OVERRIDE {
|
| - scoped_ptr<AudioBus> audio_bus;
|
| - const int num_samples = len / sizeof(int16) / num_channels_;
|
| - if (num_samples <= 0)
|
| - return audio_bus.Pass();
|
| -
|
| - int16* const pcm_data = reinterpret_cast<int16*>(data);
|
| -#if defined(ARCH_CPU_LITTLE_ENDIAN)
|
| - // Convert endianness.
|
| - const int num_elements = num_samples * num_channels_;
|
| - for (int i = 0; i < num_elements; ++i)
|
| - pcm_data[i] = static_cast<int16>(base::NetToHost16(pcm_data[i]));
|
| -#endif
|
| - audio_bus = AudioBus::Create(num_channels_, num_samples).Pass();
|
| - audio_bus->FromInterleaved(pcm_data, num_samples, sizeof(int16));
|
| - return audio_bus.Pass();
|
| - }
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Pcm16Impl);
|
| -};
|
| -
|
| -AudioDecoder::AudioDecoder(
|
| - const scoped_refptr<CastEnvironment>& cast_environment,
|
| - const FrameReceiverConfig& audio_config)
|
| - : cast_environment_(cast_environment) {
|
| - switch (audio_config.codec.audio) {
|
| - case transport::kOpus:
|
| - impl_ = new OpusImpl(cast_environment,
|
| - audio_config.channels,
|
| - audio_config.frequency);
|
| - break;
|
| - case transport::kPcm16:
|
| - impl_ = new Pcm16Impl(cast_environment,
|
| - audio_config.channels,
|
| - audio_config.frequency);
|
| - break;
|
| - default:
|
| - NOTREACHED() << "Unknown or unspecified codec.";
|
| - break;
|
| - }
|
| -}
|
| -
|
| -AudioDecoder::~AudioDecoder() {}
|
| -
|
| -CastInitializationStatus AudioDecoder::InitializationResult() const {
|
| - if (impl_)
|
| - return impl_->InitializationResult();
|
| - return STATUS_UNSUPPORTED_AUDIO_CODEC;
|
| -}
|
| -
|
| -void AudioDecoder::DecodeFrame(
|
| - scoped_ptr<transport::EncodedFrame> encoded_frame,
|
| - const DecodeFrameCallback& callback) {
|
| - DCHECK(encoded_frame.get());
|
| - DCHECK(!callback.is_null());
|
| - if (!impl_ || impl_->InitializationResult() != STATUS_AUDIO_INITIALIZED) {
|
| - callback.Run(make_scoped_ptr<AudioBus>(NULL), false);
|
| - return;
|
| - }
|
| - cast_environment_->PostTask(CastEnvironment::AUDIO,
|
| - FROM_HERE,
|
| - base::Bind(&AudioDecoder::ImplBase::DecodeFrame,
|
| - impl_,
|
| - base::Passed(&encoded_frame),
|
| - callback));
|
| -}
|
| -
|
| -} // namespace cast
|
| -} // namespace media
|
|
|