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

Side by Side Diff: media/gpu/ipc/service/gpu_video_encode_accelerator.cc

Issue 2427053002: Move video encode accelerator IPC messages to GPU IO thread (Closed)
Patch Set: posciak@ comments. Created 4 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
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/gpu/ipc/service/gpu_video_encode_accelerator.h" 5 #include "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 } 52 }
53 53
54 if (!stub->decoder()->MakeCurrent()) { 54 if (!stub->decoder()->MakeCurrent()) {
55 DLOG(ERROR) << "Failed to MakeCurrent()"; 55 DLOG(ERROR) << "Failed to MakeCurrent()";
56 return false; 56 return false;
57 } 57 }
58 58
59 return true; 59 return true;
60 } 60 }
61 61
62 void DropSharedMemory(std::unique_ptr<base::SharedMemory> shm) {
63 // Just let |shm| fall out of scope.
64 }
65
62 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) 66 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
63 std::unique_ptr<VideoEncodeAccelerator> CreateV4L2VEA() { 67 std::unique_ptr<VideoEncodeAccelerator> CreateV4L2VEA() {
64 scoped_refptr<V4L2Device> device = V4L2Device::Create(); 68 scoped_refptr<V4L2Device> device = V4L2Device::Create();
65 if (!device) 69 if (!device)
66 return nullptr; 70 return nullptr;
67 return base::WrapUnique<VideoEncodeAccelerator>( 71 return base::WrapUnique<VideoEncodeAccelerator>(
68 new V4L2VideoEncodeAccelerator(device)); 72 new V4L2VideoEncodeAccelerator(device));
69 } 73 }
70 #endif 74 #endif
71 75
(...skipping 20 matching lines...) Expand all
92 96
93 #if defined(OS_WIN) 97 #if defined(OS_WIN)
94 std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA() { 98 std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA() {
95 return base::WrapUnique<media::VideoEncodeAccelerator>( 99 return base::WrapUnique<media::VideoEncodeAccelerator>(
96 new MediaFoundationVideoEncodeAccelerator()); 100 new MediaFoundationVideoEncodeAccelerator());
97 } 101 }
98 #endif 102 #endif
99 103
100 } // anonymous namespace 104 } // anonymous namespace
101 105
106 class GpuVideoEncodeAccelerator::MessageFilter : public IPC::MessageFilter {
107 public:
108 MessageFilter(GpuVideoEncodeAccelerator* owner, int32_t host_route_id)
109 : owner_(owner), host_route_id_(host_route_id), sender_(nullptr) {}
Pawel Osciak 2016/11/07 02:00:35 Nit: perhaps sender_ = nullptr in the declaration
emircan 2016/11/07 19:35:29 Done.
110
111 void OnChannelError() override { sender_ = nullptr; }
112
113 void OnChannelClosing() override { sender_ = nullptr; }
114
115 void OnFilterAdded(IPC::Channel* channel) override { sender_ = channel; }
116
117 void OnFilterRemoved() override { owner_->OnFilterRemoved(); }
118
119 bool OnMessageReceived(const IPC::Message& msg) override {
120 if (msg.routing_id() != host_route_id_)
121 return false;
122
123 IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
124 IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_Encode, owner_,
125 GpuVideoEncodeAccelerator::OnEncode)
126 IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
127 owner_,
128 GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer)
129 IPC_MESSAGE_FORWARD(
130 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, owner_,
131 GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange)
132 IPC_MESSAGE_UNHANDLED(return false)
133 IPC_END_MESSAGE_MAP()
134 return true;
135 }
136
137 bool SendOnIOThread(IPC::Message* message) {
138 if (!sender_ || message->is_sync()) {
139 DCHECK(!message->is_sync());
140 delete message;
141 return false;
142 }
143 return sender_->Send(message);
144 }
145
146 protected:
147 ~MessageFilter() override {}
148
149 private:
150 GpuVideoEncodeAccelerator* const owner_;
151 const int32_t host_route_id_;
152 // The sender to which this filter was added.
153 IPC::Sender* sender_;
154
155 DISALLOW_COPY_AND_ASSIGN(MessageFilter);
156 };
157
102 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator( 158 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(
103 int32_t host_route_id, 159 int32_t host_route_id,
104 gpu::GpuCommandBufferStub* stub) 160 gpu::GpuCommandBufferStub* stub,
161 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
105 : host_route_id_(host_route_id), 162 : host_route_id_(host_route_id),
106 stub_(stub), 163 stub_(stub),
107 input_format_(PIXEL_FORMAT_UNKNOWN), 164 input_format_(PIXEL_FORMAT_UNKNOWN),
108 output_buffer_size_(0), 165 output_buffer_size_(0),
166 filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL,
167 base::WaitableEvent::InitialState::NOT_SIGNALED),
168 encoder_worker_thread_("EncoderWorkerThread"),
169 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
170 io_task_runner_(io_task_runner),
171 encode_task_runner_(main_task_runner_),
172 weak_this_factory_for_encoder_worker(this),
109 weak_this_factory_(this) { 173 weak_this_factory_(this) {
110 stub_->AddDestructionObserver(this); 174 stub_->AddDestructionObserver(this);
111 make_context_current_ = 175 make_context_current_ =
112 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); 176 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
113 } 177 }
114 178
115 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() { 179 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
116 // This class can only be self-deleted from OnWillDestroyStub(), which means 180 // This class can only be self-deleted from OnWillDestroyStub(), which means
117 // the VEA has already been destroyed in there. 181 // the VEA has already been destroyed in there.
118 DCHECK(!encoder_); 182 DCHECK(!encoder_);
183 if (encoder_worker_thread_.IsRunning()) {
184 encoder_worker_task_runner_->PostTask(
185 FROM_HERE,
186 base::Bind(&GpuVideoEncodeAccelerator::DestroyOnEncoderWorker,
187 weak_this_factory_for_encoder_worker.GetWeakPtr()));
188 encoder_worker_thread_.Stop();
189 }
119 } 190 }
120 191
121 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format, 192 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format,
122 const gfx::Size& input_visible_size, 193 const gfx::Size& input_visible_size,
123 VideoCodecProfile output_profile, 194 VideoCodecProfile output_profile,
124 uint32_t initial_bitrate) { 195 uint32_t initial_bitrate) {
125 DVLOG(1) << __FUNCTION__ 196 DCHECK(main_task_runner_->BelongsToCurrentThread());
197 DVLOG(1) << __func__
126 << " input_format=" << VideoPixelFormatToString(input_format) 198 << " input_format=" << VideoPixelFormatToString(input_format)
127 << ", input_visible_size=" << input_visible_size.ToString() 199 << ", input_visible_size=" << input_visible_size.ToString()
128 << ", output_profile=" << GetProfileName(output_profile) 200 << ", output_profile=" << GetProfileName(output_profile)
129 << ", initial_bitrate=" << initial_bitrate; 201 << ", initial_bitrate=" << initial_bitrate;
130 DCHECK(!encoder_); 202 DCHECK(!encoder_);
131 203
132 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) { 204 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) {
133 DLOG(ERROR) << __FUNCTION__ << " failed to add route"; 205 DLOG(ERROR) << __func__ << " failed to add route";
134 return false; 206 return false;
135 } 207 }
136 208
137 if (input_visible_size.width() > limits::kMaxDimension || 209 if (input_visible_size.width() > limits::kMaxDimension ||
138 input_visible_size.height() > limits::kMaxDimension || 210 input_visible_size.height() > limits::kMaxDimension ||
139 input_visible_size.GetArea() > limits::kMaxCanvas) { 211 input_visible_size.GetArea() > limits::kMaxCanvas) {
140 DLOG(ERROR) << __FUNCTION__ << "too large input_visible_size " 212 DLOG(ERROR) << __func__ << "too large input_visible_size "
141 << input_visible_size.ToString(); 213 << input_visible_size.ToString();
142 return false; 214 return false;
143 } 215 }
144 216
145 const gpu::GpuPreferences& gpu_preferences = 217 const gpu::GpuPreferences& gpu_preferences =
146 stub_->channel()->gpu_channel_manager()->gpu_preferences(); 218 stub_->channel()->gpu_channel_manager()->gpu_preferences();
147 219
148 // Try all possible encoders and use the first successful encoder. 220 // Try all possible encoders and use the first successful encoder.
149 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { 221 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) {
150 encoder_ = factory_function.Run(); 222 encoder_ = factory_function.Run();
151 if (encoder_ && 223 if (encoder_ &&
152 encoder_->Initialize(input_format, input_visible_size, output_profile, 224 encoder_->Initialize(input_format, input_visible_size, output_profile,
153 initial_bitrate, this)) { 225 initial_bitrate, this)) {
154 input_format_ = input_format; 226 input_format_ = input_format;
155 input_visible_size_ = input_visible_size; 227 input_visible_size_ = input_visible_size;
228 // Attempt to set up performing encoding tasks on IO thread, if supported
229 // by the VEA.
230 if (encoder_->TryToSetupEncodeOnSeparateThread(
231 weak_this_factory_.GetWeakPtr(), io_task_runner_)) {
232 filter_ = new MessageFilter(this, host_route_id_);
233 stub_->channel()->AddFilter(filter_.get());
234 encode_task_runner_ = io_task_runner_;
235 }
236
237 if (!encoder_worker_thread_.Start()) {
238 DLOG(ERROR) << "Failed spawning encoder worker thread.";
239 return false;
240 }
241 encoder_worker_task_runner_ = encoder_worker_thread_.task_runner();
242
156 return true; 243 return true;
157 } 244 }
158 } 245 }
159 encoder_.reset(); 246 encoder_.reset();
160 DLOG(ERROR) << __FUNCTION__ << " VEA initialization failed"; 247 DLOG(ERROR) << __func__ << " VEA initialization failed";
161 return false; 248 return false;
162 } 249 }
163 250
164 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) { 251 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) {
165 bool handled = true; 252 bool handled = true;
166 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message) 253 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message)
167 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode) 254 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode)
168 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer, 255 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
169 OnUseOutputBitstreamBuffer) 256 OnUseOutputBitstreamBuffer)
170 IPC_MESSAGE_HANDLER( 257 IPC_MESSAGE_HANDLER(
171 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, 258 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
172 OnRequestEncodingParametersChange) 259 OnRequestEncodingParametersChange)
173 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy) 260 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy)
174 IPC_MESSAGE_UNHANDLED(handled = false) 261 IPC_MESSAGE_UNHANDLED(handled = false)
175 IPC_END_MESSAGE_MAP() 262 IPC_END_MESSAGE_MAP()
176 return handled; 263 return handled;
177 } 264 }
178 265
179 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers( 266 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers(
180 unsigned int input_count, 267 unsigned int input_count,
181 const gfx::Size& input_coded_size, 268 const gfx::Size& input_coded_size,
182 size_t output_buffer_size) { 269 size_t output_buffer_size) {
183 Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers( 270 DCHECK(main_task_runner_->BelongsToCurrentThread());
184 host_route_id_, input_count, input_coded_size, output_buffer_size)); 271 if (!Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
272 host_route_id_, input_count, input_coded_size, output_buffer_size))) {
273 DLOG(ERROR) << __func__ << " failed.";
Pawel Osciak 2016/11/07 02:00:35 Perhaps return here?
emircan 2016/11/07 19:35:28 Done.
274 }
185 input_coded_size_ = input_coded_size; 275 input_coded_size_ = input_coded_size;
186 output_buffer_size_ = output_buffer_size; 276 output_buffer_size_ = output_buffer_size;
187 } 277 }
188 278
189 void GpuVideoEncodeAccelerator::BitstreamBufferReady( 279 void GpuVideoEncodeAccelerator::BitstreamBufferReady(
190 int32_t bitstream_buffer_id, 280 int32_t bitstream_buffer_id,
191 size_t payload_size, 281 size_t payload_size,
192 bool key_frame, 282 bool key_frame,
193 base::TimeDelta timestamp) { 283 base::TimeDelta timestamp) {
194 Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady( 284 DCHECK(CheckIfCalledOnCorrectThread());
195 host_route_id_, bitstream_buffer_id, payload_size, key_frame, timestamp)); 285 if (!Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
286 host_route_id_, bitstream_buffer_id, payload_size, key_frame,
287 timestamp))) {
288 DLOG(ERROR) << __func__ << " failed.";
289 }
196 } 290 }
197 291
198 void GpuVideoEncodeAccelerator::NotifyError( 292 void GpuVideoEncodeAccelerator::NotifyError(
199 VideoEncodeAccelerator::Error error) { 293 VideoEncodeAccelerator::Error error) {
200 Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_, error)); 294 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_,
295 error))) {
296 DLOG(ERROR) << __func__ << " failed.";
297 }
201 } 298 }
202 299
203 void GpuVideoEncodeAccelerator::OnWillDestroyStub() { 300 void GpuVideoEncodeAccelerator::OnWillDestroyStub() {
301 DVLOG(2) << __func__;
302 DCHECK(main_task_runner_->BelongsToCurrentThread());
204 DCHECK(stub_); 303 DCHECK(stub_);
304
305 // The stub is going away, so we have to stop and destroy VEA here before
306 // returning. We cannot destroy the VEA before the IO thread message filter is
307 // removed however, since we cannot service incoming messages with VEA gone.
308 // We cannot simply check for existence of VEA on IO thread though, because
309 // we don't want to synchronize the IO thread with the ChildThread.
310 // So we have to wait for the RemoveFilter callback here instead and remove
311 // the VEA after it arrives and before returning.
312 if (filter_) {
313 stub_->channel()->RemoveFilter(filter_.get());
314 filter_removed_.Wait();
315 }
316
205 stub_->channel()->RemoveRoute(host_route_id_); 317 stub_->channel()->RemoveRoute(host_route_id_);
206 stub_->RemoveDestructionObserver(this); 318 stub_->RemoveDestructionObserver(this);
207 encoder_.reset(); 319 encoder_.reset();
208 delete this; 320 delete this;
209 } 321 }
210 322
211 // static 323 // static
212 gpu::VideoEncodeAcceleratorSupportedProfiles 324 gpu::VideoEncodeAcceleratorSupportedProfiles
213 GpuVideoEncodeAccelerator::GetSupportedProfiles( 325 GpuVideoEncodeAccelerator::GetSupportedProfiles(
214 const gpu::GpuPreferences& gpu_preferences) { 326 const gpu::GpuPreferences& gpu_preferences) {
215 VideoEncodeAccelerator::SupportedProfiles profiles; 327 VideoEncodeAccelerator::SupportedProfiles profiles;
216 328
217 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { 329 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) {
218 std::unique_ptr<VideoEncodeAccelerator> encoder = factory_function.Run(); 330 std::unique_ptr<VideoEncodeAccelerator> encoder = factory_function.Run();
219 if (!encoder) 331 if (!encoder)
220 continue; 332 continue;
221 VideoEncodeAccelerator::SupportedProfiles vea_profiles = 333 VideoEncodeAccelerator::SupportedProfiles vea_profiles =
222 encoder->GetSupportedProfiles(); 334 encoder->GetSupportedProfiles();
223 GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles, 335 GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles,
224 &profiles); 336 &profiles);
225 } 337 }
226 return GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(profiles); 338 return GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(profiles);
227 } 339 }
228 340
341 void GpuVideoEncodeAccelerator::OnFilterRemoved() {
342 DVLOG(2) << __func__;
343
344 // We're destroying; cancel all callbacks.
345 weak_this_factory_.InvalidateWeakPtrs();
346 filter_removed_.Signal();
347 }
348
229 // static 349 // static
230 std::vector<GpuVideoEncodeAccelerator::VEAFactoryFunction> 350 std::vector<GpuVideoEncodeAccelerator::VEAFactoryFunction>
231 GpuVideoEncodeAccelerator::GetVEAFactoryFunctions( 351 GpuVideoEncodeAccelerator::GetVEAFactoryFunctions(
232 const gpu::GpuPreferences& gpu_preferences) { 352 const gpu::GpuPreferences& gpu_preferences) {
233 std::vector<VEAFactoryFunction> vea_factory_functions; 353 std::vector<VEAFactoryFunction> vea_factory_functions;
234 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) 354 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
235 vea_factory_functions.push_back(base::Bind(&CreateV4L2VEA)); 355 vea_factory_functions.push_back(base::Bind(&CreateV4L2VEA));
236 #endif 356 #endif
237 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) 357 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
238 if (!gpu_preferences.disable_vaapi_accelerated_video_encode) 358 if (!gpu_preferences.disable_vaapi_accelerated_video_encode)
239 vea_factory_functions.push_back(base::Bind(&CreateVaapiVEA)); 359 vea_factory_functions.push_back(base::Bind(&CreateVaapiVEA));
240 #endif 360 #endif
241 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC) 361 #if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
242 if (!gpu_preferences.disable_web_rtc_hw_encoding) 362 if (!gpu_preferences.disable_web_rtc_hw_encoding)
243 vea_factory_functions.push_back(base::Bind(&CreateAndroidVEA)); 363 vea_factory_functions.push_back(base::Bind(&CreateAndroidVEA));
244 #endif 364 #endif
245 #if defined(OS_MACOSX) 365 #if defined(OS_MACOSX)
246 vea_factory_functions.push_back(base::Bind(&CreateVTVEA)); 366 vea_factory_functions.push_back(base::Bind(&CreateVTVEA));
247 #endif 367 #endif
248 #if defined(OS_WIN) 368 #if defined(OS_WIN)
249 if (base::FeatureList::IsEnabled(kMediaFoundationH264Encoding)) 369 if (base::FeatureList::IsEnabled(kMediaFoundationH264Encoding))
250 vea_factory_functions.push_back(base::Bind(&CreateMediaFoundationVEA)); 370 vea_factory_functions.push_back(base::Bind(&CreateMediaFoundationVEA));
251 #endif 371 #endif
252 return vea_factory_functions; 372 return vea_factory_functions;
253 } 373 }
254 374
255 void GpuVideoEncodeAccelerator::OnEncode( 375 void GpuVideoEncodeAccelerator::OnEncode(
256 const AcceleratedVideoEncoderMsg_Encode_Params& params) { 376 const AcceleratedVideoEncoderMsg_Encode_Params& params) {
257 DVLOG(3) << __FUNCTION__ << " frame_id = " << params.frame_id 377 DVLOG(3) << __func__ << " frame_id = " << params.frame_id
258 << ", buffer_size=" << params.buffer_size 378 << ", buffer_size=" << params.buffer_size
259 << ", force_keyframe=" << params.force_keyframe; 379 << ", force_keyframe=" << params.force_keyframe;
380 DCHECK(CheckIfCalledOnCorrectThread());
260 DCHECK_EQ(PIXEL_FORMAT_I420, input_format_); 381 DCHECK_EQ(PIXEL_FORMAT_I420, input_format_);
261 382
262 // Wrap into a SharedMemory in the beginning, so that |params.buffer_handle|
263 // is cleaned properly in case of an early return.
264 std::unique_ptr<base::SharedMemory> shm(
265 new base::SharedMemory(params.buffer_handle, true));
266
267 if (!encoder_) 383 if (!encoder_)
268 return; 384 return;
269 385
270 if (params.frame_id < 0) { 386 if (params.frame_id < 0) {
271 DLOG(ERROR) << __FUNCTION__ << " invalid frame_id=" << params.frame_id; 387 DLOG(ERROR) << __func__ << " invalid frame_id=" << params.frame_id;
272 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); 388 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
273 return; 389 return;
274 } 390 }
275 391
276 const uint32_t aligned_offset = 392 encoder_worker_task_runner_->PostTask(
277 params.buffer_offset % base::SysInfo::VMAllocationGranularity(); 393 FROM_HERE,
278 base::CheckedNumeric<off_t> map_offset = params.buffer_offset; 394 base::Bind(&GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker,
279 map_offset -= aligned_offset; 395 weak_this_factory_for_encoder_worker.GetWeakPtr(), params));
280 base::CheckedNumeric<size_t> map_size = params.buffer_size;
281 map_size += aligned_offset;
282
283 if (!map_offset.IsValid() || !map_size.IsValid()) {
284 DLOG(ERROR) << __FUNCTION__ << " invalid map_offset or map_size";
285 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
286 return;
287 }
288
289 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
290 DLOG(ERROR) << __FUNCTION__
291 << " could not map frame_id=" << params.frame_id;
292 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
293 return;
294 }
295
296 uint8_t* shm_memory =
297 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset;
298 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory(
299 input_format_, input_coded_size_, gfx::Rect(input_visible_size_),
300 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle,
301 params.buffer_offset, params.timestamp);
302 if (!frame) {
303 DLOG(ERROR) << __FUNCTION__ << " could not create a frame";
304 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
305 return;
306 }
307 frame->AddDestructionObserver(BindToCurrentLoop(base::Bind(
308 &GpuVideoEncodeAccelerator::EncodeFrameFinished,
309 weak_this_factory_.GetWeakPtr(), params.frame_id, base::Passed(&shm))));
310 encoder_->Encode(frame, params.force_keyframe);
311 } 396 }
312 397
313 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( 398 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
314 int32_t buffer_id, 399 int32_t buffer_id,
315 base::SharedMemoryHandle buffer_handle, 400 base::SharedMemoryHandle buffer_handle,
316 uint32_t buffer_size) { 401 uint32_t buffer_size) {
317 DVLOG(3) << __FUNCTION__ << " buffer_id=" << buffer_id 402 DVLOG(3) << __func__ << " buffer_id=" << buffer_id
318 << ", buffer_size=" << buffer_size; 403 << ", buffer_size=" << buffer_size;
404 DCHECK(CheckIfCalledOnCorrectThread());
319 if (!encoder_) 405 if (!encoder_)
320 return; 406 return;
321 if (buffer_id < 0) { 407 if (buffer_id < 0) {
322 DLOG(ERROR) << __FUNCTION__ << " invalid buffer_id=" << buffer_id; 408 DLOG(ERROR) << __func__ << " invalid buffer_id=" << buffer_id;
323 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); 409 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
324 return; 410 return;
325 } 411 }
326 if (buffer_size < output_buffer_size_) { 412 if (buffer_size < output_buffer_size_) {
327 DLOG(ERROR) << __FUNCTION__ 413 DLOG(ERROR) << __func__ << " buffer too small for buffer_id=" << buffer_id;
328 << " buffer too small for buffer_id=" << buffer_id;
329 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); 414 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
330 return; 415 return;
331 } 416 }
332 encoder_->UseOutputBitstreamBuffer( 417 encoder_->UseOutputBitstreamBuffer(
333 BitstreamBuffer(buffer_id, buffer_handle, buffer_size)); 418 BitstreamBuffer(buffer_id, buffer_handle, buffer_size));
334 } 419 }
335 420
336 void GpuVideoEncodeAccelerator::OnDestroy() { 421 void GpuVideoEncodeAccelerator::OnDestroy() {
337 DVLOG(2) << __FUNCTION__; 422 DVLOG(2) << __func__;
423 DCHECK(main_task_runner_->BelongsToCurrentThread());
338 OnWillDestroyStub(); 424 OnWillDestroyStub();
339 } 425 }
340 426
341 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange( 427 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
342 uint32_t bitrate, 428 uint32_t bitrate,
343 uint32_t framerate) { 429 uint32_t framerate) {
344 DVLOG(2) << __FUNCTION__ << " bitrate=" << bitrate 430 DVLOG(2) << __func__ << " bitrate=" << bitrate << ", framerate=" << framerate;
345 << ", framerate=" << framerate; 431 DCHECK(CheckIfCalledOnCorrectThread());
346 if (!encoder_) 432 if (!encoder_)
347 return; 433 return;
348 encoder_->RequestEncodingParametersChange(bitrate, framerate); 434 encoder_->RequestEncodingParametersChange(bitrate, framerate);
349 } 435 }
350 436
351 void GpuVideoEncodeAccelerator::EncodeFrameFinished( 437 void GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker(
352 int32_t frame_id, 438 const AcceleratedVideoEncoderMsg_Encode_Params& params) {
353 std::unique_ptr<base::SharedMemory> shm) { 439 DVLOG(3) << __func__;
354 Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_, 440 DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread());
355 frame_id)); 441
356 // Just let |shm| fall out of scope. 442 // Wrap into a SharedMemory in the beginning, so that |params.buffer_handle|
443 // is cleaned properly in case of an early return.
444 std::unique_ptr<base::SharedMemory> shm(
445 new base::SharedMemory(params.buffer_handle, true));
446 const uint32_t aligned_offset =
447 params.buffer_offset % base::SysInfo::VMAllocationGranularity();
448 base::CheckedNumeric<off_t> map_offset = params.buffer_offset;
449 map_offset -= aligned_offset;
450 base::CheckedNumeric<size_t> map_size = params.buffer_size;
451 map_size += aligned_offset;
452
453 if (!map_offset.IsValid() || !map_size.IsValid()) {
454 DLOG(ERROR) << __func__ << " invalid map_offset or map_size";
455 encode_task_runner_->PostTask(
456 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError,
457 weak_this_factory_.GetWeakPtr(),
458 VideoEncodeAccelerator::kPlatformFailureError));
459 return;
460 }
461
462 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
463 DLOG(ERROR) << __func__ << " could not map frame_id=" << params.frame_id;
464 encode_task_runner_->PostTask(
465 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError,
466 weak_this_factory_.GetWeakPtr(),
467 VideoEncodeAccelerator::kPlatformFailureError));
468 return;
469 }
470
471 uint8_t* shm_memory =
472 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset;
473 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory(
474 input_format_, input_coded_size_, gfx::Rect(input_visible_size_),
475 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle,
476 params.buffer_offset, params.timestamp);
477 if (!frame) {
478 DLOG(ERROR) << __func__ << " could not create a frame";
479 encode_task_runner_->PostTask(
480 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError,
481 weak_this_factory_.GetWeakPtr(),
482 VideoEncodeAccelerator::kPlatformFailureError));
483 return;
484 }
485
486 frame->AddDestructionObserver(
Pawel Osciak 2016/11/07 02:00:35 Please add a comment why we are doing this.
emircan 2016/11/07 19:35:28 Done.
487 base::Bind(&DropSharedMemory, base::Passed(&shm)));
488 encode_task_runner_->PostTask(
489 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::OnEncodeFrameCreated,
490 weak_this_factory_.GetWeakPtr(), params.frame_id,
491 params.force_keyframe, frame));
357 } 492 }
358 493
359 void GpuVideoEncodeAccelerator::Send(IPC::Message* message) { 494 void GpuVideoEncodeAccelerator::DestroyOnEncoderWorker() {
360 stub_->channel()->Send(message); 495 DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread());
496 weak_this_factory_for_encoder_worker.InvalidateWeakPtrs();
497 }
498
499 void GpuVideoEncodeAccelerator::OnEncodeFrameCreated(
500 int32_t frame_id,
501 bool force_keyframe,
502 const scoped_refptr<media::VideoFrame>& frame) {
503 DVLOG(3) << __func__;
504 DCHECK(CheckIfCalledOnCorrectThread());
505
506 if (!frame) {
507 DLOG(ERROR) << __func__ << " could not create a frame";
508 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
509 return;
510 }
511
512 frame->AddDestructionObserver(BindToCurrentLoop(
513 base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished,
514 weak_this_factory_.GetWeakPtr(), frame_id)));
515 encoder_->Encode(frame, force_keyframe);
516 }
517
518 void GpuVideoEncodeAccelerator::EncodeFrameFinished(int32_t frame_id) {
519 DCHECK(CheckIfCalledOnCorrectThread());
520 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_,
521 frame_id))) {
522 DLOG(ERROR) << __func__ << " failed.";
523 }
524 }
525
526 bool GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
527 if (filter_ && io_task_runner_->BelongsToCurrentThread()) {
528 return filter_->SendOnIOThread(message);
529 }
530 DCHECK(main_task_runner_->BelongsToCurrentThread());
531 return stub_->channel()->Send(message);
532 }
533
534 bool GpuVideoEncodeAccelerator::CheckIfCalledOnCorrectThread() {
535 return (filter_ && io_task_runner_->BelongsToCurrentThread()) ||
536 (!filter_ && main_task_runner_->BelongsToCurrentThread());
361 } 537 }
362 538
363 } // namespace media 539 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698