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

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

Powered by Google App Engine
This is Rietveld 408576698