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

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: Created 5 years, 3 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 int32_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
51 void AudioEncoderShim::EncoderImpl::Encode(
52 const scoped_refptr<AudioData>& input,
53 const scoped_refptr<AudioData>& output,
54 BitstreamBufferReadyCB callback) {
55 int32_t size = EncodeInternal(input, output);
56 renderer_task_runner_->PostTask(
57 FROM_HERE, base::Bind(&AudioEncoderShim::OnEncodeDone, shim_, output,
58 size < 0 ? -1 : size, callback));
59 }
60
61 void AudioEncoderShim::EncoderImpl::Stop() {
62 }
63
64 class AudioEncoderShim::OpusEncoderImpl : public AudioEncoderShim::EncoderImpl {
65 public:
66 OpusEncoderImpl(const base::WeakPtr<AudioEncoderShim>& shim);
67 ~OpusEncoderImpl() override;
68
69 private:
70 // AudioEncoderShim::Impl:
71 std::vector<PP_AudioProfileDescription> GetSupportedProfiles() override;
72 bool Initialize(
73 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) override;
74 int32_t GetNumberOfSamplesPerFrame() override;
75 int32_t EncodeInternal(
76 const scoped_refptr<AudioEncoderShim::AudioData>& input,
77 const scoped_refptr<AudioEncoderShim::AudioData>& output) override;
78 void RequestBitrateChange(uint32_t bitrate) override;
79
80 scoped_ptr<uint8[]> encoder_memory_;
81 OpusEncoder* opus_encoder_;
82
83 ppapi::proxy::PPB_AudioEncodeParameters parameters_;
84
85 DISALLOW_COPY_AND_ASSIGN(OpusEncoderImpl);
86 };
87
88 AudioEncoderShim::OpusEncoderImpl::OpusEncoderImpl(
89 const base::WeakPtr<AudioEncoderShim>& shim)
90 : EncoderImpl(shim), opus_encoder_(nullptr) {
91 }
92
93 AudioEncoderShim::OpusEncoderImpl::~OpusEncoderImpl() {
94 }
95
96 std::vector<PP_AudioProfileDescription>
97 AudioEncoderShim::OpusEncoderImpl::GetSupportedProfiles() {
98 std::vector<PP_AudioProfileDescription> profiles;
99 uint32_t sampling_rates[] = {8000, 12000, 16000, 24000, 48000};
Tom Sepez 2015/09/17 18:11:12 nit: probably a static const.
llandwerlin-old 2015/10/05 16:10:59 Done.
100
101 for (uint32_t i = 0; i < arraysize(sampling_rates); i++) {
Tom Sepez 2015/09/17 18:11:12 nit: ++i
llandwerlin-old 2015/10/05 16:10:59 Done.
102 PP_AudioProfileDescription profile;
103 profile.profile = PP_AUDIOPROFILE_OPUS;
104 profile.max_channels = 2;
105 profile.sample_size = PP_AUDIOBUFFER_SAMPLESIZE_16_BITS;
106 profile.sample_rate = sampling_rates[i];
107 profile.hardware_accelerated = PP_FALSE;
108 profiles.push_back(profile);
109 }
110 return profiles;
111 }
112
113 bool AudioEncoderShim::OpusEncoderImpl::Initialize(
114 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) {
115 DCHECK(!encoder_memory_);
116
117 int32_t encoder_size = opus_encoder_get_size(parameters.channels);
118 if (encoder_size < 1)
119 return false;
120
121 encoder_memory_.reset(new uint8[encoder_size]);
122 opus_encoder_ = reinterpret_cast<OpusEncoder*>(encoder_memory_.get());
123
124 if (opus_encoder_init(opus_encoder_, parameters.input_sample_rate,
125 parameters.channels, OPUS_APPLICATION_AUDIO) != OPUS_OK)
126 return false;
127
128 if (opus_encoder_ctl(opus_encoder_,
129 OPUS_SET_BITRATE(parameters.initial_bitrate <= 0
130 ? OPUS_AUTO
131 : parameters.initial_bitrate)) !=
132 OPUS_OK)
133 return false;
134
135 parameters_ = parameters;
136
137 return true;
138 }
139
140 int32_t AudioEncoderShim::OpusEncoderImpl::GetNumberOfSamplesPerFrame() {
141 // Opus supports 2.5, 5, 10, 20, 40 or 60ms audio frames. We take
142 // 10ms by default.
143 return parameters_.input_sample_rate / 100;
144 }
145
146 int32_t AudioEncoderShim::OpusEncoderImpl::EncodeInternal(
147 const scoped_refptr<AudioData>& input,
148 const scoped_refptr<AudioData>& output) {
149 return opus_encode(
150 opus_encoder_, reinterpret_cast<opus_int16*>(input->GetData()),
151 (input->GetSize() / parameters_.channels) / parameters_.input_sample_size,
152 output->GetData(), output->GetSize());
153 }
154
155 void AudioEncoderShim::OpusEncoderImpl::RequestBitrateChange(uint32_t bitrate) {
156 opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate));
157 }
158
159 AudioEncoderShim::AudioEncoderShim()
160 : media_task_runner_(
161 RenderThreadImpl::current()->GetMediaThreadTaskRunner()),
162 weak_ptr_factory_(this) {
163 }
164
165 AudioEncoderShim::~AudioEncoderShim() {
166 if (encoder_impl_)
167 media_task_runner_->PostTask(
168 FROM_HERE, base::Bind(&AudioEncoderShim::EncoderImpl::Stop,
169 base::Owned(encoder_impl_.release())));
170 }
171
172 std::vector<PP_AudioProfileDescription>
173 AudioEncoderShim::GetSupportedProfiles() {
174 std::vector<PP_AudioProfileDescription> profiles;
175 scoped_ptr<EncoderImpl> encoder(
176 new OpusEncoderImpl(weak_ptr_factory_.GetWeakPtr()));
177 std::vector<PP_AudioProfileDescription> codec_profiles =
178 encoder->GetSupportedProfiles();
179 for (const PP_AudioProfileDescription desc : codec_profiles)
Tom Sepez 2015/09/17 18:11:12 nit: how about const auto& desc :
llandwerlin-old 2015/10/05 16:10:59 Done.
180 profiles.push_back(desc);
181 return profiles;
182 }
183
184 bool AudioEncoderShim::Initialize(
185 const ppapi::proxy::PPB_AudioEncodeParameters& parameters) {
186 if (encoder_impl_)
187 return false;
188
189 if (parameters.output_profile == PP_AUDIOPROFILE_OPUS) {
190 encoder_impl_.reset(new OpusEncoderImpl(weak_ptr_factory_.GetWeakPtr()));
Tom Sepez 2015/09/17 18:11:12 nit: prefer early return if !=, combine with line
llandwerlin-old 2015/10/05 16:10:59 Done.
191 return encoder_impl_->Initialize(parameters);
192 }
193 return false;
194 }
195
196 int32_t AudioEncoderShim::GetNumberOfSamplesPerFrame() {
197 DCHECK(encoder_impl_);
Tom Sepez 2015/09/17 18:11:12 nit: pointless DCHECK, the next line will segv if
llandwerlin-old 2015/10/05 16:10:59 Done.
198 return encoder_impl_->GetNumberOfSamplesPerFrame();
199 }
200
201 void AudioEncoderShim::Encode(const scoped_refptr<AudioData>& input,
202 const scoped_refptr<AudioData>& output,
203 BitstreamBufferReadyCB callback) {
204 DCHECK(encoder_impl_);
205 media_task_runner_->PostTask(
206 FROM_HERE, base::Bind(&AudioEncoderShim::EncoderImpl::Encode,
207 base::Unretained(encoder_impl_.get()), input,
208 output, callback));
209 }
210
211 void AudioEncoderShim::RequestBitrateChange(uint32_t bitrate) {
212 DCHECK(encoder_impl_);
213 media_task_runner_->PostTask(
214 FROM_HERE,
215 base::Bind(&AudioEncoderShim::EncoderImpl::RequestBitrateChange,
216 base::Unretained(encoder_impl_.get()), bitrate));
217 }
218
219 void AudioEncoderShim::OnEncodeDone(const scoped_refptr<AudioData>& output,
220 int32_t size,
Tom Sepez 2015/09/17 18:11:12 nit: sizes should usually be size_t's unless you h
llandwerlin-old 2015/10/05 16:10:59 Done.
221 BitstreamBufferReadyCB callback) {
222 callback.Run(output, size);
223 }
224
225 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698