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

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

Powered by Google App Engine
This is Rietveld 408576698