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

Side by Side Diff: content/renderer/pepper/pepper_video_encoder_host.cc

Issue 905023005: Pepper: PPB_VideoEncoder implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix unittest on win_chromium_x64_rel_ng Created 5 years, 10 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/memory/shared_memory.h"
7 #include "base/numerics/safe_math.h"
8 #include "content/common/gpu/client/command_buffer_proxy_impl.h"
9 #include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
10 #include "content/public/renderer/renderer_ppapi_host.h"
11 #include "content/renderer/pepper/gfx_conversion.h"
12 #include "content/renderer/pepper/host_globals.h"
13 #include "content/renderer/pepper/pepper_video_encoder_host.h"
14 #include "content/renderer/render_thread_impl.h"
15 #include "media/base/bind_to_current_loop.h"
16 #include "media/base/video_frame.h"
17 #include "media/filters/gpu_video_accelerator_factories.h"
18 #include "media/video/video_encode_accelerator.h"
19 #include "ppapi/c/pp_codecs.h"
20 #include "ppapi/c/pp_errors.h"
21 #include "ppapi/c/pp_graphics_3d.h"
22 #include "ppapi/host/dispatch_host_message.h"
23 #include "ppapi/host/ppapi_host.h"
24 #include "ppapi/proxy/ppapi_messages.h"
25 #include "ppapi/shared_impl/media_stream_buffer.h"
26
27 using ppapi::proxy::SerializedHandle;
28
29 namespace content {
30
31 namespace {
32
33 const uint32_t kDefaultNumberOfBitstreamBuffers = 4;
34
35 base::PlatformFile ConvertSharedMemoryHandle(
36 const base::SharedMemory& shared_memory) {
37 #if defined(OS_POSIX)
38 return shared_memory.handle().fd;
39 #elif defined(OS_WIN)
40 return shared_memory.handle();
41 #else
42 #error "Platform not supported."
43 #endif
44 }
45
46 int32_t PP_FromMediaEncodeAcceleratorError(
47 media::VideoEncodeAccelerator::Error error) {
48 switch (error) {
49 case media::VideoEncodeAccelerator::kInvalidArgumentError:
50 return PP_ERROR_MALFORMED_INPUT;
51 case media::VideoEncodeAccelerator::kIllegalStateError:
52 case media::VideoEncodeAccelerator::kPlatformFailureError:
53 return PP_ERROR_RESOURCE_FAILED;
54 // No default case, to catch unhandled enum values.
55 }
56 return PP_ERROR_FAILED;
57 }
58
59 // TODO(llandwerlin): move following to media_conversion.cc/h?
60 media::VideoCodecProfile PP_ToMediaVideoProfile(PP_VideoProfile profile) {
61 switch (profile) {
62 case PP_VIDEOPROFILE_H264BASELINE:
63 return media::H264PROFILE_BASELINE;
64 case PP_VIDEOPROFILE_H264MAIN:
65 return media::H264PROFILE_MAIN;
66 case PP_VIDEOPROFILE_H264EXTENDED:
67 return media::H264PROFILE_EXTENDED;
68 case PP_VIDEOPROFILE_H264HIGH:
69 return media::H264PROFILE_HIGH;
70 case PP_VIDEOPROFILE_H264HIGH10PROFILE:
71 return media::H264PROFILE_HIGH10PROFILE;
72 case PP_VIDEOPROFILE_H264HIGH422PROFILE:
73 return media::H264PROFILE_HIGH422PROFILE;
74 case PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE:
75 return media::H264PROFILE_HIGH444PREDICTIVEPROFILE;
76 case PP_VIDEOPROFILE_H264SCALABLEBASELINE:
77 return media::H264PROFILE_SCALABLEBASELINE;
78 case PP_VIDEOPROFILE_H264SCALABLEHIGH:
79 return media::H264PROFILE_SCALABLEHIGH;
80 case PP_VIDEOPROFILE_H264STEREOHIGH:
81 return media::H264PROFILE_STEREOHIGH;
82 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH:
83 return media::H264PROFILE_MULTIVIEWHIGH;
84 case PP_VIDEOPROFILE_VP8_ANY:
85 return media::VP8PROFILE_ANY;
86 case PP_VIDEOPROFILE_VP9_ANY:
87 return media::VP9PROFILE_ANY;
88 // No default case, to catch unhandled PP_VideoProfile values.
89 }
90 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
91 }
92
93 PP_VideoProfile PP_FromMediaVideoProfile(media::VideoCodecProfile profile) {
94 switch (profile) {
95 case media::H264PROFILE_BASELINE:
96 return PP_VIDEOPROFILE_H264BASELINE;
97 case media::H264PROFILE_MAIN:
98 return PP_VIDEOPROFILE_H264MAIN;
99 case media::H264PROFILE_EXTENDED:
100 return PP_VIDEOPROFILE_H264EXTENDED;
101 case media::H264PROFILE_HIGH:
102 return PP_VIDEOPROFILE_H264HIGH;
103 case media::H264PROFILE_HIGH10PROFILE:
104 return PP_VIDEOPROFILE_H264HIGH10PROFILE;
105 case media::H264PROFILE_HIGH422PROFILE:
106 return PP_VIDEOPROFILE_H264HIGH422PROFILE;
107 case media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
108 return PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE;
109 case media::H264PROFILE_SCALABLEBASELINE:
110 return PP_VIDEOPROFILE_H264SCALABLEBASELINE;
111 case media::H264PROFILE_SCALABLEHIGH:
112 return PP_VIDEOPROFILE_H264SCALABLEHIGH;
113 case media::H264PROFILE_STEREOHIGH:
114 return PP_VIDEOPROFILE_H264STEREOHIGH;
115 case media::H264PROFILE_MULTIVIEWHIGH:
116 return PP_VIDEOPROFILE_H264MULTIVIEWHIGH;
117 case media::VP8PROFILE_ANY:
118 return PP_VIDEOPROFILE_VP8_ANY;
119 case media::VP9PROFILE_ANY:
120 return PP_VIDEOPROFILE_VP9_ANY;
121 default:
122 NOTREACHED();
123 return static_cast<PP_VideoProfile>(-1);
124 }
125 }
126
127 media::VideoFrame::Format PP_ToMediaVideoFormat(PP_VideoFrame_Format format) {
128 switch (format) {
129 case PP_VIDEOFRAME_FORMAT_UNKNOWN:
130 return media::VideoFrame::UNKNOWN;
131 case PP_VIDEOFRAME_FORMAT_YV12:
132 return media::VideoFrame::YV12;
133 case PP_VIDEOFRAME_FORMAT_I420:
134 return media::VideoFrame::I420;
135 case PP_VIDEOFRAME_FORMAT_BGRA:
136 return media::VideoFrame::UNKNOWN;
137 // No default case, to catch unhandled PP_VideoFrame_Format values.
138 }
139 return media::VideoFrame::UNKNOWN;
140 }
141
142 PP_VideoFrame_Format PP_FromMediaVideoFormat(media::VideoFrame::Format format) {
143 switch (format) {
144 case media::VideoFrame::UNKNOWN:
145 return PP_VIDEOFRAME_FORMAT_UNKNOWN;
146 case media::VideoFrame::YV12:
147 return PP_VIDEOFRAME_FORMAT_YV12;
148 case media::VideoFrame::I420:
149 return PP_VIDEOFRAME_FORMAT_I420;
150 default:
151 return PP_VIDEOFRAME_FORMAT_UNKNOWN;
152 }
153 }
154
155 PP_VideoProfileDescription PP_FromVideoEncodeAcceleratorSupportedProfile(
156 media::VideoEncodeAccelerator::SupportedProfile profile,
157 PP_HardwareAcceleration acceleration) {
158 PP_VideoProfileDescription pp_profile;
159 pp_profile.profile = PP_FromMediaVideoProfile(profile.profile);
160 pp_profile.max_resolution = PP_FromGfxSize(profile.max_resolution);
161 pp_profile.max_framerate_numerator = profile.max_framerate_numerator;
162 pp_profile.max_framerate_denominator = profile.max_framerate_denominator;
163 pp_profile.acceleration = acceleration;
164 return pp_profile;
165 }
166
167 bool PP_HardwareAccelerationCompatible(PP_HardwareAcceleration supply,
168 PP_HardwareAcceleration demand) {
169 switch (supply) {
170 case PP_HARDWAREACCELERATION_ONLY:
171 return (demand == PP_HARDWAREACCELERATION_ONLY ||
172 demand == PP_HARDWAREACCELERATION_WITHFALLBACK);
173 case PP_HARDWAREACCELERATION_WITHFALLBACK:
174 return true;
175 case PP_HARDWAREACCELERATION_NONE:
176 return (demand == PP_HARDWAREACCELERATION_WITHFALLBACK ||
177 demand == PP_HARDWAREACCELERATION_NONE);
178 // No default case, to catch unhandled PP_HardwareAcceleration values.
179 }
180 return false;
181 }
182
183 } // namespace
184
185 PepperVideoEncoderHost::ShmBuffer::ShmBuffer(uint32_t id,
186 scoped_ptr<base::SharedMemory> shm)
187 : id(id), shm(shm.Pass()), in_use(true) {
188 DCHECK(this->shm);
189 }
190
191 PepperVideoEncoderHost::ShmBuffer::~ShmBuffer() {
192 }
193
194 media::BitstreamBuffer PepperVideoEncoderHost::ShmBuffer::ToBitstreamBuffer() {
195 return media::BitstreamBuffer(id, shm->handle(), shm->mapped_size());
196 }
197
198 PepperVideoEncoderHost::PepperVideoEncoderHost(RendererPpapiHost* host,
199 PP_Instance instance,
200 PP_Resource resource)
201 : ResourceHost(host->GetPpapiHost(), instance, resource),
202 renderer_ppapi_host_(host),
203 buffer_manager_(this),
204 command_buffer_(nullptr),
205 initialized_(false),
206 encoder_last_error_(PP_ERROR_FAILED),
207 frame_count_(0),
208 media_input_format_(media::VideoFrame::UNKNOWN),
209 weak_ptr_factory_(this) {
210 }
211
212 PepperVideoEncoderHost::~PepperVideoEncoderHost() {
213 Close();
214 }
215
216 int32_t PepperVideoEncoderHost::OnResourceMessageReceived(
217 const IPC::Message& msg,
218 ppapi::host::HostMessageContext* context) {
219 PPAPI_BEGIN_MESSAGE_MAP(PepperVideoEncoderHost, msg)
220 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
221 PpapiHostMsg_VideoEncoder_GetSupportedProfiles,
222 OnHostMsgGetSupportedProfiles)
223 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoEncoder_Initialize,
224 OnHostMsgInitialize)
225 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
226 PpapiHostMsg_VideoEncoder_GetVideoFrames,
227 OnHostMsgGetVideoFrames)
228 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoEncoder_Encode,
229 OnHostMsgEncode)
230 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
231 PpapiHostMsg_VideoEncoder_RecycleBitstreamBuffer,
232 OnHostMsgRecycleBitstreamBuffer)
233 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
234 PpapiHostMsg_VideoEncoder_RequestEncodingParametersChange,
235 OnHostMsgRequestEncodingParametersChange)
236 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoEncoder_Close,
237 OnHostMsgClose)
238 PPAPI_END_MESSAGE_MAP()
239 return PP_ERROR_FAILED;
240 }
241
242 int32_t PepperVideoEncoderHost::OnHostMsgGetSupportedProfiles(
243 ppapi::host::HostMessageContext* context) {
244 std::vector<PP_VideoProfileDescription> pp_profiles;
245 GetSupportedProfiles(&pp_profiles);
246
247 host()->SendReply(
248 context->MakeReplyMessageContext(),
249 PpapiPluginMsg_VideoEncoder_GetSupportedProfilesReply(pp_profiles));
250
251 return PP_OK_COMPLETIONPENDING;
252 }
253
254 int32_t PepperVideoEncoderHost::OnHostMsgInitialize(
255 ppapi::host::HostMessageContext* context,
256 PP_VideoFrame_Format input_format,
257 const PP_Size& input_visible_size,
258 PP_VideoProfile output_profile,
259 uint32_t initial_bitrate,
260 PP_HardwareAcceleration acceleration) {
261 if (initialized_)
262 return PP_ERROR_FAILED;
263
264 media_input_format_ = PP_ToMediaVideoFormat(input_format);
265 if (media_input_format_ == media::VideoFrame::UNKNOWN)
266 return PP_ERROR_BADARGUMENT;
267
268 media::VideoCodecProfile media_profile =
269 PP_ToMediaVideoProfile(output_profile);
270 if (media_profile == media::VIDEO_CODEC_PROFILE_UNKNOWN)
271 return PP_ERROR_BADARGUMENT;
272
273 gfx::Size input_size(input_visible_size.width, input_visible_size.height);
274 if (input_size.IsEmpty())
275 return PP_ERROR_BADARGUMENT;
276
277 if (!IsInitializationValid(input_visible_size, output_profile, acceleration))
278 return PP_ERROR_NOTSUPPORTED;
279
280 int32_t error = PP_ERROR_NOTSUPPORTED;
281 initialize_reply_context_ = context->MakeReplyMessageContext();
282
283 if (acceleration == PP_HARDWAREACCELERATION_ONLY ||
284 acceleration == PP_HARDWAREACCELERATION_WITHFALLBACK) {
285 if (InitializeHardware(media_input_format_, input_size, media_profile,
286 initial_bitrate))
287 return PP_OK_COMPLETIONPENDING;
288
289 if (acceleration == PP_HARDWAREACCELERATION_ONLY)
290 error = PP_ERROR_FAILED;
291 }
292
293 // TODO(llandwerlin): Software encoder.
294 initialize_reply_context_ = ppapi::host::ReplyMessageContext();
295 Close();
296 return error;
297 }
298
299 int32_t PepperVideoEncoderHost::OnHostMsgGetVideoFrames(
300 ppapi::host::HostMessageContext* context) {
301 if (encoder_last_error_)
302 return encoder_last_error_;
303
304 get_video_frames_reply_context_ = context->MakeReplyMessageContext();
305 AllocateVideoFrames();
306
307 return PP_OK_COMPLETIONPENDING;
308 }
309
310 int32_t PepperVideoEncoderHost::OnHostMsgEncode(
311 ppapi::host::HostMessageContext* context,
312 uint32_t frame_id,
313 bool force_keyframe) {
314 if (encoder_last_error_)
315 return encoder_last_error_;
316
317 if (frame_id >= frame_count_)
318 return PP_ERROR_FAILED;
319
320 encoder_->Encode(
321 CreateVideoFrame(frame_id, context->MakeReplyMessageContext()),
322 force_keyframe);
323
324 return PP_OK_COMPLETIONPENDING;
325 }
326
327 int32_t PepperVideoEncoderHost::OnHostMsgRecycleBitstreamBuffer(
328 ppapi::host::HostMessageContext* context,
329 uint32_t buffer_id) {
330 if (encoder_last_error_)
331 return encoder_last_error_;
332
333 if (buffer_id >= shm_buffers_.size() || shm_buffers_[buffer_id]->in_use)
334 return PP_ERROR_FAILED;
335
336 shm_buffers_[buffer_id]->in_use = true;
337 encoder_->UseOutputBitstreamBuffer(
338 shm_buffers_[buffer_id]->ToBitstreamBuffer());
339
340 return PP_OK;
341 }
342
343 int32_t PepperVideoEncoderHost::OnHostMsgRequestEncodingParametersChange(
344 ppapi::host::HostMessageContext* context,
345 uint32_t bitrate,
346 uint32_t framerate) {
347 if (encoder_last_error_)
348 return encoder_last_error_;
349
350 encoder_->RequestEncodingParametersChange(bitrate, framerate);
351
352 return PP_OK;
353 }
354
355 int32_t PepperVideoEncoderHost::OnHostMsgClose(
356 ppapi::host::HostMessageContext* context) {
357 encoder_last_error_ = PP_ERROR_FAILED;
358 Close();
359
360 return PP_OK;
361 }
362
363 void PepperVideoEncoderHost::RequireBitstreamBuffers(
364 unsigned int frame_count,
365 const gfx::Size& input_coded_size,
366 size_t output_buffer_size) {
367 DCHECK(RenderThreadImpl::current());
368 // We assume RequireBitstreamBuffers is only called once.
369 DCHECK(!initialized_);
370
371 input_coded_size_ = input_coded_size;
372 frame_count_ = frame_count;
373
374 for (uint32_t i = 0; i < kDefaultNumberOfBitstreamBuffers; ++i) {
375 scoped_ptr<base::SharedMemory> shm(
376 RenderThread::Get()
377 ->HostAllocateSharedMemoryBuffer(output_buffer_size)
378 .Pass());
379
380 if (!shm || !shm->Map(output_buffer_size)) {
381 shm_buffers_.clear();
382 break;
383 }
384
385 shm_buffers_.push_back(new ShmBuffer(i, shm.Pass()));
386 }
387
388 // Feed buffers to the encoder.
389 std::vector<SerializedHandle> handles;
390 for (size_t i = 0; i < shm_buffers_.size(); ++i) {
391 encoder_->UseOutputBitstreamBuffer(shm_buffers_[i]->ToBitstreamBuffer());
392 handles.push_back(SerializedHandle(
393 renderer_ppapi_host_->ShareHandleWithRemote(
394 ConvertSharedMemoryHandle(*shm_buffers_[i]->shm), false),
395 output_buffer_size));
396 }
397
398 host()->SendUnsolicitedReplyWithHandles(
399 pp_resource(), PpapiPluginMsg_VideoEncoder_BitstreamBuffers(
400 static_cast<uint32_t>(output_buffer_size)),
401 handles);
402
403 if (!initialized_) {
404 // Tell the plugin that initialization has been successful if we
405 // haven't already.
406 initialized_ = true;
407 encoder_last_error_ = PP_OK;
408 host()->SendReply(initialize_reply_context_,
409 PpapiPluginMsg_VideoEncoder_InitializeReply(
410 frame_count, PP_FromGfxSize(input_coded_size)));
411 }
412
413 if (shm_buffers_.empty()) {
414 NotifyPepperError(PP_ERROR_NOMEMORY);
415 return;
416 }
417
418 // If the plugin already requested video frames, we can now answer
419 // that request.
420 if (get_video_frames_reply_context_.is_valid())
421 AllocateVideoFrames();
422 }
423
424 void PepperVideoEncoderHost::BitstreamBufferReady(int32 buffer_id,
425 size_t payload_size,
426 bool key_frame) {
427 DCHECK(RenderThreadImpl::current());
428 DCHECK(shm_buffers_[buffer_id]->in_use);
429
430 shm_buffers_[buffer_id]->in_use = false;
431 host()->SendUnsolicitedReply(
432 pp_resource(),
433 PpapiPluginMsg_VideoEncoder_BitstreamBufferReady(
434 buffer_id, static_cast<uint32_t>(payload_size), key_frame));
435 }
436
437 void PepperVideoEncoderHost::NotifyError(
438 media::VideoEncodeAccelerator::Error error) {
439 DCHECK(RenderThreadImpl::current());
440 NotifyPepperError(PP_FromMediaEncodeAcceleratorError(error));
441 }
442
443 void PepperVideoEncoderHost::GetSupportedProfiles(
444 std::vector<PP_VideoProfileDescription>* pp_profiles) {
445 DCHECK(RenderThreadImpl::current());
446
447 if (!EnsureGpuChannel())
448 return;
449
450 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles =
451 GpuVideoEncodeAcceleratorHost::ConvertGpuToMediaProfiles(
452 channel_->gpu_info().video_encode_accelerator_supported_profiles);
453 for (media::VideoEncodeAccelerator::SupportedProfile profile : profiles)
454 pp_profiles->push_back(PP_FromVideoEncodeAcceleratorSupportedProfile(
455 profile, PP_HARDWAREACCELERATION_ONLY));
456
457 // TODO(llandwerlin): add software supported profiles.
458 }
459
460 bool PepperVideoEncoderHost::IsInitializationValid(
461 const PP_Size& input_size,
462 PP_VideoProfile output_profile,
463 PP_HardwareAcceleration acceleration) {
464 DCHECK(RenderThreadImpl::current());
465
466 std::vector<PP_VideoProfileDescription> profiles;
467 GetSupportedProfiles(&profiles);
468
469 for (const PP_VideoProfileDescription& profile : profiles) {
470 if (output_profile == profile.profile &&
471 input_size.width <= profile.max_resolution.width &&
472 input_size.height <= profile.max_resolution.height &&
473 PP_HardwareAccelerationCompatible(profile.acceleration, acceleration))
474 return true;
475 }
476
477 return false;
478 }
479
480 bool PepperVideoEncoderHost::EnsureGpuChannel() {
481 DCHECK(RenderThreadImpl::current());
482
483 if (command_buffer_)
484 return true;
485
486 // There is no guarantee that we have a 3D context to work with. So
487 // we create a dummy command buffer to communicate with the gpu process.
488 channel_ = RenderThreadImpl::current()->EstablishGpuChannelSync(
489 CAUSE_FOR_GPU_LAUNCH_PEPPERVIDEOENCODERACCELERATOR_INITIALIZE);
490 if (!channel_)
491 return false;
492
493 std::vector<int32> attribs(1, PP_GRAPHICS3DATTRIB_NONE);
494 command_buffer_ = channel_->CreateOffscreenCommandBuffer(
495 gfx::Size(), nullptr, attribs, GURL::EmptyGURL(),
496 gfx::PreferIntegratedGpu);
497 if (!command_buffer_) {
498 Close();
499 return false;
500 }
501
502 command_buffer_->SetChannelErrorCallback(media::BindToCurrentLoop(
503 base::Bind(&PepperVideoEncoderHost::NotifyPepperError,
504 weak_ptr_factory_.GetWeakPtr(), PP_ERROR_RESOURCE_FAILED)));
505 if (!command_buffer_->Initialize()) {
506 Close();
507 return false;
508 }
509
510 return true;
511 }
512
513 bool PepperVideoEncoderHost::InitializeHardware(
514 media::VideoFrame::Format input_format,
515 const gfx::Size& input_visible_size,
516 media::VideoCodecProfile output_profile,
517 uint32_t initial_bitrate) {
518 DCHECK(RenderThreadImpl::current());
519
520 if (!EnsureGpuChannel())
521 return false;
522
523 encoder_ = command_buffer_->CreateVideoEncoder();
524 if (!encoder_ ||
525 !encoder_->Initialize(input_format, input_visible_size, output_profile,
526 initial_bitrate, this))
527 return false;
528
529 return true;
530 }
531
532 void PepperVideoEncoderHost::Close() {
533 DCHECK(RenderThreadImpl::current());
534
535 encoder_ = nullptr;
536 if (command_buffer_) {
537 DCHECK(channel_);
538 channel_->DestroyCommandBuffer(command_buffer_);
539 command_buffer_ = nullptr;
540 }
541 }
542
543 void PepperVideoEncoderHost::AllocateVideoFrames() {
544 DCHECK(RenderThreadImpl::current());
545 DCHECK(get_video_frames_reply_context_.is_valid());
546
547 // Frames have already been allocated.
548 if (buffer_manager_.number_of_buffers() > 0) {
549 SendGetFramesErrorReply(PP_ERROR_FAILED);
550 NOTREACHED();
551 return;
552 }
553
554 base::CheckedNumeric<uint32_t> size =
555 media::VideoFrame::AllocationSize(media_input_format_, input_coded_size_);
556 uint32_t frame_size = size.ValueOrDie();
557 size += sizeof(ppapi::MediaStreamBuffer::Video);
558 uint32_t buffer_size = size.ValueOrDie();
559 // Make each buffer 4 byte aligned.
560 size += (4 - buffer_size % 4);
561 uint32_t buffer_size_aligned = size.ValueOrDie();
562 size *= frame_count_;
563 uint32_t total_size = size.ValueOrDie();
564
565 scoped_ptr<base::SharedMemory> shm(
566 RenderThreadImpl::current()
567 ->HostAllocateSharedMemoryBuffer(total_size)
568 .Pass());
569 if (!shm ||
570 !buffer_manager_.SetBuffers(frame_count_,
571 buffer_size_aligned,
572 shm.Pass(),
573 true)) {
574 SendGetFramesErrorReply(PP_ERROR_NOMEMORY);
575 return;
576 }
577
578 VLOG(4) << " frame_count=" << frame_count_ << " frame_size=" << frame_size
579 << " buffer_size=" << buffer_size_aligned;
580
581 for (int32_t i = 0; i < buffer_manager_.number_of_buffers(); ++i) {
582 ppapi::MediaStreamBuffer::Video* buffer =
583 &(buffer_manager_.GetBufferPointer(i)->video);
584 buffer->header.size = buffer_manager_.buffer_size();
585 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO;
586 buffer->format = PP_FromMediaVideoFormat(media_input_format_);
587 buffer->size.width = input_coded_size_.width();
588 buffer->size.height = input_coded_size_.height();
589 buffer->data_size = frame_size;
590 }
591
592 DCHECK(get_video_frames_reply_context_.is_valid());
593 get_video_frames_reply_context_.params.AppendHandle(SerializedHandle(
594 renderer_ppapi_host_->ShareHandleWithRemote(
595 ConvertSharedMemoryHandle(*buffer_manager_.shm()), false),
596 total_size));
597
598 host()->SendReply(get_video_frames_reply_context_,
599 PpapiPluginMsg_VideoEncoder_GetVideoFramesReply(
600 frame_count_, buffer_size_aligned,
601 PP_FromGfxSize(input_coded_size_)));
602 get_video_frames_reply_context_ = ppapi::host::ReplyMessageContext();
603 }
604
605 void PepperVideoEncoderHost::SendGetFramesErrorReply(int32_t error) {
606 get_video_frames_reply_context_.params.set_result(error);
607 host()->SendReply(
608 get_video_frames_reply_context_,
609 PpapiPluginMsg_VideoEncoder_GetVideoFramesReply(0, 0, PP_MakeSize(0, 0)));
610 get_video_frames_reply_context_ = ppapi::host::ReplyMessageContext();
611 }
612
613 scoped_refptr<media::VideoFrame> PepperVideoEncoderHost::CreateVideoFrame(
614 uint32_t frame_id,
615 const ppapi::host::ReplyMessageContext& reply_context) {
616 DCHECK(RenderThreadImpl::current());
617
618 ppapi::MediaStreamBuffer* buffer = buffer_manager_.GetBufferPointer(frame_id);
619 DCHECK(buffer);
620 uint32_t shm_offset = static_cast<uint8*>(buffer->video.data) -
621 static_cast<uint8*>(buffer_manager_.shm()->memory());
622
623 return media::VideoFrame::WrapExternalPackedMemory(
624 media_input_format_, input_coded_size_, gfx::Rect(input_coded_size_),
625 input_coded_size_, static_cast<uint8*>(buffer->video.data),
626 buffer->video.data_size, buffer_manager_.shm()->handle(), shm_offset,
627 base::TimeDelta(),
628 base::Bind(&PepperVideoEncoderHost::FrameReleased,
629 weak_ptr_factory_.GetWeakPtr(), reply_context, frame_id));
630 }
631
632 void PepperVideoEncoderHost::FrameReleased(
633 const ppapi::host::ReplyMessageContext& reply_context,
634 uint32_t frame_id) {
635 DCHECK(RenderThreadImpl::current());
636
637 ppapi::host::ReplyMessageContext context = reply_context;
638 context.params.set_result(encoder_last_error_);
639 host()->SendReply(context, PpapiPluginMsg_VideoEncoder_EncodeReply(frame_id));
640 }
641
642 void PepperVideoEncoderHost::NotifyPepperError(int32_t error) {
643 DCHECK(RenderThreadImpl::current());
644
645 encoder_last_error_ = error;
646 Close();
647 host()->SendUnsolicitedReply(
648 pp_resource(),
649 PpapiPluginMsg_VideoEncoder_NotifyError(encoder_last_error_));
650 }
651
652 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/pepper/pepper_video_encoder_host.h ('k') | content/test/ppapi/ppapi_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698