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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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.
4
5 #include "base/bind.h"
6 #include "base/thread_task_runner_handle.h"
7 #include "content/renderer/pepper/audio_encoder_shim.h"
8 #include "content/renderer/render_thread_impl.h"
9 #include "ppapi/c/ppb_audio_buffer.h"
10 #include "ppapi/proxy/serialized_structs.h"
11 #include "third_party/opus/src/include/opus.h"
12
13 namespace content {
14
15 class AudioEncoderShim::EncoderImpl {
16 public:
17 virtual ~EncoderImpl() {}
18
19 // Called on the media thread.
20 void Encode(const scoped_refptr<AudioData>& input,
21 const scoped_refptr<AudioData>& output,
22 BitstreamBufferReadyCB callback);
23 void Stop();
24
25 // Called on the renderer thread.
26 virtual std::vector<PP_AudioProfileDescription> GetSupportedProfiles() = 0;
27 virtual bool Initialize(
28 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) = 0;
29 virtual int32_t GetNumberOfSamplesPerFrame() = 0;
30 virtual void RequestBitrateChange(uint32_t bitrate) = 0;
31
32 protected:
33 EncoderImpl(const base::WeakPtr<AudioEncoderShim>& shim);
34
35 // Called on the media thread.
36 virtual size_t EncodeInternal(const scoped_refptr<AudioData>& input,
37 const scoped_refptr<AudioData>& output) = 0;
38
39 private:
40 base::WeakPtr<AudioEncoderShim> shim_;
41 scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_;
42
43 DISALLOW_COPY_AND_ASSIGN(EncoderImpl);
44 };
45
46 AudioEncoderShim::EncoderImpl::EncoderImpl(
47 const base::WeakPtr<AudioEncoderShim>& shim)
48 : shim_(shim), renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
49
50 void AudioEncoderShim::EncoderImpl::Encode(
51 const scoped_refptr<AudioData>& input,
52 const scoped_refptr<AudioData>& output,
53 BitstreamBufferReadyCB callback) {
54 size_t size = EncodeInternal(input, output);
55 renderer_task_runner_->PostTask(
56 FROM_HERE, base::Bind(&AudioEncoderShim::OnEncodeDone, shim_, output,
57 size < 0 ? -1 : size, callback));
58 }
59
60 void AudioEncoderShim::EncoderImpl::Stop() {}
61
62 class AudioEncoderShim::OpusEncoderImpl : public AudioEncoderShim::EncoderImpl {
63 public:
64 OpusEncoderImpl(const base::WeakPtr<AudioEncoderShim>& shim);
65 ~OpusEncoderImpl() override;
66
67 private:
68 // AudioEncoderShim::Impl:
69 std::vector<PP_AudioProfileDescription> GetSupportedProfiles() override;
70 bool Initialize(
71 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) override;
72 int32_t GetNumberOfSamplesPerFrame() override;
73 size_t EncodeInternal(
74 const scoped_refptr<AudioEncoderShim::AudioData>& input,
75 const scoped_refptr<AudioEncoderShim::AudioData>& output) override;
76 void RequestBitrateChange(uint32_t bitrate) override;
77
78 scoped_ptr<uint8[]> encoder_memory_;
79 OpusEncoder* opus_encoder_;
80
81 ppapi::proxy::PPB_AudioEncodeParameters parameters_;
82
83 DISALLOW_COPY_AND_ASSIGN(OpusEncoderImpl);
84 };
85
86 AudioEncoderShim::OpusEncoderImpl::OpusEncoderImpl(
87 const base::WeakPtr<AudioEncoderShim>& shim)
88 : EncoderImpl(shim), opus_encoder_(nullptr) {}
89
90 AudioEncoderShim::OpusEncoderImpl::~OpusEncoderImpl() {}
91
92 std::vector<PP_AudioProfileDescription>
93 AudioEncoderShim::OpusEncoderImpl::GetSupportedProfiles() {
94 std::vector<PP_AudioProfileDescription> profiles;
95 static const uint32_t sampling_rates[] = {8000, 12000, 16000, 24000, 48000};
96
97 for (uint32_t i = 0; i < arraysize(sampling_rates); ++i) {
98 PP_AudioProfileDescription profile;
99 profile.profile = PP_AUDIOPROFILE_OPUS;
100 profile.max_channels = 2;
101 profile.sample_size = PP_AUDIOBUFFER_SAMPLESIZE_16_BITS;
102 profile.sample_rate = sampling_rates[i];
103 profile.hardware_accelerated = PP_FALSE;
104 profiles.push_back(profile);
105 }
106 return profiles;
107 }
108
109 bool AudioEncoderShim::OpusEncoderImpl::Initialize(
110 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) {
111 DCHECK(!encoder_memory_);
112
113 int32_t encoder_size = opus_encoder_get_size(parameters.channels);
114 if (encoder_size < 1)
115 return false;
116
117 encoder_memory_.reset(new uint8[encoder_size]);
118 opus_encoder_ = reinterpret_cast<OpusEncoder*>(encoder_memory_.get());
119
120 if (opus_encoder_init(opus_encoder_, parameters.input_sample_rate,
121 parameters.channels, OPUS_APPLICATION_AUDIO) != OPUS_OK)
122 return false;
123
124 if (opus_encoder_ctl(opus_encoder_,
125 OPUS_SET_BITRATE(parameters.initial_bitrate <= 0
126 ? OPUS_AUTO
127 : parameters.initial_bitrate)) !=
128 OPUS_OK)
129 return false;
130
131 parameters_ = parameters;
132
133 return true;
134 }
135
136 int32_t AudioEncoderShim::OpusEncoderImpl::GetNumberOfSamplesPerFrame() {
137 // Opus supports 2.5, 5, 10, 20, 40 or 60ms audio frames. We take
138 // 10ms by default.
139 return parameters_.input_sample_rate / 100;
140 }
141
142 size_t AudioEncoderShim::OpusEncoderImpl::EncodeInternal(
143 const scoped_refptr<AudioData>& input,
144 const scoped_refptr<AudioData>& output) {
145 return opus_encode(
146 opus_encoder_, reinterpret_cast<opus_int16*>(input->GetData()),
147 (input->GetSize() / parameters_.channels) / parameters_.input_sample_size,
148 output->GetData(), output->GetSize());
149 }
150
151 void AudioEncoderShim::OpusEncoderImpl::RequestBitrateChange(uint32_t bitrate) {
152 opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate));
153 }
154
155 AudioEncoderShim::AudioEncoderShim()
156 : media_task_runner_(RenderThreadImpl::current()
157 ->GetMediaThreadTaskRunner()),
158 weak_ptr_factory_(this) {}
159
160 AudioEncoderShim::~AudioEncoderShim() {
161 if (encoder_impl_)
162 media_task_runner_->PostTask(
163 FROM_HERE, base::Bind(&AudioEncoderShim::EncoderImpl::Stop,
164 base::Owned(encoder_impl_.release())));
165 }
166
167 std::vector<PP_AudioProfileDescription>
168 AudioEncoderShim::GetSupportedProfiles() {
169 std::vector<PP_AudioProfileDescription> profiles;
170 scoped_ptr<EncoderImpl> encoder(
171 new OpusEncoderImpl(weak_ptr_factory_.GetWeakPtr()));
172 std::vector<PP_AudioProfileDescription> codec_profiles =
173 encoder->GetSupportedProfiles();
174 for (const auto& desc : codec_profiles)
175 profiles.push_back(desc);
176 return profiles;
177 }
178
179 bool AudioEncoderShim::Initialize(
180 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) {
181 if (encoder_impl_ || parameters.output_profile != PP_AUDIOPROFILE_OPUS)
182 return false;
183
184 encoder_impl_.reset(new OpusEncoderImpl(weak_ptr_factory_.GetWeakPtr()));
185 return encoder_impl_->Initialize(parameters);
186 }
187
188 int32_t AudioEncoderShim::GetNumberOfSamplesPerFrame() {
189 return encoder_impl_->GetNumberOfSamplesPerFrame();
190 }
191
192 void AudioEncoderShim::Encode(const scoped_refptr<AudioData>& input,
193 const scoped_refptr<AudioData>& output,
194 BitstreamBufferReadyCB callback) {
195 media_task_runner_->PostTask(
196 FROM_HERE, base::Bind(&AudioEncoderShim::EncoderImpl::Encode,
197 base::Unretained(encoder_impl_.get()), input,
198 output, callback));
199 }
200
201 void AudioEncoderShim::RequestBitrateChange(uint32_t bitrate) {
202 media_task_runner_->PostTask(
203 FROM_HERE,
204 base::Bind(&AudioEncoderShim::EncoderImpl::RequestBitrateChange,
205 base::Unretained(encoder_impl_.get()), bitrate));
206 }
207
208 void AudioEncoderShim::OnEncodeDone(const scoped_refptr<AudioData>& output,
209 size_t size,
210 BitstreamBufferReadyCB callback) {
211 callback.Run(output, size);
212 }
213
214 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698