Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(928)

Unified Diff: content/renderer/pepper/audio_encoder_shim.cc

Issue 1348563003: ppapi: implement PPB_AudioEncoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address tsepez's review Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/pepper/audio_encoder_shim.cc
diff --git a/content/renderer/pepper/audio_encoder_shim.cc b/content/renderer/pepper/audio_encoder_shim.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a125537693bb4dd09f9ed37bfb2441f5977449c3
--- /dev/null
+++ b/content/renderer/pepper/audio_encoder_shim.cc
@@ -0,0 +1,214 @@
+// Copyright 2015 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 "base/bind.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/renderer/pepper/audio_encoder_shim.h"
+#include "content/renderer/render_thread_impl.h"
+#include "ppapi/c/ppb_audio_buffer.h"
+#include "ppapi/proxy/serialized_structs.h"
+#include "third_party/opus/src/include/opus.h"
+
+namespace content {
+
+class AudioEncoderShim::EncoderImpl {
+ public:
+ virtual ~EncoderImpl() {}
+
+ // Called on the media thread.
+ void Encode(const scoped_refptr<AudioData>& input,
+ const scoped_refptr<AudioData>& output,
+ BitstreamBufferReadyCB callback);
+ void Stop();
+
+ // Called on the renderer thread.
+ virtual std::vector<PP_AudioProfileDescription> GetSupportedProfiles() = 0;
+ virtual bool Initialize(
+ const ppapi::proxy::PPB_AudioEncodeParameters& parameters) = 0;
+ virtual int32_t GetNumberOfSamplesPerFrame() = 0;
+ virtual void RequestBitrateChange(uint32_t bitrate) = 0;
+
+ protected:
+ EncoderImpl(const base::WeakPtr<AudioEncoderShim>& shim);
+
+ // Called on the media thread.
+ virtual size_t EncodeInternal(const scoped_refptr<AudioData>& input,
+ const scoped_refptr<AudioData>& output) = 0;
+
+ private:
+ base::WeakPtr<AudioEncoderShim> shim_;
+ scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(EncoderImpl);
+};
+
+AudioEncoderShim::EncoderImpl::EncoderImpl(
+ const base::WeakPtr<AudioEncoderShim>& shim)
+ : shim_(shim), renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
+
+void AudioEncoderShim::EncoderImpl::Encode(
+ const scoped_refptr<AudioData>& input,
+ const scoped_refptr<AudioData>& output,
+ BitstreamBufferReadyCB callback) {
+ size_t size = EncodeInternal(input, output);
+ renderer_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AudioEncoderShim::OnEncodeDone, shim_, output,
+ size < 0 ? -1 : size, callback));
+}
+
+void AudioEncoderShim::EncoderImpl::Stop() {}
+
+class AudioEncoderShim::OpusEncoderImpl : public AudioEncoderShim::EncoderImpl {
+ public:
+ OpusEncoderImpl(const base::WeakPtr<AudioEncoderShim>& shim);
+ ~OpusEncoderImpl() override;
+
+ private:
+ // AudioEncoderShim::Impl:
+ std::vector<PP_AudioProfileDescription> GetSupportedProfiles() override;
+ bool Initialize(
+ const ppapi::proxy::PPB_AudioEncodeParameters& parameters) override;
+ int32_t GetNumberOfSamplesPerFrame() override;
+ size_t EncodeInternal(
+ const scoped_refptr<AudioEncoderShim::AudioData>& input,
+ const scoped_refptr<AudioEncoderShim::AudioData>& output) override;
+ void RequestBitrateChange(uint32_t bitrate) override;
+
+ scoped_ptr<uint8[]> encoder_memory_;
+ OpusEncoder* opus_encoder_;
+
+ ppapi::proxy::PPB_AudioEncodeParameters parameters_;
+
+ DISALLOW_COPY_AND_ASSIGN(OpusEncoderImpl);
+};
+
+AudioEncoderShim::OpusEncoderImpl::OpusEncoderImpl(
+ const base::WeakPtr<AudioEncoderShim>& shim)
+ : EncoderImpl(shim), opus_encoder_(nullptr) {}
+
+AudioEncoderShim::OpusEncoderImpl::~OpusEncoderImpl() {}
+
+std::vector<PP_AudioProfileDescription>
+AudioEncoderShim::OpusEncoderImpl::GetSupportedProfiles() {
+ std::vector<PP_AudioProfileDescription> profiles;
+ static const uint32_t sampling_rates[] = {8000, 12000, 16000, 24000, 48000};
+
+ for (uint32_t i = 0; i < arraysize(sampling_rates); ++i) {
+ PP_AudioProfileDescription profile;
+ profile.profile = PP_AUDIOPROFILE_OPUS;
+ profile.max_channels = 2;
+ profile.sample_size = PP_AUDIOBUFFER_SAMPLESIZE_16_BITS;
+ profile.sample_rate = sampling_rates[i];
+ profile.hardware_accelerated = PP_FALSE;
+ profiles.push_back(profile);
+ }
+ return profiles;
+}
+
+bool AudioEncoderShim::OpusEncoderImpl::Initialize(
+ const ppapi::proxy::PPB_AudioEncodeParameters& parameters) {
+ DCHECK(!encoder_memory_);
+
+ int32_t encoder_size = opus_encoder_get_size(parameters.channels);
+ if (encoder_size < 1)
+ return false;
+
+ encoder_memory_.reset(new uint8[encoder_size]);
+ opus_encoder_ = reinterpret_cast<OpusEncoder*>(encoder_memory_.get());
+
+ if (opus_encoder_init(opus_encoder_, parameters.input_sample_rate,
+ parameters.channels, OPUS_APPLICATION_AUDIO) != OPUS_OK)
+ return false;
+
+ if (opus_encoder_ctl(opus_encoder_,
+ OPUS_SET_BITRATE(parameters.initial_bitrate <= 0
+ ? OPUS_AUTO
+ : parameters.initial_bitrate)) !=
+ OPUS_OK)
+ return false;
+
+ parameters_ = parameters;
+
+ return true;
+}
+
+int32_t AudioEncoderShim::OpusEncoderImpl::GetNumberOfSamplesPerFrame() {
+ // Opus supports 2.5, 5, 10, 20, 40 or 60ms audio frames. We take
+ // 10ms by default.
+ return parameters_.input_sample_rate / 100;
+}
+
+size_t AudioEncoderShim::OpusEncoderImpl::EncodeInternal(
+ const scoped_refptr<AudioData>& input,
+ const scoped_refptr<AudioData>& output) {
+ return opus_encode(
+ opus_encoder_, reinterpret_cast<opus_int16*>(input->GetData()),
+ (input->GetSize() / parameters_.channels) / parameters_.input_sample_size,
+ output->GetData(), output->GetSize());
+}
+
+void AudioEncoderShim::OpusEncoderImpl::RequestBitrateChange(uint32_t bitrate) {
+ opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate));
+}
+
+AudioEncoderShim::AudioEncoderShim()
+ : media_task_runner_(RenderThreadImpl::current()
+ ->GetMediaThreadTaskRunner()),
+ weak_ptr_factory_(this) {}
+
+AudioEncoderShim::~AudioEncoderShim() {
+ if (encoder_impl_)
+ media_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AudioEncoderShim::EncoderImpl::Stop,
+ base::Owned(encoder_impl_.release())));
+}
+
+std::vector<PP_AudioProfileDescription>
+AudioEncoderShim::GetSupportedProfiles() {
+ std::vector<PP_AudioProfileDescription> profiles;
+ scoped_ptr<EncoderImpl> encoder(
+ new OpusEncoderImpl(weak_ptr_factory_.GetWeakPtr()));
+ std::vector<PP_AudioProfileDescription> codec_profiles =
+ encoder->GetSupportedProfiles();
+ for (const auto& desc : codec_profiles)
+ profiles.push_back(desc);
+ return profiles;
+}
+
+bool AudioEncoderShim::Initialize(
+ const ppapi::proxy::PPB_AudioEncodeParameters& parameters) {
+ if (encoder_impl_ || parameters.output_profile != PP_AUDIOPROFILE_OPUS)
+ return false;
+
+ encoder_impl_.reset(new OpusEncoderImpl(weak_ptr_factory_.GetWeakPtr()));
+ return encoder_impl_->Initialize(parameters);
+}
+
+int32_t AudioEncoderShim::GetNumberOfSamplesPerFrame() {
+ return encoder_impl_->GetNumberOfSamplesPerFrame();
+}
+
+void AudioEncoderShim::Encode(const scoped_refptr<AudioData>& input,
+ const scoped_refptr<AudioData>& output,
+ BitstreamBufferReadyCB callback) {
+ media_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AudioEncoderShim::EncoderImpl::Encode,
+ base::Unretained(encoder_impl_.get()), input,
+ output, callback));
+}
+
+void AudioEncoderShim::RequestBitrateChange(uint32_t bitrate) {
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioEncoderShim::EncoderImpl::RequestBitrateChange,
+ base::Unretained(encoder_impl_.get()), bitrate));
+}
+
+void AudioEncoderShim::OnEncodeDone(const scoped_refptr<AudioData>& output,
+ size_t size,
+ BitstreamBufferReadyCB callback) {
+ callback.Run(output, size);
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698