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

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: Deal with Encode() callbacks in the proxy 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(
185 int32_t id,
186 scoped_ptr<base::SharedMemory> memory,
bbudge 2015/02/12 22:22:09 nit: s/memory/shm ?
llandwerlin-old 2015/02/13 20:12:25 Done.
187 size_t size)
188 : id(id), shm(memory.Pass()), in_use(true) {
189 if (shm)
bbudge 2015/02/12 22:22:09 Since it's only called inside this file, shm shoul
llandwerlin-old 2015/02/13 20:12:24 Done.
190 shm->Map(size);
191 }
192
193 PepperVideoEncoderHost::ShmBuffer::~ShmBuffer() {
194 }
195
196 media::BitstreamBuffer PepperVideoEncoderHost::ShmBuffer::toBitstreamBuffer() {
197 return media::BitstreamBuffer(id, shm->handle(), shm->mapped_size());
198 }
199
200 PepperVideoEncoderHost::PepperVideoEncoderHost(RendererPpapiHost* host,
201 PP_Instance instance,
202 PP_Resource resource)
203 : ResourceHost(host->GetPpapiHost(), instance, resource),
204 renderer_ppapi_host_(host),
205 buffer_manager_(this),
206 command_buffer_(nullptr),
207 initialized_(false),
208 encoder_last_error_(PP_ERROR_FAILED),
209 frame_count_(0),
210 media_input_format_(media::VideoFrame::UNKNOWN),
211 weak_ptr_factory_(this) {
212 }
213
214 PepperVideoEncoderHost::~PepperVideoEncoderHost() {
215 if (encoder_)
bbudge 2015/02/12 22:22:09 nit: 'if' isn't necessary.
llandwerlin-old 2015/02/13 20:12:24 Done.
216 encoder_ = nullptr;
217 if (command_buffer_) {
218 DCHECK(channel_);
219 channel_->DestroyCommandBuffer(command_buffer_);
220 command_buffer_ = nullptr;
221 }
222 }
bbudge 2015/02/12 22:22:10 Suggestion: Add a new utility method, Close() that
llandwerlin-old 2015/02/13 20:12:25 Done.
223
224 int32_t PepperVideoEncoderHost::OnResourceMessageReceived(
225 const IPC::Message& msg,
226 ppapi::host::HostMessageContext* context) {
227 PPAPI_BEGIN_MESSAGE_MAP(PepperVideoEncoderHost, msg)
228 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
229 PpapiHostMsg_VideoEncoder_GetSupportedProfiles,
230 OnHostMsgGetSupportedProfiles)
231 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoEncoder_Initialize,
232 OnHostMsgInitialize)
233 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
234 PpapiHostMsg_VideoEncoder_GetVideoFrames,
235 OnHostMsgGetVideoFrames)
236 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoEncoder_Encode,
237 OnHostMsgEncode)
238 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
239 PpapiHostMsg_VideoEncoder_RecycleBitstreamBuffer,
240 OnHostMsgRecycleBitstreamBuffer)
241 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
242 PpapiHostMsg_VideoEncoder_RequestEncodingParametersChange,
243 OnHostMsgRequestEncodingParametersChange)
244 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoEncoder_Close,
245 OnHostMsgClose)
246 PPAPI_END_MESSAGE_MAP()
247 return PP_ERROR_FAILED;
248 }
249
250 int32_t PepperVideoEncoderHost::OnHostMsgGetSupportedProfiles(
251 ppapi::host::HostMessageContext* context) {
252 std::vector<PP_VideoProfileDescription> pp_profiles;
253 GetSupportedProfiles(&pp_profiles);
254
255 host()->SendReply(
256 context->MakeReplyMessageContext(),
257 PpapiPluginMsg_VideoEncoder_GetSupportedProfilesReply(pp_profiles));
258
259 return PP_OK_COMPLETIONPENDING;
260 }
261
262 int32_t PepperVideoEncoderHost::OnHostMsgInitialize(
263 ppapi::host::HostMessageContext* context,
264 PP_VideoFrame_Format input_format,
265 const PP_Size& input_visible_size,
266 PP_VideoProfile output_profile,
267 uint32_t initial_bitrate,
268 PP_HardwareAcceleration acceleration) {
269 if (initialized_)
270 return PP_ERROR_FAILED;
271
272 media_input_format_ = PP_ToMediaVideoFormat(input_format);
273 if (media_input_format_ == media::VideoFrame::UNKNOWN)
274 return PP_ERROR_BADARGUMENT;
275
276 media::VideoCodecProfile media_profile =
277 PP_ToMediaVideoProfile(output_profile);
278 if (media_profile == media::VIDEO_CODEC_PROFILE_UNKNOWN)
279 return PP_ERROR_BADARGUMENT;
280
281 gfx::Size input_size(input_visible_size.width, input_visible_size.height);
282 if (input_size.IsEmpty())
283 return PP_ERROR_BADARGUMENT;
284
285 if (!IsInitializationValid(input_visible_size, output_profile, acceleration))
286 return PP_ERROR_NOTSUPPORTED;
287
288 initialize_reply_context_ = context->MakeReplyMessageContext();
289
290 if (acceleration == PP_HARDWAREACCELERATION_ONLY ||
291 acceleration == PP_HARDWAREACCELERATION_WITHFALLBACK) {
292 // There is no guarantee that we have a 3D context to work with. So
293 // we create a dummy command buffer to communicate with the gpu process.
294 channel_ = RenderThreadImpl::current()->EstablishGpuChannelSync(
295 CAUSE_FOR_GPU_LAUNCH_PEPPERVIDEOENCODERACCELERATOR_INITIALIZE);
296 if (!channel_.get())
297 return PP_ERROR_FAILED;
298
299 std::vector<int32> attribs(1, PP_GRAPHICS3DATTRIB_NONE);
300
301 command_buffer_ = channel_->CreateOffscreenCommandBuffer(
302 gfx::Size(), nullptr, attribs, GURL::EmptyGURL(),
303 gfx::PreferIntegratedGpu);
304 if (!command_buffer_)
305 return PP_ERROR_FAILED;
306
307 command_buffer_->SetChannelErrorCallback(media::BindToCurrentLoop(
308 base::Bind(&PepperVideoEncoderHost::NotifyPepperError,
309 weak_ptr_factory_.GetWeakPtr(), PP_ERROR_FAILED)));
310
311 if (!command_buffer_->Initialize())
312 return PP_ERROR_FAILED;
313
314 encoder_ = command_buffer_->CreateVideoEncoder();
315 if (encoder_ &&
316 encoder_->Initialize(media_input_format_, input_size, media_profile,
317 initial_bitrate, this)) {
318 initialized_ = true;
319 host()->SendReply(context->MakeReplyMessageContext(),
320 PpapiPluginMsg_VideoEncoder_InitializeReply());
321 return PP_OK;
322 }
323
324 if (acceleration == PP_HARDWAREACCELERATION_ONLY) {
325 encoder_ = nullptr;
bbudge 2015/02/12 22:22:09 You probably should Close() this instance here. Se
llandwerlin-old 2015/02/13 20:12:25 Done.
326 return PP_ERROR_FAILED;
327 }
328 }
329
330 // TODO(llandwerlin): Software encoder.
331 return PP_ERROR_NOTSUPPORTED;
332 }
333
334 int32_t PepperVideoEncoderHost::OnHostMsgGetVideoFrames(
335 ppapi::host::HostMessageContext* context) {
336 if (encoder_last_error_)
337 return encoder_last_error_;
338
339 uint32_t frame_length =
340 media::VideoFrame::AllocationSize(media_input_format_, input_coded_size_);
bbudge 2015/02/12 22:22:09 This doesn't overflow because of your input valida
llandwerlin-old 2015/02/13 20:12:24 Done.
341 uint32_t buffer_size = frame_length +
342 sizeof(ppapi::MediaStreamBuffer::Video) -
343 sizeof(ppapi::MediaStreamBuffer::Video::data);
344
345 // Make each buffer 4 byte aligned.
346 base::CheckedNumeric<int32_t> buffer_size_aligned = buffer_size;
347 buffer_size_aligned += (4 - buffer_size % 4);
348
349 base::CheckedNumeric<int32_t> total_size = frame_count_ * buffer_size_aligned;
350 if (!total_size.IsValid())
351 return PP_ERROR_FAILED;
352
353 scoped_ptr<base::SharedMemory> shm(
354 RenderThreadImpl::current()
355 ->HostAllocateSharedMemoryBuffer(total_size.ValueOrDie())
356 .Pass());
357 if (!shm)
358 return PP_ERROR_FAILED;
bbudge 2015/02/12 22:22:10 PP_ERROR_NOMEMORY is more consistent.
llandwerlin-old 2015/02/13 20:12:25 Done.
359
360 VLOG(4) << " frame_count=" << frame_count_ << " frame_length=" << frame_length
361 << " buffer_size=" << buffer_size_aligned.ValueOrDie();
362
363 if (!buffer_manager_.SetBuffers(
364 frame_count_, buffer_size_aligned.ValueOrDie(), shm.Pass(), true))
365 return PP_ERROR_FAILED;
366
367 for (int32_t i = 0; i < buffer_manager_.number_of_buffers(); ++i) {
368 ppapi::MediaStreamBuffer::Video* buffer =
369 &(buffer_manager_.GetBufferPointer(i)->video);
370 buffer->header.size = buffer_manager_.buffer_size();
371 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO;
372 buffer->format = PP_FromMediaVideoFormat(media_input_format_);
373 buffer->size.width = input_coded_size_.width();
374 buffer->size.height = input_coded_size_.height();
375 buffer->data_size = frame_length;
376 }
377
378 ppapi::host::ReplyMessageContext reply_context =
379 context->MakeReplyMessageContext();
380 reply_context.params.AppendHandle(SerializedHandle(
381 renderer_ppapi_host_->ShareHandleWithRemote(
382 ConvertSharedMemoryHandle(*buffer_manager_.shm()), false),
383 total_size.ValueOrDie()));
384
385 host()->SendReply(reply_context,
386 PpapiPluginMsg_VideoEncoder_GetVideoFramesReply(
387 frame_count_, buffer_size_aligned.ValueOrDie(),
388 PP_FromGfxSize(input_coded_size_)));
389
390 return PP_OK_COMPLETIONPENDING;
391 }
392
393 int32_t PepperVideoEncoderHost::OnHostMsgEncode(
394 ppapi::host::HostMessageContext* context,
395 uint32_t frame_id,
396 bool force_keyframe) {
397 if (encoder_last_error_)
398 return encoder_last_error_;
399
400 if (frame_id >= static_cast<uint32_t>(buffer_manager_.number_of_buffers()))
bbudge 2015/02/12 22:22:09 Could you use frame_count_ instead of buffer_manag
llandwerlin-old 2015/02/13 20:12:24 Done.
401 return PP_ERROR_FAILED;
402
403 encoder_->Encode(
404 CreateVideoFrame(frame_id, context->MakeReplyMessageContext()),
405 force_keyframe);
406
407 return PP_OK_COMPLETIONPENDING;
408 }
409
410 int32_t PepperVideoEncoderHost::OnHostMsgRecycleBitstreamBuffer(
411 ppapi::host::HostMessageContext* context,
412 uint32_t buffer_id) {
413 if (encoder_last_error_)
414 return encoder_last_error_;
415
416 if (buffer_id < 0 ||
bbudge 2015/02/12 22:22:09 buffer_id is unsigned
llandwerlin-old 2015/02/13 20:12:25 Done.
417 buffer_id >= shm_buffers_.size() ||
418 shm_buffers_[buffer_id]->in_use)
419 return PP_ERROR_FAILED;
420
421 shm_buffers_[buffer_id]->in_use = true;
422 encoder_->UseOutputBitstreamBuffer(
423 shm_buffers_[buffer_id]->toBitstreamBuffer());
424
425 return PP_OK;
426 }
427
428 int32_t PepperVideoEncoderHost::OnHostMsgRequestEncodingParametersChange(
429 ppapi::host::HostMessageContext* context,
430 uint32_t bitrate,
431 uint32_t framerate) {
432 if (encoder_last_error_)
433 return encoder_last_error_;
434
435 encoder_->RequestEncodingParametersChange(bitrate, framerate);
436
437 return PP_OK;
438 }
439
440 int32_t PepperVideoEncoderHost::OnHostMsgClose(
441 ppapi::host::HostMessageContext* context) {
442 encoder_last_error_ = PP_ERROR_ABORTED;
bbudge 2015/02/12 22:22:09 This error code just seems odd to me here, as it's
llandwerlin-old 2015/02/13 20:12:25 Sure.
443 encoder_ = nullptr;
444
445 return PP_OK;
446 }
447
448 void PepperVideoEncoderHost::RequireBitstreamBuffers(
449 unsigned int frame_count,
450 const gfx::Size& input_coded_size,
451 size_t output_buffer_size) {
452 DCHECK(RenderThreadImpl::current());
453
454 std::vector<SerializedHandle> handles;
455 for (int32_t i = 0; i < kDefaultNumberOfBitstreamBuffers; ++i) {
456 scoped_ptr<base::SharedMemory> shm(
457 RenderThread::Get()
458 ->HostAllocateSharedMemoryBuffer(output_buffer_size)
459 .Pass());
460
461 if (!shm || !shm->Map(output_buffer_size)) {
462 shm_buffers_.clear();
463 break;
464 }
465
466 shm_buffers_.push_back(new ShmBuffer(i, shm.Pass(), output_buffer_size));
467
468 handles.push_back(SerializedHandle(
469 renderer_ppapi_host_->ShareHandleWithRemote(
470 ConvertSharedMemoryHandle(*shm_buffers_.back()->shm), false),
471 output_buffer_size));
bbudge 2015/02/12 22:22:10 You could save a loop by creating the SerializedHa
llandwerlin-old 2015/02/13 20:12:25 Nicer indeed.
472 }
473
474 if (shm_buffers_.empty()) {
475 for (SerializedHandle& handle : handles)
476 handle.Close();
477 NotifyPepperError(PP_ERROR_FAILED);
bbudge 2015/02/12 22:22:09 PP_ERROR_NOMEMORY
llandwerlin-old 2015/02/13 20:12:25 Done.
478 return;
479 }
480
481 // Feed buffers to the encoder.
482 for (size_t i = 0; i < shm_buffers_.size(); ++i) {
483 encoder_->UseOutputBitstreamBuffer(shm_buffers_[i]->toBitstreamBuffer());
484 }
485
486 // Notify the plugin of the buffers and the input size.
bbudge 2015/02/12 22:22:09 nit: s/input size/encoding parameters because ther
llandwerlin-old 2015/02/13 20:12:25 Done.
487 PP_Size size =
488 PP_MakeSize(input_coded_size.width(), input_coded_size.height());
489 input_coded_size_ = input_coded_size;
490 frame_count_ = frame_count;
491 encoder_last_error_ = PP_OK;
bbudge 2015/02/12 22:22:09 I think this should be set in OnHostMsgInitialize(
llandwerlin-old 2015/02/13 20:12:25 Done.
492
493 host()->SendUnsolicitedReplyWithHandles(
494 pp_resource(),
495 PpapiPluginMsg_VideoEncoder_BitstreamBuffers(output_buffer_size,
bbudge 2015/02/12 22:22:09 output_buffer_size is size_t but param is uint32_t
llandwerlin-old 2015/02/13 20:12:25 Done.
496 frame_count,
497 size),
498 handles);
499 }
500
501 void PepperVideoEncoderHost::BitstreamBufferReady(int32 buffer_id,
502 size_t payload_size,
503 bool key_frame) {
504 DCHECK(RenderThreadImpl::current());
505 DCHECK(shm_buffers_[buffer_id]->in_use);
506
507 shm_buffers_[buffer_id]->in_use = false;
508 host()->SendUnsolicitedReply(pp_resource(),
509 PpapiPluginMsg_VideoEncoder_BitstreamBufferReady(
510 buffer_id, payload_size, key_frame));
511 }
512
513 void PepperVideoEncoderHost::NotifyError(
514 media::VideoEncodeAccelerator::Error error) {
515 DCHECK(RenderThreadImpl::current());
516 NotifyPepperError(PP_FromMediaEncodeAcceleratorError(error));
517 }
518
519 void PepperVideoEncoderHost::GetSupportedProfiles(
520 std::vector<PP_VideoProfileDescription>* pp_profiles) {
521 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles =
522 RenderThreadImpl::current()
523 ->GetGpuFactories()
524 ->GetVideoEncodeAcceleratorSupportedProfiles();
525 for (media::VideoEncodeAccelerator::SupportedProfile profile : profiles)
526 pp_profiles->push_back(PP_FromVideoEncodeAcceleratorSupportedProfile(
527 profile, PP_HARDWAREACCELERATION_ONLY));
528
529 // TODO(llandwerlin): add software supported profiles.
530 }
531
532 bool PepperVideoEncoderHost::IsInitializationValid(
533 const PP_Size& input_size,
534 PP_VideoProfile output_profile,
535 PP_HardwareAcceleration acceleration) {
536 std::vector<PP_VideoProfileDescription> profiles;
537 GetSupportedProfiles(&profiles);
538
539 for (const PP_VideoProfileDescription& profile : profiles) {
540 if (output_profile == profile.profile &&
541 input_size.width <= profile.max_resolution.width &&
542 input_size.height <= profile.max_resolution.height &&
543 PP_HardwareAccelerationCompatible(profile.acceleration, acceleration))
544 return true;
545 }
546
547 return false;
548 }
549
550 scoped_refptr<media::VideoFrame> PepperVideoEncoderHost::CreateVideoFrame(
551 uint32_t frame_id,
552 const ppapi::host::ReplyMessageContext& reply_context) {
553 DCHECK_LT(frame_id,
554 static_cast<uint32_t>(buffer_manager_.number_of_buffers()));
bbudge 2015/02/12 22:22:09 frame_count_?
llandwerlin-old 2015/02/13 20:12:25 Done.
555
556 ppapi::MediaStreamBuffer* buffer = buffer_manager_.GetBufferPointer(frame_id);
bbudge 2015/02/12 22:22:10 This returns NULL if frame_id is out of range, so
llandwerlin-old 2015/02/13 20:12:25 Done.
557 uint32_t shm_offset = frame_id * buffer_manager_.buffer_size() +
558 sizeof(ppapi::MediaStreamBuffer::Video) -
559 sizeof(ppapi::MediaStreamBuffer::Video::data);
560
561 return media::VideoFrame::WrapExternalPackedMemory(
562 media_input_format_, input_coded_size_, gfx::Rect(input_coded_size_),
563 input_coded_size_, static_cast<uint8*>(buffer->video.data),
564 buffer->video.data_size, buffer_manager_.shm()->handle(), shm_offset,
565 base::TimeDelta(), base::Bind(
566 &PepperVideoEncoderHost::EncodeDone,
567 weak_ptr_factory_.GetWeakPtr(), reply_context, frame_id));
568 }
569
570 void PepperVideoEncoderHost::EncodeDone(
571 const ppapi::host::ReplyMessageContext& reply_context,
572 uint32_t frame_id) {
573 DCHECK(RenderThreadImpl::current());
574
575 ppapi::host::ReplyMessageContext context = reply_context;
576 context.params.set_result(encoder_last_error_);
bbudge 2015/02/12 22:22:09 EncodeDone is a confusing to me. Could we rename t
llandwerlin-old 2015/02/13 20:12:24 Sure.
577 host()->SendReply(reply_context,
578 PpapiPluginMsg_VideoEncoder_EncodeReply(frame_id));
579 }
580
581 void PepperVideoEncoderHost::NotifyPepperError(int32_t error) {
582 DCHECK(RenderThreadImpl::current());
583
584 encoder_last_error_ = error;
585 encoder_ = nullptr;
bbudge 2015/02/12 22:22:10 Close() here instead?
llandwerlin-old 2015/02/13 20:12:25 Done.
586 host()->SendUnsolicitedReply(
587 pp_resource(),
588 PpapiPluginMsg_VideoEncoder_NotifyError(encoder_last_error_));
589 }
590
591 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698